diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-08-16 23:05:20 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-08-16 23:05:20 +0000 |
commit | a5fb7c3b56c3698e19a7c1e97d41150de33cf6c9 (patch) | |
tree | ed5d2161d769c878c2564b48f9da0176af0b5f0d /lib/Frontend/ASTUnit.cpp | |
parent | 57dae1a312e3f7591e957adc89776ef4bca6a097 (diff) |
Implement support for cached code completions for
nested-name-specifiers. Also includes fixes to the generation of
nested-name-specifier result in the non-cached case; we were producing
lame results for namespaces and namespace aliases, which (1) didn't
always have nested-name-specifiers when we want them, and (2) did not
have the necessary "::" as part of the completion.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111203 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/ASTUnit.cpp')
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 72 |
1 files changed, 51 insertions, 21 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 564ef56c97..41c5dbc460 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -92,7 +92,10 @@ void ASTUnit::CleanTemporaryFiles() { /// \brief Determine the set of code-completion contexts in which this /// declaration should be shown. static unsigned getDeclShowContexts(NamedDecl *ND, - const LangOptions &LangOpts) { + const LangOptions &LangOpts, + bool &IsNestedNameSpecifier) { + IsNestedNameSpecifier = false; + if (isa<UsingShadowDecl>(ND)) ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl()); if (!ND) @@ -122,19 +125,19 @@ static unsigned getDeclShowContexts(NamedDecl *ND, if (isa<EnumDecl>(ND)) { Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1)); - // Part of the nested-name-specifier. + // Part of the nested-name-specifier in C++0x. if (LangOpts.CPlusPlus0x) - Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1)); + IsNestedNameSpecifier = true; } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) { if (Record->isUnion()) Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1)); else Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)); - // Part of the nested-name-specifier. if (LangOpts.CPlusPlus) - Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1)); - } + IsNestedNameSpecifier = true; + } else if (isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) + IsNestedNameSpecifier = true; } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { // Values can appear in these contexts. Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1)) @@ -143,20 +146,10 @@ static unsigned getDeclShowContexts(NamedDecl *ND, } else if (isa<ObjCProtocolDecl>(ND)) { Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1)); } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) { - Contexts = (1 << (CodeCompletionContext::CCC_TopLevel - 1)) - | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) - | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1)) - | (1 << (CodeCompletionContext::CCC_Statement - 1)) - | (1 << (CodeCompletionContext::CCC_Expression - 1)) - | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)) - | (1 << (CodeCompletionContext::CCC_Namespace - 1)); + Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1)); // Part of the nested-name-specifier. - Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1)) - | (1 << (CodeCompletionContext::CCC_EnumTag - 1)) - | (1 << (CodeCompletionContext::CCC_UnionTag - 1)) - | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)) - | (1 << (CodeCompletionContext::CCC_Type - 1)); + IsNestedNameSpecifier = true; } return Contexts; @@ -188,10 +181,12 @@ void ASTUnit::CacheCodeCompletionResults() { for (unsigned I = 0, N = Results.size(); I != N; ++I) { switch (Results[I].Kind) { case Result::RK_Declaration: { + bool IsNestedNameSpecifier = false; CachedCodeCompletionResult CachedResult; CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema); CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration, - Ctx->getLangOptions()); + Ctx->getLangOptions(), + IsNestedNameSpecifier); CachedResult.Priority = Results[I].Priority; CachedResult.Kind = Results[I].CursorKind; @@ -220,6 +215,41 @@ void ASTUnit::CacheCodeCompletionResults() { } CachedCompletionResults.push_back(CachedResult); + + /// Handle nested-name-specifiers in C++. + if (TheSema->Context.getLangOptions().CPlusPlus && + IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) { + // The contexts in which a nested-name-specifier can appear in C++. + unsigned NNSContexts + = (1 << (CodeCompletionContext::CCC_TopLevel - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) + | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1)) + | (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Expression - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)) + | (1 << (CodeCompletionContext::CCC_EnumTag - 1)) + | (1 << (CodeCompletionContext::CCC_UnionTag - 1)) + | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)) + | (1 << (CodeCompletionContext::CCC_Type - 1)); + + if (isa<NamespaceDecl>(Results[I].Declaration) || + isa<NamespaceAliasDecl>(Results[I].Declaration)) + NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1)); + + if (unsigned RemainingContexts + = NNSContexts & ~CachedResult.ShowInContexts) { + // If there any contexts where this completion can be a + // nested-name-specifier but isn't already an option, create a + // nested-name-specifier completion. + Results[I].StartsNestedNameSpecifier = true; + CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema); + CachedResult.ShowInContexts = RemainingContexts; + CachedResult.Priority = CCP_NestedNameSpecifier; + CachedResult.TypeClass = STC_Void; + CachedResult.Type = 0; + CachedCompletionResults.push_back(CachedResult); + } + } break; } @@ -1482,8 +1512,8 @@ void CalculateHiddenNames(const CodeCompletionContext &Context, Hiding = (IDNS & Decl::IDNS_Tag); else { unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member | - Decl::IDNS_Namespace | Decl::IDNS_Ordinary | - Decl::IDNS_NonMemberOperator); + Decl::IDNS_Namespace | Decl::IDNS_Ordinary | + Decl::IDNS_NonMemberOperator); if (Ctx.getLangOptions().CPlusPlus) HiddenIDNS |= Decl::IDNS_Tag; Hiding = (IDNS & HiddenIDNS); |