Refactor sir from psi builder, in order to check transatability of psi element
Merge-request: KT-MR-14555 Merged-by: Artem Olkov <artem.olkov@jetbrains.com>
This commit is contained in:
@@ -8,6 +8,7 @@ package org.jetbrains.sir.passes.builder
|
|||||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
|
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
|
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.symbols.KtSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
@@ -20,56 +21,97 @@ import org.jetbrains.kotlin.sir.util.SirSwiftModule
|
|||||||
|
|
||||||
public fun KtAnalysisSession.buildSirDeclarationList(from: KtElement): List<SirDeclaration> {
|
public fun KtAnalysisSession.buildSirDeclarationList(from: KtElement): List<SirDeclaration> {
|
||||||
val res = mutableListOf<SirDeclaration>()
|
val res = mutableListOf<SirDeclaration>()
|
||||||
from.accept(Visitor(res, this))
|
from.accept(
|
||||||
|
PsiToSirTranslationCollector(
|
||||||
|
res,
|
||||||
|
PsiToSirTranslatableChecker(this),
|
||||||
|
PsiToSirElementTranslation(this)
|
||||||
|
)
|
||||||
|
)
|
||||||
return res.toList()
|
return res.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Visitor(
|
private abstract class PsiToSirTranslation<T>(
|
||||||
|
val analysisSession: KtAnalysisSession,
|
||||||
|
) : KtVisitor<T, Unit?>() {
|
||||||
|
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<SirDeclaration>,
|
private val res: MutableList<SirDeclaration>,
|
||||||
private val analysisSession: KtAnalysisSession
|
private val checker: PsiToSirTranslation<Boolean>,
|
||||||
|
private val translator: PsiToSirTranslation<SirDeclaration>,
|
||||||
) : KtTreeVisitorVoid() {
|
) : KtTreeVisitorVoid() {
|
||||||
|
|
||||||
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
||||||
// we do not handle inner declarations of class currently. No need to go deeper.
|
classOrObject.checkAndTranslate(null)
|
||||||
// super.visitClassOrObject(classOrObject)
|
|
||||||
with(analysisSession) {
|
|
||||||
classOrObject.process {
|
|
||||||
buildSirClassFromPsi(classOrObject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||||
super.visitNamedFunction(function)
|
function.checkAndTranslate(null)
|
||||||
with(analysisSession) {
|
|
||||||
function.process {
|
|
||||||
buildSirFunctionFromPsi(function)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitProperty(property: KtProperty) {
|
override fun visitProperty(property: KtProperty) {
|
||||||
super.visitProperty(property)
|
property.checkAndTranslate(null)
|
||||||
with(analysisSession) {
|
|
||||||
property.process {
|
|
||||||
buildSirVariableFromPsi(property)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <T : KtDeclaration> T.process(converter: T.() -> SirDeclaration?) {
|
private fun KtElement.checkAndTranslate(data: Unit?) = takeIf { it.accept(checker, data) }
|
||||||
this.takeIf { it.isPublic }
|
?.let { res.add(it.accept(translator, data)) }
|
||||||
?.let(converter)
|
}
|
||||||
?.let { res.add(it) }
|
|
||||||
|
private class PsiToSirTranslatableChecker(
|
||||||
|
analysisSession: KtAnalysisSession,
|
||||||
|
) : PsiToSirTranslation<Boolean>(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<SirDeclaration>(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)
|
context(KtAnalysisSession)
|
||||||
internal fun buildSirClassFromPsi(classOrObject: KtClassOrObject): SirNamedDeclaration? {
|
internal fun buildSirClassFromPsi(classOrObject: KtClassOrObject): SirNamedDeclaration {
|
||||||
val symbol = classOrObject
|
// if there is no symbol - it will be handled by `PsiToSirTranslatableChecker`
|
||||||
.getNamedClassOrObjectSymbol()
|
val symbol = classOrObject.getNamedClassOrObjectSymbol()!!
|
||||||
?.takeIf { it.isConsumableBySirBuilder() }
|
|
||||||
?: return null // todo: error handling strategy: KT-65980
|
|
||||||
return buildClass {
|
return buildClass {
|
||||||
name = classOrObject.name ?: "UNKNOWN_CLASS" // todo: error handling strategy: KT-65980
|
name = classOrObject.name ?: "UNKNOWN_CLASS" // todo: error handling strategy: KT-65980
|
||||||
origin = KotlinSource(symbol)
|
origin = KotlinSource(symbol)
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
import KotlinBridges
|
import KotlinBridges
|
||||||
|
import KotlinRuntime
|
||||||
|
|
||||||
public class Foo {
|
public class Foo {
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
// we do not support extention fun. This should not be exported
|
||||||
|
fun Int.foo(): Unit = TODO()
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
// we do not support sus fun. This should not be exported
|
||||||
|
suspend fun suspending_fun(): Int = TODO()
|
||||||
Reference in New Issue
Block a user