-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement SkieVisibility propagation.
- Loading branch information
1 parent
011cd2f
commit f0b0cf0
Showing
19 changed files
with
288 additions
and
9 deletions.
There are no files selected for viewing
Submodule acceptance-tests
updated
from 5d11cd to 60ecd3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
...monMain/kotlin/co/touchlab/skie/phases/sir/member/PropagateSirVisibilityToMembersPhase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package co.touchlab.skie.phases.sir.member | ||
|
||
import co.touchlab.skie.phases.SirPhase | ||
import co.touchlab.skie.sir.element.SirCallableDeclaration | ||
import co.touchlab.skie.sir.element.SirConstructor | ||
import co.touchlab.skie.sir.element.SirProperty | ||
import co.touchlab.skie.sir.element.SirSimpleFunction | ||
import co.touchlab.skie.sir.element.minimumVisibility | ||
import co.touchlab.skie.sir.type.visibilityConstraint | ||
|
||
object PropagateSirVisibilityToMembersPhase : SirPhase { | ||
|
||
context(SirPhase.Context) | ||
override suspend fun execute() { | ||
sirProvider.allLocalDeclarations | ||
.filterIsInstance<SirCallableDeclaration>() | ||
.forEach { | ||
updateVisibility(it) | ||
} | ||
} | ||
|
||
private fun updateVisibility(sirCallableDeclaration: SirCallableDeclaration) { | ||
when (sirCallableDeclaration) { | ||
is SirConstructor -> updateVisibility(sirCallableDeclaration) | ||
is SirSimpleFunction -> updateVisibility(sirCallableDeclaration) | ||
is SirProperty -> updateVisibility(sirCallableDeclaration) | ||
} | ||
} | ||
|
||
private fun updateVisibility(sirConstructor: SirConstructor) { | ||
val allConstraints = listOfNotNull( | ||
sirConstructor.visibility, | ||
sirConstructor.parent.classDeclaration.visibility, | ||
) + | ||
sirConstructor.valueParameters.map { it.type.visibilityConstraint } | ||
|
||
sirConstructor.visibility = allConstraints.minimumVisibility() | ||
} | ||
|
||
private fun updateVisibility(sirFunction: SirSimpleFunction) { | ||
val allConstraints = listOfNotNull( | ||
sirFunction.visibility, | ||
sirFunction.memberOwner?.visibility, | ||
sirFunction.returnType.visibilityConstraint, | ||
) + | ||
sirFunction.valueParameters.map { it.type.visibilityConstraint } + | ||
sirFunction.typeParameters.flatMap { typeParameter -> typeParameter.bounds.map { it.visibilityConstraint } } | ||
|
||
sirFunction.visibility = allConstraints.minimumVisibility() | ||
} | ||
|
||
private fun updateVisibility(sirProperty: SirProperty) { | ||
val allConstraints = listOfNotNull( | ||
sirProperty.visibility, | ||
sirProperty.memberOwner?.visibility, | ||
sirProperty.type.visibilityConstraint, | ||
) | ||
|
||
sirProperty.visibility = allConstraints.minimumVisibility() | ||
} | ||
} |
101 changes: 101 additions & 0 deletions
101
...ommonMain/kotlin/co/touchlab/skie/phases/sir/type/PropagateSirVisibilityToClassesPhase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package co.touchlab.skie.phases.sir.type | ||
|
||
import co.touchlab.skie.kir.element.KirClass | ||
import co.touchlab.skie.phases.SirPhase | ||
import co.touchlab.skie.sir.element.SirClass | ||
import co.touchlab.skie.sir.element.SirModule | ||
import co.touchlab.skie.sir.element.SirVisibility | ||
import co.touchlab.skie.sir.element.coerceAtMostInSwift | ||
import co.touchlab.skie.sir.element.kirClassOrNull | ||
import co.touchlab.skie.sir.element.superClassType | ||
import co.touchlab.skie.sir.element.superProtocolTypes | ||
import co.touchlab.skie.sir.type.SirType | ||
|
||
object PropagateSirVisibilityToClassesPhase : SirPhase { | ||
|
||
context(SirPhase.Context) | ||
override suspend fun execute() { | ||
val updaterProvider = TypeVisibilityUpdaterProvider(sirProvider.allLocalClasses) | ||
|
||
updaterProvider.allTypeVisibilityUpdaters.forEach { | ||
it.propagateVisibility() | ||
} | ||
} | ||
|
||
private class TypeVisibilityUpdaterProvider( | ||
sirClasses: List<SirClass>, | ||
) { | ||
|
||
private val cache = sirClasses.associateWith { ClassVisibilityUpdater(it) } | ||
|
||
init { | ||
cache.values.forEach { | ||
it.initialize(this) | ||
} | ||
} | ||
|
||
val allTypeVisibilityUpdaters: Collection<ClassVisibilityUpdater> = cache.values | ||
|
||
operator fun get(sirClass: SirClass): ClassVisibilityUpdater = | ||
cache.getValue(sirClass) | ||
} | ||
|
||
private class ClassVisibilityUpdater(private val sirClass: SirClass) { | ||
|
||
private val directDependents = mutableListOf<ClassVisibilityUpdater>() | ||
|
||
fun initialize(typeVisibilityUpdaterProvider: TypeVisibilityUpdaterProvider) { | ||
getDependencies() | ||
.filter { it.module is SirModule.Skie || it.module is SirModule.Kotlin } | ||
.forEach { | ||
typeVisibilityUpdaterProvider[it].registerDirectDependentDeclaration(this) | ||
} | ||
} | ||
|
||
private fun registerDirectDependentDeclaration(typeVisibilityUpdater: ClassVisibilityUpdater) { | ||
directDependents.add(typeVisibilityUpdater) | ||
} | ||
|
||
fun propagateVisibility() { | ||
directDependents.forEach { | ||
it.coerceVisibilityAtMost(sirClass.visibility) | ||
} | ||
} | ||
|
||
private fun coerceVisibilityAtMost(limit: SirVisibility) { | ||
val newVisibility = sirClass.visibility.coerceAtMostInSwift(limit) | ||
|
||
if (sirClass.visibility == newVisibility) { | ||
return | ||
} | ||
|
||
sirClass.visibility = newVisibility | ||
|
||
propagateVisibility() | ||
} | ||
|
||
private fun getDependencies(): Set<SirClass> = | ||
setOfNotNull( | ||
sirClass.namespace?.classDeclaration, | ||
(sirClass.kirClassOrNull?.parent as? KirClass)?.originalSirClass, | ||
) + | ||
sirClass.typeParameters.flatMap { typeParameter -> typeParameter.bounds.flatMap { it.referencedClasses } }.toSet() + | ||
getSuperTypesDependencies() | ||
|
||
private fun getSuperTypesDependencies(): List<SirClass> = | ||
if (sirClass.kind != SirClass.Kind.Protocol) { | ||
val classSuperType = listOfNotNull(sirClass.superClassType) | ||
val protocolSuperTypes = sirClass.superProtocolTypes | ||
|
||
val consideredTypes = protocolSuperTypes.flatMap { it.typeArguments } + classSuperType | ||
|
||
consideredTypes.flatMap { it.referencedClasses } | ||
} else { | ||
sirClass.superTypes.flatMap { it.referencedClasses } | ||
} | ||
|
||
private val SirType.referencedClasses: List<SirClass> | ||
get() = this.normalizedEvaluatedType().referencedTypeDeclarations | ||
.map { it as? SirClass ?: error("Normalized type should only reference SirClasses: $it") } | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...nMain/kotlin/co/touchlab/skie/phases/sir/type/PropagateSirVisibilityToTypeAliasesPhase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package co.touchlab.skie.phases.sir.type | ||
|
||
import co.touchlab.skie.phases.SirPhase | ||
import co.touchlab.skie.sir.element.SirTypeAlias | ||
import co.touchlab.skie.sir.element.minimumVisibility | ||
import co.touchlab.skie.sir.type.visibilityConstraint | ||
|
||
object PropagateSirVisibilityToTypeAliasesPhase : SirPhase { | ||
|
||
context(SirPhase.Context) | ||
override suspend fun execute() { | ||
sirProvider.allLocalTypeAliases.forEach { | ||
updateVisibility(it) | ||
} | ||
} | ||
|
||
private fun updateVisibility(sirTypeAlias: SirTypeAlias) { | ||
val allConstraints = listOfNotNull( | ||
sirTypeAlias.visibility, | ||
sirTypeAlias.namespace?.classDeclaration?.visibility, | ||
) + | ||
sirTypeAlias.type.visibilityConstraint + | ||
sirTypeAlias.typeParameters.flatMap { typeParameter -> typeParameter.bounds.map { it.visibilityConstraint } } | ||
|
||
sirTypeAlias.visibility = allConstraints.minimumVisibility() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.