]> granicus.if.org Git - clang/commitdiff
[CodeComplete] Penalize inherited ObjC properties for auto-completion
authorSam McCall <sam.mccall@gmail.com>
Tue, 20 Nov 2018 22:06:54 +0000 (22:06 +0000)
committerSam McCall <sam.mccall@gmail.com>
Tue, 20 Nov 2018 22:06:54 +0000 (22:06 +0000)
Summary:
Similar to auto-completion for ObjC methods, inherited properties
should be penalized / direct class and category properties should
be prioritized.

Note that currently, the penalty for using a result from a base class
(CCD_InBaseClass) is equal to the penalty for using a method as a
property (CCD_MethodAsProperty).

Reviewers: jkorous, sammccall, akyrtzi, arphaman, benlangmuir

Reviewed By: sammccall, akyrtzi

Subscribers: arphaman, cfe-commits

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

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

lib/Sema/SemaCodeComplete.cpp
test/CodeCompletion/objc-protocol-member-access.m
test/Index/complete-block-properties.m
test/Index/complete-block-property-assignment.m
test/Index/complete-member-access.m
test/Index/complete-properties.m

index 95714852c16e70accf07d4536b7ee8236071d4d6..a2d274827437e22a04cd4ba0639a2a2e0e1156f7 100644 (file)
@@ -3958,7 +3958,8 @@ static void AddObjCProperties(
     const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
     bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
     AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
-    bool IsBaseExprStatement = false, bool IsClassProperty = false) {
+    bool IsBaseExprStatement = false, bool IsClassProperty = false,
+    bool InOriginalClass = true) {
   typedef CodeCompletionResult Result;
 
   // Retrieve the definition.
@@ -3973,8 +3974,10 @@ static void AddObjCProperties(
     // expressions.
     if (!P->getType().getTypePtr()->isBlockPointerType() ||
         !IsBaseExprStatement) {
-      Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
-                             CurContext);
+      Result R = Result(P, Results.getBasePriority(P), nullptr);
+      if (!InOriginalClass)
+        setInBaseClass(R);
+      Results.MaybeAddResult(R, CurContext);
       return;
     }
 
@@ -3985,8 +3988,10 @@ static void AddObjCProperties(
     findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
                                  BlockProtoLoc);
     if (!BlockLoc) {
-      Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
-                             CurContext);
+      Result R = Result(P, Results.getBasePriority(P), nullptr);
+      if (!InOriginalClass)
+        setInBaseClass(R);
+      Results.MaybeAddResult(R, CurContext);
       return;
     }
 
@@ -3997,9 +4002,10 @@ static void AddObjCProperties(
     AddObjCBlockCall(Container->getASTContext(),
                      getCompletionPrintingPolicy(Results.getSema()), Builder, P,
                      BlockLoc, BlockProtoLoc);
-    Results.MaybeAddResult(
-        Result(Builder.TakeString(), P, Results.getBasePriority(P)),
-        CurContext);
+    Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
+    if (!InOriginalClass)
+      setInBaseClass(R);
+    Results.MaybeAddResult(R, CurContext);
 
     // Provide additional block setter completion iff the base expression is a
     // statement and the block property is mutable.
@@ -4025,13 +4031,15 @@ static void AddObjCProperties(
       // otherwise the setter completion should show up before the default
       // property completion, as we normally want to use the result of the
       // call.
-      Results.MaybeAddResult(
+      Result R =
           Result(Builder.TakeString(), P,
                  Results.getBasePriority(P) +
                      (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
                           ? CCD_BlockPropertySetter
-                          : -CCD_BlockPropertySetter)),
-          CurContext);
+                          : -CCD_BlockPropertySetter));
+      if (!InOriginalClass)
+        setInBaseClass(R);
+      Results.MaybeAddResult(R, CurContext);
     }
   };
 
@@ -4059,10 +4067,11 @@ static void AddObjCProperties(
       AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
       Builder.AddTypedTextChunk(
           Results.getAllocator().CopyString(Name->getName()));
-      Results.MaybeAddResult(
-          Result(Builder.TakeString(), M,
-                 CCP_MemberDeclaration + CCD_MethodAsProperty),
-          CurContext);
+      Result R = Result(Builder.TakeString(), M,
+                        CCP_MemberDeclaration + CCD_MethodAsProperty);
+      if (!InOriginalClass)
+        setInBaseClass(R);
+      Results.MaybeAddResult(R, CurContext);
     };
 
     if (IsClassProperty) {
@@ -4088,34 +4097,39 @@ static void AddObjCProperties(
     for (auto *P : Protocol->protocols())
       AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
                         CurContext, AddedProperties, Results,
-                        IsBaseExprStatement, IsClassProperty);
+                        IsBaseExprStatement, IsClassProperty,
+                        /*InOriginalClass*/false);
   } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
     if (AllowCategories) {
       // Look through categories.
       for (auto *Cat : IFace->known_categories())
         AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
                           CurContext, AddedProperties, Results,
-                          IsBaseExprStatement, IsClassProperty);
+                          IsBaseExprStatement, IsClassProperty,
+                          InOriginalClass);
     }
 
     // Look through protocols.
     for (auto *I : IFace->all_referenced_protocols())
       AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
                         CurContext, AddedProperties, Results,
