diff options
author | Sam McCall <sam.mccall@gmail.com> | 2021-12-29 04:16:47 +0100 |
---|---|---|
committer | Sam McCall <sam.mccall@gmail.com> | 2022-01-03 16:28:16 +0100 |
commit | cd45e8c7bc16dec2eeec9cc71eb3ba87d1bd6bab (patch) | |
tree | 3db9bfda04d2f78dc9bf0067bc2b4ebf56c9258a /clang/lib/Parse/ParseTemplate.cpp | |
parent | 3a33c0b1ce0db465c9d85c493674efc6c5005dbe (diff) | |
download | llvm-cd45e8c7bc16dec2eeec9cc71eb3ba87d1bd6bab.zip llvm-cd45e8c7bc16dec2eeec9cc71eb3ba87d1bd6bab.tar.gz llvm-cd45e8c7bc16dec2eeec9cc71eb3ba87d1bd6bab.tar.bz2 |
[CodeCompletion] Signature help for template argument lists
Provide signature while typing template arguments: Foo< ^here >
Here the parameters are e.g. "typename x", and the result type is e.g.
"struct" (class template) or "int" (variable template) or "bool (std::string)"
(function template).
Multiple overloads are possible when a template name is used for several
overloaded function templates.
Fixes https://github.com/clangd/clangd/issues/299
Differential Revision: https://reviews.llvm.org/D116352
Diffstat (limited to 'clang/lib/Parse/ParseTemplate.cpp')
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 45af61a..204b534 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -1222,7 +1222,6 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation LAngleLoc, return false; } - /// Parses a template-id that after the template name has /// already been parsed. /// @@ -1234,11 +1233,13 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation LAngleLoc, /// token that forms the template-id. Otherwise, we will leave the /// last token in the stream (e.g., so that it can be replaced with an /// annotation token). -bool -Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, - SourceLocation &LAngleLoc, - TemplateArgList &TemplateArgs, - SourceLocation &RAngleLoc) { +/// +/// \param NameHint is not required, and merely affects code completion. +bool Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, + SourceLocation &LAngleLoc, + TemplateArgList &TemplateArgs, + SourceLocation &RAngleLoc, + TemplateTy Template) { assert(Tok.is(tok::less) && "Must have already parsed the template-name"); // Consume the '<'. @@ -1251,7 +1252,7 @@ Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, if (!Tok.isOneOf(tok::greater, tok::greatergreater, tok::greatergreatergreater, tok::greaterequal, tok::greatergreaterequal)) - Invalid = ParseTemplateArgumentList(TemplateArgs); + Invalid = ParseTemplateArgumentList(TemplateArgs, Template, LAngleLoc); if (Invalid) { // Try to find the closing '>'. @@ -1332,8 +1333,8 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, TemplateArgList TemplateArgs; bool ArgsInvalid = false; if (!TypeConstraint || Tok.is(tok::less)) { - ArgsInvalid = ParseTemplateIdAfterTemplateName(false, LAngleLoc, - TemplateArgs, RAngleLoc); + ArgsInvalid = ParseTemplateIdAfterTemplateName( + false, LAngleLoc, TemplateArgs, RAngleLoc, Template); // If we couldn't recover from invalid arguments, don't form an annotation // token -- we don't know how much to annotate. // FIXME: This can lead to duplicate diagnostics if we retry parsing this @@ -1585,19 +1586,34 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { /// template-argument-list: [C++ 14.2] /// template-argument /// template-argument-list ',' template-argument -bool -Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { +/// +/// \param Template is only used for code completion, and may be null. +bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs, + TemplateTy Template, + SourceLocation OpenLoc) { ColonProtectionRAIIObject ColonProtection(*this, false); + auto RunSignatureHelp = [&] { + if (!Template) + return QualType(); + CalledSignatureHelp = true; + return Actions.ProduceTemplateArgumentSignatureHelp(Template, TemplateArgs, + OpenLoc); + }; + do { + PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); ParsedTemplateArgument Arg = ParseTemplateArgument(); SourceLocation EllipsisLoc; if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc); - if (Arg.isInvalid()) + if (Arg.isInvalid()) { + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) + RunSignatureHelp(); return true; + } // Save this template argument. TemplateArgs.push_back(Arg); |