[cfe-commits] r82304 - in /cfe/trunk: lib/Sema/CodeCompleteConsumer.cpp test/CodeCompletion/templates.cpp

Douglas Gregor dgregor at apple.com
Fri Sep 18 15:47:56 PDT 2009


Author: dgregor
Date: Fri Sep 18 17:47:56 2009
New Revision: 82304

URL: http://llvm.org/viewvc/llvm-project?rev=82304&view=rev
Log:
Introduce code completion patterns for templates, which provide the
angle brackets < > along with placeholder template arguments.

Added:
    cfe/trunk/test/CodeCompletion/templates.cpp   (with props)
Modified:
    cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp (original)
+++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Fri Sep 18 17:47:56 2009
@@ -762,6 +762,71 @@
   }
 }
 
+/// \brief Add template parameter chunks to the given code completion string.
+static void AddTemplateParameterChunks(ASTContext &Context,
+                                       TemplateDecl *Template,
+                                       CodeCompletionString *Result) {
+  CodeCompletionString *CCStr = Result;
+  bool FirstParameter = true;
+  
+  TemplateParameterList *Params = Template->getTemplateParameters();
+  for (TemplateParameterList::iterator P = Params->begin(), 
+                                    PEnd = Params->end();
+       P != PEnd; ++P) {
+    bool HasDefaultArg = false;
+    std::string PlaceholderStr;
+    if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
+      if (TTP->wasDeclaredWithTypename())
+        PlaceholderStr = "typename";
+      else
+        PlaceholderStr = "class";
+      
+      if (TTP->getIdentifier()) {
+        PlaceholderStr += ' ';
+        PlaceholderStr += TTP->getIdentifier()->getName();
+      }
+      
+      HasDefaultArg = TTP->hasDefaultArgument();
+    } else if (NonTypeTemplateParmDecl *NTTP 
+                 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+      if (NTTP->getIdentifier())
+        PlaceholderStr = NTTP->getIdentifier()->getName();
+      NTTP->getType().getAsStringInternal(PlaceholderStr, 
+                                          Context.PrintingPolicy);
+      HasDefaultArg = NTTP->hasDefaultArgument();
+    } else {
+      assert(isa<TemplateTemplateParmDecl>(*P));
+      TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+      
+      // Since putting the template argument list into the placeholder would
+      // be very, very long, we just use an abbreviation.
+      PlaceholderStr = "template<...> class";
+      if (TTP->getIdentifier()) {
+        PlaceholderStr += ' ';
+        PlaceholderStr += TTP->getIdentifier()->getName();
+      }
+      
+      HasDefaultArg = TTP->hasDefaultArgument();
+    }
+    
+    if (HasDefaultArg) {
+      // When we see an optional default argument, put that argument and
+      // the remaining default arguments into a new, optional string.
+      CodeCompletionString *Opt = new CodeCompletionString;
+      CCStr->AddOptionalChunk(std::auto_ptr<CodeCompletionString>(Opt));
+      CCStr = Opt;
+    }
+    
+    if (FirstParameter)
+      FirstParameter = false;
+    else
+      CCStr->AddTextChunk(", ");
+    
+    // Add the placeholder string.
+    CCStr->AddPlaceholderChunk(PlaceholderStr.c_str());
+  }    
+}
+
 /// \brief If possible, create a new code completion string for the given
 /// result.
 ///
@@ -784,6 +849,29 @@
     return Result;
   }
   
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
+    // FIXME: We treat these like functions for now, but it would be far
+    // better if we computed the template parameters that are non-deduced from
+    // a call, then printed only those template parameters in "<...>" before
+    // printing the function call arguments.
+    CodeCompletionString *Result = new CodeCompletionString;
+    FunctionDecl *Function = FunTmpl->getTemplatedDecl();
+    Result->AddTextChunk(Function->getNameAsString().c_str());
+    Result->AddTextChunk("(");
+    AddFunctionParameterChunks(getSema().Context, Function, Result);
+    Result->AddTextChunk(")");
+    return Result;
+  }
+  
+  if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
+    CodeCompletionString *Result = new CodeCompletionString;
+    Result->AddTextChunk(Template->getNameAsString().c_str());
+    Result->AddTextChunk("<");
+    AddTemplateParameterChunks(getSema().Context, Template, Result);
+    Result->AddTextChunk(">");
+    return Result;
+  }
+  
   return 0;
 }
 

Added: cfe/trunk/test/CodeCompletion/templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/templates.cpp?rev=82304&view=auto

==============================================================================
--- cfe/trunk/test/CodeCompletion/templates.cpp (added)
+++ cfe/trunk/test/CodeCompletion/templates.cpp Fri Sep 18 17:47:56 2009
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -code-completion-dump=1 %s -o - | FileCheck -check-prefix=CC1 %s &&
+// RUN: true
+
+namespace std {
+  template<typename T>
+  class allocator;
+  
+  template<typename T, typename Alloc = std::allocator<T> >
+  class vector;
+}
+
+void f() {
+  // CHECK-CC1: allocator<<#typename T#>>
+  // CHECK-CC1: vector<<#typename T#>{#, <#typename Alloc#>#}>
+  std::
+
+

Propchange: cfe/trunk/test/CodeCompletion/templates.cpp

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

Propchange: cfe/trunk/test/CodeCompletion/templates.cpp

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

Propchange: cfe/trunk/test/CodeCompletion/templates.cpp

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





More information about the cfe-commits mailing list