]> granicus.if.org Git - clang/commitdiff
[CodeComplete] Report location of opening parens for signature help
authorIlya Biryukov <ibiryukov@google.com>
Thu, 30 Aug 2018 13:08:03 +0000 (13:08 +0000)
committerIlya Biryukov <ibiryukov@google.com>
Thu, 30 Aug 2018 13:08:03 +0000 (13:08 +0000)
Summary: Used in clangd.

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: ioeric, kadircet, cfe-commits

Differential Revision: https://reviews.llvm.org/D51436

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341063 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/CodeCompleteConsumer.h
include/clang/Sema/Sema.h
lib/Frontend/ASTUnit.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseOpenMP.cpp
lib/Sema/CodeCompleteConsumer.cpp
lib/Sema/SemaCodeComplete.cpp
test/CodeCompletion/paren_locs.cpp [new file with mode: 0644]
tools/libclang/CIndexCodeCompletion.cpp

index ede3ddf9199316df43ce5d05d840f70d7c2d072e..9a06fa813e58e036c73198f4b6b113af76bf36dc 100644 (file)
@@ -1114,9 +1114,13 @@ public:
   /// \param Candidates an array of overload candidates.
   ///
   /// \param NumCandidates the number of overload candidates
+  ///
+  /// \param OpenParLoc location of the opening parenthesis of the argument
+  ///        list.
   virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                          OverloadCandidate *Candidates,
-                                         unsigned NumCandidates) {}
+                                         unsigned NumCandidates,
+                                         SourceLocation OpenParLoc) {}
   //@}
 
   /// Retrieve the allocator that will be used to allocate
@@ -1166,7 +1170,8 @@ public:
 
   void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                  OverloadCandidate *Candidates,
-                                 unsigned NumCandidates) override;
+                                 unsigned NumCandidates,
+                                 SourceLocation OpenParLoc) override;
 
   bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override;
 
index 1a4199f1dbeacff0496034c05137f4e149861ebb..5f6cc515697bc8f8e1ad7d3a51c6ada5748ece2c 100644 (file)
@@ -10230,9 +10230,11 @@ public:
                                       const VirtSpecifiers *VS = nullptr);
   void CodeCompleteBracketDeclarator(Scope *S);
   void CodeCompleteCase(Scope *S);
-  void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args);
+  void CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args,
+                        SourceLocation OpenParLoc);
   void CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
-                               ArrayRef<Expr *> Args);
+                               ArrayRef<Expr *> Args,
+                               SourceLocation OpenParLoc);
   void CodeCompleteInitializer(Scope *S, Decl *D);
   void CodeCompleteReturn(Scope *S);
   void CodeCompleteAfterIf(Scope *S);
