From ff5098d7168406ba0e38e6b5fe409d644cbb1038 Mon Sep 17 00:00:00 2001 From: Artem Olkov Date: Wed, 28 Feb 2024 10:32:11 +0000 Subject: [PATCH] Refactor sir from psi builder, in order to check transatability of psi element Merge-request: KT-MR-14555 Merged-by: Artem Olkov --- .../sir/passes/builder/SirFromPsiBuilder.kt | 104 ++++++++++++------ .../classes/golden_result/result.swift | 1 + .../functions/input_root/extension_fun.kt | 2 + .../functions/input_root/suspend_function.kt | 2 + 4 files changed, 78 insertions(+), 31 deletions(-) create mode 100644 native/swift/swift-export-standalone/testData/functions/input_root/extension_fun.kt create mode 100644 native/swift/swift-export-standalone/testData/functions/input_root/suspend_function.kt diff --git a/native/swift/sir-passes/src/org/jetbrains/sir/passes/builder/SirFromPsiBuilder.kt b/native/swift/sir-passes/src/org/jetbrains/sir/passes/builder/SirFromPsiBuilder.kt index 883bd642b51..26df7b4f70f 100644 --- a/native/swift/sir-passes/src/org/jetbrains/sir/passes/builder/SirFromPsiBuilder.kt +++ b/native/swift/sir-passes/src/org/jetbrains/sir/passes/builder/SirFromPsiBuilder.kt @@ -8,6 +8,7 @@ package org.jetbrains.sir.passes.builder import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.descriptors.Modality @@ -20,56 +21,97 @@ import org.jetbrains.kotlin.sir.util.SirSwiftModule public fun KtAnalysisSession.buildSirDeclarationList(from: KtElement): List { val res = mutableListOf() - from.accept(Visitor(res, this)) + from.accept( + PsiToSirTranslationCollector( + res, + PsiToSirTranslatableChecker(this), + PsiToSirElementTranslation(this) + ) + ) return res.toList() } -private class Visitor( +private abstract class PsiToSirTranslation( + val analysisSession: KtAnalysisSession, +) : KtVisitor() { + abstract override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Unit?): T + abstract override fun visitNamedFunction(function: KtNamedFunction, data: Unit?): T + abstract override fun visitProperty(property: KtProperty, data: Unit?): T +} + +private class PsiToSirTranslationCollector( private val res: MutableList, - private val analysisSession: KtAnalysisSession + private val checker: PsiToSirTranslation, + private val translator: PsiToSirTranslation, ) : KtTreeVisitorVoid() { override fun visitClassOrObject(classOrObject: KtClassOrObject) { - // we do not handle inner declarations of class currently. No need to go deeper. - // super.visitClassOrObject(classOrObject) - with(analysisSession) { - classOrObject.process { - buildSirClassFromPsi(classOrObject) - } - } + classOrObject.checkAndTranslate(null) } override fun visitNamedFunction(function: KtNamedFunction) { - super.visitNamedFunction(function) - with(analysisSession) { - function.process { - buildSirFunctionFromPsi(function) - } - } + function.checkAndTranslate(null) } override fun visitProperty(property: KtProperty) { - super.visitProperty(property) - with(analysisSession) { - property.process { - buildSirVariableFromPsi(property) - } - } + property.checkAndTranslate(null) } - private inline fun T.process(converter: T.() -> SirDeclaration?) { - this.takeIf { it.isPublic } - ?.let(converter) - ?.let { res.add(it) } + private fun KtElement.checkAndTranslate(data: Unit?) = takeIf { it.accept(checker, data) } + ?.let { res.add(it.accept(translator, data)) } +} + +private class PsiToSirTranslatableChecker( + analysisSession: KtAnalysisSession, +) : PsiToSirTranslation(analysisSession) { + + override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Unit?): Boolean = with(analysisSession) { + return classOrObject.isPublic + && classOrObject.getNamedClassOrObjectSymbol()?.isConsumableBySirBuilder() ?: false + } + + override fun visitNamedFunction(function: KtNamedFunction, data: Unit?): Boolean = with(analysisSession) { + val functionIsPublicAndTopLevel = function.isPublic + && function.isTopLevel + && !function.isAnonymous + val functionSymbolIsTranslatable = (function.getFunctionLikeSymbol() as? KtFunctionSymbol) + ?.let { symbol -> + !symbol.isSuspend + && !symbol.isInline + && !symbol.isExtension + && !symbol.isOperator + } + ?: true + return functionIsPublicAndTopLevel && functionSymbolIsTranslatable + } + + override fun visitProperty(property: KtProperty, data: Unit?): Boolean { + return property.isPublic + && property.isTopLevel + } +} + +private class PsiToSirElementTranslation( + analysisSession: KtAnalysisSession, +) : PsiToSirTranslation(analysisSession) { + + override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Unit?): SirDeclaration = with(analysisSession) { + buildSirClassFromPsi(classOrObject) + } + + override fun visitNamedFunction(function: KtNamedFunction, data: Unit?): SirDeclaration = with(analysisSession) { + buildSirFunctionFromPsi(function) + } + + override fun visitProperty(property: KtProperty, data: Unit?): SirDeclaration = with(analysisSession) { + buildSirVariableFromPsi(property) } } context(KtAnalysisSession) -internal fun buildSirClassFromPsi(classOrObject: KtClassOrObject): SirNamedDeclaration? { - val symbol = classOrObject - .getNamedClassOrObjectSymbol() - ?.takeIf { it.isConsumableBySirBuilder() } - ?: return null // todo: error handling strategy: KT-65980 +internal fun buildSirClassFromPsi(classOrObject: KtClassOrObject): SirNamedDeclaration { + // if there is no symbol - it will be handled by `PsiToSirTranslatableChecker` + val symbol = classOrObject.getNamedClassOrObjectSymbol()!! return buildClass { name = classOrObject.name ?: "UNKNOWN_CLASS" // todo: error handling strategy: KT-65980 origin = KotlinSource(symbol) diff --git a/native/swift/swift-export-standalone/testData/classes/golden_result/result.swift b/native/swift/swift-export-standalone/testData/classes/golden_result/result.swift index 0942b6ae230..8e4b6d25f6e 100644 --- a/native/swift/swift-export-standalone/testData/classes/golden_result/result.swift +++ b/native/swift/swift-export-standalone/testData/classes/golden_result/result.swift @@ -1,4 +1,5 @@ import KotlinBridges +import KotlinRuntime public class Foo { } diff --git a/native/swift/swift-export-standalone/testData/functions/input_root/extension_fun.kt b/native/swift/swift-export-standalone/testData/functions/input_root/extension_fun.kt new file mode 100644 index 00000000000..d668300da6e --- /dev/null +++ b/native/swift/swift-export-standalone/testData/functions/input_root/extension_fun.kt @@ -0,0 +1,2 @@ +// we do not support extention fun. This should not be exported +fun Int.foo(): Unit = TODO() \ No newline at end of file diff --git a/native/swift/swift-export-standalone/testData/functions/input_root/suspend_function.kt b/native/swift/swift-export-standalone/testData/functions/input_root/suspend_function.kt new file mode 100644 index 00000000000..c9aac14d1b6 --- /dev/null +++ b/native/swift/swift-export-standalone/testData/functions/input_root/suspend_function.kt @@ -0,0 +1,2 @@ +// we do not support sus fun. This should not be exported +suspend fun suspending_fun(): Int = TODO()