Mercurial > hg > CbC > CbC_llvm
comparison clang-tools-extra/clangd/IncludeFixer.cpp @ 221:79ff65ed7e25
LLVM12 Original
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 15 Jun 2021 19:15:29 +0900 |
parents | 0572611fdcc8 |
children | c4bab56944e8 |
comparison
equal
deleted
inserted
replaced
220:42394fc6a535 | 221:79ff65ed7e25 |
---|---|
38 #include "llvm/ADT/StringExtras.h" | 38 #include "llvm/ADT/StringExtras.h" |
39 #include "llvm/ADT/StringRef.h" | 39 #include "llvm/ADT/StringRef.h" |
40 #include "llvm/ADT/StringSet.h" | 40 #include "llvm/ADT/StringSet.h" |
41 #include "llvm/Support/Error.h" | 41 #include "llvm/Support/Error.h" |
42 #include "llvm/Support/FormatVariadic.h" | 42 #include "llvm/Support/FormatVariadic.h" |
43 #include <algorithm> | |
44 #include <set> | |
45 #include <string> | |
43 #include <vector> | 46 #include <vector> |
44 | 47 |
45 namespace clang { | 48 namespace clang { |
46 namespace clangd { | 49 namespace clangd { |
47 | |
48 namespace { | |
49 | |
50 // Collects contexts visited during a Sema name lookup. | |
51 class VisitedContextCollector : public VisibleDeclConsumer { | |
52 public: | |
53 void EnteredContext(DeclContext *Ctx) override { Visited.push_back(Ctx); } | |
54 | |
55 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, | |
56 bool InBaseClass) override {} | |
57 | |
58 std::vector<DeclContext *> takeVisitedContexts() { | |
59 return std::move(Visited); | |
60 } | |
61 | |
62 private: | |
63 std::vector<DeclContext *> Visited; | |
64 }; | |
65 | |
66 } // namespace | |
67 | 50 |
68 std::vector<Fix> IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel, | 51 std::vector<Fix> IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel, |
69 const clang::Diagnostic &Info) const { | 52 const clang::Diagnostic &Info) const { |
70 switch (Info.getID()) { | 53 switch (Info.getID()) { |
54 case diag::err_incomplete_nested_name_spec: | |
55 case diag::err_incomplete_base_class: | |
56 case diag::err_incomplete_member_access: | |
71 case diag::err_incomplete_type: | 57 case diag::err_incomplete_type: |
72 case diag::err_incomplete_member_access: | 58 case diag::err_typecheck_decl_incomplete_type: |
73 case diag::err_incomplete_base_class: | 59 case diag::err_typecheck_incomplete_tag: |
74 case diag::err_incomplete_nested_name_spec: | 60 case diag::err_invalid_incomplete_type_use: |
61 case diag::err_sizeof_alignof_incomplete_or_sizeless_type: | |
62 case diag::err_for_range_incomplete_type: | |
63 case diag::err_func_def_incomplete_result: | |
64 case diag::err_field_incomplete_or_sizeless: | |
75 // Incomplete type diagnostics should have a QualType argument for the | 65 // Incomplete type diagnostics should have a QualType argument for the |
76 // incomplete type. | 66 // incomplete type. |
77 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) { | 67 for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) { |
78 if (Info.getArgKind(Idx) == DiagnosticsEngine::ak_qualtype) { | 68 if (Info.getArgKind(Idx) == DiagnosticsEngine::ak_qualtype) { |
79 auto QT = QualType::getFromOpaquePtr((void *)Info.getRawArg(Idx)); | 69 auto QT = QualType::getFromOpaquePtr((void *)Info.getRawArg(Idx)); |
92 case diag::err_undeclared_use_suggest: | 82 case diag::err_undeclared_use_suggest: |
93 case diag::err_undeclared_var_use: | 83 case diag::err_undeclared_var_use: |
94 case diag::err_undeclared_var_use_suggest: | 84 case diag::err_undeclared_var_use_suggest: |
95 case diag::err_no_member: // Could be no member in namespace. | 85 case diag::err_no_member: // Could be no member in namespace. |
96 case diag::err_no_member_suggest: | 86 case diag::err_no_member_suggest: |
87 case diag::err_no_member_template: | |
88 case diag::err_no_member_template_suggest: | |
97 if (LastUnresolvedName) { | 89 if (LastUnresolvedName) { |
98 // Try to fix unresolved name caused by missing declaration. | 90 // Try to fix unresolved name caused by missing declaration. |
99 // E.g. | 91 // E.g. |
100 // clang::SourceManager SM; | 92 // clang::SourceManager SM; |
101 // ~~~~~~~~~~~~~ | 93 // ~~~~~~~~~~~~~ |
125 vlog("Trying to fix include for incomplete type {0}", TypeName); | 117 vlog("Trying to fix include for incomplete type {0}", TypeName); |
126 | 118 |
127 auto ID = getSymbolID(TD); | 119 auto ID = getSymbolID(TD); |
128 if (!ID) | 120 if (!ID) |
129 return {}; | 121 return {}; |
130 llvm::Optional<const SymbolSlab *> Symbols = lookupCached(*ID); | 122 llvm::Optional<const SymbolSlab *> Symbols = lookupCached(ID); |
131 if (!Symbols) | 123 if (!Symbols) |
132 return {}; | 124 return {}; |
133 const SymbolSlab &Syms = **Symbols; | 125 const SymbolSlab &Syms = **Symbols; |
134 std::vector<Fix> Fixes; | 126 std::vector<Fix> Fixes; |
135 if (!Syms.empty()) { | 127 if (!Syms.empty()) { |
151 auto ResolvedInserted = toHeaderFile(Header, File); | 143 auto ResolvedInserted = toHeaderFile(Header, File); |
152 if (!ResolvedInserted) | 144 if (!ResolvedInserted) |
153 return ResolvedInserted.takeError(); | 145 return ResolvedInserted.takeError(); |
154 auto Spelled = Inserter->calculateIncludePath(*ResolvedInserted, File); | 146 auto Spelled = Inserter->calculateIncludePath(*ResolvedInserted, File); |
155 if (!Spelled) | 147 if (!Spelled) |
156 return llvm::createStringError(llvm::inconvertibleErrorCode(), | 148 return error("Header not on include path"); |
157 "Header not on include path"); | |
158 return std::make_pair( | 149 return std::make_pair( |
159 std::move(*Spelled), | 150 std::move(*Spelled), |
160 Inserter->shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted)); | 151 Inserter->shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted)); |
161 }; | 152 }; |
162 | 153 |
303 | 294 |
304 /// Returns all namespace scopes that the unqualified lookup would visit. | 295 /// Returns all namespace scopes that the unqualified lookup would visit. |
305 std::vector<std::string> | 296 std::vector<std::string> |
306 collectAccessibleScopes(Sema &Sem, const DeclarationNameInfo &Typo, Scope *S, | 297 collectAccessibleScopes(Sema &Sem, const DeclarationNameInfo &Typo, Scope *S, |
307 Sema::LookupNameKind LookupKind) { | 298 Sema::LookupNameKind LookupKind) { |
299 // Collects contexts visited during a Sema name lookup. | |
300 struct VisitedContextCollector : public VisibleDeclConsumer { | |
301 VisitedContextCollector(std::vector<std::string> &Out) : Out(Out) {} | |
302 void EnteredContext(DeclContext *Ctx) override { | |
303 if (llvm::isa<NamespaceDecl>(Ctx)) | |
304 Out.push_back(printNamespaceScope(*Ctx)); | |
305 } | |
306 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, | |
307 bool InBaseClass) override {} | |
308 std::vector<std::string> &Out; | |
309 }; | |
310 | |
308 std::vector<std::string> Scopes; | 311 std::vector<std::string> Scopes; |
309 VisitedContextCollector Collector; | 312 Scopes.push_back(""); |
313 VisitedContextCollector Collector(Scopes); | |
310 Sem.LookupVisibleDecls(S, LookupKind, Collector, | 314 Sem.LookupVisibleDecls(S, LookupKind, Collector, |
311 /*IncludeGlobalScope=*/false, | 315 /*IncludeGlobalScope=*/false, |
312 /*LoadExternal=*/false); | 316 /*LoadExternal=*/false); |
313 | 317 std::sort(Scopes.begin(), Scopes.end()); |
314 Scopes.push_back(""); | 318 Scopes.erase(std::unique(Scopes.begin(), Scopes.end()), Scopes.end()); |
315 for (const auto *Ctx : Collector.takeVisitedContexts()) { | |
316 if (isa<NamespaceDecl>(Ctx)) | |
317 Scopes.push_back(printNamespaceScope(*Ctx)); | |
318 } | |
319 return Scopes; | 319 return Scopes; |
320 } | 320 } |
321 | 321 |
322 class IncludeFixer::UnresolvedNameRecorder : public ExternalSemaSource { | 322 class IncludeFixer::UnresolvedNameRecorder : public ExternalSemaSource { |
323 public: | 323 public: |