Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 94 additions & 19 deletions lib/Index/Index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1108,12 +1108,19 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
/// Whether the given decl should be marked implicit in the index data.
bool hasImplicitRole(Decl *D);

bool initIndexSymbol(ValueDecl *D, SourceLoc Loc, bool IsRef,
IndexSymbol &Info);
bool initIndexSymbol(
ValueDecl *D, SourceLoc Loc, bool IsRef, IndexSymbol &Info,
llvm::function_ref<bool(IndexSymbol &)> updateInfo = [](IndexSymbol &) {
return false;
});
bool initIndexSymbol(ExtensionDecl *D, ValueDecl *ExtendedD, SourceLoc Loc,
IndexSymbol &Info);
bool initFuncDeclIndexSymbol(FuncDecl *D, IndexSymbol &Info);
bool initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
bool initFuncRefIndexSymbol(
ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
llvm::function_ref<bool(IndexSymbol &)> updateInfo = [](IndexSymbol &) {
return false;
});
bool initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc,
IndexSymbol &Info,
std::optional<AccessKind> AccKind);
Expand Down Expand Up @@ -1663,22 +1670,18 @@ bool IndexSwiftASTWalker::reportPseudoAccessor(AbstractStorageDecl *D,
// AbstractStorageDecl.
assert(getParentDecl() == D);
auto PreviousTop = EntitiesStack.pop_back_val();
bool initFailed = initFuncRefIndexSymbol(D, Loc, Info);
bool initFailed = initFuncRefIndexSymbol(D, Loc, Info, updateInfo);
EntitiesStack.push_back(PreviousTop);

if (initFailed)
return true; // continue walking.
if (updateInfo(Info))
return true;

if (!IdxConsumer.startSourceEntity(Info) || !IdxConsumer.finishSourceEntity(Info.symInfo, Info.roles))
Cancelled = true;
} else {
IndexSymbol Info;
if (initIndexSymbol(D, Loc, IsRef, Info))
if (initIndexSymbol(D, Loc, IsRef, Info, updateInfo))
return true; // continue walking.
if (updateInfo(Info))
return true;
if (addRelation(Info, (SymbolRoleSet)SymbolRole::RelationAccessorOf |
(SymbolRoleSet)SymbolRole::RelationChildOf , D))
return true;
Expand Down Expand Up @@ -1898,16 +1901,20 @@ bool IndexSwiftASTWalker::reportImplicitConformance(ValueDecl *witness, ValueDec
loc = container->getLoc(/*SerializedOK*/false);

IndexSymbol info;
if (initIndexSymbol(witness, loc, /*IsRef=*/true, info))
bool initFailed = initIndexSymbol(
witness, loc, /*IsRef=*/true, info, [](IndexSymbol &info) {
// Remove the 'ref' role that \c initIndexSymbol introduces. This isn't
// actually a 'reference', but an 'implicit' override.
info.roles &= ~(SymbolRoleSet)SymbolRole::Reference;
info.roles |= (SymbolRoleSet)SymbolRole::Implicit;
return false;
});
if (initFailed)
return true;
if (addRelation(info, (SymbolRoleSet) SymbolRole::RelationOverrideOf, requirement))
return true;
if (addRelation(info, (SymbolRoleSet) SymbolRole::RelationContainedBy, container))
return true;
// Remove the 'ref' role that \c initIndexSymbol introduces. This isn't
// actually a 'reference', but an 'implicit' override.
info.roles &= ~(SymbolRoleSet)SymbolRole::Reference;
info.roles |= (SymbolRoleSet)SymbolRole::Implicit;

if (!startEntity(witness, info, /*IsRef=*/true))
return true;
Expand All @@ -1929,8 +1936,47 @@ bool IndexSwiftASTWalker::hasImplicitRole(Decl *D) {
return false;
}

bool IndexSwiftASTWalker::initIndexSymbol(ValueDecl *D, SourceLoc Loc,
bool IsRef, IndexSymbol &Info) {
bool shouldOutputEffectiveAccessOfValueSymbol(SymbolInfo Info) {
SymbolKind Kind = Info.Kind;
SymbolSubKind SubKind = Info.SubKind;
switch (SubKind) {
case SymbolSubKind::AccessorGetter:
case SymbolSubKind::AccessorSetter:
case SymbolSubKind::SwiftAccessorWillSet:
case SymbolSubKind::SwiftAccessorDidSet:
case SymbolSubKind::SwiftAccessorAddressor:
case SymbolSubKind::SwiftAccessorMutableAddressor:
case SymbolSubKind::SwiftGenericTypeParam:
return false;
default:
break;
}
switch (Kind) {
case SymbolKind::Enum:
case SymbolKind::Struct:
case SymbolKind::Class:
case SymbolKind::Protocol:
case SymbolKind::Constructor:
case SymbolKind::EnumConstant:
case SymbolKind::Function:
case SymbolKind::StaticMethod:
case SymbolKind::Variable:
case SymbolKind::InstanceMethod:
case SymbolKind::ClassMethod:
case SymbolKind::InstanceProperty:
case SymbolKind::ClassProperty:
case SymbolKind::StaticProperty:
case SymbolKind::TypeAlias:
case SymbolKind::Macro:
return true;
default:
return false;
}
}

bool IndexSwiftASTWalker::initIndexSymbol(
ValueDecl *D, SourceLoc Loc, bool IsRef, IndexSymbol &Info,
llvm::function_ref<bool(IndexSymbol &)> updateInfo) {
assert(D);

auto MappedLoc = getMappedLocation(Loc);
Expand Down Expand Up @@ -1970,6 +2016,34 @@ bool IndexSwiftASTWalker::initIndexSymbol(ValueDecl *D, SourceLoc Loc,
Info.roles |= (unsigned)SymbolRole::Implicit;
}

if (updateInfo(Info)) {
return true;
}

if (shouldOutputEffectiveAccessOfValueSymbol(Info.symInfo) &&
(Info.roles & (SymbolRoleSet)SymbolRole::Reference) == 0 &&
!isLocalSymbol(D)) {
AccessScope Scope = D->getFormalAccessScope();
if (Scope.isPublic()) {
if (D->isSPI()) {
Info.symInfo.Properties |= SymbolProperty::SwiftAccessControlSPI;
} else {
Info.symInfo.Properties |= SymbolProperty::SwiftAccessControlPublic;
}
} else if (Scope.isPackage()) {
Info.symInfo.Properties |= SymbolProperty::SwiftAccessControlPackage;
} else if (Scope.isInternal()) {
Info.symInfo.Properties |= SymbolProperty::SwiftAccessControlInternal;
} else if (Scope.isFileScope()) {
Info.symInfo.Properties |= SymbolProperty::SwiftAccessControlFilePrivate;
} else if (Scope.isPrivate()) {
Info.symInfo.Properties |=
SymbolProperty::SwiftAccessControlLessThanFilePrivate;
} else {
llvm_unreachable("Unsupported access scope");
}
}

return false;
}

Expand Down Expand Up @@ -2036,10 +2110,11 @@ bool IndexSwiftASTWalker::initFuncDeclIndexSymbol(FuncDecl *D,
return false;
}

bool IndexSwiftASTWalker::initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc,
IndexSymbol &Info) {
bool IndexSwiftASTWalker::initFuncRefIndexSymbol(
ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
llvm::function_ref<bool(IndexSymbol &)> updateInfo) {

if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info, updateInfo))
return true;

if (!isa<AbstractStorageDecl>(D) && !ide::isBeingCalled(ExprStack))
Expand Down
52 changes: 52 additions & 0 deletions test/Index/access_level.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s -package-name MyModule | %FileCheck %s

private func myPrivateFunc() {}
// CHECK: [[@LINE-1]]:14 | function(fileprivate)/Swift | myPrivateFunc() | {{.*}} | Def | rel: 0

fileprivate func myFileprivateFunc() {}
// CHECK: [[@LINE-1]]:18 | function(fileprivate)/Swift | myFileprivateFunc() | {{.*}} | Def | rel: 0

func myInternalFunc() {}
// CHECK: [[@LINE-1]]:6 | function(internal)/Swift | myInternalFunc() | {{.*}} | Def | rel: 0

package func myPackageFunc() {}
// CHECK: [[@LINE-1]]:14 | function(package)/Swift | myPackageFunc() | {{.*}} | Def | rel: 0

public func myPublicFunc() {}
// CHECK: [[@LINE-1]]:13 | function(public)/Swift | myPublicFunc() | {{.*}} | Def | rel: 0

open class MyOpenClass {}
// CHECK: [[@LINE-1]]:12 | class(public)/Swift | MyOpenClass | {{.*}} | Def | rel: 0

@_spi(MySPI)
public class MyPublicSPIClass {
// CHECK: [[@LINE-1]]:14 | class(SPI)/Swift | MyPublicSPIClass | {{.*}} | Def | rel: 0

public func publicInSPI() {}
// CHECK: [[@LINE-1]]:15 | instance-method(SPI)/Swift | publicInSPI() | {{.*}} | Def,Dyn,RelChild | rel: 1
}

@_spi(MySPI)
open class MyOpenSPIClass {}
// CHECK: [[@LINE-1]]:12 | class(SPI)/Swift | MyOpenSPIClass | {{.*}} | Def | rel: 0

private class Foo {
public func publicInPrivate() {}
// CHECK: [[@LINE-1]]:15 | instance-method(fileprivate)/Swift | publicInPrivate() | {{.*}} | Def,Dyn,RelChild | rel: 1
}

private enum PrivateEnum {
// CHECK: [[@LINE-1]]:14 | enum(fileprivate)/Swift | PrivateEnum | {{.*}} | Def | rel: 0
case myCase
// CHECK: [[@LINE-1]]:8 | enumerator(fileprivate)/Swift | myCase | {{.*}} | Def,RelChild | rel: 1
}
extension PrivateEnum {
private func f() { print("Hello") }
// CHECK: [[@LINE-1]]:16 | instance-method(less_than_private)/Swift | f() | {{.*}} | Def,RelChild | rel: 1
}

enum InternalEnum {
// CHECK: [[@LINE-1]]:6 | enum(internal)/Swift | InternalEnum | {{.*}} | Def | rel: 0
case myCase
// CHECK: [[@LINE-1]]:8 | enumerator(internal)/Swift | myCase | {{.*}} | Def,RelChild | rel: 1
}
6 changes: 3 additions & 3 deletions test/Index/async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s

func globalAsyncFunc() async {}
// CHECK: [[@LINE-1]]:6 | function(swift_async)/Swift | globalAsyncFunc() | {{.*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:6 | function(swift_async,internal)/Swift | globalAsyncFunc() | {{.*}} | Def | rel: 0

struct MyStruct {
func asyncMethod() async {}
// CHECK: [[@LINE-1]]:8 | instance-method(swift_async)/Swift | asyncMethod() |
// CHECK: [[@LINE-1]]:8 | instance-method(swift_async,internal)/Swift | asyncMethod() |
}

class XCTestCase {}
class MyTestCase : XCTestCase {
func testSomeAsync() async {}
// CHECK: [[@LINE-1]]:8 | instance-method(test,swift_async)/Swift | testSomeAsync() |
// CHECK: [[@LINE-1]]:8 | instance-method(test,swift_async,internal)/Swift | testSomeAsync() |
}
30 changes: 15 additions & 15 deletions test/Index/circular.swift
Original file line number Diff line number Diff line change
@@ -1,66 +1,66 @@
// RUN: %target-swift-ide-test -print-indexed-symbols -source-filename %s | %FileCheck %s

class SelfCycle : SelfCycle {}
// CHECK: [[@LINE-1]]:7 | class/Swift | SelfCycle | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | SelfCycle | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:19 | class/Swift | SelfCycle | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | SelfCycle | {{\W*}}

class Cycle1_A: Cycle1_B {}
// CHECK: [[@LINE-1]]:7 | class/Swift | Cycle1_A | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | Cycle1_A | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:17 | class/Swift | Cycle1_B | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | Cycle1_A | {{[^ ]*}}
class Cycle1_B: Cycle1_A {}
// CHECK: [[@LINE-1]]:7 | class/Swift | Cycle1_B | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | Cycle1_B | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:17 | class/Swift | Cycle1_A | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | Cycle1_B | {{[^ ]*}}

class Cycle2_A: Cycle2_C {}
// CHECK: [[@LINE-1]]:7 | class/Swift | Cycle2_A | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | Cycle2_A | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:17 | class/Swift | Cycle2_C | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | Cycle2_A | {{[^ ]*}}
class Cycle2_B: Cycle2_A {}
// CHECK: [[@LINE-1]]:7 | class/Swift | Cycle2_B | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | Cycle2_B | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:17 | class/Swift | Cycle2_A | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | Cycle2_B | {{[^ ]*}}
class Cycle2_C: Cycle2_B {}
// CHECK: [[@LINE-1]]:7 | class/Swift | Cycle2_C | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | Cycle2_C | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:17 | class/Swift | Cycle2_B | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | Cycle2_C | {{[^ ]*}}

class TestCase1: XCTestCase {}
// CHECK: [[@LINE-1]]:7 | class/Swift | TestCase1 | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | TestCase1 | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:18 | class/Swift | XCTestCase | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | TestCase1 | {{[^ ]*}}
class XCTestCase: TestCase1 {}
// CHECK: [[@LINE-1]]:7 | class/Swift | XCTestCase | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | XCTestCase | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:19 | class/Swift | TestCase1 | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | XCTestCase | {{[^ ]*}}
class TestCase2: TestCase1 {}
// CHECK: [[@LINE-1]]:7 | class/Swift | TestCase2 | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:7 | class(internal)/Swift | TestCase2 | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:18 | class/Swift | TestCase1 | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | class/Swift | TestCase2 | {{[^ ]*}}

protocol SelfCycleP: SelfCycleP {}
// CHECK: [[@LINE-1]]:10 | protocol/Swift | SelfCycleP | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:10 | protocol(internal)/Swift | SelfCycleP | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:22 | protocol/Swift | SelfCycleP | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | protocol/Swift | SelfCycleP | {{[^ ]*}}
protocol Cycle1P_A: Cycle1P_B {}
// CHECK: [[@LINE-1]]:10 | protocol/Swift | Cycle1P_A | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:10 | protocol(internal)/Swift | Cycle1P_A | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:21 | protocol/Swift | Cycle1P_B | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | protocol/Swift | Cycle1P_A | {{[^ ]*}}
protocol Cycle1P_B: Cycle1P_A {}
// CHECK: [[@LINE-1]]:10 | protocol/Swift | Cycle1P_B | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:10 | protocol(internal)/Swift | Cycle1P_B | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:21 | protocol/Swift | Cycle1P_A | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | protocol/Swift | Cycle1P_B | {{[^ ]*}}
protocol Cycle2P_A: Cycle2P_C {}
// CHECK: [[@LINE-1]]:10 | protocol/Swift | Cycle2P_A | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:10 | protocol(internal)/Swift | Cycle2P_A | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:21 | protocol/Swift | Cycle2P_C | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | protocol/Swift | Cycle2P_A | {{[^ ]*}}
protocol Cycle2P_B: Cycle2P_A {}
// CHECK: [[@LINE-1]]:10 | protocol/Swift | Cycle2P_B | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:10 | protocol(internal)/Swift | Cycle2P_B | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:21 | protocol/Swift | Cycle2P_A | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | protocol/Swift | Cycle2P_B | {{[^ ]*}}
protocol Cycle2P_C: Cycle2P_B {}
// CHECK: [[@LINE-1]]:10 | protocol/Swift | Cycle2P_C | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-1]]:10 | protocol(internal)/Swift | Cycle2P_C | {{[^ ]*}} | Def | rel: 0
// CHECK: [[@LINE-2]]:21 | protocol/Swift | Cycle2P_B | {{[^ ]*}} | Ref,RelBase | rel: 1
// CHECK: RelBase | protocol/Swift | Cycle2P_C | {{[^ ]*}}
Loading