mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[SourceKit] Add whether a property is dynamic
Properties can also be specified in a protocol/overridden by subclasses, so they should also be classed as "dynamic" in these cases. Removed receiver USRs when *not* dynamic, since it's not used for anything in that case and should be equivalent to the container anyway. Resolves rdar://92882348.
This commit is contained in:
@@ -1252,12 +1252,44 @@ Expr *swift::ide::getBase(ArrayRef<Expr *> ExprStack) {
|
||||
return Base;
|
||||
}
|
||||
|
||||
bool swift::ide::isDynamicCall(Expr *Base, ValueDecl *D) {
|
||||
auto TyD = D->getDeclContext()->getSelfNominalTypeDecl();
|
||||
if (!TyD)
|
||||
bool swift::ide::isDeclOverridable(ValueDecl *D) {
|
||||
auto *NTD = D->getDeclContext()->getSelfNominalTypeDecl();
|
||||
if (!NTD)
|
||||
return false;
|
||||
|
||||
if (isa<StructDecl>(TyD) || isa<EnumDecl>(TyD) || D->isFinal())
|
||||
// Only classes and protocols support overridding by subtypes.
|
||||
if (!(isa<ClassDecl>(NTD) || isa<ProtocolDecl>(NTD)))
|
||||
return false;
|
||||
|
||||
// Decls where either they themselves are final or their containing type is
|
||||
// final cannot be overridden. Actors cannot be subclassed and thus the given
|
||||
// decl also can't be overridden.
|
||||
if (D->isFinal() || NTD->isFinal() || NTD->isActor())
|
||||
return false;
|
||||
|
||||
// No need to check accessors here - willSet/didSet are not "overridable",
|
||||
// but that's already covered by the `isFinal` check above (they are both
|
||||
// final).
|
||||
|
||||
// Static functions on classes cannot be overridden. Static functions on
|
||||
// structs and enums are already covered by the more general check above.
|
||||
if (isa<ClassDecl>(NTD)) {
|
||||
if (auto *FD = dyn_cast<FuncDecl>(D)) {
|
||||
if (FD->isStatic() &&
|
||||
FD->getCorrectStaticSpelling() == StaticSpellingKind::KeywordStatic)
|
||||
return false;
|
||||
} else if (auto *ASD = dyn_cast<AbstractStorageDecl>(D)) {
|
||||
if (ASD->isStatic() &&
|
||||
ASD->getCorrectStaticSpelling() == StaticSpellingKind::KeywordStatic)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool swift::ide::isDynamicRef(Expr *Base, ValueDecl *D) {
|
||||
if (!isDeclOverridable(D))
|
||||
return false;
|
||||
|
||||
// super.method()
|
||||
@@ -1268,20 +1300,18 @@ bool swift::ide::isDynamicCall(Expr *Base, ValueDecl *D) {
|
||||
if (Base->isSuperExpr())
|
||||
return false;
|
||||
|
||||
// `SomeType.staticOrClassMethod()`
|
||||
// `SomeType.staticOrClassMethod()` spelled directly, so this must be a ref
|
||||
// to this exact decl.
|
||||
if (isa<TypeExpr>(Base))
|
||||
return false;
|
||||
|
||||
// `type(of: foo).staticOrClassMethod()`, not "dynamic" if the instance type
|
||||
// is a struct/enum or if it is a class and the function is a static method
|
||||
// (rather than a class method).
|
||||
// `type(of: foo).staticOrClassMethod()`. A static method may be "dynamic"
|
||||
// here, but not if the instance type is a struct/enum.
|
||||
if (auto IT = Base->getType()->getAs<MetatypeType>()) {
|
||||
auto InstanceType = IT->getInstanceType();
|
||||
if (InstanceType->getStructOrBoundGenericStruct() ||
|
||||
InstanceType->getEnumOrBoundGenericEnum())
|
||||
return false;
|
||||
if (InstanceType->getClassOrBoundGenericClass() && D->isFinal())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user