]> granicus.if.org Git - clang/commitdiff
Avoid printing some redundant name qualifiers in completion
authorIlya Biryukov <ibiryukov@google.com>
Wed, 8 Nov 2017 10:39:09 +0000 (10:39 +0000)
committerIlya Biryukov <ibiryukov@google.com>
Wed, 8 Nov 2017 10:39:09 +0000 (10:39 +0000)
Summary:
Adjusted PrintingPolicy inside code completion to avoid printing some
redundant name qualifiers.

Before this change, typedefs that were written unqualified in source
code were printed with qualifiers in completion. For example, in the
following code

    struct foo {
        typedef int type;
        type method();
    };

completion item for `method` had return type of `foo::type`, even
though the original code used `type` without qualifiers.
After this change, the completion item has return type `type`, as
originally written in the source code.

Note that this change does not suppress qualifiers written by the
user. For example, in the following code

    typedef int type;
    struct foo {
        typedef int type;
        ::type method(foo::type);
    };

completion item for `method` has return type of `::type` and
parameter type of `foo::type`, as originally written in the source
code.

Reviewers: arphaman, bkramer, klimek

Reviewed By: arphaman

Subscribers: mgorny, eraman, cfe-commits

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

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

lib/Sema/SemaCodeComplete.cpp
test/CodeCompletion/call.cpp
test/CodeCompletion/qualifiers-as-written.cpp [new file with mode: 0644]
test/CodeCompletion/uninstantiated_params.cpp
test/Index/complete-cxx-inline-methods.cpp

index 72ab65fc58ce0a27a3ee7a7feecc74e1a4a75b23..26004cf3c36e1c0fa0318f0ff72dc84ea524f729 100644 (file)
@@ -14,6 +14,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
+#include "clang/AST/QualTypeNames.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/MacroInfo.h"
@@ -1495,6 +1496,7 @@ static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
   Policy.AnonymousTagLocations = false;
   Policy.SuppressStrongLifetime = true;
   Policy.SuppressUnwrittenScope = true;
+  Policy.SuppressScope = true;
   return Policy;
 }
 
@@ -2139,9 +2141,10 @@ static void AddResultTypeChunk(ASTContext &Context,
       T = Method->getSendResultType(BaseType);
     else
       T = Method->getReturnType();
-  } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+  } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
     T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
-  else if (isa<UnresolvedUsingValueDecl>(ND)) {
+    T = clang::TypeName::getFullyQualifiedType(T, Context);
+  } else if (isa<UnresolvedUsingValueDecl>(ND)) {
     /* Do nothing: ignore unresolved using declarations*/
   } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
     if (!BaseType.isNull())
index 40a72ba83602258469d30c05966bbf27ef2739fc..3e062109a9aa4f5339eb306081e11553878418e8 100644 (file)
@@ -19,10 +19,10 @@ void test() {
   f(Y(), 0, 0);
   // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
   // CHECK-CC1: COMPLETION: Pattern : dynamic_cast<<#type#>>(<#expression#>)
-  // CHECK-CC1: f(N::Y y, <#int ZZ#>)
+  // CHECK-CC1: f(Y y, <#int ZZ#>)
   // CHECK-CC1-NEXT: f(int i, <#int j#>, int k)
   // CHECK-CC1-NEXT: f(float x, <#float y#>)
   // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:13 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
-  // CHECK-CC2-NOT: f(N::Y y, int ZZ)
+  // CHECK-CC2-NOT: f(Y y, int ZZ)
   // CHECK-CC2: f(int i, int j, <#int k#>)
 }
diff --git a/test/CodeCompletion/qualifiers-as-written.cpp b/test/CodeCompletion/qualifiers-as-written.cpp
new file mode 100644 (file)
index 0000000..e600267
--- /dev/null
@@ -0,0 +1,30 @@
+struct foo {
+  typedef int type;
+
+  type method(type, foo::type, ::foo::type, ::foo::foo::type);
+};
+
+namespace ns {
+  struct bar {
+  };
+
+  struct baz {
+  };
+
+  int func(foo::type a, bar b, baz c);
+}
+
+typedef ns::bar bar;
+
+int func(foo a, bar b, ns::bar c, ns::baz d);
+using ns::func;
+
+void test() {
+  foo().method(0, 0, 0, 0);
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:9 %s -o - | FileCheck %s --check-prefix=CHECK-1
+  // CHECK-1: COMPLETION: method : [#type#]method(<#type#>, <#foo::type#>, <#::foo::type#>, <#::foo::foo::type#>)
+  f
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:26:3 %s -o - | FileCheck %s --check-prefix=CHECK-2
+  // CHECK-2: COMPLETION: func : [#int#]func(<#foo a#>, <#bar b#>, <#ns::bar c#>, <#ns::baz d#>
+  // CHECK-2: COMPLETION: func : [#int#]func(<#foo::type a#>, <#bar b#>, <#baz c#>
+}
index 57a520dd5712e9fec491b6927e5ce9e0f5a5ad10..643f2f72553b1c3b15b4afc2db14ba1afd84c114 100644 (file)
@@ -9,5 +9,5 @@ void test() {
   unique_ptr<int> x;
   x.
   // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:5 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
-  // CHECK-CC1: [#void#]reset({#<#unique_ptr<int>::pointer ptr = pointer()#>#})
+  // CHECK-CC1: [#void#]reset({#<#pointer ptr = pointer()#>#})
 }
index c0a4a8d75c6d580f3ce828d5d6974616fbe6d9a8..0f78e8caa748c51484354daa98925939967bd130 100644 (file)
@@ -25,7 +25,7 @@ private:
 
 // RUN: c-index-test -code-completion-at=%s:4:9 -std=c++98 %s | FileCheck %s
 // RUN: c-index-test -code-completion-at=%s:13:7 -std=c++98 %s | FileCheck %s
-// CHECK:      CXXMethod:{ResultType MyCls::Vec &}{TypedText operator=}{LeftParen (}{Placeholder const MyCls::Vec &}{RightParen )} (79)
+// CHECK:      CXXMethod:{ResultType Vec &}{TypedText operator=}{LeftParen (}{Placeholder const Vec &}{RightParen )} (79)
 // CHECK-NEXT: StructDecl:{TypedText Vec}{Text ::} (75)
 // CHECK-NEXT: FieldDecl:{ResultType int}{TypedText x} (35)
 // CHECK-NEXT: FieldDecl:{ResultType int}{TypedText y} (35)