[cfe-commits] r85594 - in /cfe/trunk: include/clang/Sema/CodeCompleteConsumer.h lib/Sema/CodeCompleteConsumer.cpp lib/Sema/SemaCodeComplete.cpp test/CodeCompletion/macros.c

Douglas Gregor dgregor at apple.com
Fri Oct 30 09:50:04 PDT 2009


Author: dgregor
Date: Fri Oct 30 11:50:04 2009
New Revision: 85594

URL: http://llvm.org/viewvc/llvm-project?rev=85594&view=rev
Log:
Include macros in code-completion results

Added:
    cfe/trunk/test/CodeCompletion/macros.c   (with props)
Modified:
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=85594&r1=85593&r2=85594&view=diff

==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Fri Oct 30 11:50:04 2009
@@ -26,6 +26,7 @@
 class FunctionDecl;
 class FunctionType;
 class FunctionTemplateDecl;
+class IdentifierInfo;
 class NamedDecl;
 class NestedNameSpecifier;
 class Sema;
@@ -150,7 +151,8 @@
     /// \brief Describes the kind of result generated.
     enum ResultKind {
       RK_Declaration = 0, //< Refers to a declaration
-      RK_Keyword          //< Refers to a keyword or symbol.
+      RK_Keyword,         //< Refers to a keyword or symbol.
+      RK_Macro            //< Refers to a macro
     };
     
     /// \brief The kind of result stored here.
@@ -164,6 +166,9 @@
       /// \brief When Kind == RK_Keyword, the string representing the keyword 
       /// or symbol's spelling.
       const char *Keyword;
+      
+      /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
+      IdentifierInfo *Macro;
     };
     
     /// \brief Describes how good this result is, with zero being the best
@@ -199,6 +204,12 @@
         QualifierIsInformative(0), StartsNestedNameSpecifier(false), 
         Qualifier(0) { }
     
+    /// \brief Build a result that refers to a macro.
+    Result(IdentifierInfo *Macro, unsigned Rank)
+     : Kind(RK_Macro), Macro(Macro), Rank(Rank), Hidden(false), 
+       QualifierIsInformative(0), StartsNestedNameSpecifier(false),
+       Qualifier(0) { }
+    
     /// \brief Retrieve the declaration stored in this result.
     NamedDecl *getDeclaration() const {
       assert(Kind == RK_Declaration && "Not a declaration result");

Modified: cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp?rev=85594&r1=85593&r2=85594&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp (original)
+++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Fri Oct 30 11:50:04 2009
@@ -156,6 +156,17 @@
     case Result::RK_Keyword:
       OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
       break;
+        
+    case Result::RK_Macro: {
+      OS << Results[I].Macro->getName() << " : " << Results[I].Rank;
+      if (CodeCompletionString *CCS 
+          = Results[I].CreateCodeCompletionString(SemaRef)) {
+        OS << " : " << CCS->getAsString();
+        delete CCS;
+      }
+      OS << '\n';
+      break;
+    }
     }
   }
   

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=85594&r1=85593&r2=85594&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Oct 30 11:50:04 2009
@@ -13,6 +13,8 @@
 #include "Sema.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include <list>
@@ -801,9 +803,45 @@
 /// result is all that is needed.
 CodeCompletionString *
 CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
-  if (Kind != RK_Declaration)
+  if (Kind == RK_Keyword)
     return 0;
   
+  if (Kind == RK_Macro) {
+    MacroInfo *MI = S.PP.getMacroInfo(Macro);
+    if (!MI || !MI->isFunctionLike())
+      return 0;
+    
+    // Format a function-like macro with placeholders for the arguments.
+    CodeCompletionString *Result = new CodeCompletionString;
+    Result->AddTextChunk(Macro->getName().str().c_str());
+    Result->AddTextChunk("(");
+    for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
+         A != AEnd; ++A) {
+      if (A != MI->arg_begin())
+        Result->AddTextChunk(", ");
+      
+      if (!MI->isVariadic() || A != AEnd - 1) {
+        // Non-variadic argument.
+        Result->AddPlaceholderChunk((*A)->getName().str().c_str());
+        continue;
+      }
+      
+      // Variadic argument; cope with the different between GNU and C99
+      // variadic macros, providing a single placeholder for the rest of the
+      // arguments.
+      if ((*A)->isStr("__VA_ARGS__"))
+        Result->AddPlaceholderChunk("...");
+      else {
+        std::string Arg = (*A)->getName();
+        Arg += "...";
+        Result->AddPlaceholderChunk(Arg.c_str());
+      }
+    }
+    Result->AddTextChunk(")");
+    return Result;
+  }
+  
+  assert(Kind == RK_Declaration && "Missed a macro kind?");
   NamedDecl *ND = Declaration;
   
   if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
@@ -999,6 +1037,10 @@
           
         case Result::RK_Keyword:
           return strcmp(X.Keyword, Y.Keyword) < 0;
