summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2019-03-25 14:09:10 +0000
committerNico Weber <nicolasweber@gmx.de>2019-03-25 14:09:10 +0000
commit43356f56bd2ede05c70db537e3f8b50a31444487 (patch)
tree2e5053b7c5d732251b093c2baeb9be2446d2f547 /clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp
parent2ef15d82e9086b97a18d7acbcbca31a81450105c (diff)
downloadbcm5719-llvm-43356f56bd2ede05c70db537e3f8b50a31444487.tar.gz
bcm5719-llvm-43356f56bd2ede05c70db537e3f8b50a31444487.zip
Rename directory housing clang-include-fixer to be eponymous
Makes the name of this directory consistent with the names of the other directories in clang-tools-extra. Similar to r356254. No intended behavior change. Differential Revision: https://reviews.llvm.org/D59750 llvm-svn: 356897
Diffstat (limited to 'clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp')
-rw-r--r--clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp b/clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp
new file mode 100644
index 00000000000..a9fef45c46c
--- /dev/null
+++ b/clang-tools-extra/clang-include-fixer/IncludeFixerContext.cpp
@@ -0,0 +1,115 @@
+//===-- IncludeFixerContext.cpp - Include fixer context ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "IncludeFixerContext.h"
+#include <algorithm>
+
+namespace clang {
+namespace include_fixer {
+
+namespace {
+
+// Splits a multiply qualified names (e.g. a::b::c).
+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) {
+ // No need to add missing qualifiers if SymbolIndentifer has a global scope
+ // operator "::".
+ if (RawSymbolName.startswith("::"))
+ return RawSymbolName;
+
+ std::string QualifiedName = MatchedSymbol.getQualifiedName();
+
+ // For nested classes, the qualified name constructed from database misses
+ // some stripped qualifiers, because when we search a symbol in database,
+ // we strip qualifiers from the end until we find a result. So append the
+ // missing stripped qualifiers here.
+ //
+ // Get stripped qualifiers.
+ auto SymbolQualifiers = SplitQualifiers(RawSymbolName);
+ std::string StrippedQualifiers;
+ while (!SymbolQualifiers.empty() &&
+ !llvm::StringRef(QualifiedName).endswith(SymbolQualifiers.back())) {
+ StrippedQualifiers =
+ "::" + SymbolQualifiers.back().str() + StrippedQualifiers;
+ SymbolQualifiers.pop_back();
+ }
+ // Append the missing stripped qualifiers.
+ std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;
+
+ // Try to find and skip the common prefix qualifiers.
+ 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;
+}
+
+} // anonymous namespace
+
+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)) {
+ // Remove replicated QuerySymbolInfos with the same range.
+ //
+ // QuerySymbolInfos may contain replicated elements. Because CorrectTypo
+ // callback doesn't always work as we expected. In somecases, it will be
+ // triggered at the same position or unidentified symbol multiple times.
+ std::sort(QuerySymbolInfos.begin(), QuerySymbolInfos.end(),
+ [&](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)});
+ }
+ // Deduplicate header infos.
+ 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());
+}
+
+} // include_fixer
+} // clang
OpenPOWER on IntegriCloud