Create FIR transformer generator #KT-24062 Fixed

This commit is contained in:
Simon Ogorodnik
2018-03-16 21:06:02 +03:00
committed by Mikhail Glukhikh
parent fda49736ee
commit 2ddf52123a
10 changed files with 552 additions and 7 deletions
@@ -0,0 +1,8 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir
annotation class BaseTransformedType
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.fir
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
@@ -24,4 +26,7 @@ interface FirElement {
fun acceptChildren(visitor: FirVisitorVoid) =
acceptChildren(visitor, null)
fun <E : FirElement, D> transform(visitor: FirTransformer<D>, data: D): CompositeTransformResult<E> =
accept(visitor, data) as CompositeTransformResult<E>
}
@@ -5,9 +5,11 @@
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.BaseTransformedType
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.visitors.FirVisitor
@BaseTransformedType
interface FirDeclaration : FirElement {
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
@@ -14,6 +14,7 @@ abstract class AbstractVisitorGenerator(val referencesData: DataCollector.Refere
returnType: String,
override: Boolean = false,
final: Boolean = false,
typeParameters: List<String> = emptyList(),
body: (Printer.() -> Unit)?
) {
@@ -31,7 +32,13 @@ abstract class AbstractVisitorGenerator(val referencesData: DataCollector.Refere
printWithNoIndent("override ")
}
}
printWithNoIndent("fun ", name, "(")
printWithNoIndent("fun ")
if (typeParameters.isNotEmpty()) {
printWithNoIndent("<")
separatedOneLine(typeParameters, ", ")
printWithNoIndent("> ")
}
printWithNoIndent(name, "(")
parameters
.flatMap { (a, b) ->
listOf(a, ": ", b, ", ")
@@ -109,6 +116,12 @@ abstract class AbstractVisitorGenerator(val referencesData: DataCollector.Refere
return builder.toString()
}
fun allElementTypes() =
referencesData.back.let {
it.keys + it.values.flatten()
}.distinct()
abstract fun Printer.generateContent()
}
@@ -13,6 +13,7 @@ class DataCollector {
private val references = mutableMapOf<String, List<String>>()
private val packagePerClass = mutableMapOf<String, FqName>()
private val baseTransformedTypes = mutableListOf<String>()
fun readFile(file: KtFile) {
file.acceptChildren(object : KtVisitorVoid() {
@@ -26,6 +27,12 @@ class DataCollector {
val className = klass.name
if (klass.isInterface() && className != null) {
packagePerClass[className] = file.packageFqName
val isBaseTT = klass.annotationEntries.any {
it.shortName?.asString() == BASE_TRANSFORMED_TYPE_ANNOTATION_NAME
}
if (isBaseTT) {
baseTransformedTypes += className
}
val manual = klass.superTypeListEntries.find {
it.typeReference?.findDescendantOfType<KtAnnotationEntry> { annotationEntry ->
@@ -75,9 +82,15 @@ class DataCollector {
return ReferencesData(
cleanBack.computeBackReferences().sorted(),
cleanBack.sorted(),
packagePerClass.filterKeys { it in keysToKeep }.values.distinct().sortedBy { it.asString() }
packagePerClass.filterKeys { it in keysToKeep }.values.distinct().sortedBy { it.asString() },
baseTransformedTypes.sorted()
)
}
data class ReferencesData(val direct: Map<String, List<String>>, val back: Map<String, List<String>>, val usedPackages: List<FqName>)
data class ReferencesData(
val direct: Map<String, List<String>>,
val back: Map<String, List<String>>,
val usedPackages: List<FqName>,
val baseTransformedTypes: List<String>
)
}
@@ -0,0 +1,108 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.visitors.generator
import org.jetbrains.kotlin.utils.Printer
class ParametricTransformerGenerator(data: DataCollector.ReferencesData) : AbstractVisitorGenerator(data) {
override fun Printer.generateContent() {
println("abstract class $PARAMETRIC_TRANSFORMER_NAME<in D> : $SIMPLE_VISITOR_NAME<$TRANSFORMER_RESULT_NAME<$FIR_ELEMENT_CLASS_NAME>, D>() {")
indented {
generateFunction(
"transformElement",
mapOf(
"element" to "E",
"data" to "D"
),
constructCompositeBoxType("E"),
typeParameters = listOf("E : $FIR_ELEMENT_CLASS_NAME"),
body = null
)
referencesData.walkHierarchyTopDown(FIR_ELEMENT_CLASS_NAME) { parent, className ->
generateTransformMethod(className, parent)
}
allElementTypes().forEach {
generateTrampolineVisit(it)
}
}
println("}")
}
fun constructCompositeBoxType(type: String): String {
return "$TRANSFORMER_RESULT_NAME<$type>"
}
val baseTypes = mutableMapOf<String, String>().also {
for (baseTransformedType in referencesData.baseTransformedTypes) {
it[baseTransformedType] = baseTransformedType
}
data.walkHierarchyTopDown(FIR_ELEMENT_CLASS_NAME) { parent, element ->
it[element] = it[parent] ?: return@walkHierarchyTopDown
}
}
fun Printer.generateTrampolineVisit(className: String) {
val shortcutName = className.classNameWithoutFir
val parameterName = shortcutName.decapitalize().safeName
generateFunction(
name = "visit$shortcutName",
parameters = mapOf(
parameterName to className,
"data" to "D"
),
returnType = constructCompositeBoxType(FIR_ELEMENT_CLASS_NAME),
override = true,
final = true
) {
print("return ")
generateCall("transform$shortcutName", listOf(parameterName, "data"))
println()
}
}
fun Printer.generateTransformMethod(className: String, parent: String) {
val baseType = baseTypes[className]
val shortcutName = className.classNameWithoutFir
val parameterName = shortcutName.decapitalize().safeName
if (baseType == null) {
generateFunction(
"transform$shortcutName",
mapOf(
parameterName to "E",
"data" to "D"
),
constructCompositeBoxType("E"),
typeParameters = listOf("E : $parent")
) {
print("return ")
generateCall("transform${parent.classNameWithoutFir}", listOf(parameterName, "data"))
printlnWithNoIndent()
}
} else {
generateFunction(
"transform$shortcutName",
mapOf(
parameterName to className,
"data" to "D"
),
constructCompositeBoxType(baseType)
) {
print("return ")
generateCall("transform${parent.classNameWithoutFir}", listOf(parameterName, "data"))
printlnWithNoIndent()
}
}
}
}
@@ -24,10 +24,7 @@ class UnitVisitorGenerator(referencesData: DataCollector.ReferencesData) : Abstr
generateVisit(klass, parent)
}
val trampolines = referencesData.back.let {
it.keys + it.values.flatten()
}.distinct()
trampolines.forEach {
allElementTypes().forEach {
generateTrampolineVisit(it)
}
@@ -18,6 +18,10 @@ const val FIR_ELEMENT_CLASS_NAME = "FirElement"
const val VISITOR_PACKAGE = "org.jetbrains.kotlin.fir.visitors"
const val SIMPLE_VISITOR_NAME = "FirVisitor"
const val UNIT_VISITOR_NAME = "FirVisitorVoid"
const val PARAMETRIC_TRANSFORMER_NAME = "FirTransformer"
const val TRANSFORMER_RESULT_NAME = "CompositeTransformResult"
const val BASE_TRANSFORMED_TYPE_ANNOTATION_NAME = "BaseTransformedType"
const val VISITED_SUPERTYPE_ANNOTATION_NAME = "VisitedSupertype"
const val WARNING_GENERATED_FILE =
@@ -55,6 +59,7 @@ fun main(args: Array<String>) {
SimpleVisitorGenerator(data).runGenerator(packageDirectory.resolve("${SIMPLE_VISITOR_NAME}Generated.kt"))
UnitVisitorGenerator(data).runGenerator(packageDirectory.resolve("${UNIT_VISITOR_NAME}Generated.kt"))
ParametricTransformerGenerator(data).runGenerator(packageDirectory.resolve("${PARAMETRIC_TRANSFORMER_NAME}Generated.kt"))
}
}
@@ -0,0 +1,35 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.visitors
import org.jetbrains.kotlin.fir.FirElement
@Suppress("UNSUPPORTED_FEATURE")
inline class CompositeTransformResult<out T : Any>(val a: Any) {
companion object {
fun <T : Any> empty() = CompositeTransformResult<T>(emptyList<T>())
fun <T : Any> single(t: T) = CompositeTransformResult<T>(t)
fun <T : Any> many(l: List<T>) = CompositeTransformResult<T>(l)
}
val isSingle get() = a !is List<*>
val isEmpty get() = a is List<*> && a.isEmpty()
val single: T
get() {
assert(isSingle)
return a as T
}
val list: List<T>
get() {
return a as List<T>
}
}
inline fun <reified T : FirElement> T.compose() = CompositeTransformResult.single(this)
@@ -0,0 +1,359 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.visitors
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.types.*
/** This file generated by :compiler:fir:tree:generateVisitors. DO NOT MODIFY MANUALLY! */
abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirElement>, D>() {
abstract fun <E : FirElement> transformElement(element: E, data: D): CompositeTransformResult<E>
open fun transformDeclaration(declaration: FirDeclaration, data: D): CompositeTransformResult<FirDeclaration> {
return transformElement(declaration, data)
}
open fun transformCallableMember(callableMember: FirCallableMember, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclaration(callableMember, data)
}
open fun transformDeclarationWithBody(declarationWithBody: FirDeclarationWithBody, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclaration(declarationWithBody, data)
}
open fun transformAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
data: D
): CompositeTransformResult<FirDeclaration> {
return transformDeclarationWithBody(anonymousInitializer, data)
}
open fun transformFunction(function: FirFunction, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclarationWithBody(function, data)
}
open fun transformConstructor(constructor: FirConstructor, data: D): CompositeTransformResult<FirDeclaration> {
return transformFunction(constructor, data)
}
open fun transformNamedFunction(namedFunction: FirNamedFunction, data: D): CompositeTransformResult<FirDeclaration> {
return transformFunction(namedFunction, data)
}
open fun transformPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: D): CompositeTransformResult<FirDeclaration> {
return transformFunction(propertyAccessor, data)
}
open fun transformErrorDeclaration(errorDeclaration: FirErrorDeclaration, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclaration(errorDeclaration, data)
}
open fun transformNamedDeclaration(namedDeclaration: FirNamedDeclaration, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclaration(namedDeclaration, data)
}
open fun transformMemberDeclaration(memberDeclaration: FirMemberDeclaration, data: D): CompositeTransformResult<FirDeclaration> {
return transformNamedDeclaration(memberDeclaration, data)
}
open fun transformClass(klass: FirClass, data: D): CompositeTransformResult<FirDeclaration> {
return transformMemberDeclaration(klass, data)
}
open fun transformEnumEntry(enumEntry: FirEnumEntry, data: D): CompositeTransformResult<FirDeclaration> {
return transformClass(enumEntry, data)
}
open fun transformTypeAlias(typeAlias: FirTypeAlias, data: D): CompositeTransformResult<FirDeclaration> {
return transformMemberDeclaration(typeAlias, data)
}
open fun transformTypeParameter(typeParameter: FirTypeParameter, data: D): CompositeTransformResult<FirDeclaration> {
return transformNamedDeclaration(typeParameter, data)
}
open fun transformProperty(property: FirProperty, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclaration(property, data)
}
open fun transformTypedDeclaration(typedDeclaration: FirTypedDeclaration, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclaration(typedDeclaration, data)
}
open fun transformValueParameter(valueParameter: FirValueParameter, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclaration(valueParameter, data)
}
open fun transformVariable(variable: FirVariable, data: D): CompositeTransformResult<FirDeclaration> {
return transformDeclaration(variable, data)
}
open fun <E : FirElement> transformImport(import: E, data: D): CompositeTransformResult<E> {
return transformElement(import, data)
}
open fun <E : FirElement> transformPackageFragment(packageFragment: E, data: D): CompositeTransformResult<E> {
return transformElement(packageFragment, data)
}
open fun <E : FirPackageFragment> transformFile(file: E, data: D): CompositeTransformResult<E> {
return transformPackageFragment(file, data)
}
open fun <E : FirElement> transformStatement(statement: E, data: D): CompositeTransformResult<E> {
return transformElement(statement, data)
}
open fun <E : FirStatement> transformExpression(expression: E, data: D): CompositeTransformResult<E> {
return transformStatement(expression, data)
}
open fun <E : FirExpression> transformBody(body: E, data: D): CompositeTransformResult<E> {
return transformExpression(body, data)
}
open fun <E : FirExpression> transformCall(call: E, data: D): CompositeTransformResult<E> {
return transformExpression(call, data)
}
open fun <E : FirCall> transformAnnotationCall(annotationCall: E, data: D): CompositeTransformResult<E> {
return transformCall(annotationCall, data)
}
open fun <E : FirCall> transformConstructorCall(constructorCall: E, data: D): CompositeTransformResult<E> {
return transformCall(constructorCall, data)
}
open fun <E : FirElement> transformType(type: E, data: D): CompositeTransformResult<E> {
return transformElement(type, data)
}
open fun <E : FirType> transformDelegatedType(delegatedType: E, data: D): CompositeTransformResult<E> {
return transformType(delegatedType, data)
}
open fun <E : FirType> transformErrorType(errorType: E, data: D): CompositeTransformResult<E> {
return transformType(errorType, data)
}
open fun <E : FirType> transformImplicitType(implicitType: E, data: D): CompositeTransformResult<E> {
return transformType(implicitType, data)
}
open fun <E : FirType> transformTypeWithNullability(typeWithNullability: E, data: D): CompositeTransformResult<E> {
return transformType(typeWithNullability, data)
}
open fun <E : FirTypeWithNullability> transformDynamicType(dynamicType: E, data: D): CompositeTransformResult<E> {
return transformTypeWithNullability(dynamicType, data)
}
open fun <E : FirTypeWithNullability> transformFunctionType(functionType: E, data: D): CompositeTransformResult<E> {
return transformTypeWithNullability(functionType, data)
}
open fun <E : FirTypeWithNullability> transformResolvedType(resolvedType: E, data: D): CompositeTransformResult<E> {
return transformTypeWithNullability(resolvedType, data)
}
open fun <E : FirTypeWithNullability> transformUserType(userType: E, data: D): CompositeTransformResult<E> {
return transformTypeWithNullability(userType, data)
}
open fun <E : FirElement> transformTypeProjection(typeProjection: E, data: D): CompositeTransformResult<E> {
return transformElement(typeProjection, data)
}
open fun <E : FirTypeProjection> transformStarProjection(starProjection: E, data: D): CompositeTransformResult<E> {
return transformTypeProjection(starProjection, data)
}
open fun <E : FirTypeProjection> transformTypeProjectionWithVariance(
typeProjectionWithVariance: E,
data: D
): CompositeTransformResult<E> {
return transformTypeProjection(typeProjectionWithVariance, data)
}
final override fun visitCall(call: FirCall, data: D): CompositeTransformResult<FirElement> {
return transformCall(call, data)
}
final override fun visitClass(klass: FirClass, data: D): CompositeTransformResult<FirElement> {
return transformClass(klass, data)
}
final override fun visitDeclaration(declaration: FirDeclaration, data: D): CompositeTransformResult<FirElement> {
return transformDeclaration(declaration, data)
}
final override fun visitDeclarationWithBody(
declarationWithBody: FirDeclarationWithBody,
data: D
): CompositeTransformResult<FirElement> {
return transformDeclarationWithBody(declarationWithBody, data)
}
final override fun visitElement(element: FirElement, data: D): CompositeTransformResult<FirElement> {
return transformElement(element, data)
}
final override fun visitExpression(expression: FirExpression, data: D): CompositeTransformResult<FirElement> {
return transformExpression(expression, data)
}
final override fun visitFunction(function: FirFunction, data: D): CompositeTransformResult<FirElement> {
return transformFunction(function, data)
}
final override fun visitMemberDeclaration(memberDeclaration: FirMemberDeclaration, data: D): CompositeTransformResult<FirElement> {
return transformMemberDeclaration(memberDeclaration, data)
}
final override fun visitNamedDeclaration(namedDeclaration: FirNamedDeclaration, data: D): CompositeTransformResult<FirElement> {
return transformNamedDeclaration(namedDeclaration, data)
}
final override fun visitPackageFragment(packageFragment: FirPackageFragment, data: D): CompositeTransformResult<FirElement> {
return transformPackageFragment(packageFragment, data)
}
final override fun visitStatement(statement: FirStatement, data: D): CompositeTransformResult<FirElement> {
return transformStatement(statement, data)
}
final override fun visitType(type: FirType, data: D): CompositeTransformResult<FirElement> {
return transformType(type, data)
}
final override fun visitTypeProjection(typeProjection: FirTypeProjection, data: D): CompositeTransformResult<FirElement> {
return transformTypeProjection(typeProjection, data)
}
final override fun visitTypeWithNullability(
typeWithNullability: FirTypeWithNullability,
data: D
): CompositeTransformResult<FirElement> {
return transformTypeWithNullability(typeWithNullability, data)
}
final override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: D): CompositeTransformResult<FirElement> {
return transformAnnotationCall(annotationCall, data)
}
final override fun visitConstructorCall(constructorCall: FirConstructorCall, data: D): CompositeTransformResult<FirElement> {
return transformConstructorCall(constructorCall, data)
}
final override fun visitEnumEntry(enumEntry: FirEnumEntry, data: D): CompositeTransformResult<FirElement> {
return transformEnumEntry(enumEntry, data)
}
final override fun visitCallableMember(callableMember: FirCallableMember, data: D): CompositeTransformResult<FirElement> {
return transformCallableMember(callableMember, data)
}
final override fun visitErrorDeclaration(errorDeclaration: FirErrorDeclaration, data: D): CompositeTransformResult<FirElement> {
return transformErrorDeclaration(errorDeclaration, data)
}
final override fun visitProperty(property: FirProperty, data: D): CompositeTransformResult<FirElement> {
return transformProperty(property, data)
}
final override fun visitTypedDeclaration(typedDeclaration: FirTypedDeclaration, data: D): CompositeTransformResult<FirElement> {
return transformTypedDeclaration(typedDeclaration, data)
}
final override fun visitValueParameter(valueParameter: FirValueParameter, data: D): CompositeTransformResult<FirElement> {
return transformValueParameter(valueParameter, data)
}
final override fun visitVariable(variable: FirVariable, data: D): CompositeTransformResult<FirElement> {
return transformVariable(variable, data)
}
final override fun visitAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
data: D
): CompositeTransformResult<FirElement> {
return transformAnonymousInitializer(anonymousInitializer, data)
}
final override fun visitImport(import: FirImport, data: D): CompositeTransformResult<FirElement> {
return transformImport(import, data)
}
final override fun visitBody(body: FirBody, data: D): CompositeTransformResult<FirElement> {
return transformBody(body, data)
}
final override fun visitConstructor(constructor: FirConstructor, data: D): CompositeTransformResult<FirElement> {
return transformConstructor(constructor, data)
}
final override fun visitNamedFunction(namedFunction: FirNamedFunction, data: D): CompositeTransformResult<FirElement> {
return transformNamedFunction(namedFunction, data)
}
final override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: D): CompositeTransformResult<FirElement> {
return transformPropertyAccessor(propertyAccessor, data)
}
final override fun visitTypeAlias(typeAlias: FirTypeAlias, data: D): CompositeTransformResult<FirElement> {
return transformTypeAlias(typeAlias, data)
}
final override fun visitTypeParameter(typeParameter: FirTypeParameter, data: D): CompositeTransformResult<FirElement> {
return transformTypeParameter(typeParameter, data)
}
final override fun visitFile(file: FirFile, data: D): CompositeTransformResult<FirElement> {
return transformFile(file, data)
}
final override fun visitDelegatedType(delegatedType: FirDelegatedType, data: D): CompositeTransformResult<FirElement> {
return transformDelegatedType(delegatedType, data)
}
final override fun visitErrorType(errorType: FirErrorType, data: D): CompositeTransformResult<FirElement> {
return transformErrorType(errorType, data)
}
final override fun visitImplicitType(implicitType: FirImplicitType, data: D): CompositeTransformResult<FirElement> {
return transformImplicitType(implicitType, data)
}
final override fun visitStarProjection(starProjection: FirStarProjection, data: D): CompositeTransformResult<FirElement> {
return transformStarProjection(starProjection, data)
}
final override fun visitTypeProjectionWithVariance(
typeProjectionWithVariance: FirTypeProjectionWithVariance,
data: D
): CompositeTransformResult<FirElement> {
return transformTypeProjectionWithVariance(typeProjectionWithVariance, data)
}
final override fun visitDynamicType(dynamicType: FirDynamicType, data: D): CompositeTransformResult<FirElement> {
return transformDynamicType(dynamicType, data)
}
final override fun visitFunctionType(functionType: FirFunctionType, data: D): CompositeTransformResult<FirElement> {
return transformFunctionType(functionType, data)
}
final override fun visitResolvedType(resolvedType: FirResolvedType, data: D): CompositeTransformResult<FirElement> {
return transformResolvedType(resolvedType, data)
}
final override fun visitUserType(userType: FirUserType, data: D): CompositeTransformResult<FirElement> {
return transformUserType(userType, data)
}
}