-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[clangd] Update XRefs to support overriden ObjC methods #127109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
d335931
65f19b7
68fd059
e962112
4f88a70
478cd5a
13c7011
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -372,6 +372,15 @@ void enhanceLocatedSymbolsFromIndex(llvm::MutableArrayRef<LocatedSymbol> Result, | |
| }); | ||
| } | ||
|
|
||
| bool objcMethodIsTouched(const SourceManager &SM, const ObjCMethodDecl *OMD, | ||
| SourceLocation Loc) { | ||
| unsigned NumSels = OMD->getNumSelectorLocs(); | ||
| for (unsigned I = 0; I < NumSels; ++I) | ||
| if (SM.getSpellingLoc(OMD->getSelectorLoc(I)) == Loc) | ||
| return true; | ||
| return false; | ||
| } | ||
|
|
||
| // Decls are more complicated. | ||
| // The AST contains at least a declaration, maybe a definition. | ||
| // These are up-to-date, and so generally preferred over index results. | ||
|
|
@@ -430,6 +439,22 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, | |
| continue; | ||
| } | ||
| } | ||
| // Special case: - (void)^method; should jump to all overrides. Note that an | ||
| // Objective-C method can override a parent class or protocol. | ||
| if (const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(D)) { | ||
| if (TouchedIdentifier && | ||
| objcMethodIsTouched(SM, OMD, TouchedIdentifier->location())) { | ||
| llvm::SmallVector<const ObjCMethodDecl *, 4> Overrides; | ||
| OMD->getOverriddenMethods(Overrides); | ||
| if (!Overrides.empty()) { | ||
| for (const auto *Override : Overrides) | ||
| AddResultDecl(Override); | ||
| LocateASTReferentMetric.record(1, "objc-overriden-method"); | ||
| } | ||
| AddResultDecl(OMD); | ||
| continue; | ||
| } | ||
| } | ||
|
|
||
| // Special case: the cursor is on an alias, prefer other results. | ||
| // This targets "using ns::^Foo", where the target is more interesting. | ||
|
|
@@ -1283,6 +1308,12 @@ std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos, | |
| } else if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) { | ||
| IDs.insert(getSymbolID(RD)); | ||
| QueryKind = RelationKind::BaseOf; | ||
| } else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(ND)) { | ||
| IDs.insert(getSymbolID(OMD)); | ||
| QueryKind = RelationKind::OverriddenBy; | ||
| } else if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) { | ||
| IDs.insert(getSymbolID(ID)); | ||
| QueryKind = RelationKind::BaseOf; | ||
| } | ||
| } | ||
| return findImplementors(std::move(IDs), QueryKind, Index, AST.tuPath()); | ||
|
|
@@ -1438,6 +1469,15 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, | |
| getOverriddenMethods(CMD, OverriddenMethods); | ||
| } | ||
| } | ||
| // Special case: Objective-C methods can override a parent class or | ||
| // protocol, we should be sure to report references to those. | ||
| if (const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(ND)) { | ||
| OverriddenBy.Subjects.insert(getSymbolID(OMD)); | ||
| llvm::SmallVector<const ObjCMethodDecl *, 4> Overrides; | ||
| OMD->getOverriddenMethods(Overrides); | ||
| for (const auto *Override : Overrides) | ||
| OverriddenMethods.insert(getSymbolID(Override)); | ||
|
||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think it's worthwhile to also add a test to check we don't return overridden methods when calling xrefs on usage of the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.