+          
+        case Result::RK_Macro:
+          return llvm::LowercaseString(X.Macro->getName()) < 
+                   llvm::LowercaseString(Y.Macro->getName());
       }
       
       // Silence GCC warning.
@@ -1007,6 +1049,16 @@
   };
 }
 
+// Add all of the known macros as code-completion results.
+static void AddMacroResults(Preprocessor &PP, unsigned Rank, 
+                            ResultBuilder &Results) {
+  Results.EnterNewScope();
+  for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end();
+       M != MEnd; ++M)
+    Results.MaybeAddResult(CodeCompleteConsumer::Result(M->first, Rank));
+  Results.ExitScope();
+}
+
 static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
                                       CodeCompleteConsumer::Result *Results,
                                       unsigned NumResults) {
@@ -1019,8 +1071,9 @@
 
 void Sema::CodeCompleteOrdinaryName(Scope *S) {
   ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName);
-  CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext, 
-                       Results);
+  unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 
+                                           0, CurContext, Results);
+  AddMacroResults(PP, NextRank, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
 }
 
@@ -1076,6 +1129,9 @@
                            CurContext, Results);
     }
     
+    // Add macros
+    AddMacroResults(PP, NextRank, Results);
+    
     // Hand off the results found for code completion.
     HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
     
@@ -1117,10 +1173,11 @@
     // We could have the start of a nested-name-specifier. Add those
     // results as well.
     Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
-    CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank, 
-                         CurContext, Results);
+    NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 
+                                    NextRank, CurContext, Results);
   }
   
+  AddMacroResults(PP, NextRank, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
 }
 
@@ -1198,6 +1255,7 @@
   }
   Results.ExitScope();
   
+  AddMacroResults(PP, 1, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
 }
 
@@ -1292,6 +1350,7 @@
   if (!Results.empty() && NNS->isDependent())
     Results.MaybeAddResult(CodeCompleteConsumer::Result("template", NextRank));
   
+  AddMacroResults(PP, NextRank + 1, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
 }
 
@@ -1308,10 +1367,11 @@
   
   // After "using", we can see anything that would start a 
   // nested-name-specifier.
-  CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, 
-                       CurContext, Results);
+  unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 
+                                           0, CurContext, Results);
   Results.ExitScope();
   
+  AddMacroResults(PP, NextRank, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
 }
 
@@ -1323,9 +1383,10 @@
   // alias.
   ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
   Results.EnterNewScope();
-  CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
-                       Results);
+  unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 
+                                           0, CurContext, Results);
   Results.ExitScope();
+  AddMacroResults(PP, NextRank, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
 }
 
@@ -1360,6 +1421,7 @@
     Results.ExitScope();
   }
   
+  AddMacroResults(PP, 1, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
 }
 
@@ -1369,8 +1431,9 @@
   
   // After "namespace", we expect to see a namespace or alias.
   ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
-  CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
-                       Results);
+  unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 
+                                           0, CurContext, Results);
+  AddMacroResults(PP, NextRank, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
 }
 
@@ -1397,10 +1460,11 @@
   
   // Add any nested-name-specifiers
   Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
-  CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank + 1, 
-                       CurContext, Results);
+  NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 
+                                  NextRank + 1, CurContext, Results);
   Results.ExitScope();
   
+  AddMacroResults(PP, NextRank, Results);
   HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
 }
 

Added: cfe/trunk/test/CodeCompletion/macros.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/macros.c?rev=85594&view=auto

==============================================================================
--- cfe/trunk/test/CodeCompletion/macros.c (added)
+++ cfe/trunk/test/CodeCompletion/macros.c Fri Oct 30 11:50:04 2009
@@ -0,0 +1,37 @@
+#define FOO
+#define BAR(X, Y) X, Y
+#define IDENTITY(X) X
+#define WIBBLE(...)
+
+enum Color {
+  Red, Green, Blue
+};
+
+struct Point {
+  float x, y, z;
+  enum Color color;
+};
+
+void test(struct Point *p) {
+  // RUN: clang-cc -fsyntax-only -code-completion-at=%s:17:14 %s -o - | FileCheck -check-prefix=CC1 %s &&
+  switch (p->IDENTITY(color)) {
+  // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC2 %s &&
+    case 
+  }
+  // CC1: color
+  // CC1: x
+  // CC1: y
+  // CC1: z
+  // CC1: BAR(<#X#>, <#Y#>)
+  // CC1: FOO
+  // CC1: IDENTITY(<#X#>)
+  // CC1: WIBBLE
+  // CC2: Blue
+  // CC2: Green
+  // CC2: Red
+  // CC2: BAR(<#X#>, <#Y#>)
+  // CC2: FOO
+  // CC2: IDENTITY(<#X#>)
+  // CC2: WIBBLE
+  // RUN: true
+}

Propchange: cfe/trunk/test/CodeCompletion/macros.c

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CodeCompletion/macros.c

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CodeCompletion/macros.c

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list