From 56ff871ae74b1edccff44efe296f3167d694ce48 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 18 Sep 2009 22:47:56 +0000 Subject: [PATCH] Introduce code completion patterns for templates, which provide the angle brackets < > along with placeholder template arguments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82304 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/CodeCompleteConsumer.cpp | 88 +++++++++++++++++++++++++++++++ test/CodeCompletion/templates.cpp | 17 ++++++ 2 files changed, 105 insertions(+) create mode 100644 test/CodeCompletion/templates.cpp diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 9bf9e15253..2c682ebbfc 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -762,6 +762,71 @@ static void AddFunctionParameterChunks(ASTContext &Context, } } +/// \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(*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(*P)) { + if (NTTP->getIdentifier()) + PlaceholderStr = NTTP->getIdentifier()->getName(); + NTTP->getType().getAsStringInternal(PlaceholderStr, + Context.PrintingPolicy); + HasDefaultArg = NTTP->hasDefaultArgument(); + } else { + assert(isa(*P)); + TemplateTemplateParmDecl *TTP = cast(*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(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 @@ CodeCompleteConsumer::CreateCodeCompletionString(Result R) { return Result; } + if (FunctionTemplateDecl *FunTmpl = dyn_cast(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(ND)) { + CodeCompletionString *Result = new CodeCompletionString; + Result->AddTextChunk(Template->getNameAsString().c_str()); + Result->AddTextChunk("<"); + AddTemplateParameterChunks(getSema().Context, Template, Result); + Result->AddTextChunk(">"); + return Result; + } + return 0; } diff --git a/test/CodeCompletion/templates.cpp b/test/CodeCompletion/templates.cpp new file mode 100644 index 0000000000..f7751413b9 --- /dev/null +++ b/test/CodeCompletion/templates.cpp @@ -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 + class allocator; + + template > + class vector; +} + +void f() { + // CHECK-CC1: allocator<<#typename T#>> + // CHECK-CC1: vector<<#typename T#>{#, <#typename Alloc#>#}> + std:: + + -- 2.40.0