aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/ASTUnit.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-08-16 23:05:20 +0000
committerDouglas Gregor <dgregor@apple.com>2010-08-16 23:05:20 +0000
commita5fb7c3b56c3698e19a7c1e97d41150de33cf6c9 (patch)
treeed5d2161d769c878c2564b48f9da0176af0b5f0d /lib/Frontend/ASTUnit.cpp
parent57dae1a312e3f7591e957adc89776ef4bca6a097 (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.cpp72
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);