blob: 2deaedcf098bb26717396f7bd610da9ee7748996 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---- CodeCompleteConsumer.h - Code Completion Interface ----*- 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// This file implements the CodeCompleteConsumer class.
11//
12//===----------------------------------------------------------------------===//
13#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor56c2dbc2009-09-18 17:54:00 +000014#include "clang/AST/DeclCXX.h"
Douglas Gregorf45b0cf2009-09-18 15:37:17 +000015#include "clang/Parse/Scope.h"
Douglas Gregor2436e712009-09-17 21:32:03 +000016#include "clang/Lex/Preprocessor.h"
17#include "Sema.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/Support/Compiler.h"
20#include "llvm/Support/raw_ostream.h"
21#include <algorithm>
22#include <string.h>
23using namespace clang;
24
25CodeCompleteConsumer::CodeCompleteConsumer(Sema &S) : SemaRef(S) {
26 SemaRef.setCodeCompleteConsumer(this);
27}
28
29CodeCompleteConsumer::~CodeCompleteConsumer() {
30 SemaRef.setCodeCompleteConsumer(0);
31}
32
33void
34CodeCompleteConsumer::CodeCompleteMemberReferenceExpr(Scope *S,
35 QualType BaseType,
36 bool IsArrow) {
37 if (IsArrow) {
38 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
39 BaseType = Ptr->getPointeeType();
40 else if (BaseType->isObjCObjectPointerType())
41 /*Do nothing*/ ;
42 else
43 return;
44 }
45
Douglas Gregorf45b0cf2009-09-18 15:37:17 +000046 ResultSet Results(*this);
Douglas Gregor2436e712009-09-17 21:32:03 +000047 unsigned NextRank = 0;
48
49 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +000050 NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank, Results);
Douglas Gregor2436e712009-09-17 21:32:03 +000051
52 if (getSema().getLangOptions().CPlusPlus) {
53 if (!Results.empty())
54 // The "template" keyword can follow "->" or "." in the grammar.
55 Results.MaybeAddResult(Result("template", NextRank++));
56
Douglas Gregor945e8d92009-09-18 17:42:29 +000057 // We could have the start of a nested-name-specifier. Add those
58 // results as well.
59 Results.setFilter(&CodeCompleteConsumer::IsNestedNameSpecifier);
60 CollectLookupResults(S, NextRank, Results);
Douglas Gregor2436e712009-09-17 21:32:03 +000061 }
62
63 // Hand off the results found for code completion.
64 ProcessCodeCompleteResults(Results.data(), Results.size());
65
66 // We're done!
67 return;
68 }
69}
70
Douglas Gregorf45b0cf2009-09-18 15:37:17 +000071void CodeCompleteConsumer::CodeCompleteTag(Scope *S, ElaboratedType::TagKind TK) {
72 ResultSet::LookupFilter Filter = 0;
73 switch (TK) {
74 case ElaboratedType::TK_enum:
75 Filter = &CodeCompleteConsumer::IsEnum;
76 break;
77
78 case ElaboratedType::TK_class:
79 case ElaboratedType::TK_struct:
80 Filter = &CodeCompleteConsumer::IsClassOrStruct;
81 break;
82
83 case ElaboratedType::TK_union:
84 Filter = &CodeCompleteConsumer::IsUnion;
85 break;
86 }
87
88 ResultSet Results(*this, Filter);
Douglas Gregor945e8d92009-09-18 17:42:29 +000089 unsigned NextRank = CollectLookupResults(S, 0, Results);
Douglas Gregorf45b0cf2009-09-18 15:37:17 +000090
Douglas Gregor945e8d92009-09-18 17:42:29 +000091 if (getSema().getLangOptions().CPlusPlus) {
92 // We could have the start of a nested-name-specifier. Add those
93 // results as well.
94 Results.setFilter(&CodeCompleteConsumer::IsNestedNameSpecifier);
95 CollectLookupResults(S, NextRank, Results);
96 }
Douglas Gregorf45b0cf2009-09-18 15:37:17 +000097
98 ProcessCodeCompleteResults(Results.data(), Results.size());
99}
100
Douglas Gregor2436e712009-09-17 21:32:03 +0000101void
102CodeCompleteConsumer::CodeCompleteQualifiedId(Scope *S,
103 NestedNameSpecifier *NNS,
104 bool EnteringContext) {
105 CXXScopeSpec SS;
106 SS.setScopeRep(NNS);
107 DeclContext *Ctx = getSema().computeDeclContext(SS, EnteringContext);
108 if (!Ctx)
109 return;
110
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000111 ResultSet Results(*this);
112 unsigned NextRank = CollectMemberLookupResults(Ctx, 0, Results);
Douglas Gregor2436e712009-09-17 21:32:03 +0000113
114 // The "template" keyword can follow "::" in the grammar
115 if (!Results.empty())
116 Results.MaybeAddResult(Result("template", NextRank));
117
118 ProcessCodeCompleteResults(Results.data(), Results.size());
119}
120
121void CodeCompleteConsumer::ResultSet::MaybeAddResult(Result R) {
122 if (R.Kind != Result::RK_Declaration) {
123 // For non-declaration results, just add the result.
124 Results.push_back(R);
125 return;
126 }
Douglas Gregor56c2dbc2009-09-18 17:54:00 +0000127
128 // Look through using declarations.
129 if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration))
130 return MaybeAddResult(Result(Using->getTargetDecl(), R.Rank));
Douglas Gregor2436e712009-09-17 21:32:03 +0000131
Douglas Gregor56c2dbc2009-09-18 17:54:00 +0000132 // Handle each declaration in an overload set separately.
133 if (OverloadedFunctionDecl *Ovl
134 = dyn_cast<OverloadedFunctionDecl>(R.Declaration)) {
135 for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
136 FEnd = Ovl->function_end();
137 F != FEnd; ++F)
138 MaybeAddResult(Result(*F, R.Rank));
139
140 return;
141 }
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000142
Douglas Gregor2436e712009-09-17 21:32:03 +0000143 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
144 unsigned IDNS = CanonDecl->getIdentifierNamespace();
145
146 // Friend declarations and declarations introduced due to friends are never
147 // added as results.
148 if (isa<FriendDecl>(CanonDecl) ||
149 (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)))
150 return;
151
Douglas Gregor945e8d92009-09-18 17:42:29 +0000152 if (const IdentifierInfo *Id = R.Declaration->getIdentifier()) {
153 // __va_list_tag is a freak of nature. Find it and skip it.
154 if (Id->isStr("__va_list_tag"))
155 return;
156
157 // FIXME: Should we filter out other names in the implementation's
158 // namespace, e.g., those containing a __ or that start with _[A-Z]?
159 }
160
161 // C++ constructors are never found by name lookup.
162 if (isa<CXXConstructorDecl>(CanonDecl))
163 return;
164
165 // Filter out any unwanted results.
166 if (Filter && !(Completer.*Filter)(R.Declaration))
167 return;
168
Douglas Gregor2436e712009-09-17 21:32:03 +0000169 ShadowMap &SMap = ShadowMaps.back();
170 ShadowMap::iterator I, IEnd;
171 for (llvm::tie(I, IEnd) = SMap.equal_range(R.Declaration->getDeclName());
172 I != IEnd; ++I) {
173 NamedDecl *ND = I->second.first;
174 unsigned Index = I->second.second;
175 if (ND->getCanonicalDecl() == CanonDecl) {
176 // This is a redeclaration. Always pick the newer declaration.
177 I->second.first = R.Declaration;
178 Results[Index].Declaration = R.Declaration;
179
180 // Pick the best rank of the two.
181 Results[Index].Rank = std::min(Results[Index].Rank, R.Rank);
182
183 // We're done.
184 return;
185 }
186 }
187
188 // This is a new declaration in this scope. However, check whether this
189 // declaration name is hidden by a similarly-named declaration in an outer
190 // scope.
191 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
192 --SMEnd;
193 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
194 for (llvm::tie(I, IEnd) = SM->equal_range(R.Declaration->getDeclName());
195 I != IEnd; ++I) {
196 // A tag declaration does not hide a non-tag declaration.
197 if (I->second.first->getIdentifierNamespace() == Decl::IDNS_Tag &&
198 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
199 Decl::IDNS_ObjCProtocol)))
200 continue;
201
202 // Protocols are in distinct namespaces from everything else.
203 if (((I->second.first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
204 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
205 I->second.first->getIdentifierNamespace() != IDNS)
206 continue;
207
208 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor2da11082009-09-18 15:51:54 +0000209 if (Completer.canHiddenResultBeFound(R.Declaration, I->second.first)) {
210 // Note that this result was hidden.
211 R.Hidden = true;
212 } else {
213 // This result was hidden and cannot be found; don't bother adding
214 // it.
215 return;
216 }
217
Douglas Gregor2436e712009-09-17 21:32:03 +0000218 break;
219 }
220 }
221
Douglas Gregor945e8d92009-09-18 17:42:29 +0000222 // Make sure that any given declaration only shows up in the result set once.
223 if (!AllDeclsFound.insert(CanonDecl))
224 return;
225
Douglas Gregor2436e712009-09-17 21:32:03 +0000226 // Insert this result into the set of results and into the current shadow
227 // map.
228 SMap.insert(std::make_pair(R.Declaration->getDeclName(),
229 std::make_pair(R.Declaration, Results.size())));
230 Results.push_back(R);
231}
232
233/// \brief Enter into a new scope.
234void CodeCompleteConsumer::ResultSet::EnterNewScope() {
235 ShadowMaps.push_back(ShadowMap());
236}
237
238/// \brief Exit from the current scope.
239void CodeCompleteConsumer::ResultSet::ExitScope() {
240 ShadowMaps.pop_back();
241}
242
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000243// Find the next outer declaration context corresponding to this scope.
244static DeclContext *findOuterContext(Scope *S) {
245 for (S = S->getParent(); S; S = S->getParent())
246 if (S->getEntity())
247 return static_cast<DeclContext *>(S->getEntity())->getPrimaryContext();
248
249 return 0;
250}
251
252/// \brief Collect the results of searching for declarations within the given
253/// scope and its parent scopes.
254///
255/// \param S the scope in which we will start looking for declarations.
256///
257/// \param InitialRank the initial rank given to results in this scope.
258/// Larger rank values will be used for results found in parent scopes.
259unsigned CodeCompleteConsumer::CollectLookupResults(Scope *S,
260 unsigned InitialRank,
261 ResultSet &Results) {
262 if (!S)
263 return InitialRank;
264
265 // FIXME: Using directives!
266
267 unsigned NextRank = InitialRank;
268 Results.EnterNewScope();
269 if (S->getEntity() &&
270 !((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
271 // Look into this scope's declaration context, along with any of its
272 // parent lookup contexts (e.g., enclosing classes), up to the point
273 // where we hit the context stored in the next outer scope.
274 DeclContext *Ctx = (DeclContext *)S->getEntity();
275 DeclContext *OuterCtx = findOuterContext(S);
276
277 for (; Ctx && Ctx->getPrimaryContext() != OuterCtx;
278 Ctx = Ctx->getLookupParent()) {
279 if (Ctx->isFunctionOrMethod())
280 continue;
281
282 NextRank = CollectMemberLookupResults(Ctx, NextRank + 1, Results);
283 }
284 } else if (!S->getParent()) {
285 // Look into the translation unit scope. We walk through the translation
286 // unit's declaration context, because the Scope itself won't have all of
287 // the declarations if
288 NextRank = CollectMemberLookupResults(
289 getSema().Context.getTranslationUnitDecl(),
290 NextRank + 1, Results);
291 } else {
292 // Walk through the declarations in this Scope.
293 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
294 D != DEnd; ++D) {
295 if (NamedDecl *ND = dyn_cast<NamedDecl>((Decl *)((*D).get())))
296 Results.MaybeAddResult(Result(ND, NextRank));
297 }
298
299 NextRank = NextRank + 1;
300 }
301
302 // Lookup names in the parent scope.
303 NextRank = CollectLookupResults(S->getParent(), NextRank, Results);
304 Results.ExitScope();
305
306 return NextRank;
307}
308
Douglas Gregor2436e712009-09-17 21:32:03 +0000309/// \brief Collect the results of searching for members within the given
310/// declaration context.
311///
312/// \param Ctx the declaration context from which we will gather results.
313///
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000314/// \param InitialRank the initial rank given to results in this declaration
315/// context. Larger rank values will be used for, e.g., members found in
316/// base classes.
Douglas Gregor2436e712009-09-17 21:32:03 +0000317///
318/// \param Results the result set that will be extended with any results
319/// found within this declaration context (and, for a C++ class, its bases).
320///
321/// \returns the next higher rank value, after considering all of the
322/// names within this declaration context.
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000323unsigned CodeCompleteConsumer::CollectMemberLookupResults(DeclContext *Ctx,
Douglas Gregor2ecab752009-09-18 18:07:23 +0000324 unsigned InitialRank,
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000325 ResultSet &Results) {
Douglas Gregor2ecab752009-09-18 18:07:23 +0000326 llvm::SmallPtrSet<DeclContext *, 16> Visited;
327 return CollectMemberLookupResults(Ctx, InitialRank, Visited, Results);
328}
329
330/// \brief Collect the results of searching for members within the given
331/// declaration context.
332///
333/// \param Ctx the declaration context from which we will gather results.
334///
335/// \param InitialRank the initial rank given to results in this declaration
336/// context. Larger rank values will be used for, e.g., members found in
337/// base classes.
338///
339/// \param Visited the set of declaration contexts that have already been
340/// visited. Declaration contexts will only be visited once.
341///
342/// \param Results the result set that will be extended with any results
343/// found within this declaration context (and, for a C++ class, its bases).
344///
345/// \returns the next higher rank value, after considering all of the
346/// names within this declaration context.
347unsigned CodeCompleteConsumer::CollectMemberLookupResults(DeclContext *Ctx,
348 unsigned InitialRank,
349 llvm::SmallPtrSet<DeclContext *, 16> &Visited,
350 ResultSet &Results) {
351 // Make sure we don't visit the same context twice.
352 if (!Visited.insert(Ctx->getPrimaryContext()))
353 return InitialRank;
354
Douglas Gregor2436e712009-09-17 21:32:03 +0000355 // Enumerate all of the results in this context.
356 Results.EnterNewScope();
357 for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
358 CurCtx = CurCtx->getNextContext()) {
359 for (DeclContext::decl_iterator D = CurCtx->decls_begin(),
360 DEnd = CurCtx->decls_end();
361 D != DEnd; ++D) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000362 if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
Douglas Gregor2436e712009-09-17 21:32:03 +0000363 Results.MaybeAddResult(Result(ND, InitialRank));
Douglas Gregor2436e712009-09-17 21:32:03 +0000364 }
365 }
366
367 // Traverse the contexts of inherited classes.
368 unsigned NextRank = InitialRank;
369 if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
370 for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
371 BEnd = Record->bases_end();
372 B != BEnd; ++B) {
373 QualType BaseType = B->getType();
374
375 // Don't look into dependent bases, because name lookup can't look
376 // there anyway.
377 if (BaseType->isDependentType())
378 continue;
379
380 const RecordType *Record = BaseType->getAs<RecordType>();
381 if (!Record)
382 continue;
383
Douglas Gregor2436e712009-09-17 21:32:03 +0000384 // FIXME: It would be nice to be able to determine whether referencing
385 // a particular member would be ambiguous. For example, given
386 //
387 // struct A { int member; };
388 // struct B { int member; };
389 // struct C : A, B { };
390 //
391 // void f(C *c) { c->### }
392 // accessing 'member' would result in an ambiguity. However, code
393 // completion could be smart enough to qualify the member with the
394 // base class, e.g.,
395 //
396 // c->B::member
397 //
398 // or
399 //
400 // c->A::member
401
402 // Collect results from this base class (and its bases).
403 NextRank = std::max(NextRank,
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000404 CollectMemberLookupResults(Record->getDecl(),
Douglas Gregor2ecab752009-09-18 18:07:23 +0000405 InitialRank + 1,
406 Visited,
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000407 Results));
Douglas Gregor2436e712009-09-17 21:32:03 +0000408 }
409 }
410
411 // FIXME: Look into base classes in Objective-C!
412
413 Results.ExitScope();
414 return NextRank;
415}
416
Douglas Gregorf45b0cf2009-09-18 15:37:17 +0000417/// \brief Determines whether the given declaration is suitable as the
418/// start of a C++ nested-name-specifier, e.g., a class or namespace.
419bool CodeCompleteConsumer::IsNestedNameSpecifier(NamedDecl *ND) const {
420 // Allow us to find class templates, too.
421 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
422 ND = ClassTemplate->getTemplatedDecl();
423
424 return getSema().isAcceptableNestedNameSpecifier(ND);
425}
426
427/// \brief Determines whether the given declaration is an enumeration.
428bool CodeCompleteConsumer::IsEnum(NamedDecl *ND) const {
429 return isa<EnumDecl>(ND);
430}
431
432/// \brief Determines whether the given declaration is a class or struct.
433bool CodeCompleteConsumer::IsClassOrStruct(NamedDecl *ND) const {
434 // Allow us to find class templates, too.
435 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
436 ND = ClassTemplate->getTemplatedDecl();
437
438 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
439 return RD->getTagKind() == TagDecl::TK_class ||
440 RD->getTagKind() == TagDecl::TK_struct;
441
442 return false;
443}
444
445/// \brief Determines whether the given declaration is a union.
446bool CodeCompleteConsumer::IsUnion(NamedDecl *ND) const {
447 // Allow us to find class templates, too.
448 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
449 ND = ClassTemplate->getTemplatedDecl();
450
451 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
452 return RD->getTagKind() == TagDecl::TK_union;
453
454 return false;
455}
456
Douglas Gregor2436e712009-09-17 21:32:03 +0000457namespace {
458 struct VISIBILITY_HIDDEN SortCodeCompleteResult {
459 typedef CodeCompleteConsumer::Result Result;
460
461 bool operator()(const Result &X, const Result &Y) const {
462 // Sort first by rank.
463 if (X.Rank < Y.Rank)
464 return true;
465 else if (X.Rank > Y.Rank)
466 return false;
467
468 // Result kinds are ordered by decreasing importance.
469 if (X.Kind < Y.Kind)
470 return true;
471 else if (X.Kind > Y.Kind)
472 return false;
473
474 // Non-hidden names precede hidden names.
475 if (X.Hidden != Y.Hidden)
476 return !X.Hidden;
477
478 // Ordering depends on the kind of result.
479 switch (X.Kind) {
480 case Result::RK_Declaration:
481 // Order based on the declaration names.
482 return X.Declaration->getDeclName() < Y.Declaration->getDeclName();
483
484 case Result::RK_Keyword:
485 return strcmp(X.Keyword, Y.Keyword) == -1;
486 }
487
488 // If only our C++ compiler did control-flow warnings properly.
489 return false;
490 }
491 };
492}
493
Douglas Gregor2da11082009-09-18 15:51:54 +0000494/// \brief Determines whether the given hidden result could be found with
495/// some extra work, e.g., by qualifying the name.
496///
497/// \param Hidden the declaration that is hidden by the currenly \p Visible
498/// declaration.
499///
500/// \param Visible the declaration with the same name that is already visible.
501///
502/// \returns true if the hidden result can be found by some mechanism,
503/// false otherwise.
504bool CodeCompleteConsumer::canHiddenResultBeFound(NamedDecl *Hidden,
505 NamedDecl *Visible) {
506 // In C, there is no way to refer to a hidden name.
507 if (!getSema().getLangOptions().CPlusPlus)
508 return false;
509
510 DeclContext *HiddenCtx = Hidden->getDeclContext()->getLookupContext();
511
512 // There is no way to qualify a name declared in a function or method.
513 if (HiddenCtx->isFunctionOrMethod())
514 return false;
515
516 // If the hidden and visible declarations are in different name-lookup
517 // contexts, then we can qualify the name of the hidden declaration.
518 // FIXME: Optionally compute the string needed to refer to the hidden
519 // name.
520 return HiddenCtx != Visible->getDeclContext()->getLookupContext();
521}
522
Douglas Gregor2436e712009-09-17 21:32:03 +0000523void
524PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
525 unsigned NumResults) {
526 // Sort the results by rank/kind/etc.
527 std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult());
528
529 // Print the results.
530 for (unsigned I = 0; I != NumResults; ++I) {
531 switch (Results[I].Kind) {
532 case Result::RK_Declaration:
533 OS << Results[I].Declaration->getNameAsString() << " : "
534 << Results[I].Rank;
535 if (Results[I].Hidden)
536 OS << " (Hidden)";
537 OS << '\n';
538 break;
539
540 case Result::RK_Keyword:
541 OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
542 break;
543 }
544 }
545
546 // Once we've printed the code-completion results, suppress remaining
547 // diagnostics.
548 // FIXME: Move this somewhere else!
549 getSema().PP.getDiagnostics().setSuppressAllDiagnostics();
550}