Add code completion to produce "else" blocks after an "if"

statement. Fixes <rdar://problem/9229438>.

llvm-svn: 136564
This commit is contained in:
Douglas Gregor 2011-07-30 08:36:53 +00:00
parent 0c50531a46
commit 4ecb7209bf
4 changed files with 71 additions and 0 deletions

View File

@ -5824,6 +5824,7 @@ public:
void CodeCompleteCall(Scope *S, Expr *Fn, Expr **Args, unsigned NumArgs);
void CodeCompleteInitializer(Scope *S, Decl *D);
void CodeCompleteReturn(Scope *S);
void CodeCompleteAfterIf(Scope *S);
void CodeCompleteAssignmentRHS(Scope *S, Expr *LHS);
void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,

View File

@ -953,6 +953,9 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) {
// Pop the 'else' scope if needed.
InnerScope.Exit();
} else if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteAfterIf(getCurScope());
ConsumeCodeCompletionToken();
}
IfScope.Exit();

View File

@ -3702,6 +3702,61 @@ void Sema::CodeCompleteReturn(Scope *S) {
CodeCompleteExpression(S, ResultType);
}
void Sema::CodeCompleteAfterIf(Scope *S) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
mapCodeCompletionContext(*this, PCC_Statement));
Results.setFilter(&ResultBuilder::IsOrdinaryName);
Results.EnterNewScope();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals());
AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
// "else" block
CodeCompletionBuilder Builder(Results.getAllocator());
Builder.AddTypedTextChunk("else");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Builder.TakeString());
// "else if" block
Builder.AddTypedTextChunk("else");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("if");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (getLangOptions().CPlusPlus)
Builder.AddPlaceholderChunk("condition");
else
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Builder.TakeString());
Results.ExitScope();
if (S->getFnParent())
AddPrettyFunctionResults(PP.getLangOptions(), Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(),Results.size());
}
void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
if (LHS)
CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());

View File

@ -0,0 +1,12 @@
// Note: the run lines follow their respective tests, since line/column
// matter in this test.
void f(int x) {
if (x) {
}
}
// RUN: c-index-test -code-completion-at=%s:7:4 %s | FileCheck -check-prefix=CHECK-IF-ELSE %s
// CHECK-IF-ELSE: NotImplemented:{TypedText else}{HorizontalSpace }{LeftBrace {}{VerticalSpace }{Placeholder statements}{VerticalSpace }{RightBrace }} (40)
// CHECK-IF-ELSE: NotImplemented:{TypedText else}{HorizontalSpace }{Text if}{HorizontalSpace }{LeftParen (}{Placeholder expression}{RightParen )}{HorizontalSpace }{LeftBrace {}{VerticalSpace }{Placeholder statements}{VerticalSpace }{RightBrace }} (40)