Index: clangd/CodeComplete.cpp =================================================================== --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -792,9 +792,19 @@ Allocator(std::make_shared()), CCTUInfo(Allocator), Index(Index) {} - void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, - OverloadCandidate *Candidates, - unsigned NumCandidates) override { + void ProcessOverloadCandidates( + Sema &S, unsigned CurrentArg, OverloadCandidate *Candidates, + unsigned NumCandidates, + SourceLocation OpenParLoc) override { + assert(!OpenParLoc.isInvalid()); + SourceManager &SrcMgr = S.getSourceManager(); + OpenParLoc = SrcMgr.getFileLoc(OpenParLoc); + if (SrcMgr.isInMainFile(OpenParLoc)) + SigHelp.argListStart = sourceLocToPosition(SrcMgr, OpenParLoc); + else + elog("Location oustide main file in signature help: {0}", + OpenParLoc.printToString(SrcMgr)); + std::vector ScoredSignatures; SigHelp.signatures.reserve(NumCandidates); ScoredSignatures.reserve(NumCandidates); Index: clangd/Protocol.h =================================================================== --- clangd/Protocol.h +++ clangd/Protocol.h @@ -828,6 +828,11 @@ /// The active parameter of the active signature. int activeParameter = 0; + + /// Position of the opening paren of the argument list. + /// This is a clangd-specific extension, it is only available via C++ API and + /// not currently serialized for the LSP. + Position argListStart; }; llvm::json::Value toJSON(const SignatureHelp &); Index: unittests/clangd/CodeCompleteTests.cpp =================================================================== --- unittests/clangd/CodeCompleteTests.cpp +++ unittests/clangd/CodeCompleteTests.cpp @@ -825,8 +825,7 @@ EXPECT_TRUE(Results.Completions.empty()); } - -SignatureHelp signatures(StringRef Text, +SignatureHelp signatures(StringRef Text, Position Point, std::vector IndexSymbols = {}) { std::unique_ptr Index; if (!IndexSymbols.empty()) @@ -840,9 +839,14 @@ ClangdServer Server(CDB, FS, DiagConsumer, Opts); auto File = testPath("foo.cpp"); + runAddDocument(Server, File, Text); + return cantFail(runSignatureHelp(Server, File, Point)); +} + +SignatureHelp signatures(StringRef Text, + std::vector IndexSymbols = {}) { Annotations Test(Text); - runAddDocument(Server, File, Test.code()); - return cantFail(runSignatureHelp(Server, File, Test.point())); + return signatures(Test.code(), Test.point(), std::move(IndexSymbols)); } MATCHER_P(ParamsAre, P, "") { @@ -907,6 +911,38 @@ EXPECT_EQ(1, Results.activeParameter); } +TEST(SignatureHelpTest, OpeningParen) { + Annotations Code(R"cpp( + int foo(int a, int b, int c); + struct Foo { + Foo(int a, int b, int c); + }; + int main() { + // Check recursive functions. + foo(foo $par1^( foo(10, 10, 10), $pos1^ ))); + // Types. + Foo $par2^( 10, $pos2^ ); + // new experssions. + new Foo $par3^( 10, $pos3^ ); + + // Macro expansions. + #define FOO foo( + $par4^FOO 10, $pos4^ ); + + // Macro arguments. + #define ID(X) X + ID(foo $par5^( foo(10), $pos5^ )) + } + )cpp"); + + for (int Test = 1; Test <=5; ++Test) { + EXPECT_EQ( + signatures(Code.code(), Code.point("pos" + itostr(Test))).argListStart, + Code.point("par" + itostr(Test))) + << "for test number " << Test; + } +} + class IndexRequestCollector : public SymbolIndex { public: bool