-                        IsBaseExprStatement, IsClassProperty);
+                        IsBaseExprStatement, IsClassProperty,
+                        /*InOriginalClass*/false);
 
     // Look in the superclass.
     if (IFace->getSuperClass())
       AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
                         AllowNullaryMethods, CurContext, AddedProperties,
-                        Results, IsBaseExprStatement, IsClassProperty);
+                        Results, IsBaseExprStatement, IsClassProperty,
+                        /*InOriginalClass*/false);
   } else if (const ObjCCategoryDecl *Category
                                     = dyn_cast<ObjCCategoryDecl>(Container)) {
     // Look through protocols.
     for (auto *P : Category->protocols())
       AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
                         CurContext, AddedProperties, Results,
-                        IsBaseExprStatement, IsClassProperty);
+                        IsBaseExprStatement, IsClassProperty,
+                        /*InOriginalClass*/false);
   }
 }
 
@@ -4249,7 +4263,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
       for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
         AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
                           CurContext, AddedProperties, Results,
-                          IsBaseExprStatement);
+                          IsBaseExprStatement, /*IsClassProperty*/false,
+                          /*InOriginalClass*/false);
     } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
                (!IsArrow && BaseType->isObjCObjectType())) {
       // Objective-C instance variable access.
index 0ed55387e3d666a7ab2d0947de6c0e3c78c51d08..9e769d5afa86cb50884195f9c27e10165f860fba 100644 (file)
@@ -19,6 +19,6 @@ int getFoo(id object) {
 }
 
 // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:17:25 %s -o - | FileCheck %s
-// CHECK: bar : [#int#]bar
-// CHECK: foo : [#int#]foo
+// CHECK: bar (InBase) : [#int#]bar
+// CHECK: foo (InBase) : [#int#]foo
 // CHECK-NOT: foobar
index a754712e4c998667133e5e2c4596836dac53b73d..0e8872dece23ea341c414c5a8acce711b09b21cb 100644 (file)
@@ -40,15 +40,15 @@ typedef int (^BarBlock)(int *);
 // RUN: c-index-test -code-completion-at=%s:35:33 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // RUN: c-index-test -code-completion-at=%s:36:21 %s | FileCheck -check-prefix=CHECK-CC1 %s
 //CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText barBlock}{LeftParen (}{Placeholder int *}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText block}{LeftParen (}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)()}{TypedText block}{Equal  = }{Placeholder ^(void)} (38)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo}{TypedText blocker}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder Foo y}{Comma , }{Placeholder ^(Foo *someParameter)foo}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo (^)(int, Foo, FooBlock)}{TypedText blocker}{Equal  = }{Placeholder ^Foo(int x, Foo y, FooBlock foo)} (32)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText block}{LeftParen (}{RightParen )} (37)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)()}{TypedText block}{Equal  = }{Placeholder ^(void)} (40)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo}{TypedText blocker}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder Foo y}{Comma , }{Placeholder ^(Foo *someParameter)foo}{RightParen )} (37)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo (^)(int, Foo, FooBlock)}{TypedText blocker}{Equal  = }{Placeholder ^Foo(int x, Foo y, FooBlock foo)} (34)
 //CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 //CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText fooBlock}{LeftParen (}{Placeholder Foo *someParameter}{RightParen )} (35)
 //CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Test *}{TypedText getObject}{LeftParen (}{Placeholder int index}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performA}{LeftParen (}{RightParen )} (35)
-//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performB}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder int y}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performA}{LeftParen (}{RightParen )} (37)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performB}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder int y}{RightParen )} (37)
 
 @end
 
index 48b6aea3a6750244a144c69acda1ba4e8c1415a9..c1abc03ad06dc37a3a848a04cfc92bbb24c6f2ec 100644 (file)
@@ -34,10 +34,10 @@ typedef void (^FooBlock)(Foo *someParameter);
 // RUN: c-index-test -code-completion-at=%s:28:27 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // RUN: c-index-test -code-completion-at=%s:29:22 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // RUN: c-index-test -code-completion-at=%s:30:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (37)
 // CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
-// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onAction}{LeftParen (}{Placeholder Obj *object}{RightParen )} (35)
-// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction}{Equal  = }{Placeholder ^(Obj *object)} (38)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onAction}{LeftParen (}{Placeholder Obj *object}{RightParen )} (37)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction}{Equal  = }{Placeholder ^(Obj *object)} (40)
 // CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onEventHandler}{LeftParen (}{Placeholder Foo *someParameter}{RightParen )} (35)
 // CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler}{Equal  = }{Placeholder ^(Foo *someParameter)} (38)
 // CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onReadonly}{LeftParen (}{Placeholder int *someParameter}{RightParen )} (35)
@@ -61,17 +61,17 @@ typedef void (^FooBlock)(Foo *someParameter);
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
-// CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (37)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
-// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (37)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
 
 // RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
-// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (37)
 // CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
-// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (37)
 // CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
 // CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
 // CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
index 5e40be1eac013f0e156342c9caad89ffa1ebf765..0248cd1fabc19aae2f563131064da673539d6bc6 100644 (file)
@@ -61,8 +61,8 @@ int test_two_levels(Other *other) {
 // RUN: c-index-test -code-completion-at=%s:34:12 %s | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: ObjCInstanceMethodDecl:{ResultType int}{TypedText myOtherPropLikeThing} (37)
 // CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText myProp} (35)
-// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (35)
-// CHECK-CC3: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (35)
+// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (37)
+// CHECK-CC3: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (37)
 // CHECK-CC3: Completion contexts:
 // CHECK-CC3-NEXT: Objective-C property access
 // CHECK-CC3-NEXT: Container Kind: ObjCInterfaceDecl
@@ -72,6 +72,6 @@ int test_two_levels(Other *other) {
 // RUN: c-index-test -code-completion-at=%s:42:20 %s | FileCheck -check-prefix=CHECK-CC4 %s
 // CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText myOtherPropLikeThing} (37)
 // CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText myProp} (35)
-// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (35)
-// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (35)
+// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (37)
+// CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (37)
 
index 0c49819ac2a7e508b78fb891fe77dca59b5eedfd..7dd4f1c9afb0fe98317712906c4c98a6d12bf5fe 100644 (file)
@@ -77,11 +77,11 @@ id test(I3 *i3) {
 // CHECK-CC4-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop4}
 
 // RUN: c-index-test -code-completion-at=%s:29:13 %s | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5: ObjCPropertyDecl:{ResultType int}{TypedText Prop0} (35)
-// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText Prop1} (35)
-// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType float}{TypedText Prop2} (35)
+// CHECK-CC5: ObjCPropertyDecl:{ResultType int}{TypedText Prop0} (37)
+// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText Prop1} (37)
+// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType float}{TypedText Prop2} (37)
 // CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop3} (35)
-// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop4} (35)
+// CHECK-CC5-NEXT: ObjCPropertyDecl:{ResultType id}{TypedText Prop4} (37)
 
 // RUN: c-index-test -code-completion-at=%s:9:11 %s | FileCheck -check-prefix=CHECK-CC6 %s
 // CHECK-CC6: ObjCInterfaceDecl:{TypedText MyClass} (50)
@@ -93,7 +93,7 @@ id test(I3 *i3) {
 // CHECK-CC7: ObjCIvarDecl:{ResultType id}{TypedText Prop2_} (7)
 
 // RUN: c-index-test -code-completion-at=%s:57:13 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC8 %s
-// CHECK-CC8: ObjCPropertyDecl:{ResultType int}{TypedText Prop5} (35)
+// CHECK-CC8: ObjCPropertyDecl:{ResultType int}{TypedText Prop5} (37)
 
 @interface ClassProperties
 
@@ -157,12 +157,12 @@ void classProperties() {
 // CHECK-CC9-NOT: instanceProperty
 
 // RUN: c-index-test -code-completion-at=%s:145:28 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC10 %s
-// CHECK-CC10: ObjCPropertyDecl:{ResultType int}{TypedText explicit} (35)
-// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitInProtocol} (35)
-// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitReadonly} (35)
-// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicit} (37)
-// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitInCategory} (37)
-// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitReadonly} (37)
+// CHECK-CC10: ObjCPropertyDecl:{ResultType int}{TypedText explicit} (37)
+// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitInProtocol} (37)
+// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitReadonly} (37)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicit} (39)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitInCategory} (39)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitReadonly} (39)
 // CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType ClassProperties *}{TypedText shadowedImplicit} (35)
 // CHECK-CC10-NOT: implicitInstance
 // CHECK-CC10-NOT: noProperty