blob: 51713b57b4e2c17664fb8c7459dbe9e5e8ee590c [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 Wu39a718c2016-07-15 08:12:48 +000018// Splits a multiply qualified names (e.g. a::b::c).
19llvm::SmallVector<llvm::StringRef, 8>
20SplitQualifiers(llvm::StringRef StringQualifiers) {
21 llvm::SmallVector<llvm::StringRef, 8> Qualifiers;
22 StringQualifiers.split(Qualifiers, "::");
23 return Qualifiers;
24}
25
Haojian Wu68c34a02016-07-13 16:43:54 +000026std::string createQualifiedNameForReplacement(
27 llvm::StringRef RawSymbolName,
Haojian Wu39a718c2016-07-15 08:12:48 +000028 llvm::StringRef SymbolScopedQualifiersName,
Haojian Wu68c34a02016-07-13 16:43:54 +000029 const find_all_symbols::SymbolInfo &MatchedSymbol) {
Haojian Wu5d9482d2016-07-08 14:28:43 +000030 // No need to add missing qualifiers if SymbolIndentifer has a global scope
31 // operator "::".
Haojian Wu68c34a02016-07-13 16:43:54 +000032 if (RawSymbolName.startswith("::"))
33 return RawSymbolName;
34
35 std::string QualifiedName = MatchedSymbol.getQualifiedName();
36
Haojian Wu783d4312016-07-08 13:11:38 +000037 // 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.
Haojian Wu39a718c2016-07-15 08:12:48 +000043 auto SymbolQualifiers = SplitQualifiers(RawSymbolName);
Haojian Wu783d4312016-07-08 13:11:38 +000044 std::string StrippedQualifiers;
45 while (!SymbolQualifiers.empty() &&
46 !llvm::StringRef(QualifiedName).endswith(SymbolQualifiers.back())) {
47 StrippedQualifiers = "::" + SymbolQualifiers.back().str();
48 SymbolQualifiers.pop_back();
49 }
50 // Append the missing stripped qualifiers.
51 std::string FullyQualifiedName = QualifiedName + StrippedQualifiers;
Haojian Wu0c05e2e2016-07-14 09:39:12 +000052
Haojian Wu39a718c2016-07-15 08:12:48 +000053 // Try to find and skip the common prefix qualifiers.
54 auto FullySymbolQualifiers = SplitQualifiers(FullyQualifiedName);
55 auto ScopedQualifiers = SplitQualifiers(SymbolScopedQualifiersName);
56 auto FullySymbolQualifiersIter = FullySymbolQualifiers.begin();
57 auto SymbolScopedQualifiersIter = ScopedQualifiers.begin();
58 while (FullySymbolQualifiersIter != FullySymbolQualifiers.end() &&
59 SymbolScopedQualifiersIter != ScopedQualifiers.end()) {
60 if (*FullySymbolQualifiersIter != *SymbolScopedQualifiersIter)
61 break;
62 ++FullySymbolQualifiersIter;
63 ++SymbolScopedQualifiersIter;
64 }
65 std::string Result;
66 for (; FullySymbolQualifiersIter != FullySymbolQualifiers.end();
67 ++FullySymbolQualifiersIter) {
68 if (!Result.empty())
69 Result += "::";
70 Result += *FullySymbolQualifiersIter;
71 }
72 return Result;
Haojian Wu68c34a02016-07-13 16:43:54 +000073}
74
75} // anonymous namespace
76
77IncludeFixerContext::IncludeFixerContext(
Haojian Wu9e4bd0c2016-07-19 14:49:04 +000078 const QuerySymbolInfo &QuerySymbol,
Haojian Wu20dba052016-07-20 09:00:22 +000079 std::vector<find_all_symbols::SymbolInfo> Symbols)
Haojian Wu9e4bd0c2016-07-19 14:49:04 +000080 : MatchedSymbols(std::move(Symbols)), QuerySymbol(QuerySymbol) {
Haojian Wu68c34a02016-07-13 16:43:54 +000081 for (const auto &Symbol : MatchedSymbols) {
Haojian Wu9e4bd0c2016-07-19 14:49:04 +000082 HeaderInfos.push_back(
83 {Symbol.getFilePath().str(),
84 createQualifiedNameForReplacement(
85 QuerySymbol.RawIdentifier, QuerySymbol.ScopedQualifiers, Symbol)});
Haojian Wu68c34a02016-07-13 16:43:54 +000086 }
87 // Deduplicate header infos.
88 HeaderInfos.erase(std::unique(HeaderInfos.begin(), HeaderInfos.end(),
89 [](const HeaderInfo &A, const HeaderInfo &B) {
90 return A.Header == B.Header &&
91 A.QualifiedName == B.QualifiedName;
92 }),
93 HeaderInfos.end());
Haojian Wu783d4312016-07-08 13:11:38 +000094}
95
96} // include_fixer
97} // clang