[clang-tools-extra] 5709842 - [clangd] Fix highlighting for implicit ObjC property refs

David Goldman via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 30 09:32:29 PDT 2021


Author: David Goldman
Date: 2021-06-30T12:31:50-04:00
New Revision: 570984204f24c326699dedcc05793b77b013f068

URL: https://github.com/llvm/llvm-project/commit/570984204f24c326699dedcc05793b77b013f068
DIFF: https://github.com/llvm/llvm-project/commit/570984204f24c326699dedcc05793b77b013f068.diff

LOG: [clangd] Fix highlighting for implicit ObjC property refs

Objective-C lets you use the `self.prop` syntax as sugar for both
`[self prop]` and `[self setProp:]`, but clangd previously did not
provide a semantic token for `prop`.

Now, we provide a semantic token, treating it like a normal property
except it's backed by a `ObjCMethodDecl` instead of a
`ObjCPropertyDecl`.

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

Added: 
    

Modified: 
    clang-tools-extra/clangd/SemanticHighlighting.cpp
    clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index bb192596f8c52..b49eb785f2deb 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -556,6 +556,42 @@ class CollectExtraHighlightings
     return true;
   }
 
+  // Objective-C allows you to use property syntax `self.prop` as sugar for
+  // `[self prop]` and `[self setProp:]` when there's no explicit `@property`
+  // for `prop` as well as for class properties. We treat this like a property
+  // even though semantically it's equivalent to a method expression.
+  void highlightObjCImplicitPropertyRef(const ObjCMethodDecl *OMD,
+                                        SourceLocation Loc) {
+    auto &Tok = H.addToken(Loc, HighlightingKind::Field)
+                    .addModifier(HighlightingModifier::ClassScope);
+    if (OMD->isClassMethod())
+      Tok.addModifier(HighlightingModifier::Static);
+    if (isDefaultLibrary(OMD))
+      Tok.addModifier(HighlightingModifier::DefaultLibrary);
+  }
+
+  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *OPRE) {
+    // We need to handle implicit properties here since they will appear to
+    // reference `ObjCMethodDecl` via an implicit `ObjCMessageExpr`, so normal
+    // highlighting will not work.
+    if (!OPRE->isImplicitProperty())
+      return true;
+    // A single property expr can reference both a getter and setter, but we can
+    // only provide a single semantic token, so prefer the getter. In most cases
+    // the end result should be the same, although it's technically possible
+    // that the user defines a setter for a system SDK.
+    if (OPRE->isMessagingGetter()) {
+      highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertyGetter(),
+                                       OPRE->getLocation());
+      return true;
+    }
+    if (OPRE->isMessagingSetter()) {
+      highlightObjCImplicitPropertyRef(OPRE->getImplicitPropertySetter(),
+                                       OPRE->getLocation());
+    }
+    return true;
+  }
+
   bool VisitOverloadExpr(OverloadExpr *E) {
     if (!E->decls().empty())
       return true; // handled by findExplicitReferences.

diff  --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
index 02ab6bef0a817..a0212856427d6 100644
--- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -696,11 +696,16 @@ sizeof...($TemplateParameter[[Elements]]);
           int $Field_decl[[_someProperty]];
         }
         @property(nonatomic, assign) int $Field_decl[[someProperty]];
+        @property(readonly, class) $Class[[Foo]] *$Field_decl_readonly_static[[sharedInstance]];
         @end
         @implementation $Class_decl[[Foo]]
         @synthesize someProperty = _someProperty;
+        - (int)$Method_decl[[otherMethod]] {
+          return 0;
+        }
         - (int)$Method_decl[[doSomething]] {
-          self.$Field[[someProperty]] = self.$Field[[someProperty]] + 1;
+          $Class[[Foo]].$Field_static[[sharedInstance]].$Field[[someProperty]] = 1;
+          self.$Field[[someProperty]] = self.$Field[[someProperty]] + self.$Field[[otherMethod]] + 1;
           self->$Field[[_someProperty]] = $Field[[_someProperty]] + 1;
         }
         @end


        


More information about the cfe-commits mailing list