clang-tools  7.0.0
IncludeFixerContext.cpp
Go to the documentation of this file.
1 //===-- IncludeFixerContext.cpp - Include fixer context ---------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "IncludeFixerContext.h"
11 #include <algorithm>
12 
13 namespace clang {
14 namespace include_fixer {
15 
16 namespace {
17 
18 // Splits a multiply qualified names (e.g. a::b::c).
19 llvm::SmallVector<llvm::StringRef, 8>
20 SplitQualifiers(llvm::StringRef StringQualifiers) {
21  llvm::SmallVector<llvm::StringRef, 8> Qualifiers;
22  StringQualifiers.split(Qualifiers, "::");
23  return Qualifiers;
24 }
25 
26 std::string createQualifiedNameForReplacement(
27  llvm::StringRef RawSymbolName,
28  llvm::StringRef SymbolScopedQualifiersName,
29  const find_all_symbols::SymbolInfo &MatchedSymbol) {
30  // No need to add missing qualifiers if SymbolIndentifer has a global scope
31  // operator "::".
32  if (RawSymbolName.startswith("::"))
33  return RawSymbolName;
34 
35  std::string QualifiedName = MatchedSymbol.getQualifiedName();
36 
37  // For nested classes, the qualified name constructed from database misses
38  // some stripped qualifiers, because when we search a symbol in database,
39  // we strip qualifiers from the end until we find a result. So append the
40  // missing stripped qualifiers here.
41  //
42  // Get stripped qualifiers.
43  auto SymbolQualifiers = SplitQualifiers(RawSymbolName);
44  std::string StrippedQualifiers;
45  while (!SymbolQualifiers.empty() &&
46  !llvm::StringRef(QualifiedName).endswith(SymbolQualifiers.back())) {
47  StrippedQualifiers =
48  "::" + SymbolQualifiers.back().str() + StrippedQualifiers;
49  SymbolQualifiers.pop_back();
50  }
51  // Append the missing stripped qualifiers.
52  std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;
53 
54  // Try to find and skip the common prefix qualifiers.
55  auto FullySymbolQualifiers = SplitQualifiers(FullyQualifiedName);
56  auto ScopedQualifiers = SplitQualifiers(SymbolScopedQualifiersName);
57  auto FullySymbolQualifiersIter = FullySymbolQualifiers.begin();
58  auto SymbolScopedQualifiersIter = ScopedQualifiers.begin();
59  while (FullySymbolQualifiersIter != FullySymbolQualifiers.end() &&
60  SymbolScopedQualifiersIter != ScopedQualifiers.end()) {
61  if (*FullySymbolQualifiersIter != *SymbolScopedQualifiersIter)
62  break;
63  ++FullySymbolQualifiersIter;
64  ++SymbolScopedQualifiersIter;
65  }
66  std::string Result;
67  for (; FullySymbolQualifiersIter != FullySymbolQualifiers.end();
68  ++FullySymbolQualifiersIter) {
69  if (!Result.empty())
70  Result += "::";
71  Result += *FullySymbolQualifiersIter;
72  }
73  return Result;
74 }
75 
76 } // anonymous namespace
77 
79  StringRef FilePath, std::vector<QuerySymbolInfo> QuerySymbols,
80  std::vector<find_all_symbols::SymbolInfo> Symbols)
81  : FilePath(FilePath), QuerySymbolInfos(std::move(QuerySymbols)),
82  MatchedSymbols(std::move(Symbols)) {
83  // Remove replicated QuerySymbolInfos with the same range.
84  //
85  // QuerySymbolInfos may contain replicated elements. Because CorrectTypo
86  // callback doesn't always work as we expected. In somecases, it will be
87  // triggered at the same position or unidentified symbol multiple times.
88  std::sort(QuerySymbolInfos.begin(), QuerySymbolInfos.end(),
89  [&](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {
90  return std::make_pair(A.Range.getOffset(), A.Range.getLength()) <
91  std::make_pair(B.Range.getOffset(), B.Range.getLength());
92  });
93  QuerySymbolInfos.erase(
94  std::unique(QuerySymbolInfos.begin(), QuerySymbolInfos.end(),
95  [](const QuerySymbolInfo &A, const QuerySymbolInfo &B) {
96  return A.Range == B.Range;
97  }),
98  QuerySymbolInfos.end());
99  for (const auto &Symbol : MatchedSymbols) {
100  HeaderInfos.push_back(
101  {Symbol.getFilePath().str(),
102  createQualifiedNameForReplacement(
103  QuerySymbolInfos.front().RawIdentifier,
104  QuerySymbolInfos.front().ScopedQualifiers, Symbol)});
105  }
106  // Deduplicate header infos.
107  HeaderInfos.erase(std::unique(HeaderInfos.begin(), HeaderInfos.end(),
108  [](const HeaderInfo &A, const HeaderInfo &B) {
109  return A.Header == B.Header &&
110  A.QualifiedName == B.QualifiedName;
111  }),
112  HeaderInfos.end());
113 }
114 
115 } // include_fixer
116 } // clang
std::string QualifiedName
A symbol name with completed namespace qualifiers which will replace the original symbol...
std::string Header
The header where QualifiedName comes from.
tooling::Range Range
The replacement range of RawIdentifier.
clang::find_all_symbols::SymbolInfo SymbolInfo
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//