]> granicus.if.org Git - clang/commitdiff
Speed up code-completion by skipping function bodies.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 3 Jan 2011 19:44:02 +0000 (19:44 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 3 Jan 2011 19:44:02 +0000 (19:44 +0000)
When we are in code-completion mode, skip parsing of all function bodies except the one where the
code-completion point resides.

For big .cpp files like 'SemaExpr.cpp' the improvement makes a huge difference, in some cases cutting down
code-completion time -62% !

We don't get diagnostics for the bodies though, so modify the code-completion tests that check for errors.

See rdar://8814203.

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

include/clang/Lex/Preprocessor.h
include/clang/Parse/Parser.h
lib/Parse/ParseStmt.cpp
lib/Parse/Parser.cpp
test/Index/code-complete-errors.c [deleted file]
test/Index/remap-complete.c

index ca4b9fddabbfd79ccacdd78ac049ce2c08a09800..df3a5b234bc9a94d79ddf19718d522eacb0c7a79 100644 (file)
@@ -618,6 +618,9 @@ public:
   /// for which we are performing code completion.
   bool isCodeCompletionFile(SourceLocation FileLoc) const;
 
+  /// \brief Determine if we are performing code completion.
+  bool isCodeCompletionEnabled() const { return CodeCompletionFile != 0; }
+
   /// \brief Instruct the preprocessor to skip part of the main
   /// the main source file.
   ///
index db4d1b7a4b77650ec8fb7e002218967ebce7e47e..f523bed9761a16b0e851560115945cbabea50110 100644 (file)
@@ -553,16 +553,17 @@ private:
   /// If SkipUntil finds the specified token, it returns true, otherwise it
   /// returns false.
   bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true,
-                 bool DontConsume = false) {
-    return SkipUntil(&T, 1, StopAtSemi, DontConsume);
+                 bool DontConsume = false, bool StopAtCodeCompletion = false) {
+    return SkipUntil(&T, 1, StopAtSemi, DontConsume, StopAtCodeCompletion);
   }
   bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true,
-                 bool DontConsume = false) {
+                 bool DontConsume = false, bool StopAtCodeCompletion = false) {
     tok::TokenKind TokArray[] = {T1, T2};
-    return SkipUntil(TokArray, 2, StopAtSemi, DontConsume);
+    return SkipUntil(TokArray, 2, StopAtSemi, DontConsume,StopAtCodeCompletion);
   }
   bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
-                 bool StopAtSemi = true, bool DontConsume = false);
+                 bool StopAtSemi = true, bool DontConsume = false,
+                 bool StopAtCodeCompletion = false);
 
   //===--------------------------------------------------------------------===//
   // Lexing and parsing of C++ inline methods.
index dafe3737783584cceb5852924cb0728e65bb29f6..d25cc110a8a8c3f31921b6316abeeffa2c796798 100644 (file)
@@ -1466,6 +1466,19 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
   assert(Tok.is(tok::l_brace));
   SourceLocation LBraceLoc = Tok.getLocation();
 
+  // When in code-completion, skip parsing for all function bodies unless
+  // the body contains the code-completion point.
+  if (PP.isCodeCompletionEnabled()) {
+    TentativeParsingAction PA(*this);
+    ConsumeBrace();
+    if (SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false,
+                  /*StopAtCodeCompletion=*/true)) {
+      PA.Commit();
+      return Actions.ActOnFinishFunctionBody(Decl, 0);
+    }
+    PA.Revert();
+  }
+
   PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
                                       "parsing function body");
 
index 2a569b58d8c42eee027d9ee507be586c9d4c3778..aa0ad795cab7f8f8f9cd33555d9fa487056ca046 100644 (file)
@@ -214,7 +214,8 @@ bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
 /// If SkipUntil finds the specified token, it returns true, otherwise it
 /// returns false.
 bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
-                       bool StopAtSemi, bool DontConsume) {
+                       bool StopAtSemi, bool DontConsume,
+                       bool StopAtCodeCompletion) {
   // We always want this function to skip at least one token if the first token
   // isn't T and if not at EOF.
   bool isFirstTokenSkipped = true;
@@ -237,23 +238,24 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
       return false;
         
     case tok::code_completion:
-      ConsumeToken();
+      if (!StopAtCodeCompletion)
+        ConsumeToken();
       return false;
         
     case tok::l_paren:
       // Recursively skip properly-nested parens.
       ConsumeParen();
-      SkipUntil(tok::r_paren, false);
+      SkipUntil(tok::r_paren, false, false, StopAtCodeCompletion);
       break;
     case tok::l_square:
       // Recursively skip properly-nested square brackets.
       ConsumeBracket();
-      SkipUntil(tok::r_square, false);
+      SkipUntil(tok::r_square, false, false, StopAtCodeCompletion);
       break;
     case tok::l_brace:
       // Recursively skip properly-nested braces.
       ConsumeBrace();
-      SkipUntil(tok::r_brace, false);
+      SkipUntil(tok::r_brace, false, false, StopAtCodeCompletion);
       break;
 
     // Okay, we found a ']' or '}' or ')', which we think should be balanced.
diff --git a/test/Index/code-complete-errors.c b/test/Index/code-complete-errors.c
deleted file mode 100644 (file)
index 51cfb89..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-_Complex cd; // CHECK: code-complete-errors.c:1:1: warning: plain '_Complex' requires a type specifier; assuming '_Complex double'
-// CHECK: FIX-IT: Insert " double" at 1:9
-struct s {
-  int x, y;; // CHECK: code-complete-errors.c:4:12: warning: extra ';' inside a struct
-}; // CHECK: FIX-IT: Remove [4:12 - 4:13]
-
-struct s s0 = { y: 5 }; // CHECK: code-complete-errors.c:7:20: warning: use of GNU old-style field designator extension
-// CHECK: FIX-IT: Replace [7:17 - 7:19] with ".y = "
-int f(int *ptr1, float *ptr2) {
-  return ptr1 != ptr2; // CHECK: code-complete-errors.c:10:15:{10:10-10:14}{10:18-10:22}: warning: comparison of distinct pointer types ('int *' and 'float *')
-}
-
-#define expand_to_binary_function(ret, name, parm1, parm2, code) ret name(parm1, parm2) code
-
-expand_to_binary_function(int, g, int *ip, float *fp, {
- // CHECK: code-complete-errors.c:17:12:{17:9-17:24}: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
-    if (ip = (float*)fp) ;
-// CHECK: code-complete-errors.c:19:15:{19:12-19:14}{19:18-19:20}: warning: comparison of distinct pointer types ('int *' and 'float *')
-    return ip == fp;
-  })
-
-void g() {  }
-
-// RUN: c-index-test -code-completion-at=%s:21:12 -pedantic %s 2> %t
-// RUN: FileCheck -check-prefix=CHECK %s < %t
index e5b782930db623c822cd9291ff857853e3dbd42c..93fb6236c243f7d5d450128b121183fabe21975b 100644 (file)
@@ -1,7 +1,4 @@
-// RUN: c-index-test -code-completion-at=%s:6:2 -remap-file="%s;%S/Inputs/remap-complete-to.c" %s 2> %t.err | FileCheck %s
-// RUN: FileCheck -check-prefix=CHECK-DIAGS %s < %t.err
+// RUN: c-index-test -code-completion-at=%s:6:2 -remap-file="%s;%S/Inputs/remap-complete-to.c" %s | FileCheck %s
 
 // CHECK: FunctionDecl:{ResultType int}{TypedText f0}{LeftParen (}
 void f() { }
-
-// CHECK-DIAGS: remap-complete.c:2:19