[clang-tools-extra] c20e4fb - [clangd] Improve handling of Objective-C protocols in types
David Goldman via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 27 07:20:48 PDT 2021
Author: David Goldman
Date: 2021-04-27T10:20:35-04:00
New Revision: c20e4fbfa6d154616c2dd41e828a02facd000d71
URL: https://github.com/llvm/llvm-project/commit/c20e4fbfa6d154616c2dd41e828a02facd000d71
DIFF: https://github.com/llvm/llvm-project/commit/c20e4fbfa6d154616c2dd41e828a02facd000d71.diff
LOG: [clangd] Improve handling of Objective-C protocols in types
Improve support for Objective-C protocols for types/type locs
Differential Revision: https://reviews.llvm.org/D98984
Added:
Modified:
clang-tools-extra/clangd/FindTarget.cpp
clang-tools-extra/clangd/unittests/FindTargetTests.cpp
clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index 16433151d902..6032676b0acd 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -432,10 +432,13 @@ struct TargetFinder {
Outer.add(OIT->getDecl(), Flags);
}
void VisitObjCObjectType(const ObjCObjectType *OOT) {
- // FIXME: ObjCObjectTypeLoc has no children for the protocol list, so
- // there is no node in id<Foo> that refers to ObjCProtocolDecl Foo.
- if (OOT->isObjCQualifiedId() && OOT->getNumProtocols() == 1)
- Outer.add(OOT->getProtocol(0), Flags);
+ // Make all of the protocols targets since there's no child nodes for
+ // protocols. This isn't needed for the base type, which *does* have a
+ // child `ObjCInterfaceTypeLoc`. This structure is a hack, but it works
+ // well for go-to-definition.
+ unsigned NumProtocols = OOT->getNumProtocols();
+ for (unsigned I = 0; I < NumProtocols; I++)
+ Outer.add(OOT->getProtocol(I), Flags);
}
};
Visitor(*this, Flags).Visit(T.getTypePtr());
@@ -813,30 +816,34 @@ refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) {
Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {}
const HeuristicResolver *Resolver;
- llvm::Optional<ReferenceLoc> Ref;
+ llvm::SmallVector<ReferenceLoc> Refs;
void VisitElaboratedTypeLoc(ElaboratedTypeLoc L) {
// We only know about qualifier, rest if filled by inner locations.
+ size_t InitialSize = Refs.size();
Visit(L.getNamedTypeLoc().getUnqualifiedLoc());
- // Fill in the qualifier.
- if (!Ref)
- return;
- assert(!Ref->Qualifier.hasQualifier() && "qualifier already set");
- Ref->Qualifier = L.getQualifierLoc();
+ size_t NewSize = Refs.size();
+ // Add qualifier for the newly-added refs.
+ for (unsigned I = InitialSize; I < NewSize; ++I) {
+ ReferenceLoc *Ref = &Refs[I];
+ // Fill in the qualifier.
+ assert(!Ref->Qualifier.hasQualifier() && "qualifier already set");
+ Ref->Qualifier = L.getQualifierLoc();
+ }
}
void VisitTagTypeLoc(TagTypeLoc L) {
- Ref = ReferenceLoc{NestedNameSpecifierLoc(),
- L.getNameLoc(),
- /*IsDecl=*/false,
- {L.getDecl()}};
+ Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ L.getNameLoc(),
+ /*IsDecl=*/false,
+ {L.getDecl()}});
}
void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) {
- Ref = ReferenceLoc{NestedNameSpecifierLoc(),
- L.getNameLoc(),
- /*IsDecl=*/false,
- {L.getDecl()}};
+ Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ L.getNameLoc(),
+ /*IsDecl=*/false,
+ {L.getDecl()}});
}
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
@@ -848,63 +855,71 @@ refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) {
// 1. valias with mask 'Alias'.
// 2. 'vector<int>' with mask 'Underlying'.
// we want to return only #1 in this case.
- Ref = ReferenceLoc{
+ Refs.push_back(ReferenceLoc{
NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false,
explicitReferenceTargets(DynTypedNode::create(L.getType()),
- DeclRelation::Alias, Resolver)};
+ DeclRelation::Alias, Resolver)});
}
void VisitDeducedTemplateSpecializationTypeLoc(
DeducedTemplateSpecializationTypeLoc L) {
- Ref = ReferenceLoc{
+ Refs.push_back(ReferenceLoc{
NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false,
explicitReferenceTargets(DynTypedNode::create(L.getType()),
- DeclRelation::Alias, Resolver)};
+ DeclRelation::Alias, Resolver)});
}
void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
- Ref = ReferenceLoc{NestedNameSpecifierLoc(),
- TL.getNameLoc(),
- /*IsDecl=*/false,
- {TL.getDecl()}};
+ Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ TL.getNameLoc(),
+ /*IsDecl=*/false,
+ {TL.getDecl()}});
}
void VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc L) {
- Ref = ReferenceLoc{L.getQualifierLoc(), L.getTemplateNameLoc(),
- /*IsDecl=*/false,
- explicitReferenceTargets(
- DynTypedNode::create(L.getType()), {}, Resolver)};
+ Refs.push_back(
+ ReferenceLoc{L.getQualifierLoc(), L.getTemplateNameLoc(),
+ /*IsDecl=*/false,
+ explicitReferenceTargets(
+ DynTypedNode::create(L.getType()), {}, Resolver)});
}
void VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
- Ref = ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false,
- explicitReferenceTargets(
- DynTypedNode::create(L.getType()), {}, Resolver)};
+ Refs.push_back(
+ ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(),
+ /*IsDecl=*/false,
+ explicitReferenceTargets(
+ DynTypedNode::create(L.getType()), {}, Resolver)});
}
void VisitTypedefTypeLoc(TypedefTypeLoc L) {
- Ref = ReferenceLoc{NestedNameSpecifierLoc(),
- L.getNameLoc(),
- /*IsDecl=*/false,
- {L.getTypedefNameDecl()}};
+ Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ L.getNameLoc(),
+ /*IsDecl=*/false,
+ {L.getTypedefNameDecl()}});
}
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc L) {
- Ref = ReferenceLoc{NestedNameSpecifierLoc(),
- L.getNameLoc(),
- /*IsDecl=*/false,
- {L.getIFaceDecl()}};
+ Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ L.getNameLoc(),
+ /*IsDecl=*/false,
+ {L.getIFaceDecl()}});
}
- // FIXME: add references to protocols in ObjCObjectTypeLoc and maybe
- // ObjCObjectPointerTypeLoc.
+ void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc L) {
+ unsigned NumProtocols = L.getNumProtocols();
+ for (unsigned I = 0; I < NumProtocols; I++) {
+ Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+ L.getProtocolLoc(I),
+ /*IsDecl=*/false,
+ {L.getProtocol(I)}});
+ }
+ }
};
Visitor V{Resolver};
V.Visit(L.getUnqualifiedLoc());
- if (!V.Ref)
- return {};
- return {*V.Ref};
+ return V.Refs;
}
class ExplicitReferenceCollector
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 2263c790d713..5bcbdbd2f1cd 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -943,14 +943,32 @@ TEST_F(TargetDeclTest, ObjC) {
)cpp";
EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo");
+ Code = R"cpp(
+ @class C;
+ @protocol Foo
+ @end
+ void test([[C]]<Foo> *p);
+ )cpp";
+ EXPECT_DECLS("ObjCInterfaceTypeLoc", "@class C;");
+
Code = R"cpp(
@class C;
@protocol Foo
@end
void test(C<[[Foo]]> *p);
)cpp";
- // FIXME: there's no AST node corresponding to 'Foo', so we're stuck.
- EXPECT_DECLS("ObjCObjectTypeLoc");
+ EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo");
+
+ Code = R"cpp(
+ @class C;
+ @protocol Foo
+ @end
+ @protocol Bar
+ @end
+ void test(C<[[Foo]], Bar> *p);
+ )cpp";
+ // FIXME: We currently can't disambiguate between multiple protocols.
+ EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo", "@protocol Bar");
}
class FindExplicitReferencesTest : public ::testing::Test {
@@ -1610,12 +1628,12 @@ TEST_F(FindExplicitReferencesTest, All) {
@protocol P
@end
void foo() {
- // FIXME: should reference P
- $0^I<P> *$1^x;
+ $0^I<$1^P> *$2^x;
}
)cpp",
"0: targets = {I}\n"
- "1: targets = {x}, decl\n"},
+ "1: targets = {P}\n"
+ "2: targets = {x}, decl\n"},
// Designated initializers.
{R"cpp(
diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
index d36470b6b611..815ef92c932e 100644
--- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -676,8 +676,7 @@ sizeof...($TemplateParameter[[Elements]]);
@end
@interface $Class_decl[[Klass]] <$Interface[[Protocol]]>
@end
- // FIXME: protocol list in ObjCObjectType should be highlighted.
- id<Protocol> $Variable_decl[[x]];
+ id<$Interface[[Protocol]]> $Variable_decl[[x]];
)cpp",
R"cpp(
// ObjC: Categories
More information about the cfe-commits
mailing list