14
14
namespace include_fixer {
16
IncludeFixerContext::IncludeFixerContext(
17
llvm::StringRef Name, llvm::StringRef ScopeQualifiers,
18
const std::vector<find_all_symbols::SymbolInfo> Symbols,
20
: SymbolIdentifier(Name), SymbolScopedQualifiers(ScopeQualifiers),
21
MatchedSymbols(Symbols), SymbolRange(Range) {
22
// Deduplicate headers, so that we don't want to suggest the same header
24
for (const auto &Symbol : MatchedSymbols)
25
Headers.push_back(Symbol.getFilePath());
26
Headers.erase(std::unique(Headers.begin(), Headers.end(),
27
[](const std::string &A, const std::string &B) {
34
IncludeFixerContext::createSymbolReplacement(llvm::StringRef FilePath,
36
assert(Idx < MatchedSymbols.size());
18
std::string createQualifiedNameForReplacement(
19
llvm::StringRef RawSymbolName,
20
llvm::StringRef SymbolScopedQualifiers,
21
const find_all_symbols::SymbolInfo &MatchedSymbol) {
37
22
// No need to add missing qualifiers if SymbolIndentifer has a global scope
39
if (getSymbolIdentifier().startswith("::"))
40
return tooling::Replacement();
41
std::string QualifiedName = MatchedSymbols[Idx].getQualifiedName();
24
if (RawSymbolName.startswith("::"))
27
std::string QualifiedName = MatchedSymbol.getQualifiedName();
42
29
// For nested classes, the qualified name constructed from database misses
43
30
// some stripped qualifiers, because when we search a symbol in database,
44
31
// we strip qualifiers from the end until we find a result. So append the
47
34
// Get stripped qualifiers.
48
35
llvm::SmallVector<llvm::StringRef, 8> SymbolQualifiers;
49
getSymbolIdentifier().split(SymbolQualifiers, "::");
36
RawSymbolName.split(SymbolQualifiers, "::");
50
37
std::string StrippedQualifiers;
51
38
while (!SymbolQualifiers.empty() &&
52
39
!llvm::StringRef(QualifiedName).endswith(SymbolQualifiers.back())) {
56
43
// Append the missing stripped qualifiers.
57
44
std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;
58
45
auto pos = FullyQualifiedName.find(SymbolScopedQualifiers);
59
return {FilePath, SymbolRange.getOffset(), SymbolRange.getLength(),
60
FullyQualifiedName.substr(
61
pos == std::string::npos ? 0 : SymbolScopedQualifiers.size())};
46
return FullyQualifiedName.substr(
47
pos == std::string::npos ? 0 : SymbolScopedQualifiers.size());
50
} // anonymous namespace
52
IncludeFixerContext::IncludeFixerContext(
53
llvm::StringRef Name, llvm::StringRef ScopeQualifiers,
54
std::vector<find_all_symbols::SymbolInfo> Symbols,
56
: SymbolIdentifier(Name), SymbolScopedQualifiers(ScopeQualifiers),
57
MatchedSymbols(std::move(Symbols)), SymbolRange(Range) {
58
for (const auto &Symbol : MatchedSymbols) {
59
HeaderInfos.push_back({Symbol.getFilePath().str(),
60
createQualifiedNameForReplacement(
61
SymbolIdentifier, ScopeQualifiers, Symbol)});
63
// Deduplicate header infos.
64
HeaderInfos.erase(std::unique(HeaderInfos.begin(), HeaderInfos.end(),
65
[](const HeaderInfo &A, const HeaderInfo &B) {
66
return A.Header == B.Header &&
67
A.QualifiedName == B.QualifiedName;