index 701f07f22e37f1017e465ccb6bbd547334047a11..b91870c291c5d56eb5d71f20c86182d1b1ea9faf 100644 (file)
@@ -1911,8 +1911,10 @@ namespace {
 
     void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                    OverloadCandidate *Candidates,
-                                   unsigned NumCandidates) override {
-      Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
+                                   unsigned NumCandidates,
+                                   SourceLocation OpenParLoc) override {
+      Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,
+                                     OpenParLoc);
     }
 
     CodeCompletionAllocator &getAllocator() override {
index 04c0286ec6d6ab16dff12bf12b7b84e95a6d56ee..5d780de8f553637fa3620e3df03254d5cceffbc3 100644 (file)
@@ -2304,7 +2304,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
     auto ConstructorCompleter = [&, ThisVarDecl] {
       Actions.CodeCompleteConstructor(
           getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
-          ThisDecl->getLocation(), Exprs);
+          ThisDecl->getLocation(), Exprs, T.getOpenLocation());
     };
     if (ThisVarDecl) {
       // ParseExpressionList can sometimes succeed even when ThisDecl is not
index d1d8507af8cfe05a07f7c5f68cb0427b58e7b381..39bf1c63981d1a4867ae169093c8151f100e2c5e 100644 (file)
@@ -1650,7 +1650,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
       CommaLocsTy CommaLocs;
 
       if (Tok.is(tok::code_completion)) {
-        Actions.CodeCompleteCall(getCurScope(), LHS.get(), None);
+        Actions.CodeCompleteCall(getCurScope(), LHS.get(), None,
+                                 PT.getOpenLocation());
         cutOffParsing();
         return ExprError();
       }
@@ -1658,8 +1659,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
       if (OpKind == tok::l_paren || !LHS.isInvalid()) {
         if (Tok.isNot(tok::r_paren)) {
           if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
-                Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
-             })) {
+                Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs,
+                                         PT.getOpenLocation());
+              })) {
             (void)Actions.CorrectDelayedTyposInExpr(LHS);
             LHS = ExprError();
           } else if (LHS.isInvalid()) {
index 4e27ca0cea51c8b1cfcb1a0ef6475958bb813625..fef01a4030f14ca74ed3fc3900f9601f42100ed0 100644 (file)
@@ -1687,7 +1687,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
       if (ParseExpressionList(Exprs, CommaLocs, [&] {
             Actions.CodeCompleteConstructor(
                 getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
-                DS.getEndLoc(), Exprs);
+                DS.getEndLoc(), Exprs, T.getOpenLocation());
           })) {
         SkipUntil(tok::r_paren, StopAtSemi);
         return ExprError();
@@ -2821,7 +2821,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
                                                        DeclaratorInfo).get();
             Actions.CodeCompleteConstructor(
                 getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
-                DeclaratorInfo.getEndLoc(), ConstructorArgs);
+                DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
       })) {
         SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
         return ExprError();
index a413e96a91e7cf6fc5d6b312a9caaef0530b82d6..c53eae3067e223cd2cf85b6bf86cd0756bc27b18 100644 (file)
@@ -415,11 +415,14 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
     ExprVector Exprs;
     CommaLocsTy CommaLocs;
 
-    if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
-          Actions.CodeCompleteConstructor(
-              getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
-              OmpPrivParm->getLocation(), Exprs);
-        })) {
+    SourceLocation LParLoc = T.getOpenLocation();
+    if (ParseExpressionList(
+            Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] {
+              Actions.CodeCompleteConstructor(
+                  getCurScope(),
+                  OmpPrivParm->getType()->getCanonicalTypeInternal(),
+                  OmpPrivParm->getLocation(), Exprs, LParLoc);
+            })) {
       Actions.ActOnInitializerError(OmpPrivParm);
       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
     } else {
index 8af54b993932f2fd8241a46bc46754ed66f65d59..c7d4fc4efa8711d431e729c5b38276ca1a6be44f 100644 (file)
@@ -20,8 +20,8 @@
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/IdentifierTable.h"
-#include "clang/Sema/Sema.h"
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Sema.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -29,6 +29,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cassert>
@@ -624,16 +625,17 @@ static std::string getOverloadAsString(const CodeCompletionString &CCS) {
   return OS.str();
 }
 
-void
-PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
-                                                        unsigned CurrentArg,
-                                              OverloadCandidate *Candidates,
-                                                     unsigned NumCandidates) {
+void PrintingCodeCompleteConsumer::ProcessOverloadCandidates(
+    Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates,
+    unsigned NumCandidates, SourceLocation OpenParLoc) {
+  OS << "OPENING_PAREN_LOC: ";
+  OpenParLoc.print(OS, SemaRef.getSourceManager());
+  OS << "\n";
+
   for (unsigned I = 0; I != NumCandidates; ++I) {
-    if (CodeCompletionString *CCS
-          = Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
-                                                getAllocator(), CCTUInfo,
-                                                includeBriefComments())) {
+    if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString(
+            CurrentArg, SemaRef, getAllocator(), CCTUInfo,
+            includeBriefComments())) {
       OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n";
     }
   }
index 30af826ef6cc0b1c07f34125fdaa9a69ae146bf1..e0adf38f93e94f61dd5bb2649bcc5882c744c88e 100644 (file)
@@ -4435,10 +4435,11 @@ static QualType getParamType(Sema &SemaRef,
   return ParamType;
 }
 
-static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
-                                    MutableArrayRef<ResultCandidate> Candidates,
-                                        unsigned CurrentArg,
-                                 bool CompleteExpressionWithCurrentArg = true) {
+static void
+CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
+                            MutableArrayRef<ResultCandidate> Candidates,
+                            unsigned CurrentArg, SourceLocation OpenParLoc,
+                            bool CompleteExpressionWithCurrentArg = true) {
   QualType ParamType;
   if (CompleteExpressionWithCurrentArg)
     ParamType = getParamType(SemaRef, Candidates, CurrentArg);
@@ -4449,12 +4450,12 @@ static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
     SemaRef.CodeCompleteExpression(S, ParamType);
 
   if (!Candidates.empty())
-    SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
-                                                     Candidates.data(),
-                                                     Candidates.size());
+    SemaRef.CodeCompleter->ProcessOverloadCandidates(
+        SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
 }
 
