12
12
13
13
#include " clang/Interpreter/CodeCompletion.h"
14
14
#include " clang/AST/ASTImporter.h"
15
- #include " clang/AST/DeclLookups.h"
16
15
#include " clang/AST/DeclarationName.h"
17
16
#include " clang/AST/ExternalASTSource.h"
18
17
#include " clang/Basic/IdentifierTable.h"
24
23
#include " clang/Sema/CodeCompleteConsumer.h"
25
24
#include " clang/Sema/CodeCompleteOptions.h"
26
25
#include " clang/Sema/Sema.h"
27
- #include " llvm/Support/Debug.h"
28
- #define DEBUG_TYPE " REPLCC"
29
26
30
27
namespace clang {
31
28
@@ -42,15 +39,11 @@ clang::CodeCompleteOptions getClangCompleteOpts() {
42
39
43
40
class ReplCompletionConsumer : public CodeCompleteConsumer {
44
41
public:
45
- ReplCompletionConsumer (std::vector<std::string> &Results,
46
- ReplCodeCompleter &CC)
42
+ ReplCompletionConsumer (std::vector<std::string> &Results)
47
43
: CodeCompleteConsumer(getClangCompleteOpts()),
48
44
CCAllocator (std::make_shared<GlobalCodeCompletionAllocator>()),
49
- CCTUInfo(CCAllocator), Results(Results), CC(CC) {}
45
+ CCTUInfo(CCAllocator), Results(Results){};
50
46
51
- // The entry of handling code completion. When the function is called, we
52
- // create a `Context`-based handler (see classes defined below) to handle each
53
- // completion result.
54
47
void ProcessCodeCompleteResults (class Sema &S, CodeCompletionContext Context,
55
48
CodeCompletionResult *InResults,
56
49
unsigned NumResults) final ;
@@ -63,146 +56,26 @@ class ReplCompletionConsumer : public CodeCompleteConsumer {
63
56
std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
64
57
CodeCompletionTUInfo CCTUInfo;
65
58
std::vector<std::string> &Results;
66
- ReplCodeCompleter &CC;
67
- };
68
-
69
- // / The class CompletionContextHandler contains four interfaces, each of
70
- // / which handles one type of completion result.
71
- // / Its derived classes are used to create concrete handlers based on
72
- // / \c CodeCompletionContext.
73
- class CompletionContextHandler {
74
- protected:
75
- CodeCompletionContext CCC;
76
- std::vector<std::string> &Results;
77
-
78
- private:
79
- Sema &S;
80
-
81
- public:
82
- CompletionContextHandler (Sema &S, CodeCompletionContext CCC,
83
- std::vector<std::string> &Results)
84
- : CCC(CCC), Results(Results), S(S) {}
85
-
86
- // / Converts a Declaration completion result to a completion string, and then
87
- // / stores it in Results.
88
- virtual void handleDeclaration (const CodeCompletionResult &Result) {
89
- auto PreferredType = CCC.getPreferredType ();
90
- if (PreferredType.isNull ()) {
91
- Results.push_back (Result.Declaration ->getName ().str ());
92
- return ;
93
- }
94
-
95
- if (auto *VD = dyn_cast<VarDecl>(Result.Declaration )) {
96
- auto ArgumentType = VD->getType ();
97
- if (PreferredType->isReferenceType ()) {
98
- QualType RT = PreferredType->castAs <ReferenceType>()->getPointeeType ();
99
- Sema::ReferenceConversions RefConv;
100
- Sema::ReferenceCompareResult RefRelationship =
101
- S.CompareReferenceRelationship (SourceLocation (), RT, ArgumentType,
102
- &RefConv);
103
- switch (RefRelationship) {
104
- case Sema::Ref_Compatible:
105
- case Sema::Ref_Related:
106
- Results.push_back (VD->getName ().str ());
107
- break ;
108
- case Sema::Ref_Incompatible:
109
- break ;
110
- }
111
- } else if (S.Context .hasSameType (ArgumentType, PreferredType)) {
112
- Results.push_back (VD->getName ().str ());
113
- }
114
- }
115
- }
116
-
117
- // / Converts a Keyword completion result to a completion string, and then
118
- // / stores it in Results.
119
- virtual void handleKeyword (const CodeCompletionResult &Result) {
120
- auto Prefix = S.getPreprocessor ().getCodeCompletionFilter ();
121
- // Add keyword to the completion results only if we are in a type-aware
122
- // situation.
123
- if (!CCC.getBaseType ().isNull () || !CCC.getPreferredType ().isNull ())
124
- return ;
125
- if (StringRef (Result.Keyword ).startswith (Prefix))
126
- Results.push_back (Result.Keyword );
127
- }
128
-
129
- // / Converts a Pattern completion result to a completion string, and then
130
- // / stores it in Results.
131
- virtual void handlePattern (const CodeCompletionResult &Result) {}
132
-
133
- // / Converts a Macro completion result to a completion string, and then stores
134
- // / it in Results.
135
- virtual void handleMacro (const CodeCompletionResult &Result) {}
136
- };
137
-
138
- class DotMemberAccessHandler : public CompletionContextHandler {
139
- public:
140
- DotMemberAccessHandler (Sema &S, CodeCompletionContext CCC,
141
- std::vector<std::string> &Results)
142
- : CompletionContextHandler(S, CCC, Results) {}
143
- void handleDeclaration (const CodeCompletionResult &Result) override {
144
- auto *ID = Result.Declaration ->getIdentifier ();
145
- if (!ID)
146
- return ;
147
- if (!isa<CXXMethodDecl>(Result.Declaration ))
148
- return ;
149
- const auto *Fun = cast<CXXMethodDecl>(Result.Declaration );
150
- if (Fun->getParent ()->getCanonicalDecl () ==
151
- CCC.getBaseType ()->getAsCXXRecordDecl ()->getCanonicalDecl ()) {
152
- LLVM_DEBUG (llvm::dbgs () << " [In HandleCodeCompleteDOT] Name : "
153
- << ID->getName () << " \n " );
154
- Results.push_back (ID->getName ().str ());
155
- }
156
- }
157
-
158
- void handleKeyword (const CodeCompletionResult &Result) override {}
159
59
};
160
60
161
61
void ReplCompletionConsumer::ProcessCodeCompleteResults (
162
62
class Sema &S, CodeCompletionContext Context,
163
63
CodeCompletionResult *InResults, unsigned NumResults) {
164
-
165
- auto Prefix = S.getPreprocessor ().getCodeCompletionFilter ();
166
- CC.Prefix = Prefix;
167
-
168
- std::unique_ptr<CompletionContextHandler> CCH;
169
-
170
- // initialize fine-grained code completion handler based on the code
171
- // completion context.
172
- switch (Context.getKind ()) {
173
- case CodeCompletionContext::CCC_DotMemberAccess:
174
- CCH.reset (new DotMemberAccessHandler (S, Context, this ->Results ));
175
- break ;
176
- default :
177
- CCH.reset (new CompletionContextHandler (S, Context, this ->Results ));
178
- };
179
-
180
- for (unsigned I = 0 ; I < NumResults; I++) {
64
+ for (unsigned I = 0 ; I < NumResults; ++I) {
181
65
auto &Result = InResults[I];
182
66
switch (Result.Kind ) {
183
67
case CodeCompletionResult::RK_Declaration:
184
- if (Result.Hidden ) {
185
- break ;
186
- }
187
- if (!Result.Declaration ->getDeclName ().isIdentifier () ||
188
- !Result.Declaration ->getName ().startswith (Prefix)) {
189
- break ;
68
+ if (auto *ID = Result.Declaration ->getIdentifier ()) {
69
+ Results.push_back (ID->getName ().str ());
190
70
}
191
- CCH->handleDeclaration (Result);
192
71
break ;
193
72
case CodeCompletionResult::RK_Keyword:
194
- CCH->handleKeyword (Result);
195
- break ;
196
- case CodeCompletionResult::RK_Macro:
197
- CCH->handleMacro (Result);
73
+ Results.push_back (Result.Keyword );
198
74
break ;
199
- case CodeCompletionResult::RK_Pattern:
200
- CCH->handlePattern (Result);
75
+ default :
201
76
break ;
202
77
}
203
78
}
204
-
205
- std::sort (Results.begin (), Results.end ());
206
79
}
207
80
208
81
class IncrementalSyntaxOnlyAction : public SyntaxOnlyAction {
@@ -245,16 +118,6 @@ void IncrementalSyntaxOnlyAction::ExecuteAction() {
245
118
CI.getASTContext ().getTranslationUnitDecl ()->setHasExternalVisibleStorage (
246
119
true );
247
120
248
- // Load all external decls into current context. Under the hood, it calls
249
- // ExternalSource::completeVisibleDeclsMap, which make all decls on the redecl
250
- // chain visible.
251
- //
252
- // This is crucial to code completion on dot members, since a bound variable
253
- // before "." would be otherwise treated out-of-scope.
254
- //
255
- // clang-repl> Foo f1;
256
- // clang-repl> f1.<tab>
257
- CI.getASTContext ().getTranslationUnitDecl ()->lookups ();
258
121
SyntaxOnlyAction::ExecuteAction ();
259
122
}
260
123
@@ -271,7 +134,6 @@ ExternalSource::ExternalSource(ASTContext &ChildASTCtxt, FileManager &ChildFM,
271
134
272
135
bool ExternalSource::FindExternalVisibleDeclsByName (const DeclContext *DC,
273
136
DeclarationName Name) {
274
-
275
137
IdentifierTable &ParentIdTable = ParentASTCtxt.Idents ;
276
138
277
139
auto ParentDeclName =
@@ -297,67 +159,29 @@ void ExternalSource::completeVisibleDeclsMap(
297
159
for (auto *DeclCtxt = ParentTUDeclCtxt; DeclCtxt != nullptr ;
298
160
DeclCtxt = DeclCtxt->getPreviousDecl ()) {
299
161
for (auto &IDeclContext : DeclCtxt->decls ()) {
300
- if (!llvm::isa<NamedDecl>(IDeclContext))
301
- continue ;
302
-
303
- NamedDecl *Decl = llvm::cast<NamedDecl>(IDeclContext);
304
-
305
- auto DeclOrErr = Importer->Import (Decl);
306
- if (!DeclOrErr) {
307
- // if an error happens, it usually means the decl has already been
308
- // imported or the decl is a result of a failed import. But in our
309
- // case, every import is fresh each time code completion is
310
- // triggered. So Import usually doesn't fail. If it does, it just means
311
- // the related decl can't be used in code completion and we can safely
312
- // drop it.
313
- llvm::consumeError (DeclOrErr.takeError ());
314
- continue ;
315
- }
316
-
317
- if (!llvm::isa<NamedDecl>(*DeclOrErr))
318
- continue ;
319
-
320
- NamedDecl *importedNamedDecl = llvm::cast<NamedDecl>(*DeclOrErr);
321
-
322
- SetExternalVisibleDeclsForName (ChildDeclContext,
323
- importedNamedDecl->getDeclName (),
324
- importedNamedDecl);
325
-
326
- if (!llvm::isa<CXXRecordDecl>(importedNamedDecl))
327
- continue ;
328
-
329
- auto *Record = llvm::cast<CXXRecordDecl>(importedNamedDecl);
330
-
331
- if (auto Err = Importer->ImportDefinition (Decl)) {
332
- // the same as above
333
- consumeError (std::move (Err));
334
- continue ;
162
+ if (NamedDecl *Decl = llvm::dyn_cast<NamedDecl>(IDeclContext)) {
163
+ if (auto DeclOrErr = Importer->Import (Decl)) {
164
+ if (NamedDecl *importedNamedDecl =
165
+ llvm::dyn_cast<NamedDecl>(*DeclOrErr)) {
166
+ SetExternalVisibleDeclsForName (ChildDeclContext,
167
+ importedNamedDecl->getDeclName (),
168
+ importedNamedDecl);
169
+ }
170
+
171
+ } else {
172
+ llvm::consumeError (DeclOrErr.takeError ());
173
+ }
335
174
}
336
-
337
- Record->setHasLoadedFieldsFromExternalStorage (true );
338
- LLVM_DEBUG (llvm::dbgs ()
339
- << " \n CXXRecrod : " << Record->getName () << " size(methods): "
340
- << std::distance (Record->method_begin (), Record->method_end ())
341
- << " has def?: " << Record->hasDefinition ()
342
- << " # (methods): "
343
- << std::distance (Record->getDefinition ()->method_begin (),
344
- Record->getDefinition ()->method_end ())
345
- << " \n " );
346
- for (auto *Meth : Record->methods ())
347
- SetExternalVisibleDeclsForName (ChildDeclContext, Meth->getDeclName (),
348
- Meth);
349
175
}
350
176
ChildDeclContext->setHasExternalLexicalStorage (false );
351
177
}
352
178
}
353
179
354
- void ReplCodeCompleter::codeComplete (CompilerInstance *InterpCI,
355
- llvm::StringRef Content, unsigned Line,
356
- unsigned Col,
357
- const CompilerInstance *ParentCI,
358
- std::vector<std::string> &CCResults) {
180
+ void codeComplete (CompilerInstance *InterpCI, llvm::StringRef Content,
181
+ unsigned Line, unsigned Col, const CompilerInstance *ParentCI,
182
+ std::vector<std::string> &CCResults) {
359
183
auto DiagOpts = DiagnosticOptions ();
360
- auto consumer = ReplCompletionConsumer (CCResults, * this );
184
+ auto consumer = ReplCompletionConsumer (CCResults);
361
185
362
186
auto diag = InterpCI->getDiagnosticsPtr ();
363
187
std::unique_ptr<ASTUnit> AU (ASTUnit::LoadFromCompilerInvocationAction (
0 commit comments