]> granicus.if.org Git - clang/commitdiff
[Parser] Don't code-complete twice.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 27 Mar 2013 23:58:17 +0000 (23:58 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 27 Mar 2013 23:58:17 +0000 (23:58 +0000)
When we are consuming the current token just to enter a new token stream, we push
the current token in the back of the stream so that we get it again.

Unfortunately this had the effect where if the current token is a code-completion one,
we would code-complete once during consuming it and another time after the stream ended.

Fix this by making sure that, in this case, ConsumeAnyToken() will consume a code-completion
token without invoking code-completion.

rdar://12842503

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178199 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseObjc.cpp
lib/Parse/ParseTemplate.cpp
test/Index/complete-declarators.m

index de18b86da02388dc7f22e1ef7d4fb1774d90741c..1ac0f3be5ea2db34e511da60694f91342ab9b4e3 100644 (file)
@@ -247,12 +247,12 @@ public:
   /// This does not work with all kinds of tokens: strings and specific other
   /// tokens must be consumed with custom methods below.  This returns the
   /// location of the consumed token.
-  SourceLocation ConsumeToken() {
+  SourceLocation ConsumeToken(bool ConsumeCodeCompletionTok = false) {
     assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() &&
            !isTokenBrace() &&
            "Should consume special tokens with Consume*Token");
 
-    if (Tok.is(tok::code_completion))
+    if (!ConsumeCodeCompletionTok && Tok.is(tok::code_completion))
       return handleUnexpectedCodeCompletionToken();
 
     PrevTokLocation = Tok.getLocation();
@@ -291,7 +291,7 @@ private:
   /// ConsumeAnyToken - Dispatch to the right Consume* method based on the
   /// current token type.  This should only be used in cases where the type of
   /// the token really isn't known, e.g. in error recovery.
-  SourceLocation ConsumeAnyToken() {
+  SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) {
     if (isTokenParen())
       return ConsumeParen();
     else if (isTokenBracket())
@@ -301,7 +301,7 @@ private:
     else if (isTokenStringLiteral())
       return ConsumeStringToken();
     else
-      return ConsumeToken();
+      return ConsumeToken(ConsumeCodeCompletionTok);
   }
 
   /// ConsumeParen - This consume method keeps the paren count up-to-date.
index 30aee20b267443201c653d8e76e6b17620e78dda..bc634b57d9cee4f6a460052e89601345783a6922 100644 (file)
@@ -407,7 +407,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
   PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
 
   // Consume the previously pushed token.
-  ConsumeAnyToken();
+  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
   assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
          && "Inline method not starting with '{', ':' or 'try'");
 
@@ -510,7 +510,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
   PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false);
 
   // Consume the previously pushed token.
-  ConsumeAnyToken();
+  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
 
   SourceLocation EqualLoc;
 
index 4d1147b5df9290d359628cff04ce8f28eea92ca5..7dfbf5ff86cd7e424c54c130487eefa25ae97830 100644 (file)
@@ -931,7 +931,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
   LA.Toks.push_back(Tok);
   PP.EnterTokenStream(LA.Toks.data(), LA.Toks.size(), true, false);
   // Consume the previously pushed token.
-  ConsumeAnyToken();
+  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
 
   if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) {
     // FIXME: Do not warn on C++11 attributes, once we start supporting
index e4a880e89aba37d67e162a1299ced51800fb99c2..fb0237ac05ea38ed2fb87eb3439c696d6e1f9567 100644 (file)
@@ -2896,7 +2896,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
   PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
   
   // Consume the previously pushed token.
-  ConsumeAnyToken();
+  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
     
   assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
           Tok.is(tok::colon)) && 
index 1327dd59e557d44172e14d6b1e3c1202f83d6d16..f14666922b95742cc489fa27e8d2c0c316de97e2 100644 (file)
@@ -1305,7 +1305,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
   PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false);
 
   // Consume the previously pushed token.
-  ConsumeAnyToken();
+  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
   assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
          && "Inline method not starting with '{', ':' or 'try'");
 
index d42a3c7a6c4b8f777c0534c52c3c34c094e4dda1..b3a60ded110a4379088ed9fbd054d01eb0cc27b7 100644 (file)
@@ -22,6 +22,7 @@
 
   static P *p = 0;
 }
+- (boid)method2 {}
 @end
 
 // RUN: c-index-test -code-completion-at=%s:7:4 %s | FileCheck -check-prefix=CHECK-CC0 %s
@@ -81,3 +82,8 @@
 // CHECK-CC5: NotImplemented:{TypedText unsigned} (50)
 // CHECK-CC5: NotImplemented:{TypedText void} (50)
 // CHECK-CC5: NotImplemented:{TypedText volatile} (50)
+
+// Check that there are no duplicate entries if we code-complete after an @implementation
+// RUN: c-index-test -code-completion-at=%s:27:1 %s | FileCheck -check-prefix=CHECK-CC6 %s
+// CHECK-CC6: ObjCInterfaceDecl:{TypedText A}
+// CHECK-CC6-NOT: ObjCInterfaceDecl:{TypedText A}