forked from OSchip/llvm-project
Improve code completion in failure cases in two ways:
1) Suppress diagnostics as soon as we form the code-completion token, so we don't get any error/warning spew from the early end-of-file. 2) If we consume a code-completion token when we weren't expecting one, go into a code-completion recovery path that produces the best results it can based on the context that the parser is in. llvm-svn: 104585
This commit is contained in:
parent
658dd8b176
commit
6da3db4af3
|
@ -2649,9 +2649,13 @@ public:
|
|||
/// \brief Code completion occurs at the beginning of the
|
||||
/// initialization statement (or expression) in a for loop.
|
||||
CCC_ForInit,
|
||||
/// \brief Code completion ocurs within the condition of an if,
|
||||
/// \brief Code completion occurs within the condition of an if,
|
||||
/// while, switch, or for statement.
|
||||
CCC_Condition
|
||||
CCC_Condition,
|
||||
/// \brief Code completion occurs within the body of a function on a
|
||||
/// recovery path, where we do not have a specific handle on our position
|
||||
/// in the grammar.
|
||||
CCC_RecoveryInFunction
|
||||
};
|
||||
|
||||
/// \brief Code completion for an ordinary name that occurs within the given
|
||||
|
|
|
@ -234,6 +234,11 @@ private:
|
|||
assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() &&
|
||||
!isTokenBrace() &&
|
||||
"Should consume special tokens with Consume*Token");
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
CodeCompletionRecovery();
|
||||
return ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
PrevTokLocation = Tok.getLocation();
|
||||
PP.Lex(Tok);
|
||||
return PrevTokLocation;
|
||||
|
@ -308,6 +313,22 @@ private:
|
|||
return PrevTokLocation;
|
||||
}
|
||||
|
||||
/// \brief Consume the current code-completion token.
|
||||
///
|
||||
/// This routine should be called to consume the code-completion token once
|
||||
/// a code-completion action has already been invoked.
|
||||
SourceLocation ConsumeCodeCompletionToken() {
|
||||
assert(Tok.is(tok::code_completion));
|
||||
PrevTokLocation = Tok.getLocation();
|
||||
PP.Lex(Tok);
|
||||
return PrevTokLocation;
|
||||
}
|
||||
|
||||
///\ brief When we are consuming a code-completion token within having
|
||||
/// matched specific position in the grammar, provide code-completion results
|
||||
/// based on context.
|
||||
void CodeCompletionRecovery();
|
||||
|
||||
/// GetLookAheadToken - This peeks ahead N tokens and returns that token
|
||||
/// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
|
||||
/// returns the token after Tok, etc.
|
||||
|
|
|
@ -1359,6 +1359,9 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
|
|||
|
||||
// Only do the eof -> code_completion translation once.
|
||||
PP->SetCodeCompletionPoint(0, 0, 0);
|
||||
|
||||
// Silence any diagnostics that occur once we hit the code-completion point.
|
||||
PP->getDiagnostics().setSuppressAllDiagnostics(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -839,7 +839,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
CCC = Action::CCC_ObjCImplementation;
|
||||
|
||||
Actions.CodeCompleteOrdinaryName(CurScope, CCC);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
DS.SetRangeStart(Tok.getLocation());
|
||||
|
@ -1870,7 +1870,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
// Code completion for an enum name.
|
||||
Actions.CodeCompleteTag(CurScope, DeclSpec::TST_enum);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
llvm::OwningPtr<AttributeList> Attr;
|
||||
|
|
|
@ -50,7 +50,7 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteNamespaceDecl(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
SourceLocation IdentLoc;
|
||||
|
@ -136,7 +136,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteNamespaceAliasDecl(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
CXXScopeSpec SS;
|
||||
|
@ -231,7 +231,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteUsing(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.is(tok::kw_namespace))
|
||||
|
@ -268,7 +268,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteUsingDirective(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
CXXScopeSpec SS;
|
||||
|
@ -610,7 +610,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
// Code completion for a struct, class, or union name.
|
||||
Actions.CodeCompleteTag(CurScope, TagType);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
AttributeList *AttrList = 0;
|
||||
|
|
|
@ -222,7 +222,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
|
|||
Parser::OwningExprResult Parser::ParseAssignmentExpression() {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.is(tok::kw_throw))
|
||||
|
@ -906,7 +906,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
|
||||
case tok::code_completion:
|
||||
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
|
||||
NotCastExpr, TypeOfCast);
|
||||
case tok::l_square:
|
||||
|
@ -975,7 +975,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteCall(CurScope, LHS.get(), 0, 0);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::r_paren)) {
|
||||
|
@ -1029,7 +1029,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
|
|||
Actions.CodeCompleteMemberReferenceExpr(CurScope, LHS.get(),
|
||||
OpLoc, OpKind == tok::arrow);
|
||||
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (MayBePseudoDestructor) {
|
||||
|
@ -1562,7 +1562,7 @@ bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
if (Completer)
|
||||
(Actions.*Completer)(CurScope, Data, Exprs.data(), Exprs.size());
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
OwningExprResult Expr(ParseAssignmentExpression());
|
||||
|
|
|
@ -110,7 +110,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
// Code completion for a nested-name-specifier, where the code
|
||||
// code completion token follows the '::'.
|
||||
Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -729,7 +729,7 @@ bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
|
|||
bool ConvertToBoolean) {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (!isCXXConditionDeclaration()) {
|
||||
|
@ -1274,7 +1274,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
|
|||
Actions.CodeCompleteOperatorName(CurScope);
|
||||
|
||||
// Consume the operator token.
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
|
||||
// Don't try to parse any further.
|
||||
return true;
|
||||
|
|
|
@ -32,7 +32,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, false);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
switch (Tok.getObjCKeywordID()) {
|
||||
|
@ -131,7 +131,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
|
|||
// Code completion after '@interface'.
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCInterfaceDecl(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -149,7 +149,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
|
|||
IdentifierInfo *categoryId = 0;
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId, nameLoc);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
// For ObjC2, the category name is optional (not an error).
|
||||
|
@ -204,7 +204,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
|
|||
// Code completion of superclass names.
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCSuperclass(CurScope, nameId, nameLoc);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -350,7 +350,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
|
|||
Actions.CodeCompleteOrdinaryName(CurScope,
|
||||
ObjCImpDecl? Action::CCC_ObjCImplementation
|
||||
: Action::CCC_ObjCInterface);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
// If we don't have an @ directive, parse it as a function definition.
|
||||
|
@ -371,7 +371,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
|
|||
SourceLocation AtLoc = ConsumeToken(); // the "@"
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -438,7 +438,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
|
|||
// EOF. In the former case, eat the @end. In the later case, emit an error.
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
} else if (Tok.isObjCAtKeyword(tok::objc_end))
|
||||
ConsumeToken(); // the "end" identifier
|
||||
else
|
||||
|
@ -477,7 +477,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
|
|||
while (1) {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCPropertyFlags(CurScope, DS);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
const IdentifierInfo *II = Tok.getIdentifierInfo();
|
||||
|
||||
|
@ -514,7 +514,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
|
|||
else
|
||||
Actions.CodeCompleteObjCPropertyGetter(CurScope, ClassDecl,
|
||||
Methods, NumMethods);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -782,7 +782,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCMethodDecl(CurScope, mType == tok::minus,
|
||||
/*ReturnType=*/0, IDecl);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
// Parse the return type if present.
|
||||
|
@ -799,7 +799,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCMethodDecl(CurScope, mType == tok::minus,
|
||||
ReturnType, IDecl);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
// Now parse the selector.
|
||||
|
@ -945,7 +945,7 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
|
||||
ProtocolIdents.size());
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -1026,7 +1026,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCAtVisibility(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
switch (Tok.getObjCKeywordID()) {
|
||||
|
@ -1046,7 +1046,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteOrdinaryName(CurScope,
|
||||
Action::CCC_ObjCInstanceVariableList);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
struct ObjCIvarCallback : FieldCallback {
|
||||
|
@ -1117,7 +1117,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCProtocolDecl(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -1203,7 +1203,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
|
|||
// Code completion after '@implementation'.
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCImplementationDecl(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -1222,7 +1222,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCImplementationCategory(CurScope, nameId, nameLoc);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.is(tok::identifier)) {
|
||||
|
@ -1342,7 +1342,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
|
|||
while (true) {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -1361,7 +1361,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
|
|||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCPropertySynthesizeIvar(CurScope, propertyId,
|
||||
ObjCImpDecl);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -1400,7 +1400,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
|
|||
while (true) {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
|
@ -1654,7 +1654,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
|
|||
Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteObjCAtStatement(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
return StmtError();
|
||||
}
|
||||
|
||||
|
@ -1685,7 +1685,7 @@ Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
|
|||
switch (Tok.getKind()) {
|
||||
case tok::code_completion:
|
||||
Actions.CodeCompleteObjCAtExpression(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
return ExprError();
|
||||
|
||||
case tok::string_literal: // primary-expression: string-literal
|
||||
|
@ -1925,7 +1925,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
|
|||
else
|
||||
Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(),
|
||||
0, 0);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
// Parse objc-selector
|
||||
|
@ -1979,7 +1979,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
|
|||
Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(),
|
||||
KeyIdents.data(),
|
||||
KeyIdents.size());
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
// Check for another keyword selector.
|
||||
|
|
|
@ -283,7 +283,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
|
|||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteCase(CurScope);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
/// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
|
||||
|
@ -1000,7 +1000,7 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
|
|||
Actions.CodeCompleteOrdinaryName(CurScope,
|
||||
C99orCXXorObjC? Action::CCC_ForInit
|
||||
: Action::CCC_Expression);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
}
|
||||
|
||||
// Parse the first part of the for specifier.
|
||||
|
|
|
@ -134,7 +134,7 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
|
|||
/// returned.
|
||||
bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
|
||||
const char *Msg, tok::TokenKind SkipToTok) {
|
||||
if (Tok.is(ExpectedTok)) {
|
||||
if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) {
|
||||
ConsumeAnyToken();
|
||||
return false;
|
||||
}
|
||||
|
@ -189,7 +189,11 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
|
|||
case tok::eof:
|
||||
// Ran out of tokens.
|
||||
return false;
|
||||
|
||||
|
||||
case tok::code_completion:
|
||||
ConsumeToken();
|
||||
return false;
|
||||
|
||||
case tok::l_paren:
|
||||
// Recursively skip properly-nested parens.
|
||||
ConsumeParen();
|
||||
|
@ -447,7 +451,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
|
|||
Actions.CodeCompleteOrdinaryName(CurScope,
|
||||
ObjCImpDecl? Action::CCC_ObjCImplementation
|
||||
: Action::CCC_Namespace);
|
||||
ConsumeToken();
|
||||
ConsumeCodeCompletionToken();
|
||||
return ParseExternalDeclaration(Attr);
|
||||
case tok::kw_using:
|
||||
case tok::kw_namespace:
|
||||
|
@ -1072,6 +1076,22 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Parser::CodeCompletionRecovery() {
|
||||
for (Scope *S = CurScope; S; S = S->getParent()) {
|
||||
if (S->getFlags() & Scope::FnScope) {
|
||||
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_RecoveryInFunction);
|
||||
return;
|
||||
}
|
||||
|
||||
if (S->getFlags() & Scope::ClassScope) {
|
||||
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Class);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Namespace);
|
||||
}
|
||||
|
||||
// Anchor the Parser::FieldCallback vtable to this translation unit.
|
||||
// We use a spurious method instead of the destructor because
|
||||
// destroying FieldCallbacks can actually be slightly
|
||||
|
|
|
@ -459,11 +459,6 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Once we've printed the code-completion results, suppress remaining
|
||||
// diagnostics.
|
||||
// FIXME: Move this somewhere else!
|
||||
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -478,11 +473,6 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
|
|||
delete CCS;
|
||||
}
|
||||
}
|
||||
|
||||
// Once we've printed the code-completion results, suppress remaining
|
||||
// diagnostics.
|
||||
// FIXME: Move this somewhere else!
|
||||
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -599,11 +589,6 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
|
|||
CCS->Serialize(OS);
|
||||
delete CCS;
|
||||
}
|
||||
|
||||
// Once we've printed the code-completion results, suppress remaining
|
||||
// diagnostics.
|
||||
// FIXME: Move this somewhere else!
|
||||
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -619,9 +604,4 @@ CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
|
|||
CCS->Serialize(OS);
|
||||
delete CCS;
|
||||
}
|
||||
|
||||
// Once we've printed the code-completion results, suppress remaining
|
||||
// diagnostics.
|
||||
// FIXME: Move this somewhere else!
|
||||
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
|
||||
}
|
||||
|
|
|
@ -843,6 +843,7 @@ static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC,
|
|||
case Action::CCC_Statement:
|
||||
case Action::CCC_ForInit:
|
||||
case Action::CCC_Condition:
|
||||
case Action::CCC_RecoveryInFunction:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -994,6 +995,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
|
|||
AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
|
||||
break;
|
||||
|
||||
case Action::CCC_RecoveryInFunction:
|
||||
case Action::CCC_Statement: {
|
||||
Results.AddResult(Result("typedef"));
|
||||
|
||||
|
@ -1925,6 +1927,10 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
|
|||
case CCC_Condition:
|
||||
Results.setFilter(&ResultBuilder::IsOrdinaryName);
|
||||
break;
|
||||
|
||||
case CCC_RecoveryInFunction:
|
||||
// Unfiltered
|
||||
break;
|
||||
}
|
||||
|
||||
CodeCompletionDeclConsumer Consumer(Results, CurContext);
|
||||
|
@ -3079,8 +3085,6 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
|
|||
}
|
||||
|
||||
Results.ExitScope();
|
||||
|
||||
// This also suppresses remaining diagnostics.
|
||||
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* Run lines are at the end, since line/column matter in this test. */
|
||||
|
||||
@interface A
|
||||
- (void)method:(int)x;
|
||||
@end
|
||||
|
||||
@implementation A
|
||||
- (void)method:(int)x {
|
||||
A *a = [A method:1];
|
||||
blarg * blah = wibble
|
||||
}
|
||||
@end
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:9:20 %s 2>%t | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// RUN: not grep error %t
|
||||
// CHECK-CC1: NotImplemented:{TypedText @encode}{LeftParen (}{Placeholder type-name}{RightParen )}
|
||||
// CHECK-CC1: NotImplemented:{TypedText _Bool}
|
||||
// CHECK-CC1: VarDecl:{ResultType A *}{TypedText a}
|
||||
// CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )}
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:10:24 %s 2>%t | FileCheck -check-prefix=CHECK-CC1 %s
|
Loading…
Reference in New Issue