-void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
+void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args,
+                            SourceLocation OpenParLoc) {
   if (!CodeCompleter)
     return;
 
@@ -4552,12 +4553,13 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
   }
 
   mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
-  CodeCompleteOverloadResults(*this, S, Results, Args.size(),
+  CodeCompleteOverloadResults(*this, S, Results, Args.size(), OpenParLoc,
                               !CandidateSet.empty());
 }
 
 void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
-                                   ArrayRef<Expr *> Args) {
+                                   ArrayRef<Expr *> Args,
+                                   SourceLocation OpenParLoc) {
   if (!CodeCompleter)
     return;
 
@@ -4592,7 +4594,7 @@ void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
 
   SmallVector<ResultCandidate, 8> Results;
   mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
-  CodeCompleteOverloadResults(*this, S, Results, Args.size());
+  CodeCompleteOverloadResults(*this, S, Results, Args.size(), OpenParLoc);
 }
 
 void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
diff --git a/test/CodeCompletion/paren_locs.cpp b/test/CodeCompletion/paren_locs.cpp
new file mode 100644 (file)
index 0000000..303264c
--- /dev/null
@@ -0,0 +1,33 @@
+void foo(int a, int b);
+void foo(int a, int b, int c);
+
+void test() {
+  foo(10, );
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:10 %s -o - \
+  // RUN: | FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:5:6
+
+#define FOO foo(
+  FOO 10, );
+#undef FOO
+  // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:11:10 %s -o - \
+  // RUN: | FileCheck -check-prefix=CHECK-CC2 %s
+  // CHECK-CC2: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:11:3
+
+  struct Foo {
+    Foo(int a, int b);
+    Foo(int a, int b, int c);
+  };
+  Foo a(10, );
+  // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:21:12 %s -o - \
+  // RUN: | FileCheck -check-prefix=CHECK-CC3 %s
+  // CHECK-CC3: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:21:8
+  Foo(10, );
+  // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:25:10 %s -o - \
+  // RUN: | FileCheck -check-prefix=CHECK-CC4 %s
+  // CHECK-CC4: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:25:6
+  new Foo(10, );
+  // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:29:15 %s -o - \
+  // RUN: | FileCheck -check-prefix=CHECK-CC5 %s
+  // CHECK-CC5: OPENING_PAREN_LOC: {{.*}}paren_locs.cpp:29:10
+}
index f49f9763c362a698a85eb2c12ef132af47df3f91..766745ddea18e8e72e2109ce171a4b579176f2e3 100644 (file)
@@ -653,7 +653,8 @@ namespace {
 
     void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                    OverloadCandidate *Candidates,
-                                   unsigned NumCandidates) override {
+                                   unsigned NumCandidates,
+                                   SourceLocation OpenParLoc) override {
       StoredResults.reserve(StoredResults.size() + NumCandidates);
       for (unsigned I = 0; I != NumCandidates; ++I) {
         CodeCompletionString *StoredCompletion