Changeset View
Changeset View
Standalone View
Standalone View
clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
Show First 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | for (auto Line : Lines) { | ||||
NextLineOffset = std::min(Code.size(), Offset + Line.size() + 1); | NextLineOffset = std::min(Code.size(), Offset + Line.size() + 1); | ||||
if (IncludeRegex.match(Line, &Matches)) { | if (IncludeRegex.match(Line, &Matches)) { | ||||
// If this is the last line without trailing newline, we need to make | // If this is the last line without trailing newline, we need to make | ||||
// sure we don't delete across the file boundary. | // sure we don't delete across the file boundary. | ||||
addExistingInclude( | addExistingInclude( | ||||
Include(Matches[2], | Include(Matches[2], | ||||
tooling::Range( | tooling::Range( | ||||
Offset, std::min(Line.size() + 1, Code.size() - Offset))), | Offset, std::min(Line.size() + 1, Code.size() - Offset))), | ||||
NextLineOffset); | NextLineOffset); | ||||
kadircet: i know this is not possible today, but just to be safe, can we actually check for `import` here… | |||||
} | } | ||||
Offset = NextLineOffset; | Offset = NextLineOffset; | ||||
} | } | ||||
// Populate CategoryEndOfssets: | // Populate CategoryEndOfssets: | ||||
// - Ensure that CategoryEndOffset[Highest] is always populated. | // - Ensure that CategoryEndOffset[Highest] is always populated. | ||||
// - If CategoryEndOffset[Priority] isn't set, use the next higher value | // - If CategoryEndOffset[Priority] isn't set, use the next higher value | ||||
// that is set, up to CategoryEndOffset[Highest]. | // that is set, up to CategoryEndOffset[Highest]. | ||||
Show All 28 Lines | if (CurInclude.R.getOffset() <= MaxInsertOffset) { | ||||
CategoryEndOffsets[Priority] = NextLineOffset; | CategoryEndOffsets[Priority] = NextLineOffset; | ||||
IncludesByPriority[Priority].push_back(&CurInclude); | IncludesByPriority[Priority].push_back(&CurInclude); | ||||
if (FirstIncludeOffset < 0) | if (FirstIncludeOffset < 0) | ||||
FirstIncludeOffset = CurInclude.R.getOffset(); | FirstIncludeOffset = CurInclude.R.getOffset(); | ||||
} | } | ||||
} | } | ||||
llvm::Optional<tooling::Replacement> | llvm::Optional<tooling::Replacement> | ||||
HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const { | HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled, | ||||
bool IsImport) const { | |||||
assert(IncludeName == trimInclude(IncludeName)); | assert(IncludeName == trimInclude(IncludeName)); | ||||
// If a <header> ("header") already exists in code, "header" (<header>) with | // If a <header> ("header") already exists in code, "header" (<header>) with | ||||
// different quotation will still be inserted. | // different quotation will still be inserted. | ||||
// FIXME: figure out if this is the best behavior. | // FIXME: figure out if this is the best behavior. | ||||
auto It = ExistingIncludes.find(IncludeName); | auto It = ExistingIncludes.find(IncludeName); | ||||
if (It != ExistingIncludes.end()) | if (It != ExistingIncludes.end()) | ||||
nit: can you put some braces around the outermost if, as the statements inside are getting long. kadircet: nit: can you put some braces around the outermost `if`, as the statements inside are getting… | |||||
for (const auto &Inc : It->second) | for (const auto &Inc : It->second) | ||||
if ((IsAngled && StringRef(Inc.Name).startswith("<")) || | if ((IsAngled && StringRef(Inc.Name).startswith("<")) || | ||||
(!IsAngled && StringRef(Inc.Name).startswith("\""))) | (!IsAngled && StringRef(Inc.Name).startswith("\""))) | ||||
return llvm::None; | return llvm::None; | ||||
std::string Quoted = | std::string Quoted = | ||||
std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName)); | std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName)); | ||||
StringRef QuotedName = Quoted; | StringRef QuotedName = Quoted; | ||||
int Priority = Categories.getIncludePriority( | int Priority = Categories.getIncludePriority( | ||||
QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0); | QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0); | ||||
auto CatOffset = CategoryEndOffsets.find(Priority); | auto CatOffset = CategoryEndOffsets.find(Priority); | ||||
assert(CatOffset != CategoryEndOffsets.end()); | assert(CatOffset != CategoryEndOffsets.end()); | ||||
unsigned InsertOffset = CatOffset->second; // Fall back offset | unsigned InsertOffset = CatOffset->second; // Fall back offset | ||||
auto Iter = IncludesByPriority.find(Priority); | auto Iter = IncludesByPriority.find(Priority); | ||||
if (Iter != IncludesByPriority.end()) { | if (Iter != IncludesByPriority.end()) { | ||||
for (const auto *Inc : Iter->second) { | for (const auto *Inc : Iter->second) { | ||||
if (QuotedName < Inc->Name) { | if (QuotedName < Inc->Name) { | ||||
InsertOffset = Inc->R.getOffset(); | InsertOffset = Inc->R.getOffset(); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
assert(InsertOffset <= Code.size()); | assert(InsertOffset <= Code.size()); | ||||
std::string NewInclude = | std::string NewInclude = | ||||
nit: llvm::StringLiteral DirectiveSpelling = Directive == IncludeDirective::Include ? "include" : "import"; std::string NewInclude = llvm::formatv("#{0} {1}\n", DirectiveSpelling, QuotedName); // this already has an implicit conversion operator to std::string kadircet: nit:
```
llvm::StringLiteral DirectiveSpelling = Directive == IncludeDirective::Include ? | |||||
std::string(llvm::formatv("#include {0}\n", QuotedName)); | IsImport ? std::string(llvm::formatv("#import {0}\n", QuotedName)) | ||||
: std::string(llvm::formatv("#include {0}\n", QuotedName)); | |||||
// When inserting headers at end of the code, also append '\n' to the code | // When inserting headers at end of the code, also append '\n' to the code | ||||
// if it does not end with '\n'. | // if it does not end with '\n'. | ||||
// FIXME: when inserting multiple #includes at the end of code, only one | // FIXME: when inserting multiple #includes at the end of code, only one | ||||
// newline should be added. | // newline should be added. | ||||
if (InsertOffset == Code.size() && (!Code.empty() && Code.back() != '\n')) | if (InsertOffset == Code.size() && (!Code.empty() && Code.back() != '\n')) | ||||
NewInclude = "\n" + NewInclude; | NewInclude = "\n" + NewInclude; | ||||
return tooling::Replacement(FileName, InsertOffset, 0, NewInclude); | return tooling::Replacement(FileName, InsertOffset, 0, NewInclude); | ||||
} | } | ||||
Show All 25 Lines |
i know this is not possible today, but just to be safe, can we actually check for import here and default to include ?