Add some additional information to psi renderer

1) Trim unused spaces in annotations
2) Rewrote fq name rendering
3) Added annotations to for loop variable
4) Added type arguments render along to type parameters in functions
This commit is contained in:
Ivan Cilcic
2019-08-23 11:46:53 +03:00
committed by Mikhail Glukhikh
parent 8fb2383845
commit fe328f8c7a
36 changed files with 284 additions and 223 deletions
+1
View File
@@ -4,6 +4,7 @@ plugins {
dependencies { dependencies {
testRuntime(intellijDep()) testRuntime(intellijDep())
testCompile(intellijCoreDep()) { includeJars("intellij-core") }
testCompile(project(":compiler:visualizer:render-psi")) testCompile(project(":compiler:visualizer:render-psi"))
testCompile(project(":compiler:visualizer:render-fir")) testCompile(project(":compiler:visualizer:render-fir"))
@@ -12,9 +12,9 @@ object Annotator {
private const val verticalLine = "" private const val verticalLine = ""
private const val comment = "//" private const val comment = "//"
class AnnotationInfo(val text: String, val range: TextRange) data class AnnotationInfo(val text: String, val range: TextRange)
private fun putAnnotationToLines(annotations: List<AnnotationInfo>, lineStart: Int, lineSize: Int): List<StringBuilder> { private fun putAnnotationToLines(annotations: List<AnnotationInfo>, lineStart: Int, lineSize: Int): List<String> {
val annotationLines = mutableListOf(StringBuilder(comment + " ".repeat(lineSize - comment.length))) val annotationLines = mutableListOf(StringBuilder(comment + " ".repeat(lineSize - comment.length)))
val levelToOffset = mutableMapOf(0 to 0) val levelToOffset = mutableMapOf(0 to 0)
@@ -40,10 +40,10 @@ object Annotator {
} }
} }
return annotationLines return annotationLines.map { it.trim().toString() }
} }
fun annotate(text: String, annotation: List<AnnotationInfo>): List<String> { fun annotate(text: String, annotation: Set<AnnotationInfo>): List<String> {
val lines = text.lines() val lines = text.lines()
val resultLines = mutableListOf<String>() val resultLines = mutableListOf<String>()
var lineStartOffset = 0 var lineStartOffset = 0
@@ -55,7 +55,7 @@ object Annotator {
if (annotations.isNotEmpty()) { if (annotations.isNotEmpty()) {
val annotationLines = putAnnotationToLines(annotations, lineStartOffset, line.length) val annotationLines = putAnnotationToLines(annotations, lineStartOffset, line.length)
annotationLines.asReversed().mapTo(resultLines) { it.toString() } resultLines += annotationLines.asReversed()
} }
resultLines.add(line) resultLines.add(line)
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.compiler.visualizer.Annotator.annotate import org.jetbrains.kotlin.compiler.visualizer.Annotator.annotate
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.LazyPackageViewDescriptorImpl
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.getAbbreviatedTypeOrType import org.jetbrains.kotlin.resolve.bindingContextUtil.getAbbreviatedTypeOrType
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue
@@ -34,14 +36,14 @@ import org.jetbrains.kotlin.types.*
import java.util.ArrayList import java.util.ArrayList
class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : BaseRenderer { class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : BaseRenderer {
val bindingContext = analysisResult.bindingContext private val bindingContext = analysisResult.bindingContext
private val annotations = mutableListOf<Annotator.AnnotationInfo>() private val annotations = mutableSetOf<Annotator.AnnotationInfo>()
private val filePackage = file.packageFqName.toString().replace(".", "/") private val filePackage = file.packageFqName.toString().replace(".", "/")
private val argumentsLabel = "<PLACE-FOR-ARGUMENTS>"
val descriptorRenderer = PsiDescriptorRenderer() val descriptorRenderer = PsiDescriptorRenderer()
private val unnecessaryData = mapOf( private val unnecessaryData = mapOf(
"kotlin." to "",
"kotlin/" to "" "kotlin/" to ""
) )
@@ -98,6 +100,13 @@ class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : Ba
//don't resolve this expression //don't resolve this expression
} }
override fun visitNamedFunction(function: KtNamedFunction) {
if (function.bodyExpression != null && function.equalsToken != null) {
addAnnotation(renderType(function.bodyExpression!!.getType(bindingContext)), function.equalsToken!!)
}
super.visitNamedFunction(function)
}
private fun renderVariableType(variable: KtVariableDeclaration) { private fun renderVariableType(variable: KtVariableDeclaration) {
val descriptor = bindingContext[VARIABLE, variable] val descriptor = bindingContext[VARIABLE, variable]
addAnnotation(renderType(descriptor), variable.nameIdentifier!!) addAnnotation(renderType(descriptor), variable.nameIdentifier!!)
@@ -110,6 +119,13 @@ class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : Ba
override fun visitDestructuringDeclarationEntry(multiDeclarationEntry: KtDestructuringDeclarationEntry) = override fun visitDestructuringDeclarationEntry(multiDeclarationEntry: KtDestructuringDeclarationEntry) =
renderVariableType(multiDeclarationEntry) renderVariableType(multiDeclarationEntry)
override fun visitParameter(parameter: KtParameter) {
if ((parameter.isLoopParameter && parameter.destructuringDeclaration == null) || parameter.ownerFunction is KtPropertyAccessor) {
addAnnotation(renderType(bindingContext[VALUE_PARAMETER, parameter]?.returnType), parameter.nameIdentifier!!)
}
super.visitParameter(parameter)
}
override fun visitTypeReference(typeReference: KtTypeReference) { override fun visitTypeReference(typeReference: KtTypeReference) {
if (typeReference.text.isNotEmpty()) { if (typeReference.text.isNotEmpty()) {
val hasResolvedCall = with(object : KtVisitorVoid() { val hasResolvedCall = with(object : KtVisitorVoid() {
@@ -148,7 +164,10 @@ class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : Ba
} }
val descriptor = resolvedCall.resultingDescriptor val descriptor = resolvedCall.resultingDescriptor
val annotation = descriptorRenderer.render(descriptor) val typeArguments = if (resolvedCall.typeArguments.isNotEmpty()) {
buildString { resolvedCall.typeArguments.values.joinTo(this, ", ", "<", ">") { renderType(it) } }
} else ""
val annotation = descriptorRenderer.render(descriptor).replace(argumentsLabel, typeArguments)
addAnnotation(annotation, expression, deleteDuplicate = false) addAnnotation(annotation, expression, deleteDuplicate = false)
fun addReceiverAnnotation(receiver: ReceiverValue?, receiverKind: ExplicitReceiverKind) { fun addReceiverAnnotation(receiver: ReceiverValue?, receiverKind: ExplicitReceiverKind) {
@@ -214,16 +233,15 @@ class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : Ba
} }
} }
inner class PsiDescriptorRenderer : DeclarationDescriptorVisitor<Unit, StringBuilder> { inner class PsiDescriptorRenderer(
private val needToRenderSpecialFun: Boolean = false
) : DeclarationDescriptorVisitor<Unit, StringBuilder> {
private val typeRenderer: DescriptorRenderer = DescriptorRenderer.withOptions { private val typeRenderer: DescriptorRenderer = DescriptorRenderer.withOptions {
withDefinedIn = false withDefinedIn = false
modifiers = emptySet() modifiers = emptySet()
classifierNamePolicy = object : ClassifierNamePolicy { classifierNamePolicy = object : ClassifierNamePolicy {
override fun renderClassifier(classifier: ClassifierDescriptor, renderer: DescriptorRenderer): String { override fun renderClassifier(classifier: ClassifierDescriptor, renderer: DescriptorRenderer): String {
val fqName = (if (classifier is TypeParameterDescriptor) renderer.renderName(classifier.name, false) return renderFqName(classifier)
else renderer.renderFqName(DescriptorUtils.getFqName(classifier))).replace(".", "/")
return removeCurrentFilePackage(fqName)
} }
} }
includeAdditionalModifiers = false includeAdditionalModifiers = false
@@ -238,7 +256,7 @@ class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : Ba
fun render(declarationDescriptor: DeclarationDescriptor): String { fun render(declarationDescriptor: DeclarationDescriptor): String {
if (declarationDescriptor is CallableDescriptor && declarationDescriptor.isSpecial()) { if (declarationDescriptor is CallableDescriptor && declarationDescriptor.isSpecial()) {
return this.renderSpecialFunction(declarationDescriptor) return if (needToRenderSpecialFun) this.renderSpecialFunction(declarationDescriptor) else ""
} }
return buildString { return buildString {
declarationDescriptor.accept(this@PsiDescriptorRenderer, this) declarationDescriptor.accept(this@PsiDescriptorRenderer, this)
@@ -258,25 +276,28 @@ class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : Ba
} }
private fun renderFqName(descriptor: DeclarationDescriptor, removeCurrentPackage: Boolean = true): String { private fun renderFqName(descriptor: DeclarationDescriptor, removeCurrentPackage: Boolean = true): String {
val fqName = generateSequence(descriptor) { it.containingDeclaration } if (descriptor is TypeParameterDescriptor) return descriptor.name.render()
.fold("") { acc, desc -> val fqName = qualifierNameCombine(descriptor)
val name = when (desc) {
is LazyPackageDescriptor -> desc.fqName.toString().replace(".", "/")
else -> desc.name.asString()
}
val separator = when {
acc.isEmpty() -> ""
else -> if (desc is PackageFragmentDescriptor || desc is PackageViewDescriptor) "/" else "."
}
if (name == FqName.ROOT.toString() || desc is ModuleDescriptor) {
return@fold acc
}
return@fold "$name$separator$acc"
}
return if (removeCurrentPackage) removeCurrentFilePackage(fqName) else fqName return if (removeCurrentPackage) removeCurrentFilePackage(fqName) else fqName
} }
private fun qualifierNameCombine(descriptor: DeclarationDescriptor): String {
val nameString = descriptor.name.render()
if (nameString == FqName.ROOT.toString()) return ""
val containingDeclaration = descriptor.containingDeclaration
val qualifier = qualifierName(containingDeclaration)
val separator =
if (containingDeclaration is PackageFragmentDescriptor || containingDeclaration is PackageViewDescriptor) "/" else "."
return if (qualifier != "") qualifier + separator + nameString else nameString
}
private fun qualifierName(descriptor: DeclarationDescriptor?): String = when (descriptor) {
is ModuleDescriptor, null -> ""
is PackageFragmentDescriptor, is PackageViewDescriptor -> descriptor.fqNameUnsafe.render().replace(".", "/")
else -> qualifierNameCombine(descriptor)
}
private fun removeCurrentFilePackage(fqName: String): String { private fun removeCurrentFilePackage(fqName: String): String {
return if (fqName.startsWith(filePackage) && !fqName.substring(filePackage.length + 1).contains("/")) { return if (fqName.startsWith(filePackage) && !fqName.substring(filePackage.length + 1).contains("/")) {
fqName.replaceFirst("$filePackage/", "") fqName.replaceFirst("$filePackage/", "")
@@ -367,6 +388,9 @@ class PsiRenderer(private val file: KtFile, analysisResult: AnalysisResult) : Ba
//render name //render name
data.append(renderName(function, receiver != null)) data.append(renderName(function, receiver != null))
//render type arguments
data.append(argumentsLabel)
//render value parameters //render value parameters
visitValueParameters(function.valueParameters, data) visitValueParameters(function.valueParameters, data)
@@ -5,7 +5,8 @@ open class Base<T>(val x: T)
// │ │ // │ │
class Derived<T : Any>(x: T) : Base<T>(x) class Derived<T : Any>(x: T) : Base<T>(x)
// constructor Derived<T : Any>(T) // Derived<T>
// │ create.x: T // │ constructor Derived<T : Any>(T)
// // create.x: T
// │ │ │
fun <T : Any> create(x: T): Derived<T> = Derived(x) fun <T : Any> create(x: T): Derived<T> = Derived(x)
@@ -41,7 +41,7 @@ enum class Planet(val m: Double, internal val r: Double) {
} }
}; };
// val (Planet/Companion).G: Double // val (Planet.Companion).G: Double
// │ fun (Double).times(Double): Double // │ fun (Double).times(Double): Double
// │ │ val (Planet).m: Double // │ │ val (Planet).m: Double
// │ │ │ fun (Double).div(Double): Double // │ │ │ fun (Double).div(Double): Double
@@ -9,18 +9,20 @@ enum class SomeEnum(val x: Some) {
// │object O1: Some // │object O1: Some
// ││ // ││
FIRST(O1) { FIRST(O1) {
// Boolean // Boolean
// // │ Boolean
// │ │
override fun check(y: Some): Boolean = true override fun check(y: Some): Boolean = true
}, },
// constructor SomeEnum(Some) // constructor SomeEnum(Some)
// │object O2: Some // │object O2: Some
// ││ // ││
SECOND(O2) { SECOND(O2) {
// SomeEnum.SECOND.check.y: Some // Boolean
// │ fun (Any).equals(Any?): Boolean // │ SomeEnum.SECOND.check.y: Some
// │ │ object O2: Some // │ │ fun (Any).equals(Any?): Boolean
// │ │ // │ │ object O2: Some
// │ │ │ │
override fun check(y: Some): Boolean = y == O2 override fun check(y: Some): Boolean = y == O2
}; };
@@ -8,6 +8,8 @@ expect val x: Int
actual class MyClass actual class MyClass
// String
// │
actual fun foo() = "Hello" actual fun foo() = "Hello"
// Int Int // Int Int
@@ -1,5 +1,6 @@
// fun ((T) -> Unit).invoke(T): Unit // Unit
// // │ fun ((T) -> Unit).invoke(T): Unit
// │ │
fun <T> simpleRun(f: (T) -> Unit): Unit = f() fun <T> simpleRun(f: (T) -> Unit): Unit = f()
// collections/List<T> // collections/List<T>
@@ -8,8 +9,8 @@ fun <T, R> List<T>.simpleMap(f: (T) -> R): R {
} }
// simpleWith.t: T // Unit
// │ fun T.invoke(): Unit // │ simpleWith.t: T
// │ │ // │ │ fun T.invoke(): Unit
// │ │ │
fun <T> simpleWith(t: T, f: T.() -> Unit): Unit = t.f() fun <T> simpleWith(t: T, f: T.() -> Unit): Unit = t.f()
@@ -1,5 +1,7 @@
interface Any interface Any
// T?
// │
inline fun <reified T : Any> Any.safeAs(): T? = this as? T inline fun <reified T : Any> Any.safeAs(): T? = this as? T
abstract class Summator { abstract class Summator {
@@ -1,7 +1,8 @@
// fun TODO(): Nothing // Nothing
// // │ fun TODO(): Nothing
// │ │
fun <T> genericFoo(): T = TODO() fun <T> genericFoo(): T = TODO()
// T fun <T> genericFoo(): T // T fun <T> genericFoo<T>(): T
// │ │ // │ │
val <T> T.generic: T get() = genericFoo() val <T> T.generic: T get() = genericFoo()
@@ -27,6 +27,8 @@ class SomeClass : SomeInterface {
// Boolean // Boolean
// │ // │
get() = true get() = true
// Boolean
// │
set(value) {} set(value) {}
// Double // Double
@@ -12,9 +12,12 @@ abstract class AbstractList<out T : Any> : List<T>
// constructor AbstractList<T : Any>() // constructor AbstractList<T : Any>()
// │ // │
class SomeList : AbstractList<Int>() { class SomeList : AbstractList<Int>() {
// Int // Int
// // │ Int
// │ │
override fun get(index: Int): Int = 42 override fun get(index: Int): Int = 42
// SomeList
// │
override fun concat(other: List<Int>): List<Int> = this override fun concat(other: List<Int>): List<Int> = this
} }
@@ -1,23 +1,25 @@
// Int Int // Int Int
// │ │ // │ │
val p = 0 val p = 0
// Int // Int
// // │ Int
// │ │
fun foo() = 1 fun foo() = 1
class Wrapper(val v: IntArray) class Wrapper(val v: IntArray)
// test.a: IntArray // Int
// │ Int // │ test.a: IntArray
// │ │ fun (Int).plus(Int): Int // │ │ Int
// │ │ │ test.a: IntArray // │ │ fun (Int).plus(Int): Int
// │ │ │ │ val p: Int // │ │ │ test.a: IntArray
// │ │ │ │ │ fun (Int).plus(Int): Int // │ │ │ │ val p: Int
// │ │ │ │ │ │ test.a: IntArray // │ │ │ │ │ fun (Int).plus(Int): Int
// │ │ │ │ │ │ │ fun foo(): Int // │ │ │ │ │ │ test.a: IntArray
// │ │ │ │ │ │ │ │ fun (Int).plus(Int): Int // │ │ │ │ │ │ │ fun foo(): Int
// │ │ │ │ │ │ │ │ │ test.w: Wrapper // │ │ │ │ │ │ │ │ fun (Int).plus(Int): Int
// │ │ │ │ │ │ │ │ │ │ val (Wrapper).v: IntArray // │ │ │ │ │ │ │ │ │ test.w: Wrapper
// │ │ │ │ │ │ │ │ │ │ │ Int // │ │ │ │ │ │ │ │ │ │ val (Wrapper).v: IntArray
// │ │ │ │ │ │ │ │ │ │ │ // │ │ │ │ │ │ │ │ │ │ │ Int
// │ │ │ │ │ │ │ │ │ │ │ │ │
fun test(a: IntArray, w: Wrapper) = a[0] + a[p] + a[foo()] + w.v[0] fun test(a: IntArray, w: Wrapper) = a[0] + a[p] + a[foo()] + w.v[0]
@@ -12,8 +12,9 @@ fun test() {
x[1] = 0 x[1] = 0
} }
// Int // Int
// // │ Int
// │ │
fun foo() = 1 fun foo() = 1
fun test2() { fun test2() {
@@ -1,9 +1,9 @@
// foo.a: Int // foo.a: Int
// │ fun (Int).compareTo(Int): Int // │ fun (Int).compareTo(Int): Int
// │ │ foo.b: Int // │ │ foo.b: Int
// │ │ │ foo.a: Int // Int │ │ │ foo.a: Int
// Int │ │ │ │ foo.b: Int // Int │ │ │ │ foo.b: Int
// │ │ │ │ │ │ // │ │ │ │ │ │
fun foo(a: Int, b: Int) = if (a > b) a else b fun foo(a: Int, b: Int) = if (a > b) a else b
fun bar(a: Double, b: Double): Double { fun bar(a: Double, b: Double): Double {
+27 -21
View File
@@ -1,38 +1,44 @@
// distance.x: Int // Int
// │ fun (Int).plus(Int): Int // │ distance.x: Int
// │ distance.y: Int // fun (Int).plus(Int): Int
// │ │ // │ │ distance.y: Int
// │ │ │ │
infix fun distance(x: Int, y: Int) = x + y infix fun distance(x: Int, y: Int) = x + y
// Int // [ERROR: unknown type]
// │ [ERROR: not resolved] // │ Int
// │ │ Int // │ │ [ERROR: not resolved]
// │ │ // │ │ Int
// │ │ │ │
fun test(): Int = 3 distance 4 fun test(): Int = 3 distance 4
// fun distance(Int, Int): Int // Int
// Int // │ fun distance(Int, Int): Int
// Int // │ Int
// │ │ // │ │ Int
// │ │ │ │
fun testRegular(): Int = distance(3, 4) fun testRegular(): Int = distance(3, 4)
class My(var x: Int) { class My(var x: Int) {
// var (My).x: Int // Int
// // │ var (My).x: Int
// │ │
operator fun invoke() = x operator fun invoke() = x
fun foo() {} fun foo() {}
// constructor My(Int) // My
// │ var (My).x: Int // │ constructor My(Int)
// // var (My).x: Int
// │ │ │
fun copy() = My(x) fun copy() = My(x)
} }
// constructor My(Int) // Int
// fun (My).invoke(): Int // │ constructor My(Int)
// │ Int // │ fun (My).invoke(): Int
// // Int
// │ │ │
fun testInvoke(): Int = My(13)() fun testInvoke(): Int = My(13)()
fun testQualified(first: My, second: My?) { fun testQualified(first: My, second: My?) {
+6 -6
View File
@@ -1,8 +1,8 @@
fun foo() { fun foo() {
// Int // Int
// │fun (Int).rangeTo(Int): ranges/IntRange // │fun (Int).rangeTo(Int): ranges/IntRange
// ││ Int // Int ││ Int
// ││ │ // ││ │
for (i in 1..10) { for (i in 1..10) {
// fun io/println(Int): Unit // fun io/println(Int): Unit
// │ val foo.i: Int // │ val foo.i: Int
@@ -17,8 +17,8 @@ fun bar(list: List<String>) {
// bar.list: collections/List<String> // bar.list: collections/List<String>
// │ fun (collections/List<String>).subList(Int, Int): collections/List<String> // │ fun (collections/List<String>).subList(Int, Int): collections/List<String>
// │ │ Int // │ │ Int
// │ │ │ Int // String │ │ │ Int
// │ │ │ │ // │ │ │ │
for (element in list.subList(0, 10)) { for (element in list.subList(0, 10)) {
// fun io/println(Any?): Unit // fun io/println(Any?): Unit
// │ val bar.element: String // │ val bar.element: String
@@ -28,8 +28,8 @@ fun bar(list: List<String>) {
// bar.list: collections/List<String> // bar.list: collections/List<String>
// │ fun (collections/List<String>).subList(Int, Int): collections/List<String> // │ fun (collections/List<String>).subList(Int, Int): collections/List<String>
// │ │ fun io/println(Any?): Unit // │ │ fun io/println(Any?): Unit
// │ │ Int Int │ val bar.element: String // String │ │ Int Int │ val bar.element: String
// │ │ │ │ │ │ // │ │ │ │ │ │
for (element in list.subList(10, 20)) println(element) for (element in list.subList(10, 20)) println(element)
} }
@@ -1,18 +1,19 @@
// Nothing? // Nothing?
// // │ Nothing?
// │ │
fun <T> nullableValue(): T? = null fun <T> nullableValue(): T? = null
fun test() { fun test() {
// Int? // Int?
// │ fun <T> nullableValue(): Int? // │ fun <T> nullableValue<Int>(): Int?
// │ │ // │ │
val n = nullableValue<Int>() val n = nullableValue<Int>()
// Double? // Double?
// │ fun <T> nullableValue(): Double? // │ fun <T> nullableValue<Double>(): Double?
// │ │ // │ │
val x = nullableValue<Double>() val x = nullableValue<Double>()
// String? // String?
// │ fun <T> nullableValue(): String? // │ fun <T> nullableValue<String>(): String?
// │ │ // │ │
val s = nullableValue<String>() val s = nullableValue<String>()
} }
+2 -1
View File
@@ -1,5 +1,6 @@
// collections/Collection<Int> // collections/Collection<Int>
// │ // │ Boolean
// │ │
fun foo(x: Int, y: Int, c: Collection<Int>) = fun foo(x: Int, y: Int, c: Collection<Int>) =
// foo.x: Int // foo.x: Int
// │ fun (collections/Collection<Int>).contains(Int): Boolean // │ fun (collections/Collection<Int>).contains(Int): Boolean
@@ -1,10 +1,11 @@
data class Tuple(val x: Int, val y: Int) data class Tuple(val x: Int, val y: Int)
// fun ((Tuple) -> Int).invoke(Tuple): Int // Int
// │ constructor Tuple(Int, Int) // │ fun ((Tuple) -> Int).invoke(Tuple): Int
// │ │ Int // │ │ constructor Tuple(Int, Int)
// │ │ Int // │ │ Int
// │ │ │ // │ │ │ Int
// │ │ │ │ │
inline fun use(f: (Tuple) -> Int) = f(Tuple(1, 2)) inline fun use(f: (Tuple) -> Int) = f(Tuple(1, 2))
fun foo(): Int { fun foo(): Int {
@@ -71,15 +72,15 @@ fun bar(): Int {
// │ // │
fun test(list: List<Int>) { fun test(list: List<Int>) {
// collections/MutableMap<Int, String> // collections/MutableMap<Int, String>
// │ fun <K, V> collections/mutableMapOf(): collections/MutableMap<Int, String> // │ fun <K, V> collections/mutableMapOf<Int, String>(): collections/MutableMap<Int, String>
// │ │ // │ │
val map = mutableMapOf<Int, String>() val map = mutableMapOf<Int, String>()
// test.list: collections/List<Int> // test.list: collections/List<Int>
// │ fun <T> collections/Iterable<Int>.forEach((Int) -> Unit): Unit // │ fun <T> collections/Iterable<Int>.forEach<Int>((Int) -> Unit): Unit
// │ │ val test.map: collections/MutableMap<Int, String> // │ │ val test.map: collections/MutableMap<Int, String>
// │ │ │ fun <K, V> collections/MutableMap<Int, String>.getOrPut(Int, () -> String): String // │ │ │ fun <K, V> collections/MutableMap<Int, String>.getOrPut<Int, String>(Int, () -> String): String
// │ │ │ │ test.<anonymous>.it: Int // │ │ │ │ test.<anonymous>.it: Int
// │ │ │ │ │ fun <T> collections/mutableListOf(): collections/MutableList<???> // │ │ │ │ │ fun <T> collections/mutableListOf<???>(): collections/MutableList<???>
// │ │ │ │ │ │ fun (String).plus(Any?): String // │ │ │ │ │ │ fun (String).plus(Any?): String
// │ │ │ │ │ │ │ // │ │ │ │ │ │ │
list.forEach { map.getOrPut(it, { mutableListOf() }) += "" } list.forEach { map.getOrPut(it, { mutableListOf() }) += "" }
+16 -13
View File
@@ -1,14 +1,15 @@
fun withLocals(p: Int): Int { fun withLocals(p: Int): Int {
class Local(val pp: Int) { class Local(val pp: Int) {
// val (withLocals/Local).pp: Int // Int
// │ fun (Int).minus(Int): Int // │ val (withLocals.Local).pp: Int
// │ withLocals.p: Int // fun (Int).minus(Int): Int
// │ │ // │ │ withLocals.p: Int
// │ │ │ │
fun diff() = pp - p fun diff() = pp - p
} }
// constructor withLocals.Local(Int) // constructor withLocals.Local(Int)
// Int │ Int fun (withLocals/Local).diff(): Int // Int │ Int fun (withLocals.Local).diff(): Int
// │ │ │ │ // │ │ │ │
val x = Local(42).diff() val x = Local(42).diff()
@@ -26,10 +27,11 @@ fun withLocals(p: Int): Int {
// Int constructor Any() // Int constructor Any()
// │ │ // │ │
val code = (object : Any() { val code = (object : Any() {
// fun (Any).hashCode(): Int // Int
// // │ fun (Any).hashCode(): Int
// │ │
fun foo() = hashCode() fun foo() = hashCode()
// fun (withLocals/<no name provided>).foo(): Int // fun (withLocals.<no name provided>).foo(): Int
// │ // │
}).foo() }).foo()
@@ -37,10 +39,11 @@ fun withLocals(p: Int): Int {
// │ val withLocals.code: Int // │ val withLocals.code: Int
// │ │ constructor withLocals.Local(Int) // │ │ constructor withLocals.Local(Int)
// │ │ │ Int // │ │ │ Int
// │ │ │ │ fun (withLocals/Local).diff(): Int // │ │ │ │ fun (withLocals.Local).diff(): Int
// │ │ │ │ │ withLocals.<no name provided>.x: Int // │ │ │ │ │ Int
// │ │ │ │ │ │ fun (Int).plus(Int): Int // │ │ │ │ │ │ withLocals.<no name provided>.x: Int
// │ │ │ │ │ │ │ withLocals.<no name provided>.y: Int // │ │ │ │ │ │ │ fun (Int).plus(Int): Int
// │ │ │ │ │ │ │ │ // │ │ │ │ │ │ │ │ withLocals.<no name provided>.y: Int
// │ │ │ │ │ │ │ │ │
return sum(code, Local(1).diff(), fun(x: Int, y: Int) = x + y) return sum(code, Local(1).diff(), fun(x: Int, y: Int) = x + y)
} }
@@ -27,17 +27,17 @@ fun simple() {
// collections/List<String> // collections/List<String>
// │ // │
fun List<String>.modify() { fun List<String>.modify() {
// fun <T> collections/Collection<String>.plus(String): collections/List<String> // fun <T> collections/Collection<String>.plus<String>(String): collections/List<String>
// │ // │
this += "Alpha" this += "Alpha"
// fun <T> collections/Collection<String>.plus(String): collections/List<String> // fun <T> collections/Collection<String>.plus<String>(String): collections/List<String>
// │ // │
this += "Omega" this += "Omega"
} }
fun Any.modify() { fun Any.modify() {
// collections/List<Int> // collections/List<Int>
// │ fun <T> collections/Collection<Int>.plus(Int): collections/List<Int> // │ fun <T> collections/Collection<Int>.plus<Int>(Int): collections/List<Int>
// │ │ Int // │ │ Int
// │ │ │ // │ │ │
(this as List<Int>) += 42 (this as List<Int>) += 42
@@ -1,10 +1,10 @@
// orFourtyTwo.arg: Int? // Int
// │ fun ?: (Int?, Int): Int // │ orFourtyTwo.arg: Int?
// Int // Int
// //
fun orFourtyTwo(arg: Int?) = arg ?: 42 fun orFourtyTwo(arg: Int?) = arg ?: 42
// bang.arg: Int? // Int
// │ fun !! (Int?): Int // │ bang.arg: Int?
// //
fun bang(arg: Int?) = arg!! fun bang(arg: Int?) = arg!!
@@ -1,6 +1,7 @@
class Some { class Some {
// Int // Int
// // │ Int
// │ │
fun foo(): Int = 1 fun foo(): Int = 1
fun bar(): Int { fun bar(): Int {
@@ -23,12 +24,12 @@ class Some {
} }
} }
// fun (Some).bar(): Int // Int fun (Some).bar(): Int
// //
fun Some.extension() = this.bar() fun Some.extension() = this.bar()
fun test(some: Some): Int { fun test(some: Some): Int {
// fun <T, R> with(Some, Some.() -> Int): Int // fun <T, R> with<Some, Int>(Some, Some.() -> Int): Int
// │ test.some: Some // │ test.some: Some
// │ │ with@0 // │ │ with@0
// │ │ │ // │ │ │
@@ -1,14 +1,18 @@
interface IThing interface IThing
// test1.x: Any // Boolean
// // │ test1.x: Any
// │ │
fun test1(x: Any) = x is IThing fun test1(x: Any) = x is IThing
// test2.x: Any // Boolean
// // │ test2.x: Any
// │ │
fun test2(x: Any) = x !is IThing fun test2(x: Any) = x !is IThing
// test3.x: Any // IThing
// // │ test3.x: Any
// │ │
fun test3(x: Any) = x as IThing fun test3(x: Any) = x as IThing
// test4.x: Any // IThing?
// // │ test4.x: Any
// │ │
fun test4(x: Any) = x as? IThing fun test4(x: Any) = x as? IThing
@@ -13,7 +13,7 @@ class B {
} }
fun foo(a: Int, b: Int): Int { fun foo(a: Int, b: Int): Int {
// fun <T, R> with(A, A.() -> Int): Int // fun <T, R> with<A, Int>(A, A.() -> Int): Int
// │ constructor A() // │ constructor A()
// │ │ with@0 // │ │ with@0
// │ │ │ // │ │ │
@@ -23,7 +23,7 @@ fun foo(a: Int, b: Int): Int {
// │ // │
aProp aProp
// fun <T, R> with(B, B.() -> Int): Int // fun <T, R> with<B, Int>(B, B.() -> Int): Int
// │ constructor B() // │ constructor B()
// │ │ with@1 // │ │ with@1
// │ │ │ // │ │ │
@@ -43,7 +43,7 @@ fun foo(a: Int, b: Int): Int {
} }
} }
// fun <T, R> with(A, A.() -> Int): Int // fun <T, R> with<A, Int>(A, A.() -> Int): Int
// │ constructor A() // │ constructor A()
// │ │ with@0 // │ │ with@0
// │ │ │ // │ │ │
@@ -53,7 +53,7 @@ fun foo(a: Int, b: Int): Int {
// │ // │
aProp aProp
// fun <T, R> with(B, B.() -> Int): Int // fun <T, R> with<B, Int>(B, B.() -> Int): Int
// │ constructor B() // │ constructor B()
// │ │ with@1 // │ │ with@1
// │ │ │ // │ │ │
@@ -68,7 +68,7 @@ fun foo(a: Int, b: Int): Int {
bProp bProp
} }
// fun <T, R> with(B, B.() -> Int): Int // fun <T, R> with<B, Int>(B, B.() -> Int): Int
// │ constructor B() // │ constructor B()
// │ │ with@1 // │ │ with@1
// │ │ │ // │ │ │
@@ -1,7 +1,7 @@
package org.jetbrains.kotlin.test package org.jetbrains.kotlin.test
// collections/List<Int> // collections/List<Int>
// │ fun <T> collections/listOf(vararg Int): collections/List<Int> // │ fun <T> collections/listOf<Int>(vararg Int): collections/List<Int>
// │ │ Int // │ │ Int
// │ │ │ Int // │ │ │ Int
// │ │ │ │ Int // │ │ │ │ Int
@@ -9,7 +9,7 @@ package org.jetbrains.kotlin.test
val listOfInt = listOf(1, 2, 3) val listOfInt = listOf(1, 2, 3)
// java/util/ArrayList<Int> // java/util/ArrayList<Int>
// │ package java // │ package java
// │ │ constructor util/ArrayList<E : Any!>() // │ │ constructor java/util/ArrayList<E : Any!>()
// │ │ │ // │ │ │
val javaList = java.util.ArrayList<Int>() val javaList = java.util.ArrayList<Int>()
@@ -17,8 +17,8 @@ val javaList = java.util.ArrayList<Int>()
// │ package java/util // │ package java/util
// │ │ // │ │
fun move(): java.util.ArrayList<Int> { fun move(): java.util.ArrayList<Int> {
// val listOfInt: collections/List<Int> // Int val listOfInt: collections/List<Int>
// //
for (elem in listOfInt) { for (elem in listOfInt) {
// val javaList: java/util/ArrayList<Int> // val javaList: java/util/ArrayList<Int>
// │ fun (java/util/ArrayList<Int>).add(Int): Boolean // │ fun (java/util/ArrayList<Int>).add(Int): Boolean
@@ -45,8 +45,8 @@ var withSetter
// val p4: String // val p4: String
// │ // │
get() = p4 get() = p4
// <set-withSetter>.value: String // String <set-withSetter>.value: String
// //
set(value) = value set(value) = value
// Boolean // Boolean
@@ -62,6 +62,8 @@ val withGetter2: Boolean
// │ // │
var withSetter2: String var withSetter2: String
get() = "1" get() = "1"
// String
// │
set(value) { set(value) {
// var <set-withSetter2>.field: String // var <set-withSetter2>.field: String
// │ <set-withSetter2>.value: String // │ <set-withSetter2>.value: String
@@ -4,11 +4,11 @@ fun <T> copyWhenGreater(list: List<T>, threshold: T): List<String>
where T : CharSequence, where T : CharSequence,
T : Comparable<T> { T : Comparable<T> {
// copyWhenGreater.list: collections/List<T> // copyWhenGreater.list: collections/List<T>
// │ fun <T> collections/Iterable<T>.filter((T) -> Boolean): collections/List<T> // │ fun <T> collections/Iterable<T>.filter<T>((T) -> Boolean): collections/List<T>
// │ │ copyWhenGreater.<anonymous>.it: T // │ │ copyWhenGreater.<anonymous>.it: T
// │ │ │ fun (Comparable<T>).compareTo(T): Int // │ │ │ fun (Comparable<T>).compareTo(T): Int
// │ │ │ │ copyWhenGreater.threshold: T // │ │ │ │ copyWhenGreater.threshold: T
// │ │ │ │ │ fun <T, R> collections/Iterable<T>.map((T) -> String): collections/List<String> // │ │ │ │ │ fun <T, R> collections/Iterable<T>.map<T, String>((T) -> String): collections/List<String>
// │ │ │ │ │ │ copyWhenGreater.<anonymous>.it: T // │ │ │ │ │ │ copyWhenGreater.<anonymous>.it: T
// │ │ │ │ │ │ │ fun (Any).toString(): String // │ │ │ │ │ │ │ fun (Any).toString(): String
// │ │ │ │ │ │ │ │ // │ │ │ │ │ │ │ │
@@ -17,11 +17,11 @@ fun <T> copyWhenGreater(list: List<T>, threshold: T): List<String>
fun main() { fun main() {
// collections/List<String> // collections/List<String>
// │ fun <T> collections/listOf(vararg String): collections/List<String> // │ fun <T> collections/listOf<String>(vararg String): collections/List<String>
// │ │ // │ │
val list = listOf("1", "2", "3") val list = listOf("1", "2", "3")
// collections/List<String> // collections/List<String>
// │ fun <T : CharSequence> copyWhenGreater(collections/List<String>, String): collections/List<String> where copyWhenGreater.T : Comparable<String> // │ fun <T : CharSequence> copyWhenGreater<String>(collections/List<String>, String): collections/List<String> where T : Comparable<String>
// │ │ val main.list: collections/List<String> // │ │ val main.list: collections/List<String>
// │ │ │ // │ │ │
val copy = copyWhenGreater(list, "2") val copy = copyWhenGreater(list, "2")