Skip to content

Commit c3316c2

Browse files
committed
IDE: Index references from keypaths
1 parent 68b5805 commit c3316c2

File tree

2 files changed

+57
-8
lines changed

2 files changed

+57
-8
lines changed

lib/IDE/SourceEntityWalker.cpp

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class SemaAnnotator : public ASTWalker {
6262
bool passModulePathElements(ArrayRef<ImportDecl::AccessPathElement> Path,
6363
const clang::Module *ClangMod);
6464

65+
bool passReference(ValueDecl *D, Type Ty, SourceLoc Loc, SourceRange Range,
66+
ReferenceMetaData Data);
6567
bool passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data);
6668
bool passReference(ModuleEntity Mod, std::pair<Identifier, SourceLoc> IdLoc);
6769

@@ -324,6 +326,32 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
324326
return { false, nullptr };
325327
return { false, E };
326328

329+
} else if (auto *KPE = dyn_cast<KeyPathExpr>(E)) {
330+
for (auto &component : KPE->getComponents()) {
331+
switch (component.getKind()) {
332+
case KeyPathExpr::Component::Kind::Property:
333+
case KeyPathExpr::Component::Kind::Subscript: {
334+
auto *decl = component.getDeclRef().getDecl();
335+
auto loc = component.getLoc();
336+
SourceRange range(loc, loc);
337+
passReference(decl, component.getComponentType(), loc, range,
338+
ReferenceMetaData(
339+
(isa<SubscriptDecl>(decl)
340+
? SemaReferenceKind::SubscriptRef
341+
: SemaReferenceKind::DeclMemberRef),
342+
OpAccess));
343+
break;
344+
}
345+
346+
case KeyPathExpr::Component::Kind::Invalid:
347+
case KeyPathExpr::Component::Kind::UnresolvedProperty:
348+
case KeyPathExpr::Component::Kind::UnresolvedSubscript:
349+
case KeyPathExpr::Component::Kind::OptionalChain:
350+
case KeyPathExpr::Component::Kind::OptionalWrap:
351+
case KeyPathExpr::Component::Kind::OptionalForce:
352+
break;
353+
}
354+
}
327355
} else if (auto *BinE = dyn_cast<BinaryExpr>(E)) {
328356
// Visit in source order.
329357
if (!BinE->getArg()->getElement(0)->walk(*this))
@@ -459,31 +487,37 @@ bool SemaAnnotator::passSubscriptReference(ValueDecl *D, SourceLoc Loc,
459487

460488
bool SemaAnnotator::
461489
passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data) {
490+
return passReference(D, Ty, Loc.getBaseNameLoc(), Loc.getSourceRange(), Data);
491+
}
492+
493+
bool SemaAnnotator::
494+
passReference(ValueDecl *D, Type Ty, SourceLoc BaseNameLoc, SourceRange Range,
495+
ReferenceMetaData Data) {
462496
TypeDecl *CtorTyRef = nullptr;
463497
ExtensionDecl *ExtDecl = nullptr;
464498

465499
if (auto *TD = dyn_cast<TypeDecl>(D)) {
466-
if (!CtorRefs.empty() && Loc.isValid()) {
500+
if (!CtorRefs.empty() && BaseNameLoc.isValid()) {
467501
Expr *Fn = CtorRefs.back()->getFn();
468-
if (Fn->getLoc() == Loc.getBaseNameLoc()) {
502+
if (Fn->getLoc() == BaseNameLoc) {
469503
D = extractDecl(Fn);
470504
CtorTyRef = TD;
471505
}
472506
}
473507

474-
if (!ExtDecls.empty() && Loc.isValid()) {
508+
if (!ExtDecls.empty() && BaseNameLoc.isValid()) {
475509
auto ExtTyLoc = ExtDecls.back()->getExtendedTypeLoc().getLoc();
476-
if (ExtTyLoc.isValid() && ExtTyLoc == Loc.getBaseNameLoc()) {
510+
if (ExtTyLoc.isValid() && ExtTyLoc == BaseNameLoc) {
477511
ExtDecl = ExtDecls.back();
478512
}
479513
}
480514
}
481515

482-
CharSourceRange Range =
516+
CharSourceRange CharRange =
483517
Lexer::getCharSourceRangeFromSourceRange(D->getASTContext().SourceMgr,
484-
Loc.getSourceRange());
485-
bool Continue = SEWalker.visitDeclReference(D, Range, CtorTyRef, ExtDecl, Ty,
486-
Data);
518+
Range);
519+
bool Continue = SEWalker.visitDeclReference(D, CharRange, CtorTyRef, ExtDecl,
520+
Ty, Data);
487521
if (!Continue)
488522
Cancelled = true;
489523
return Continue;

test/Index/roles.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,3 +483,18 @@ final class FinalClass {
483483
func foo() {}
484484
// CHECK: [[@LINE-1]]:8 | instance-method/Swift | {{.*}} | Def,RelChild | rel: 1
485485
}
486+
487+
struct StructWithKeypath {
488+
var x: Int = 0
489+
490+
subscript(idx: Int) -> Int { get { } set { } }
491+
}
492+
493+
_ = \StructWithKeypath.x
494+
// CHECK: [[@LINE-1]]:24 | instance-property/Swift | x | s:14swift_ide_test17StructWithKeypathV1xSivp | Ref,Read | rel: 0
495+
// CHECK: [[@LINE-2]]:24 | instance-method/acc-get/Swift | getter:x | s:14swift_ide_test17StructWithKeypathV1xSivg | Ref,Call,Impl | rel: 0
496+
497+
_ = \StructWithKeypath.[0]
498+
// CHECK: [[@LINE-1]]:24 | instance-property/subscript/Swift | subscript(_:) | s:14swift_ide_test17StructWithKeypathVyS2icip | Ref,Read | rel: 0
499+
// CHECK: [[@LINE-2]]:24 | instance-method/acc-get/Swift | getter:subscript(_:) | s:14swift_ide_test17StructWithKeypathVyS2icig | Ref,Call,Impl | rel: 0
500+

0 commit comments

Comments
 (0)