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: