forked from OSchip/llvm-project
Introduce a new code-completion point when we're parsing a
declarator. Here, we can only see a few things (e.g., cvr-qualifiers, nested name specifiers) and we do not want to provide other non-macro completions. Previously, we would end up in recovery mode and would provide a large number of non-relevant completions. llvm-svn: 111818
This commit is contained in:
parent
08fd2cf26a
commit
c49f5b2f11
|
@ -2798,6 +2798,22 @@ public:
|
|||
virtual void CodeCompleteOrdinaryName(Scope *S,
|
||||
ParserCompletionContext CompletionContext) { }
|
||||
|
||||
/// \brief Code completion for a declarator name.
|
||||
///
|
||||
///
|
||||
///
|
||||
/// \param S The scope in which code completion occurs.
|
||||
///
|
||||
/// \param AllowNonIdentifiers Whether non-identifier names are allowed in
|
||||
/// this context, e.g., operator+.
|
||||
///
|
||||
/// \param AllowNestedNameSpecifiers Whether nested-name-specifiers are
|
||||
/// allowed in this context, e.g., because it is a top-level declaration or
|
||||
/// a friend declaration.
|
||||
virtual void CodeCompleteDeclarator(Scope *S,
|
||||
bool AllowNonIdentifiers,
|
||||
bool AllowNestedNameSpecifiers) { }
|
||||
|
||||
/// \brief Code completion for a member access expression.
|
||||
///
|
||||
/// This code completion action is invoked when the code-completion token
|
||||
|
|
|
@ -164,7 +164,12 @@ public:
|
|||
/// is expected.
|
||||
CCC_Namespace,
|
||||
/// \brief Code completion occurred where a type name is expected.
|
||||
CCC_Type
|
||||
CCC_Type,
|
||||
/// \brief Code completion occurred where a new name is expected.
|
||||
CCC_Name,
|
||||
/// \brief Code completion occurred where a new name is expected and a
|
||||
/// qualified name is permissible.
|
||||
CCC_PotentiallyQualifiedName
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -4640,6 +4640,9 @@ public:
|
|||
//@{
|
||||
virtual void CodeCompleteOrdinaryName(Scope *S,
|
||||
ParserCompletionContext CompletionContext);
|
||||
virtual void CodeCompleteDeclarator(Scope *S,
|
||||
bool AllowNonIdentifiers,
|
||||
bool AllowNestedNameSpecifiers);
|
||||
virtual void CodeCompleteExpression(Scope *S, QualType T,
|
||||
bool IntegralConstantExpression = false);
|
||||
virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
|
||||
|
|
|
@ -235,7 +235,8 @@ void ASTUnit::CacheCodeCompletionResults() {
|
|||
| (1 << (CodeCompletionContext::CCC_EnumTag - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_UnionTag - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_Type - 1));
|
||||
| (1 << (CodeCompletionContext::CCC_Type - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1));
|
||||
|
||||
if (isa<NamespaceDecl>(Results[I].Declaration) ||
|
||||
isa<NamespaceAliasDecl>(Results[I].Declaration))
|
||||
|
@ -275,7 +276,10 @@ void ASTUnit::CacheCodeCompletionResults() {
|
|||
| (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_Statement - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_Expression - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
|
||||
| (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_Name - 1))
|
||||
| (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1));
|
||||
|
||||
CachedResult.Priority = Results[I].Priority;
|
||||
CachedResult.Kind = Results[I].CursorKind;
|
||||
CachedResult.TypeClass = STC_Void;
|
||||
|
@ -1532,6 +1536,8 @@ void CalculateHiddenNames(const CodeCompletionContext &Context,
|
|||
case CodeCompletionContext::CCC_MemberAccess:
|
||||
case CodeCompletionContext::CCC_Namespace:
|
||||
case CodeCompletionContext::CCC_Type:
|
||||
case CodeCompletionContext::CCC_Name:
|
||||
case CodeCompletionContext::CCC_PotentiallyQualifiedName:
|
||||
break;
|
||||
|
||||
case CodeCompletionContext::CCC_EnumTag:
|
||||
|
|
|
@ -853,21 +853,7 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
|
|||
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
AccessSpecifier AS,
|
||||
DeclSpecContext DSContext) {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Action::ParserCompletionContext CCC = Action::PCC_Namespace;
|
||||
if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
|
||||
CCC = DSContext == DSC_class? Action::PCC_MemberTemplate
|
||||
: Action::PCC_Template;
|
||||
else if (DSContext == DSC_class)
|
||||
CCC = Action::PCC_Class;
|
||||
else if (ObjCImpDecl)
|
||||
CCC = Action::PCC_ObjCImplementation;
|
||||
|
||||
Actions.CodeCompleteOrdinaryName(getCurScope(), CCC);
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
DeclSpecContext DSContext) {
|
||||
DS.SetRangeStart(Tok.getLocation());
|
||||
while (1) {
|
||||
bool isInvalid = false;
|
||||
|
@ -884,6 +870,38 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
DS.Finish(Diags, PP);
|
||||
return;
|
||||
|
||||
case tok::code_completion: {
|
||||
Action::ParserCompletionContext CCC = Action::PCC_Namespace;
|
||||
if (DS.hasTypeSpecifier()) {
|
||||
bool AllowNonIdentifiers
|
||||
= (getCurScope()->getFlags() & (Scope::ControlScope |
|
||||
Scope::BlockScope |
|
||||
Scope::TemplateParamScope |
|
||||
Scope::FunctionPrototypeScope |
|
||||
Scope::AtCatchScope)) == 0;
|
||||
bool AllowNestedNameSpecifiers
|
||||
= DSContext == DSC_top_level ||
|
||||
(DSContext == DSC_class && DS.isFriendSpecified());
|
||||
|
||||
Actions.CodeCompleteDeclarator(getCurScope(), AllowNonIdentifiers,
|
||||
AllowNestedNameSpecifiers);
|
||||
ConsumeCodeCompletionToken();
|
||||
return;
|
||||
}
|
||||
|
||||
if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
|
||||
CCC = DSContext == DSC_class? Action::PCC_MemberTemplate
|
||||
: Action::PCC_Template;
|
||||
else if (DSContext == DSC_class)
|
||||
CCC = Action::PCC_Class;
|
||||
else if (ObjCImpDecl)
|
||||
CCC = Action::PCC_ObjCImplementation;
|
||||
|
||||
Actions.CodeCompleteOrdinaryName(getCurScope(), CCC);
|
||||
ConsumeCodeCompletionToken();
|
||||
return;
|
||||
}
|
||||
|
||||
case tok::coloncolon: // ::foo::bar
|
||||
// C++ scope specifier. Annotate and loop, or bail out on error.
|
||||
if (TryAnnotateCXXScopeToken(true)) {
|
||||
|
@ -2501,6 +2519,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
|
|||
DirectDeclParseFunction DirectDeclParser) {
|
||||
if (Diags.hasAllExtensionsSilenced())
|
||||
D.setExtension();
|
||||
|
||||
// C++ member pointers start with a '::' or a nested-name.
|
||||
// Member pointers get special handling, since there's no place for the
|
||||
// scope spec in the generic path below.
|
||||
|
|
|
@ -774,9 +774,9 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
|
|||
/// __attribute__((unused))
|
||||
///
|
||||
Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
||||
tok::TokenKind mType,
|
||||
Decl *IDecl,
|
||||
tok::ObjCKeywordKind MethodImplKind) {
|
||||
tok::TokenKind mType,
|
||||
Decl *IDecl,
|
||||
tok::ObjCKeywordKind MethodImplKind) {
|
||||
ParsingDeclRAIIObject PD(*this);
|
||||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
|
|
|
@ -2222,7 +2222,7 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
|
|||
void Sema::CodeCompleteOrdinaryName(Scope *S,
|
||||
ParserCompletionContext CompletionContext) {
|
||||
typedef CodeCompleteConsumer::Result Result;
|
||||
ResultBuilder Results(*this);
|
||||
ResultBuilder Results(*this);
|
||||
|
||||
// Determine how to filter results, e.g., so that the names of
|
||||
// values (functions, enumerators, function templates, etc.) are
|
||||
|
@ -2268,6 +2268,45 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
|
|||
Results.data(),Results.size());
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteDeclarator(Scope *S,
|
||||
bool AllowNonIdentifiers,
|
||||
bool AllowNestedNameSpecifiers) {
|
||||
typedef CodeCompleteConsumer::Result Result;
|
||||
ResultBuilder Results(*this);
|
||||
Results.EnterNewScope();
|
||||
|
||||
// Type qualifiers can come after names.
|
||||
Results.AddResult(Result("const"));
|
||||
Results.AddResult(Result("volatile"));
|
||||
if (getLangOptions().C99)
|
||||
Results.AddResult(Result("restrict"));
|
||||
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
if (AllowNonIdentifiers) {
|
||||
Results.AddResult(Result("operator"));
|
||||
}
|
||||
|
||||
// Add nested-name-specifiers.
|
||||
if (AllowNestedNameSpecifiers) {
|
||||
Results.allowNestedNameSpecifiers();
|
||||
CodeCompletionDeclConsumer Consumer(Results, CurContext);
|
||||
LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
|
||||
CodeCompleter->includeGlobals());
|
||||
}
|
||||
}
|
||||
Results.ExitScope();
|
||||
|
||||
// Allow macros for names.
|
||||
if (CodeCompleter->includeMacros())
|
||||
AddMacroResults(PP, Results);
|
||||
|
||||
HandleCodeCompleteResults(this, CodeCompleter,
|
||||
AllowNestedNameSpecifiers
|
||||
? CodeCompletionContext::CCC_PotentiallyQualifiedName
|
||||
: CodeCompletionContext::CCC_Name,
|
||||
Results.data(), Results.size());
|
||||
}
|
||||
|
||||
/// \brief Perform code-completion in an expression context when we know what
|
||||
/// type we're looking for.
|
||||
///
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// This test is line- and column-sensitive, so test commands are at the bottom.
|
||||
namespace N {
|
||||
struct X {
|
||||
int f(X);
|
||||
};
|
||||
}
|
||||
|
||||
int g(int a);
|
||||
|
||||
struct Y { };
|
||||
|
||||
struct Z {
|
||||
int member;
|
||||
friend int N::X::f(N::X);
|
||||
};
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:8:5 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: NotImplemented:{TypedText const} (30)
|
||||
// CHECK-CC1: NotImplemented:{TypedText N}{Text ::} (75)
|
||||
// CHECK-CC1: NotImplemented:{TypedText operator} (30)
|
||||
// CHECK-CC1: NotImplemented:{TypedText volatile} (30)
|
||||
// RUN: c-index-test -code-completion-at=%s:8:11 %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: NotImplemented:{TypedText const} (30)
|
||||
// CHECK-CC2-NOT: NotImplemented:{TypedText N}{Text ::} (75)
|
||||
// CHECK-CC2-NOT: NotImplemented:{TypedText operator} (30)
|
||||
// CHECK-CC2: NotImplemented:{TypedText volatile} (30)
|
||||
// RUN: c-index-test -code-completion-at=%s:13:7 %s | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// CHECK-CC3: NotImplemented:{TypedText const} (30)
|
||||
// CHECK-CC3-NOT: NotImplemented:{TypedText N}{Text ::} (75)
|
||||
// CHECK-CC3: NotImplemented:{TypedText operator} (30)
|
||||
// CHECK-CC3: NotImplemented:{TypedText volatile} (30)
|
||||
// RUN: c-index-test -code-completion-at=%s:14:14 %s | FileCheck -check-prefix=CHECK-CC4 %s
|
||||
// CHECK-CC4: NotImplemented:{TypedText const} (30)
|
||||
// CHECK-CC4: NotImplemented:{TypedText N}{Text ::} (75)
|
||||
// CHECK-CC4: NotImplemented:{TypedText operator} (30)
|
||||
// CHECK-CC4: NotImplemented:{TypedText volatile} (30)
|
||||
// CHECK-CC4: StructDecl:{TypedText Y} (40)
|
||||
// CHECK-CC4: StructDecl:{TypedText Z} (20)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// This test is line- and column-sensitive, so test commands are at the bottom.
|
||||
@protocol P
|
||||
- (int)method:(id)param1;
|
||||
@end
|
||||
|
||||
@interface A <P>
|
||||
- (int)method:(id)param1;
|
||||
|
||||
@property int prop1;
|
||||
@end
|
||||
|
||||
@implementation A
|
||||
- (int)method:(id)param1 {
|
||||
for(id x in param1) {
|
||||
int y;
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:7:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1-NOT: NotImplemented:{TypedText extern} (30)
|
||||
// CHECK-CC1: NotImplemented:{TypedText param1} (30)
|
||||
// RUN: c-index-test -code-completion-at=%s:9:15 %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:14:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:15:9 %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: NotImplemented:{TypedText const} (30)
|
||||
// CHECK-CC2-NOT: int
|
||||
// CHECK-CC2: NotImplemented:{TypedText restrict} (30)
|
||||
// CHECK-CC2: NotImplemented:{TypedText volatile} (30)
|
Loading…
Reference in New Issue