blob: 02b3a0e412e55981af8ba21db0b0173dd0da0042 [file] [log] [blame]
Haojian Wu783d4312016-07-08 13:11:38 +00001//===-- 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
13namespace clang {
14namespace include_fixer {
15
Haojian Wu68c34a02016-07-13 16:43:54 +000016namespace {
Haojian Wu783d4312016-07-08 13:11:38 +000017
Haojian Wu68c34a02016-07-13 16:43:54 +000018std::string createQualifiedNameForReplacement(
19 llvm::StringRef RawSymbolName,
20 llvm::StringRef SymbolScopedQualifiers,
21 const find_all_symbols::SymbolInfo &MatchedSymbol) {
Haojian Wu5d9482d2016-07-08 14:28:43 +000022 // No need to add missing qualifiers if SymbolIndentifer has a global scope
23 // operator "::".
Haojian Wu68c34a02016-07-13 16:43:54 +000024 if (RawSymbolName.startswith("::"))
25 return RawSymbolName;
26
27 std::string QualifiedName = MatchedSymbol.getQualifiedName();
28
Haojian Wu783d4312016-07-08 13:11:38 +000029 // For nested classes, the qualified name constructed from database misses
30 // some stripped qualifiers, because when we search a symbol in database,
31 // we strip qualifiers from the end until we find a result. So append the
32 // missing stripped qualifiers here.
33 //
34 // Get stripped qualifiers.
35 llvm::SmallVector<llvm::StringRef, 8> SymbolQualifiers;
Haojian Wu68c34a02016-07-13 16:43:54 +000036 RawSymbolName.split(SymbolQualifiers, "::");
Haojian Wu783d4312016-07-08 13:11:38 +000037 std::string StrippedQualifiers;
38 while (!SymbolQualifiers.empty() &&
39 !llvm::StringRef(QualifiedName).endswith(SymbolQualifiers.back())) {
40 StrippedQualifiers = "::" + SymbolQualifiers.back().str();
41 SymbolQualifiers.pop_back();
42 }
43 // Append the missing stripped qualifiers.
44 std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;
45 auto pos = FullyQualifiedName.find(SymbolScopedQualifiers);
Haojian Wu68c34a02016-07-13 16:43:54 +000046 return FullyQualifiedName.substr(
47 pos == std::string::npos ? 0 : SymbolScopedQualifiers.size());
48}
49
50} // anonymous namespace
51
52IncludeFixerContext::IncludeFixerContext(
53 llvm::StringRef Name, llvm::StringRef ScopeQualifiers,
54 std::vector<find_all_symbols::SymbolInfo> Symbols,
55 tooling::Range Range)
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)});
62 }
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;
68 }),
69 HeaderInfos.end());
Haojian Wu783d4312016-07-08 13:11:38 +000070}
71
72} // include_fixer
73} // clang