#include "IncludeFixerContext.h"
#include "llvm/ADT/STLExtras.h"
namespace clang {
namespace include_fixer {
namespace {
llvm::SmallVector<llvm::StringRef, 8>
SplitQualifiers(llvm::StringRef StringQualifiers) {
llvm::SmallVector<llvm::StringRef, 8> Qualifiers;
StringQualifiers.split(Qualifiers, "::");
return Qualifiers;
}
std::string createQualifiedNameForReplacement(
llvm::StringRef RawSymbolName,
llvm::StringRef SymbolScopedQualifiersName,
const find_all_symbols::SymbolInfo &MatchedSymbol) {
if (RawSymbolName.starts_with("::"))
return std::string(RawSymbolName);
std::string QualifiedName = MatchedSymbol.getQualifiedName();
auto SymbolQualifiers = SplitQualifiers(RawSymbolName);
std::string StrippedQualifiers;
while (!SymbolQualifiers.empty() &&
!llvm::StringRef(QualifiedName).ends_with(SymbolQualifiers.back())) {
StrippedQualifiers =
"::" + SymbolQualifiers.back().str() + StrippedQualifiers;
SymbolQualifiers.pop_back();
}
std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;
auto FullySymbolQualifiers = SplitQualifiers(FullyQualifiedName);
auto ScopedQualifiers = SplitQualifiers(SymbolScopedQualifiersName);
auto FullySymbolQualifiersIter = FullySymbolQualifiers.begin();
auto SymbolScopedQualifiersIter = ScopedQualifiers.begin();
while (FullySymbolQualifiersIter != FullySymbolQualifiers.end() &&
SymbolScopedQualifiersIter != ScopedQualifiers.end()) {
if (*FullySymbolQualifiersIter != *SymbolScopedQualifiersIter)
break;
++FullySymbolQualifiersIter;
++SymbolScopedQualifiersIter;
}
std::string Result;
for (; FullySymbolQualifiersIter != FullySymbolQualifiers.end();
++FullySymbolQualifiersIter) {
if (!Result.empty())
Result += "::";
Result += *FullySymbolQualifiersIter;
}
return Result;
}
}
IncludeFixerContext::IncludeFixerContext(
StringRef FilePath, std::vector<QuerySymbolInfo> QuerySymbols,
std::vector<find_all_symbols::SymbolInfo> Symbols)
: FilePath(FilePath), QuerySymbolInfos(std::move(QuerySymbols)),
MatchedSymbols(std::move(Symbols)) {
llvm::sort(QuerySymbolInfos,
[&](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {
return std::make_pair(A.Range.getOffset(), A.Range.getLength()) <
std::make_pair(B.Range.getOffset(), B.Range.getLength());
});
QuerySymbolInfos.erase(
std::unique(QuerySymbolInfos.begin(), QuerySymbolInfos.end(),
[](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {
return A.Range == B.Range;
}),
QuerySymbolInfos.end());
for (const auto &Symbol : MatchedSymbols) {
HeaderInfos.push_back(
{Symbol.getFilePath().str(),
createQualifiedNameForReplacement(
QuerySymbolInfos.front().RawIdentifier,
QuerySymbolInfos.front().ScopedQualifiers, Symbol)});
}
HeaderInfos.erase(std::unique(HeaderInfos.begin(), HeaderInfos.end(),
[](const HeaderInfo &A, const HeaderInfo &B) {
return A.Header == B.Header &&
A.QualifiedName == B.QualifiedName;
}),
HeaderInfos.end());
}
}
}