Basic code completion support for the base and member initializers in
a constructor. llvm-svn: 112330
This commit is contained in:
parent
ca5af12920
commit
eaeeca9afe
|
@ -4348,7 +4348,10 @@ public:
|
|||
virtual void CodeCompleteNamespaceDecl(Scope *S);
|
||||
virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
|
||||
virtual void CodeCompleteOperatorName(Scope *S);
|
||||
|
||||
virtual void CodeCompleteConstructorInitializer(Decl *Constructor,
|
||||
CXXBaseOrMemberInitializer** Initializers,
|
||||
unsigned NumInitializers);
|
||||
|
||||
virtual void CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
|
||||
bool InInterface);
|
||||
virtual void CodeCompleteObjCAtVisibility(Scope *S);
|
||||
|
|
|
@ -1714,12 +1714,19 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
|
|||
bool AnyErrors = false;
|
||||
|
||||
do {
|
||||
MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
|
||||
if (!MemInit.isInvalid())
|
||||
MemInitializers.push_back(MemInit.get());
|
||||
else
|
||||
AnyErrors = true;
|
||||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
|
||||
MemInitializers.data(),
|
||||
MemInitializers.size());
|
||||
ConsumeCodeCompletionToken();
|
||||
} else {
|
||||
MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
|
||||
if (!MemInit.isInvalid())
|
||||
MemInitializers.push_back(MemInit.get());
|
||||
else
|
||||
AnyErrors = true;
|
||||
}
|
||||
|
||||
if (Tok.is(tok::comma))
|
||||
ConsumeToken();
|
||||
else if (Tok.is(tok::l_brace))
|
||||
|
|
|
@ -3267,6 +3267,86 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
|
|||
Results.data(),Results.size());
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
|
||||
CXXBaseOrMemberInitializer** Initializers,
|
||||
unsigned NumInitializers) {
|
||||
CXXConstructorDecl *Constructor
|
||||
= static_cast<CXXConstructorDecl *>(ConstructorD);
|
||||
if (!Constructor)
|
||||
return;
|
||||
|
||||
ResultBuilder Results(*this);
|
||||
Results.EnterNewScope();
|
||||
|
||||
// Fill in any already-initialized fields or base classes.
|
||||
llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
|
||||
llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
|
||||
for (unsigned I = 0; I != NumInitializers; ++I) {
|
||||
if (Initializers[I]->isBaseInitializer())
|
||||
InitializedBases.insert(
|
||||
Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
|
||||
else
|
||||
InitializedFields.insert(cast<FieldDecl>(Initializers[I]->getMember()));
|
||||
}
|
||||
|
||||
// Add completions for base classes.
|
||||
unsigned Priority = 1;
|
||||
CXXRecordDecl *ClassDecl = Constructor->getParent();
|
||||
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
|
||||
BaseEnd = ClassDecl->bases_end();
|
||||
Base != BaseEnd; ++Base) {
|
||||
if (!InitializedBases.insert(Context.getCanonicalType(Base->getType())))
|
||||
continue;
|
||||
|
||||
CodeCompletionString *Pattern = new CodeCompletionString;
|
||||
Pattern->AddTypedTextChunk(
|
||||
Base->getType().getAsString(Context.PrintingPolicy));
|
||||
Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
|
||||
Pattern->AddPlaceholderChunk("args");
|
||||
Pattern->AddChunk(CodeCompletionString::CK_RightParen);
|
||||
Results.AddResult(CodeCompletionResult(Pattern, Priority++));
|
||||
}
|
||||
|
||||
// Add completions for virtual base classes.
|
||||
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
|
||||
BaseEnd = ClassDecl->vbases_end();
|
||||
Base != BaseEnd; ++Base) {
|
||||
if (!InitializedBases.insert(Context.getCanonicalType(Base->getType())))
|
||||
continue;
|
||||
|
||||
CodeCompletionString *Pattern = new CodeCompletionString;
|
||||
Pattern->AddTypedTextChunk(
|
||||
Base->getType().getAsString(Context.PrintingPolicy));
|
||||
Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
|
||||
Pattern->AddPlaceholderChunk("args");
|
||||
Pattern->AddChunk(CodeCompletionString::CK_RightParen);
|
||||
Results.AddResult(CodeCompletionResult(Pattern, Priority++));
|
||||
}
|
||||
|
||||
// Add completions for members.
|
||||
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
||||
FieldEnd = ClassDecl->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl())))
|
||||
continue;
|
||||
|
||||
if (!Field->getDeclName())
|
||||
continue;
|
||||
|
||||
CodeCompletionString *Pattern = new CodeCompletionString;
|
||||
Pattern->AddTypedTextChunk(Field->getIdentifier()->getName());
|
||||
Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
|
||||
Pattern->AddPlaceholderChunk("args");
|
||||
Pattern->AddChunk(CodeCompletionString::CK_RightParen);
|
||||
Results.AddResult(CodeCompletionResult(Pattern, Priority++));
|
||||
}
|
||||
Results.ExitScope();
|
||||
|
||||
HandleCodeCompleteResults(this, CodeCompleter,
|
||||
CodeCompletionContext::CCC_Name,
|
||||
Results.data(), Results.size());
|
||||
}
|
||||
|
||||
// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
|
||||
// true or false.
|
||||
#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
|
||||
|
|
Loading…
Reference in New Issue