diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -556,6 +556,42 @@ 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 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -696,11 +696,16 @@ 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