[FIR] Reorganize some utility code of tree generator

This commit is contained in:
Dmitriy Novozhilov
2020-01-30 14:43:19 +03:00
parent f7c784adeb
commit fcd9ef043c
8 changed files with 160 additions and 110 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeImplementa
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind.Object
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind.OpenClass
import org.jetbrains.kotlin.fir.tree.generator.util.traverseParents
object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() {
private lateinit var abstractAnnotatedElement: Implementation
@@ -5,10 +5,8 @@
package org.jetbrains.kotlin.fir.tree.generator
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.printer.GENERATED_MESSAGE
import org.jetbrains.kotlin.fir.tree.generator.printer.printElements
import org.jetbrains.kotlin.fir.tree.generator.util.*
import java.io.File
@@ -22,110 +20,6 @@ fun main(args: Array<String>) {
configureInterfacesAndAbstractClasses(FirTreeBuilder)
removePreviousGeneratedFiles(generationPath)
printElements(FirTreeBuilder, generationPath)
// printTable(FirTreeBuilder)
// printInterfaceClassGraph(FirTreeBuilder)
// printFieldUsageTable(FirTreeBuilder)
// printHierarchyGraph(FirTreeBuilder)
}
fun Element.traverseParents(block: (Element) -> Unit) {
block(this)
parents.forEach { it.traverseParents(block) }
}
private fun printInterfaceClassGraph(builder: AbstractFirTreeBuilder) {
fun Implementation.Kind.toColor(): String = when (this) {
Implementation.Kind.Interface -> "green"
else -> "red"
}
val elements = builder.elements + builder.elements.flatMap { it.allParents }
data class Edge(val from: String, val to: String) {
override fun toString(): String {
return "$from -> $to"
}
}
File("FirTree.dot").printWriter().use { printer ->
with(printer) {
println("digraph FirTree {")
elements.forEach {
println(" ${it.type} [color=${it.kind!!.toColor()}]")
}
println()
val edges = mutableSetOf<Edge>()
elements.forEach { element ->
element.allParents.forEach { parent ->
edges += Edge(parent.type, element.type)
}
}
edges.forEach {
print(" ")
println(it)
}
println("}")
}
}
}
private fun detectBaseTransformerTypes(builder: AbstractFirTreeBuilder) {
val usedAsFieldType = mutableMapOf<AbstractElement, Boolean>().withDefault { false }
for (element in builder.elements) {
for (field in element.allFirFields) {
val fieldElement = when (field) {
is FirField -> field.element
is FieldList -> field.baseType as Element
else -> throw IllegalArgumentException()
}
usedAsFieldType[fieldElement] = true
}
}
for (element in builder.elements) {
element.traverseParents {
if (usedAsFieldType.getValue(it)) {
element.baseTransformerType = it
return@traverseParents
}
}
}
}
private fun removePreviousGeneratedFiles(generationPath: File) {
generationPath.walkTopDown().forEach {
if (it.isFile && it.readText().contains(GENERATED_MESSAGE)) {
it.delete()
}
}
}
private fun printTable(builder: AbstractFirTreeBuilder) {
val elements = builder.elements.filter { it.allImplementations.isNotEmpty() }
val fields = elements.flatMapTo(mutableSetOf()) { it.allFields }
val mapping = mutableMapOf<Element, Set<Field>>()
val fieldsCount = mutableMapOf<Field, Int>()
for (element in elements) {
val containingFields = mutableSetOf<Field>()
for (field in fields) {
if (field in element.allFields) {
containingFields += field
fieldsCount[field] = fieldsCount.getOrDefault(field, 0) + 1
}
}
mapping[element] = containingFields
}
val sortedFields = fields.sortedByDescending { fieldsCount[it] }
File("compiler/fir/tree/table.csv").printWriter().use { printer ->
with(printer) {
val delim = ","
print(delim)
println(sortedFields.joinToString(delim) { "${it.name}:${fieldsCount.getValue(it)}" })
for (element in elements) {
print(element.name + delim)
val containingFields = mapping.getValue(element)
println(sortedFields.joinToString(delim) { if (it in containingFields) "+" else "-" })
}
}
}
}
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.AbstractElement
import org.jetbrains.kotlin.fir.tree.generator.model.Element
import org.jetbrains.kotlin.fir.tree.generator.model.FieldList
import org.jetbrains.kotlin.fir.tree.generator.model.FirField
fun detectBaseTransformerTypes(builder: AbstractFirTreeBuilder) {
val usedAsFieldType = mutableMapOf<AbstractElement, Boolean>().withDefault { false }
for (element in builder.elements) {
for (field in element.allFirFields) {
val fieldElement = when (field) {
is FirField -> field.element
is FieldList -> field.baseType as Element
else -> throw IllegalArgumentException()
}
usedAsFieldType[fieldElement] = true
}
}
for (element in builder.elements) {
element.traverseParents {
if (usedAsFieldType.getValue(it)) {
element.baseTransformerType = it
return@traverseParents
}
}
}
}
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.printer.GENERATED_MESSAGE
import java.io.File
fun removePreviousGeneratedFiles(generationPath: File) {
generationPath.walkTopDown().forEach {
if (it.isFile && it.readText().contains(GENERATED_MESSAGE)) {
it.delete()
}
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.Element
import org.jetbrains.kotlin.fir.tree.generator.model.Field
import java.io.File
fun printFieldUsageTable(builder: AbstractFirTreeBuilder) {
val elements = builder.elements.filter { it.allImplementations.isNotEmpty() }
val fields = elements.flatMapTo(mutableSetOf()) { it.allFields }
val mapping = mutableMapOf<Element, Set<Field>>()
val fieldsCount = mutableMapOf<Field, Int>()
for (element in elements) {
val containingFields = mutableSetOf<Field>()
for (field in fields) {
if (field in element.allFields) {
containingFields += field
fieldsCount[field] = fieldsCount.getOrDefault(field, 0) + 1
}
}
mapping[element] = containingFields
}
val sortedFields = fields.sortedByDescending { fieldsCount[it] }
File("compiler/fir/tree/table.csv").printWriter().use { printer ->
with(printer) {
val delim = ","
print(delim)
println(sortedFields.joinToString(delim) { "${it.name}:${fieldsCount.getValue(it)}" })
for (element in elements) {
print(element.name + delim)
val containingFields = mapping.getValue(element)
println(sortedFields.joinToString(delim) { if (it in containingFields) "+" else "-" })
}
}
}
}
@@ -0,0 +1,47 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation
import java.io.File
fun printHierarchyGraph(builder: AbstractFirTreeBuilder) {
fun Implementation.Kind.toColor(): String = when (this) {
Implementation.Kind.Interface -> "green"
else -> "red"
}
val elements = builder.elements + builder.elements.flatMap { it.allParents }
data class Edge(val from: String, val to: String) {
override fun toString(): String {
return "$from -> $to"
}
}
File("FirTree.dot").printWriter().use { printer ->
with(printer) {
println("digraph FirTree {")
elements.forEach {
println(" ${it.type} [color=${it.kind!!.toColor()}]")
}
println()
val edges = mutableSetOf<Edge>()
elements.forEach { element ->
element.allParents.forEach { parent ->
edges += Edge(parent.type, element.type)
}
}
edges.forEach {
print(" ")
println(it)
}
println("}")
}
}
}
@@ -3,7 +3,7 @@
* 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.tree.generator
package org.jetbrains.kotlin.fir.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.Element
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.model.Element
fun Element.traverseParents(block: (Element) -> Unit) {
block(this)
parents.forEach { it.traverseParents(block) }
}