Raw FIR: implement expression trees & conversions from PSI
Testing: total kotlin test controls no stubs in FIR in non-stub-mode #KT-29002 Fixed
This commit is contained in:
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirReference
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirNamedDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirVariableImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirExplicitThisReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.types.FirType
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.*
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
|
||||
internal fun String.parseCharacter(): Char? {
|
||||
// Strip the quotes
|
||||
if (length < 2 || this[0] != '\'' || this[length - 1] != '\'') {
|
||||
return null
|
||||
}
|
||||
val text = substring(1, length - 1) // now there're no quotes
|
||||
|
||||
if (text.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
return if (text[0] != '\\') {
|
||||
// No escape
|
||||
if (text.length == 1) {
|
||||
text[0]
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
escapedStringToCharacter(text)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun escapedStringToCharacter(text: String): Char? {
|
||||
assert(text.isNotEmpty() && text[0] == '\\') {
|
||||
"Only escaped sequences must be passed to this routine: $text"
|
||||
}
|
||||
|
||||
// Escape
|
||||
val escape = text.substring(1) // strip the slash
|
||||
when (escape.length) {
|
||||
0 -> {
|
||||
// bare slash
|
||||
return null
|
||||
}
|
||||
1 -> {
|
||||
// one-char escape
|
||||
return translateEscape(escape[0]) ?: return null
|
||||
}
|
||||
5 -> {
|
||||
// unicode escape
|
||||
if (escape[0] == 'u') {
|
||||
try {
|
||||
val intValue = Integer.valueOf(escape.substring(1), 16)
|
||||
return intValue.toInt().toChar()
|
||||
} catch (e: NumberFormatException) {
|
||||
// Will be reported below
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
internal fun translateEscape(c: Char): Char? =
|
||||
when (c) {
|
||||
't' -> '\t'
|
||||
'b' -> '\b'
|
||||
'n' -> '\n'
|
||||
'r' -> '\r'
|
||||
'\'' -> '\''
|
||||
'\"' -> '\"'
|
||||
'\\' -> '\\'
|
||||
'$' -> '$'
|
||||
else -> null
|
||||
}
|
||||
|
||||
internal fun generateConstantExpressionByLiteral(session: FirSession, expression: KtConstantExpression): FirExpression {
|
||||
val type = expression.node.elementType
|
||||
val text: String = expression.text
|
||||
val convertedText: Any? = when (type) {
|
||||
KtNodeTypes.INTEGER_CONSTANT, KtNodeTypes.FLOAT_CONSTANT -> parseNumericLiteral(text, type)
|
||||
KtNodeTypes.BOOLEAN_CONSTANT -> parseBoolean(text)
|
||||
else -> null
|
||||
}
|
||||
return when (type) {
|
||||
KtNodeTypes.INTEGER_CONSTANT ->
|
||||
if (convertedText is Long &&
|
||||
(hasLongSuffix(text) || hasUnsignedLongSuffix(text) || hasUnsignedSuffix(text) ||
|
||||
convertedText > Int.MAX_VALUE || convertedText < Int.MIN_VALUE)
|
||||
) {
|
||||
FirConstExpressionImpl(
|
||||
session, expression, IrConstKind.Long, convertedText, "Incorrect long: $text"
|
||||
)
|
||||
} else {
|
||||
// TODO: support byte / short
|
||||
FirConstExpressionImpl(session, expression, IrConstKind.Int, (convertedText as Number).toInt(), "Incorrect int: $text")
|
||||
}
|
||||
KtNodeTypes.FLOAT_CONSTANT ->
|
||||
if (convertedText is Float) {
|
||||
FirConstExpressionImpl(
|
||||
session, expression, IrConstKind.Float, convertedText, "Incorrect float: $text"
|
||||
)
|
||||
} else {
|
||||
FirConstExpressionImpl(
|
||||
session, expression, IrConstKind.Double, convertedText as Double, "Incorrect double: $text"
|
||||
)
|
||||
}
|
||||
KtNodeTypes.CHARACTER_CONSTANT ->
|
||||
FirConstExpressionImpl(
|
||||
session, expression, IrConstKind.Char, text.parseCharacter(), "Incorrect character: $text"
|
||||
)
|
||||
KtNodeTypes.BOOLEAN_CONSTANT ->
|
||||
FirConstExpressionImpl(session, expression, IrConstKind.Boolean, convertedText as Boolean)
|
||||
KtNodeTypes.NULL ->
|
||||
FirConstExpressionImpl(session, expression, IrConstKind.Null, null)
|
||||
else ->
|
||||
throw AssertionError("Unknown literal type: $type, $text")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal fun IElementType.toBinaryName(): Name? {
|
||||
return OperatorConventions.BINARY_OPERATION_NAMES[this]
|
||||
}
|
||||
|
||||
internal fun IElementType.toUnaryName(): Name? {
|
||||
return OperatorConventions.UNARY_OPERATION_NAMES[this]
|
||||
}
|
||||
|
||||
internal fun IElementType.toFirOperation(): FirOperation =
|
||||
when (this) {
|
||||
KtTokens.LT -> FirOperation.LT
|
||||
KtTokens.GT -> FirOperation.GT
|
||||
KtTokens.LTEQ -> FirOperation.LT_EQ
|
||||
KtTokens.GTEQ -> FirOperation.GT_EQ
|
||||
KtTokens.EQEQ -> FirOperation.EQ
|
||||
KtTokens.EXCLEQ -> FirOperation.NOT_EQ
|
||||
KtTokens.EQEQEQ -> FirOperation.IDENTITY
|
||||
KtTokens.EXCLEQEQEQ -> FirOperation.NOT_IDENTITY
|
||||
KtTokens.ANDAND -> FirOperation.AND
|
||||
KtTokens.OROR -> FirOperation.OR
|
||||
KtTokens.IN_KEYWORD -> FirOperation.IN
|
||||
KtTokens.NOT_IN -> FirOperation.NOT_IN
|
||||
KtTokens.RANGE -> FirOperation.RANGE
|
||||
|
||||
KtTokens.EQ -> FirOperation.ASSIGN
|
||||
KtTokens.PLUSEQ -> FirOperation.PLUS_ASSIGN
|
||||
KtTokens.MINUSEQ -> FirOperation.MINUS_ASSIGN
|
||||
KtTokens.MULTEQ -> FirOperation.TIMES_ASSIGN
|
||||
KtTokens.DIVEQ -> FirOperation.DIV_ASSIGN
|
||||
KtTokens.PERCEQ -> FirOperation.REM_ASSIGN
|
||||
|
||||
KtTokens.AS_KEYWORD -> FirOperation.AS
|
||||
KtTokens.AS_SAFE -> FirOperation.SAFE_AS
|
||||
|
||||
else -> throw AssertionError(this.toString())
|
||||
}
|
||||
|
||||
internal fun FirExpression.generateNotNullOrOther(other: FirExpression, caseId: String, basePsi: KtElement): FirWhenExpression {
|
||||
val subjectName = Name.special("<$caseId>")
|
||||
val subjectVariable = generateTemporaryVariable(session, psi, subjectName, this)
|
||||
val subjectExpression = FirWhenSubjectExpression(session, psi)
|
||||
return FirWhenExpressionImpl(
|
||||
session, basePsi, this, subjectVariable
|
||||
).apply {
|
||||
branches += FirWhenBranchImpl(
|
||||
session, psi,
|
||||
FirOperatorCallImpl(session, psi, FirOperation.NOT_EQ).apply {
|
||||
arguments += subjectExpression
|
||||
arguments += FirConstExpressionImpl(session, psi, IrConstKind.Null, null)
|
||||
},
|
||||
FirSingleExpressionBlock(
|
||||
session,
|
||||
generateAccessExpression(session, psi, subjectName)
|
||||
)
|
||||
)
|
||||
branches += FirWhenBranchImpl(
|
||||
session, other.psi, FirElseIfTrueCondition(session, psi),
|
||||
FirSingleExpressionBlock(session, other)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun generateIncrementOrDecrementBlock(
|
||||
session: FirSession,
|
||||
baseExpression: KtUnaryExpression,
|
||||
argument: KtExpression?,
|
||||
callName: Name,
|
||||
prefix: Boolean,
|
||||
convert: KtExpression.() -> FirExpression
|
||||
): FirExpression {
|
||||
if (argument == null) {
|
||||
return FirErrorExpressionImpl(session, argument, "Inc/dec without operand")
|
||||
}
|
||||
return FirBlockImpl(session, baseExpression).apply {
|
||||
val tempName = Name.special("<unary>")
|
||||
statements += generateTemporaryVariable(session, baseExpression, tempName, argument.convert())
|
||||
val resultName = Name.special("<unary-result>")
|
||||
val resultInitializer = FirFunctionCallImpl(session, baseExpression).apply {
|
||||
this.calleeReference = FirSimpleNamedReference(session, baseExpression.operationReference, callName)
|
||||
this.arguments += generateAccessExpression(session, baseExpression, tempName)
|
||||
}
|
||||
val resultVar = generateTemporaryVariable(session, baseExpression, resultName, resultInitializer)
|
||||
val assignment = argument.generateAssignment(
|
||||
session, baseExpression,
|
||||
if (prefix && argument !is KtSimpleNameExpression)
|
||||
generateAccessExpression(session, baseExpression, resultName)
|
||||
else
|
||||
resultInitializer,
|
||||
FirOperation.ASSIGN, convert
|
||||
)
|
||||
|
||||
fun appendAssignment() {
|
||||
if (assignment is FirBlock) {
|
||||
statements += assignment.statements
|
||||
} else {
|
||||
statements += assignment
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
if (argument !is KtSimpleNameExpression) {
|
||||
statements += resultVar
|
||||
appendAssignment()
|
||||
statements += generateAccessExpression(session, baseExpression, resultName)
|
||||
} else {
|
||||
appendAssignment()
|
||||
statements += generateAccessExpression(session, baseExpression, argument.getReferencedNameAsName())
|
||||
}
|
||||
} else {
|
||||
appendAssignment()
|
||||
statements += generateAccessExpression(session, baseExpression, tempName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun generateAccessExpression(session: FirSession, psi: PsiElement?, name: Name): FirAccessExpression =
|
||||
FirAccessExpressionImpl(session, psi).apply {
|
||||
calleeReference = FirSimpleNamedReference(session, psi, name)
|
||||
}
|
||||
|
||||
internal fun generateDestructuringBlock(
|
||||
session: FirSession,
|
||||
multiDeclaration: KtDestructuringDeclaration,
|
||||
container: FirNamedDeclaration,
|
||||
extractAnnotationsTo: KtAnnotated.(FirAbstractAnnotatedElement) -> Unit,
|
||||
toFirOrImplicitType: KtTypeReference?.() -> FirType
|
||||
): FirExpression {
|
||||
return FirBlockImpl(session, multiDeclaration).apply {
|
||||
if (container is FirVariable) {
|
||||
statements += container
|
||||
}
|
||||
val isVar = multiDeclaration.isVar
|
||||
for ((index, entry) in multiDeclaration.entries.withIndex()) {
|
||||
statements += FirVariableImpl(
|
||||
session, entry, entry.nameAsSafeName,
|
||||
entry.typeReference.toFirOrImplicitType(), isVar,
|
||||
FirComponentCallImpl(session, entry, index + 1).apply {
|
||||
arguments += generateAccessExpression(session, entry, container.name)
|
||||
}
|
||||
).apply {
|
||||
entry.extractAnnotationsTo(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun generateTemporaryVariable(
|
||||
session: FirSession, psi: PsiElement?, name: Name, initializer: FirExpression
|
||||
): FirVariable = FirVariableImpl(session, psi, name, FirImplicitTypeImpl(session, psi), false, initializer)
|
||||
|
||||
internal fun generateTemporaryVariable(
|
||||
session: FirSession, psi: PsiElement?, specialName: String, initializer: FirExpression
|
||||
): FirVariable = generateTemporaryVariable(session, psi, Name.special("<$specialName>"), initializer)
|
||||
|
||||
private fun FirModifiableAccess.initializeLValue(
|
||||
session: FirSession,
|
||||
left: KtExpression?,
|
||||
convertQualified: KtQualifiedExpression.() -> FirAccess?
|
||||
): FirReference {
|
||||
return when (left) {
|
||||
is KtSimpleNameExpression -> {
|
||||
FirSimpleNamedReference(session, left, left.getReferencedNameAsName())
|
||||
}
|
||||
is KtThisExpression -> {
|
||||
FirExplicitThisReference(session, left, left.getLabelName())
|
||||
}
|
||||
is KtQualifiedExpression -> {
|
||||
val firMemberAccess = left.convertQualified()
|
||||
if (firMemberAccess != null) {
|
||||
explicitReceiver = firMemberAccess.explicitReceiver
|
||||
safe = firMemberAccess.safe
|
||||
firMemberAccess.calleeReference
|
||||
} else {
|
||||
FirErrorNamedReference(session, left, "Unsupported qualified LValue: ${left.text}")
|
||||
}
|
||||
}
|
||||
is KtParenthesizedExpression -> {
|
||||
initializeLValue(session, left.expression, convertQualified)
|
||||
}
|
||||
else -> {
|
||||
FirErrorNamedReference(session, left, "Unsupported LValue: ${left?.javaClass}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KtExpression?.generateAssignment(
|
||||
session: FirSession,
|
||||
psi: PsiElement?,
|
||||
value: FirExpression,
|
||||
operation: FirOperation,
|
||||
convert: KtExpression.() -> FirExpression
|
||||
): FirStatement {
|
||||
if (this is KtParenthesizedExpression) {
|
||||
return expression.generateAssignment(session, psi, value, operation, convert)
|
||||
}
|
||||
if (this is KtArrayAccessExpression) {
|
||||
val arrayExpression = this.arrayExpression
|
||||
val arraySet = FirArraySetCallImpl(session, psi, value, operation).apply {
|
||||
for (indexExpression in indexExpressions) {
|
||||
arguments += indexExpression.convert()
|
||||
}
|
||||
}
|
||||
if (arrayExpression is KtSimpleNameExpression) {
|
||||
return arraySet.apply {
|
||||
calleeReference = initializeLValue(session, arrayExpression) { convert() as? FirAccess }
|
||||
}
|
||||
}
|
||||
return FirBlockImpl(session, arrayExpression).apply {
|
||||
val name = Name.special("<array-set>")
|
||||
statements += generateTemporaryVariable(
|
||||
session, this@generateAssignment, name,
|
||||
arrayExpression?.convert() ?: FirErrorExpressionImpl(session, arrayExpression, "No array expression")
|
||||
)
|
||||
statements += arraySet.apply { calleeReference = FirSimpleNamedReference(session, arrayExpression, name) }
|
||||
}
|
||||
}
|
||||
if (operation != FirOperation.ASSIGN &&
|
||||
this !is KtSimpleNameExpression && this !is KtThisExpression &&
|
||||
(this !is KtQualifiedExpression || selectorExpression !is KtSimpleNameExpression)
|
||||
) {
|
||||
return FirBlockImpl(session, this).apply {
|
||||
val name = Name.special("<complex-set>")
|
||||
statements += generateTemporaryVariable(
|
||||
session, this@generateAssignment, name,
|
||||
this@generateAssignment?.convert() ?: FirErrorExpressionImpl(session, this@generateAssignment, "No LValue in assignment")
|
||||
)
|
||||
statements += FirPropertyAssignmentImpl(session, psi, value, operation).apply {
|
||||
calleeReference = FirSimpleNamedReference(session, this@generateAssignment, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return FirPropertyAssignmentImpl(session, psi, value, operation).apply {
|
||||
calleeReference = initializeLValue(session, this@generateAssignment) { convert() as? FirAccess }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,9 @@ FILE: derivedClass.kt
|
||||
|
||||
}
|
||||
<T : Any> public? final? class Derived : Base<T> {
|
||||
public? constructor(x: T): super<Base<T>>()
|
||||
public? constructor(x: T): super<Base<T>>(x#)
|
||||
|
||||
}
|
||||
<T : Any> public? final? function create(x: T): Derived<T> {
|
||||
STUB
|
||||
return@@@create Derived#(x#)
|
||||
}
|
||||
|
||||
@@ -28,30 +28,33 @@ FILE: enums.kt
|
||||
internal get(): Double
|
||||
|
||||
public? final enum entry MERCURY : Planet {
|
||||
public? constructor(): super<Planet>()
|
||||
public? constructor(): super<Planet>(Double(1.0), Double(2.0))
|
||||
|
||||
public? open? override function sayHello(): kotlin.Unit {
|
||||
println#(String(Hello!!!))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public? final enum entry VENERA : Planet {
|
||||
public? constructor(): super<Planet>()
|
||||
public? constructor(): super<Planet>(Double(3.0), Double(4.0))
|
||||
|
||||
public? open? override function sayHello(): kotlin.Unit {
|
||||
println#(String(Ola!!!))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public? final enum entry EARTH : Planet {
|
||||
public? constructor(): super<Planet>()
|
||||
public? constructor(): super<Planet>(Double(5.0), Double(6.0))
|
||||
|
||||
public? open? override function sayHello(): kotlin.Unit {
|
||||
println#(String(Privet!!!))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public? final? property g(val): Double = STUB
|
||||
public? final? property g(val): Double = div#(times#(G#, m#), times#(r#, r#))
|
||||
public? get(): Double
|
||||
|
||||
public? abstract function sayHello(): kotlin.Unit
|
||||
@@ -59,7 +62,7 @@ FILE: enums.kt
|
||||
public? final? companion object Companion {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
public? final? const property G(val): <implicit> = STUB
|
||||
public? final? const property G(val): <implicit> = Double(6.67E-11)
|
||||
public? get(): <implicit>
|
||||
|
||||
}
|
||||
|
||||
@@ -16,19 +16,19 @@ FILE: enums2.kt
|
||||
public? get(): Some
|
||||
|
||||
public? final enum entry FIRST : SomeEnum {
|
||||
public? constructor(): super<SomeEnum>()
|
||||
public? constructor(): super<SomeEnum>(O1#)
|
||||
|
||||
public? open? override function check(y: Some): Boolean {
|
||||
STUB
|
||||
return@@@check Boolean(true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public? final enum entry SECOND : SomeEnum {
|
||||
public? constructor(): super<SomeEnum>()
|
||||
public? constructor(): super<SomeEnum>(O2#)
|
||||
|
||||
public? open? override function check(y: Some): Boolean {
|
||||
STUB
|
||||
return@@@check ==(y#, O2#)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ FILE: expectActual.kt
|
||||
|
||||
}
|
||||
public? final? actual function foo(): <implicit> {
|
||||
STUB
|
||||
return@@@foo String(Hello)
|
||||
}
|
||||
public? final? actual property x(val): <implicit> = STUB
|
||||
public? final? actual property x(val): <implicit> = Int(42)
|
||||
public? get(): <implicit>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
FILE: functionTypes.kt
|
||||
<T> public? final? function simpleRun(f: ( (T) -> Unit )): Unit {
|
||||
STUB
|
||||
return@@@simpleRun f#()
|
||||
}
|
||||
<T, R> public? final? function simpleMap List<T>.(f: ( (T) -> R )): R {
|
||||
}
|
||||
<T> public? final? function simpleWith(t: T, f: ( T.() -> Unit )): Unit {
|
||||
STUB
|
||||
return@@@simpleWith t#.f#()
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ FILE: genericFunctions.kt
|
||||
public? final? interface Any {
|
||||
}
|
||||
<reified T : Any> public? final? inline function safeAs Any.(): T? {
|
||||
STUB
|
||||
return@@@safeAs as?/T(this#)
|
||||
}
|
||||
public? abstract class Summator {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
@@ -10,12 +10,12 @@ FILE: nestedClass.kt
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
public? final? class Derived : Base {
|
||||
public? constructor(s: String): super<Base>()
|
||||
public? constructor(s: String): super<Base>(s#)
|
||||
|
||||
}
|
||||
|
||||
public? final? object Obj : Base {
|
||||
public? constructor(): super<Base>()
|
||||
public? constructor(): super<Base>(String())
|
||||
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -4,8 +4,9 @@ FILE: noPrimaryConstructor.kt
|
||||
public? get(): String
|
||||
|
||||
public? constructor(x: String): super<kotlin.Any>() {
|
||||
this#.x# = x#
|
||||
}
|
||||
|
||||
public? constructor(): this<NoPrimary>()
|
||||
public? constructor(): this<NoPrimary>(String())
|
||||
|
||||
}
|
||||
|
||||
@@ -9,15 +9,16 @@ FILE: simpleClass.kt
|
||||
public? final? class SomeClass : SomeInterface {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
private final? property baz(val): <implicit> = STUB
|
||||
private final? property baz(val): <implicit> = Int(42)
|
||||
private get(): <implicit>
|
||||
|
||||
public? open? override function foo(x: Int, y: String): String {
|
||||
return@@@foo plus#(plus#(y#, x#), baz#)
|
||||
}
|
||||
|
||||
public? open? override property bar(var): Boolean
|
||||
public? get(): Boolean {
|
||||
STUB
|
||||
return Boolean(true)
|
||||
}
|
||||
public? set(value: Boolean): kotlin.Unit {
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ FILE: typeParameters.kt
|
||||
public? constructor(): super<AbstractList<Int>>()
|
||||
|
||||
public? open? override function get(index: Int): Int {
|
||||
STUB
|
||||
return@@@get Int(42)
|
||||
}
|
||||
|
||||
public? open? override function concat(other: List<Int>): List<Int> {
|
||||
STUB
|
||||
return@@@concat this#
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
interface A
|
||||
interface B
|
||||
|
||||
class C<T> where T : A, T : B {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
FILE: where.kt
|
||||
public? final? interface A {
|
||||
}
|
||||
public? final? interface B {
|
||||
}
|
||||
<T : A, B> public? final? class C {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
@Target(AnnotationTarget.EXPRESSION)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class Ann
|
||||
|
||||
fun foo(arg: Int): Int {
|
||||
if (@Ann arg == 0) {
|
||||
@Ann return 1
|
||||
}
|
||||
@Ann if (arg == 1) {
|
||||
return (@Ann 1)
|
||||
}
|
||||
return 42
|
||||
}
|
||||
|
||||
data class Two(x: Int, y: Int)
|
||||
|
||||
fun bar(two: Two) {
|
||||
val (@Ann x, @Ann y) = two
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
FILE: annotated.kt
|
||||
@Target(AnnotationTarget#.EXPRESSION#) @Retention(AnnotationRetention#.SOURCE#) public? final? annotation class Ann {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
}
|
||||
public? final? function foo(arg: Int): Int {
|
||||
when () {
|
||||
==(@Ann() arg#, Int(0)) -> {
|
||||
@Ann() return@@@foo Int(1)
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
@Ann() when () {
|
||||
==(arg#, Int(1)) -> {
|
||||
return@@@foo @Ann() Int(1)
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
return@@@foo Int(42)
|
||||
}
|
||||
public? final? data class Two {
|
||||
public? constructor(x: Int, y: Int): super<kotlin.Any>()
|
||||
|
||||
}
|
||||
public? final? function bar(two: Two): kotlin.Unit {
|
||||
val <destruct>: <implicit> = two#
|
||||
@Ann() val x: <implicit> = component1(<destruct>#)
|
||||
@Ann() val y: <implicit> = component2(<destruct>#)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
val p = 0
|
||||
fun foo() = 1
|
||||
|
||||
class Wrapper(val v: IntArray)
|
||||
|
||||
fun test(a: IntArray, w: Wrapper) = a[0] + a[p] + a[foo()] + w.v[0]
|
||||
@@ -0,0 +1,16 @@
|
||||
FILE: arrayAccess.kt
|
||||
public? final? property p(val): <implicit> = Int(0)
|
||||
public? get(): <implicit>
|
||||
public? final? function foo(): <implicit> {
|
||||
return@@@foo Int(1)
|
||||
}
|
||||
public? final? class Wrapper {
|
||||
public? constructor(v: IntArray): super<kotlin.Any>()
|
||||
|
||||
public? final? property v(val): IntArray
|
||||
public? get(): IntArray
|
||||
|
||||
}
|
||||
public? final? function test(a: IntArray, w: Wrapper): <implicit> {
|
||||
return@@@test plus#(plus#(plus#(a#[Int(0)], a#[p#]), a#[foo#()]), w#.v#[Int(0)])
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fun test() {
|
||||
val x = intArrayOf(1, 2, 3)
|
||||
x[1] = 0
|
||||
}
|
||||
|
||||
fun foo() = 1
|
||||
|
||||
fun test2() {
|
||||
intArrayOf(1, 2, 3)[foo()] = 1
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
FILE: arrayAssignment.kt
|
||||
public? final? function test(): kotlin.Unit {
|
||||
val x: <implicit> = intArrayOf#(Int(1), Int(2), Int(3))
|
||||
x#[Int(1)] = Int(0)
|
||||
}
|
||||
public? final? function foo(): <implicit> {
|
||||
return@@@foo Int(1)
|
||||
}
|
||||
public? final? function test2(): kotlin.Unit {
|
||||
val <array-set>: <implicit> = intArrayOf#(Int(1), Int(2), Int(3))
|
||||
<array-set>#[foo#()] = Int(1)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
fun foo(a: Int, b: Int) = if (a > b) a else b
|
||||
|
||||
fun bar(a: Double, b: Double): Double {
|
||||
if (a > b) {
|
||||
println(a)
|
||||
return a
|
||||
} else {
|
||||
println(b)
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
fun baz(a: Long, b: Long): Long {
|
||||
when {
|
||||
a > b -> {
|
||||
println(a)
|
||||
return a
|
||||
}
|
||||
else -> return b
|
||||
}
|
||||
}
|
||||
|
||||
fun grade(g: Int): String {
|
||||
return when (g) {
|
||||
6, 7 -> "Outstanding"
|
||||
5 -> "Excellent"
|
||||
4 -> "Good"
|
||||
3 -> "Mediocre"
|
||||
in 1..2 -> "Fail"
|
||||
is Number -> "Number"
|
||||
else -> "Unknown"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
FILE: branches.kt
|
||||
public? final? function foo(a: Int, b: Int): <implicit> {
|
||||
return@@@foo when () {
|
||||
>(a#, b#) -> {
|
||||
a#
|
||||
}
|
||||
else -> {
|
||||
b#
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function bar(a: Double, b: Double): Double {
|
||||
when () {
|
||||
>(a#, b#) -> {
|
||||
println#(a#)
|
||||
return@@@bar a#
|
||||
}
|
||||
else -> {
|
||||
println#(b#)
|
||||
return@@@bar b#
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function baz(a: Long, b: Long): Long {
|
||||
when () {
|
||||
>(a#, b#) -> {
|
||||
println#(a#)
|
||||
return@@@baz a#
|
||||
}
|
||||
else -> {
|
||||
return@@@baz b#
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function grade(g: Int): String {
|
||||
return@@@grade when (g#) {
|
||||
||(==($subj$, Int(6)), ==($subj$, Int(7))) -> {
|
||||
String(Outstanding)
|
||||
}
|
||||
==($subj$, Int(5)) -> {
|
||||
String(Excellent)
|
||||
}
|
||||
==($subj$, Int(4)) -> {
|
||||
String(Good)
|
||||
}
|
||||
==($subj$, Int(3)) -> {
|
||||
String(Mediocre)
|
||||
}
|
||||
in($subj$, rangeTo#(Int(1), Int(2))) -> {
|
||||
String(Fail)
|
||||
}
|
||||
is/Number($subj$) -> {
|
||||
String(Number)
|
||||
}
|
||||
else -> {
|
||||
String(Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
class A {
|
||||
fun foo() {}
|
||||
val bar = 0
|
||||
}
|
||||
|
||||
fun A.qux() {}
|
||||
|
||||
fun baz() {}
|
||||
|
||||
val test1 = A()::foo
|
||||
|
||||
val test2 = A()::bar
|
||||
|
||||
val test3 = A()::qux
|
||||
|
||||
val test4 = A::foo
|
||||
|
||||
val test5 = A::bar
|
||||
|
||||
val test6 = A::qux
|
||||
|
||||
val test7 = ::baz
|
||||
@@ -0,0 +1,29 @@
|
||||
FILE: callableReferences.kt
|
||||
public? final? class A {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
public? final? function foo(): kotlin.Unit {
|
||||
}
|
||||
|
||||
public? final? property bar(val): <implicit> = Int(0)
|
||||
public? get(): <implicit>
|
||||
|
||||
}
|
||||
public? final? function qux A.(): kotlin.Unit {
|
||||
}
|
||||
public? final? function baz(): kotlin.Unit {
|
||||
}
|
||||
public? final? property test1(val): <implicit> = A#()::foo#
|
||||
public? get(): <implicit>
|
||||
public? final? property test2(val): <implicit> = A#()::bar#
|
||||
public? get(): <implicit>
|
||||
public? final? property test3(val): <implicit> = A#()::qux#
|
||||
public? get(): <implicit>
|
||||
public? final? property test4(val): <implicit> = A#::foo#
|
||||
public? get(): <implicit>
|
||||
public? final? property test5(val): <implicit> = A#::bar#
|
||||
public? get(): <implicit>
|
||||
public? final? property test6(val): <implicit> = A#::qux#
|
||||
public? get(): <implicit>
|
||||
public? final? property test7(val): <implicit> = ::baz#
|
||||
public? get(): <implicit>
|
||||
@@ -0,0 +1,24 @@
|
||||
infix fun distance(x: Int, y: Int) = x + y
|
||||
|
||||
fun test(): Int = 3 distance 4
|
||||
|
||||
fun testRegular(): Int = distance(3, 4)
|
||||
|
||||
class My(var x: Int) {
|
||||
operator fun invoke() = x
|
||||
|
||||
fun foo() {}
|
||||
|
||||
fun copy() = My(x)
|
||||
}
|
||||
|
||||
fun testInvoke(): Int = My(13)()
|
||||
|
||||
fun testQualified(first: My, second: My?) {
|
||||
println(first.x)
|
||||
println(second?.x)
|
||||
first.foo()
|
||||
second?.foo()
|
||||
first.copy().foo()
|
||||
first.x = 42
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
FILE: calls.kt
|
||||
public? final? infix function distance(x: Int, y: Int): <implicit> {
|
||||
return@@@distance plus#(x#, y#)
|
||||
}
|
||||
public? final? function test(): Int {
|
||||
return@@@test distance#(Int(3), Int(4))
|
||||
}
|
||||
public? final? function testRegular(): Int {
|
||||
return@@@testRegular distance#(Int(3), Int(4))
|
||||
}
|
||||
public? final? class My {
|
||||
public? constructor(x: Int): super<kotlin.Any>()
|
||||
|
||||
public? final? property x(var): Int
|
||||
public? get(): Int
|
||||
public? set(value: Int): kotlin.Unit
|
||||
|
||||
public? final? operator function invoke(): <implicit> {
|
||||
return@@@invoke x#
|
||||
}
|
||||
|
||||
public? final? function foo(): kotlin.Unit {
|
||||
}
|
||||
|
||||
public? final? function copy(): <implicit> {
|
||||
return@@@copy My#(x#)
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function testInvoke(): Int {
|
||||
return@@@testInvoke invoke#(My#(Int(13)))
|
||||
}
|
||||
public? final? function testQualified(first: My, second: My?): kotlin.Unit {
|
||||
println#(first#.x#)
|
||||
println#(second#?.x#)
|
||||
first#.foo#()
|
||||
second#?.foo#()
|
||||
first#.copy#().foo#()
|
||||
first#.x# = Int(42)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
class A
|
||||
|
||||
fun test() {
|
||||
A::class
|
||||
test.A::class
|
||||
A()::class
|
||||
|
||||
A::class.java
|
||||
test.A::class.java
|
||||
A()::class.java
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
FILE: classReference.kt
|
||||
public? final? class A {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
}
|
||||
public? final? function test(): kotlin.Unit {
|
||||
<getClass>(A#)
|
||||
<getClass>(test#.A#)
|
||||
<getClass>(A#())
|
||||
<getClass>(A#).java#
|
||||
<getClass>(test#.A#).java#
|
||||
<getClass>(A#()).java#
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
annotation class Ann1(val arr: IntArray)
|
||||
|
||||
annotation class Ann2(val arr: DoubleArray)
|
||||
|
||||
annotation class Ann3(val arr: Array<String>)
|
||||
|
||||
@Ann1([])
|
||||
@Ann2([])
|
||||
@Ann3([])
|
||||
class Zero
|
||||
|
||||
@Ann1([1, 2])
|
||||
class First
|
||||
|
||||
@Ann2([3.14])
|
||||
class Second
|
||||
|
||||
@Ann3(["Alpha", "Omega"])
|
||||
class Third
|
||||
@@ -0,0 +1,38 @@
|
||||
FILE: collectionLiterals.kt
|
||||
public? final? annotation class Ann1 {
|
||||
public? constructor(arr: IntArray): super<kotlin.Any>()
|
||||
|
||||
public? final? property arr(val): IntArray
|
||||
public? get(): IntArray
|
||||
|
||||
}
|
||||
public? final? annotation class Ann2 {
|
||||
public? constructor(arr: DoubleArray): super<kotlin.Any>()
|
||||
|
||||
public? final? property arr(val): DoubleArray
|
||||
public? get(): DoubleArray
|
||||
|
||||
}
|
||||
public? final? annotation class Ann3 {
|
||||
public? constructor(arr: Array<String>): super<kotlin.Any>()
|
||||
|
||||
public? final? property arr(val): Array<String>
|
||||
public? get(): Array<String>
|
||||
|
||||
}
|
||||
@Ann1(<implicitArrayOf>()) @Ann2(<implicitArrayOf>()) @Ann3(<implicitArrayOf>()) public? final? class Zero {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
}
|
||||
@Ann1(<implicitArrayOf>(Int(1), Int(2))) public? final? class First {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
}
|
||||
@Ann2(<implicitArrayOf>(Double(3.14))) public? final? class Second {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
}
|
||||
@Ann3(<implicitArrayOf>(String(Alpha), String(Omega))) public? final? class Third {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
data class Some(val first: Int, val second: Double, val third: String)
|
||||
|
||||
fun foo(some: Some) {
|
||||
var (x, y, z: String) = some
|
||||
|
||||
x++
|
||||
y *= 2.0
|
||||
z = ""
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
FILE: destructuring.kt
|
||||
public? final? data class Some {
|
||||
public? constructor(first: Int, second: Double, third: String): super<kotlin.Any>()
|
||||
|
||||
public? final? property first(val): Int
|
||||
public? get(): Int
|
||||
|
||||
public? final? property second(val): Double
|
||||
public? get(): Double
|
||||
|
||||
public? final? property third(val): String
|
||||
public? get(): String
|
||||
|
||||
}
|
||||
public? final? function foo(some: Some): kotlin.Unit {
|
||||
val <destruct>: <implicit> = some#
|
||||
var x: <implicit> = component1(<destruct>#)
|
||||
var y: <implicit> = component2(<destruct>#)
|
||||
var z: String = component3(<destruct>#)
|
||||
val <unary>: <implicit> = x#
|
||||
x# = inc#(<unary>#)
|
||||
<unary>#
|
||||
y# *= Double(2.0)
|
||||
z# = String()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fun foo() {
|
||||
for (i in 1..10) {
|
||||
println(i)
|
||||
}
|
||||
}
|
||||
|
||||
fun bar(list: List<String>) {
|
||||
for (element in list.subList(0, 10)) {
|
||||
println(element)
|
||||
}
|
||||
for (element in list.subList(10, 20)) println(element)
|
||||
}
|
||||
|
||||
data class Some(val x: Int, val y: Int)
|
||||
|
||||
fun baz(set: Set<Some>) {
|
||||
for ((x, y) in set) {
|
||||
println("x = $x y = $y")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
FILE: for.kt
|
||||
public? final? function foo(): kotlin.Unit {
|
||||
val <range>: <implicit> = rangeTo#(Int(1), Int(10))
|
||||
val <iterator>: <implicit> = <range>#.iterator#()
|
||||
while(<iterator>#.hasNext#()) {
|
||||
val i: <implicit> = <iterator>#.next#()
|
||||
println#(i#)
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function bar(list: List<String>): kotlin.Unit {
|
||||
val <range>: <implicit> = list#.subList#(Int(0), Int(10))
|
||||
val <iterator>: <implicit> = <range>#.iterator#()
|
||||
while(<iterator>#.hasNext#()) {
|
||||
val element: <implicit> = <iterator>#.next#()
|
||||
println#(element#)
|
||||
}
|
||||
|
||||
val <range>: <implicit> = list#.subList#(Int(10), Int(20))
|
||||
val <iterator>: <implicit> = <range>#.iterator#()
|
||||
while(<iterator>#.hasNext#()) {
|
||||
val element: <implicit> = <iterator>#.next#()
|
||||
println#(element#)
|
||||
}
|
||||
|
||||
}
|
||||
public? final? data class Some {
|
||||
public? constructor(x: Int, y: Int): super<kotlin.Any>()
|
||||
|
||||
public? final? property x(val): Int
|
||||
public? get(): Int
|
||||
|
||||
public? final? property y(val): Int
|
||||
public? get(): Int
|
||||
|
||||
}
|
||||
public? final? function baz(set: Set<Some>): kotlin.Unit {
|
||||
val <range>: <implicit> = set#
|
||||
val <iterator>: <implicit> = <range>#.iterator#()
|
||||
while(<iterator>#.hasNext#()) {
|
||||
val <destruct>: <implicit> = <iterator>#.next#()
|
||||
val x: <implicit> = component1(<destruct>#)
|
||||
val y: <implicit> = component2(<destruct>#)
|
||||
println#(plus#(String(x = ), x#, String( y = ), y#))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun <T> nullableValue(): T? = null
|
||||
|
||||
fun test() {
|
||||
val n = nullableValue<Int>()
|
||||
val x = nullableValue<Double>()
|
||||
val s = nullableValue<String>()
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
FILE: genericCalls.kt
|
||||
<T> public? final? function nullableValue(): T? {
|
||||
return@@@nullableValue Null(null)
|
||||
}
|
||||
public? final? function test(): kotlin.Unit {
|
||||
val n: <implicit> = nullableValue#<Int>()
|
||||
val x: <implicit> = nullableValue#<Double>()
|
||||
val s: <implicit> = nullableValue#<String>()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class WithInit(x: Int) {
|
||||
val x: Int
|
||||
|
||||
init {
|
||||
this.x = x
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
FILE: init.kt
|
||||
public? final? class WithInit {
|
||||
public? constructor(x: Int): super<kotlin.Any>()
|
||||
|
||||
public? final? property x(val): Int
|
||||
public? get(): Int
|
||||
|
||||
init {
|
||||
this#.x# = x#
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
data class Tuple(val x: Int, val y: Int)
|
||||
|
||||
inline fun use(f: (Tuple) -> Int) = f(Tuple(1, 2))
|
||||
|
||||
fun foo(): Int {
|
||||
val l1 = { t: Tuple ->
|
||||
val x = t.x
|
||||
val y = t.y
|
||||
x + y
|
||||
}
|
||||
use { (x, y) -> x + y }
|
||||
|
||||
return use {
|
||||
if (it.x == 0) return@foo 0
|
||||
return@use it.y
|
||||
}
|
||||
}
|
||||
|
||||
fun bar(): Int {
|
||||
return use lambda@{
|
||||
if (it.x == 0) return@bar 0
|
||||
return@lambda it.y
|
||||
}
|
||||
}
|
||||
|
||||
fun test(list: List<Int>) {
|
||||
val map = mutableMapOf<Int, String>()
|
||||
list.forEach { map.getOrPut(it, { mutableListOf() }) += "" }
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
FILE: lambda.kt
|
||||
public? final? data class Tuple {
|
||||
public? constructor(x: Int, y: Int): super<kotlin.Any>()
|
||||
|
||||
public? final? property x(val): Int
|
||||
public? get(): Int
|
||||
|
||||
public? final? property y(val): Int
|
||||
public? get(): Int
|
||||
|
||||
}
|
||||
public? final? inline function use(f: ( (Tuple) -> Int )): <implicit> {
|
||||
return@@@use f#(Tuple#(Int(1), Int(2)))
|
||||
}
|
||||
public? final? function foo(): Int {
|
||||
val l1: <implicit> = function <implicit>.<anonymous>(t: Tuple): <implicit> {
|
||||
return {
|
||||
val x: <implicit> = t#.x#
|
||||
val y: <implicit> = t#.y#
|
||||
plus#(x#, y#)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
use#(use@function <implicit>.<anonymous>(<destruct>: <implicit>): <implicit> {
|
||||
return {
|
||||
val x: <implicit> = component1(<destruct>#)
|
||||
val y: <implicit> = component2(<destruct>#)
|
||||
plus#(x#, y#)
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
return@@@foo use#(use@function <implicit>.<anonymous>(): <implicit> {
|
||||
return {
|
||||
when () {
|
||||
==(it#.x#, Int(0)) -> {
|
||||
return@@@foo Int(0)
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
return@@@use it#.y#
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
public? final? function bar(): Int {
|
||||
return@@@bar use#(lambda@function <implicit>.<anonymous>(): <implicit> {
|
||||
return {
|
||||
when () {
|
||||
==(it#.x#, Int(0)) -> {
|
||||
return@@@bar Int(0)
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
return@@@lambda it#.y#
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
public? final? function test(list: List<Int>): kotlin.Unit {
|
||||
val map: <implicit> = mutableMapOf#<Int, String>()
|
||||
list#.forEach#(forEach@function <implicit>.<anonymous>(): <implicit> {
|
||||
return {
|
||||
val <complex-set>: <implicit> = map#.getOrPut#(it#, getOrPut@function <implicit>.<anonymous>(): <implicit> {
|
||||
return {
|
||||
mutableListOf#()
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
<complex-set># += String()
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
fun withLocals(p: Int): Int {
|
||||
class Local(val pp: Int) {
|
||||
fun diff() = pp - p
|
||||
}
|
||||
|
||||
val x = Local(42).diff()
|
||||
|
||||
fun sum(y: Int, z: Int, f: (Int, Int) -> Int): Int {
|
||||
return x + f(y + z)
|
||||
}
|
||||
|
||||
val code = (object : Any() {
|
||||
fun foo() = hashCode()
|
||||
}).foo()
|
||||
|
||||
return sum(code, Local(1).diff(), fun(x: Int, y: Int) = x + y)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
FILE: locals.kt
|
||||
public? final? function withLocals(p: Int): Int {
|
||||
public? final? class Local {
|
||||
public? constructor(pp: Int): super<kotlin.Any>()
|
||||
|
||||
public? final? property pp(val): Int
|
||||
public? get(): Int
|
||||
|
||||
public? final? function diff(): <implicit> {
|
||||
return@@@diff minus#(pp#, p#)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val x: <implicit> = Local#(Int(42)).diff#()
|
||||
public? final? function sum(y: Int, z: Int, f: ( (Int, Int) -> Int )): Int {
|
||||
return@@@sum plus#(x#, f#(plus#(y#, z#)))
|
||||
}
|
||||
|
||||
val code: <implicit> = object : Any {
|
||||
public? constructor(): super<Any>()
|
||||
|
||||
public? final? function foo(): <implicit> {
|
||||
return@@@foo hashCode#()
|
||||
}
|
||||
|
||||
}
|
||||
.foo#()
|
||||
return@@@withLocals sum#(code#, Local#(Int(1)).diff#(), function <anonymous>(x: Int, y: Int): <implicit> {
|
||||
return plus#(x#, y#)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fun simple() {
|
||||
var x = 10
|
||||
x += 20
|
||||
x -= 5
|
||||
x /= 5
|
||||
x *= 10
|
||||
}
|
||||
|
||||
fun List<String>.modify() {
|
||||
this += "Alpha"
|
||||
this += "Omega"
|
||||
}
|
||||
|
||||
fun Any.modify() {
|
||||
(this as List<Int>) += 42
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
FILE: modifications.kt
|
||||
public? final? function simple(): kotlin.Unit {
|
||||
var x: <implicit> = Int(10)
|
||||
x# += Int(20)
|
||||
x# -= Int(5)
|
||||
x# /= Int(5)
|
||||
x# *= Int(10)
|
||||
}
|
||||
public? final? function modify List<String>.(): kotlin.Unit {
|
||||
this# += String(Alpha)
|
||||
this# += String(Omega)
|
||||
}
|
||||
public? final? function modify Any.(): kotlin.Unit {
|
||||
val <complex-set>: <implicit> = as/List<Int>(this#)
|
||||
<complex-set># += Int(42)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fun orFourtyTwo(arg: Int?) = arg ?: 42
|
||||
|
||||
fun bang(arg: Int?) = arg!!
|
||||
@@ -0,0 +1,23 @@
|
||||
FILE: nullability.kt
|
||||
public? final? function orFourtyTwo(arg: Int?): <implicit> {
|
||||
return@@@orFourtyTwo when (val <elvis>: <implicit> = arg#) {
|
||||
!=($subj$, Null(null)) -> {
|
||||
<elvis>#
|
||||
}
|
||||
else -> {
|
||||
Int(42)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function bang(arg: Int?): <implicit> {
|
||||
return@@@bang when (val <bangbang>: <implicit> = arg#) {
|
||||
!=($subj$, Null(null)) -> {
|
||||
<bangbang>#
|
||||
}
|
||||
else -> {
|
||||
throw KotlinNullPointerException#()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
return
|
||||
}
|
||||
|
||||
fun bar(): String {
|
||||
return "Hello"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
FILE: simpleReturns.kt
|
||||
public? final? function foo(): kotlin.Unit {
|
||||
return@@@foo Unit
|
||||
}
|
||||
public? final? function bar(): String {
|
||||
return@@@bar String(Hello)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
interface A {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun foo() {}
|
||||
fun bar() {}
|
||||
}
|
||||
|
||||
class C : A, B {
|
||||
override fun bar() {
|
||||
super.bar()
|
||||
}
|
||||
|
||||
override fun foo() {
|
||||
super<A>.foo()
|
||||
super<B>.foo()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
FILE: super.kt
|
||||
public? final? interface A {
|
||||
public? final? function foo(): kotlin.Unit {
|
||||
}
|
||||
|
||||
}
|
||||
public? final? interface B {
|
||||
public? final? function foo(): kotlin.Unit {
|
||||
}
|
||||
|
||||
public? final? function bar(): kotlin.Unit {
|
||||
}
|
||||
|
||||
}
|
||||
public? final? class C : A, B {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
public? open? override function bar(): kotlin.Unit {
|
||||
super<<implicit>>.bar#()
|
||||
}
|
||||
|
||||
public? open? override function foo(): kotlin.Unit {
|
||||
super<A>.foo#()
|
||||
super<B>.foo#()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
class Some {
|
||||
fun foo(): Int = 1
|
||||
|
||||
fun bar(): Int {
|
||||
return this.foo()
|
||||
}
|
||||
|
||||
val instance: Some
|
||||
get() = this@Some
|
||||
|
||||
fun String.extension(): Int {
|
||||
return this@Some.bar() + this.length
|
||||
}
|
||||
}
|
||||
|
||||
fun Some.extension() = this.bar()
|
||||
|
||||
fun test(some: Some): Int {
|
||||
return with(some) {
|
||||
this.foo() + this@with.extension()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
FILE: these.kt
|
||||
public? final? class Some {
|
||||
public? constructor(): super<kotlin.Any>()
|
||||
|
||||
public? final? function foo(): Int {
|
||||
return@@@foo Int(1)
|
||||
}
|
||||
|
||||
public? final? function bar(): Int {
|
||||
return@@@bar this#.foo#()
|
||||
}
|
||||
|
||||
public? final? property instance(val): Some
|
||||
public? get(): Some {
|
||||
return this@Some
|
||||
}
|
||||
|
||||
public? final? function extension String.(): Int {
|
||||
return@@@extension plus#(this@Some.bar#(), this#.length#)
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function extension Some.(): <implicit> {
|
||||
return@@@extension this#.bar#()
|
||||
}
|
||||
public? final? function test(some: Some): Int {
|
||||
return@@@test with#(some#, with@function <implicit>.<anonymous>(): <implicit> {
|
||||
return {
|
||||
plus#(this#.foo#(), this@with.extension#())
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fun some() {
|
||||
try {
|
||||
throw KotlinNullPointerException()
|
||||
} catch (e: RuntimeException) {
|
||||
println("Runtime exception")
|
||||
} catch (e: Exception) {
|
||||
println("Some exception")
|
||||
} finally {
|
||||
println("finally")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
FILE: try.kt
|
||||
public? final? function some(): kotlin.Unit {
|
||||
try {
|
||||
throw KotlinNullPointerException#()
|
||||
}
|
||||
catch (e: RuntimeException) {
|
||||
println#(String(Runtime exception))
|
||||
}
|
||||
catch (e: Exception) {
|
||||
println#(String(Some exception))
|
||||
}
|
||||
finally {
|
||||
println#(String(finally))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
interface IThing
|
||||
|
||||
fun test1(x: Any) = x is IThing
|
||||
fun test2(x: Any) = x !is IThing
|
||||
fun test3(x: Any) = x as IThing
|
||||
fun test4(x: Any) = x as? IThing
|
||||
@@ -0,0 +1,15 @@
|
||||
FILE: typeOperators.kt
|
||||
public? final? interface IThing {
|
||||
}
|
||||
public? final? function test1(x: Any): <implicit> {
|
||||
return@@@test1 is/IThing(x#)
|
||||
}
|
||||
public? final? function test2(x: Any): <implicit> {
|
||||
return@@@test2 !is/IThing(x#)
|
||||
}
|
||||
public? final? function test3(x: Any): <implicit> {
|
||||
return@@@test3 as/IThing(x#)
|
||||
}
|
||||
public? final? function test4(x: Any): <implicit> {
|
||||
return@@@test4 as?/IThing(x#)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
fun test() {
|
||||
var x = 0
|
||||
val x1 = x++
|
||||
val x2 = ++x
|
||||
val x3 = --x
|
||||
val x4 = x--
|
||||
if (!(x == 0)) {
|
||||
println("000")
|
||||
}
|
||||
}
|
||||
|
||||
class X(val i: Int)
|
||||
|
||||
fun test2(x: X) {
|
||||
val x1 = x.i++
|
||||
val x2 = ++x.i
|
||||
}
|
||||
|
||||
fun test3(arr: Array<Int>) {
|
||||
val x1 = arr[0]++
|
||||
val x2 = ++arr[1]
|
||||
}
|
||||
|
||||
class Y(val arr: Array<Int>)
|
||||
|
||||
fun test4(y: Y) {
|
||||
val x1 = y.arr[0]++
|
||||
val x2 = ++y.arr[1]
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
FILE: unary.kt
|
||||
public? final? function test(): kotlin.Unit {
|
||||
var x: <implicit> = Int(0)
|
||||
val x1: <implicit> = {
|
||||
val <unary>: <implicit> = x#
|
||||
x# = inc#(<unary>#)
|
||||
<unary>#
|
||||
}
|
||||
|
||||
val x2: <implicit> = {
|
||||
val <unary>: <implicit> = x#
|
||||
x# = inc#(<unary>#)
|
||||
x#
|
||||
}
|
||||
|
||||
val x3: <implicit> = {
|
||||
val <unary>: <implicit> = x#
|
||||
x# = dec#(<unary>#)
|
||||
x#
|
||||
}
|
||||
|
||||
val x4: <implicit> = {
|
||||
val <unary>: <implicit> = x#
|
||||
x# = dec#(<unary>#)
|
||||
<unary>#
|
||||
}
|
||||
|
||||
when () {
|
||||
not#(==(x#, Int(0))) -> {
|
||||
println#(String(000))
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public? final? class X {
|
||||
public? constructor(i: Int): super<kotlin.Any>()
|
||||
|
||||
public? final? property i(val): Int
|
||||
public? get(): Int
|
||||
|
||||
}
|
||||
public? final? function test2(x: X): kotlin.Unit {
|
||||
val x1: <implicit> = {
|
||||
val <unary>: <implicit> = x#.i#
|
||||
x#.i# = inc#(<unary>#)
|
||||
<unary>#
|
||||
}
|
||||
|
||||
val x2: <implicit> = {
|
||||
val <unary>: <implicit> = x#.i#
|
||||
val <unary-result>: <implicit> = inc#(<unary>#)
|
||||
x#.i# = <unary-result>#
|
||||
<unary-result>#
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function test3(arr: Array<Int>): kotlin.Unit {
|
||||
val x1: <implicit> = {
|
||||
val <unary>: <implicit> = arr#[Int(0)]
|
||||
arr#[Int(0)] = inc#(<unary>#)
|
||||
<unary>#
|
||||
}
|
||||
|
||||
val x2: <implicit> = {
|
||||
val <unary>: <implicit> = arr#[Int(1)]
|
||||
val <unary-result>: <implicit> = inc#(<unary>#)
|
||||
arr#[Int(1)] = <unary-result>#
|
||||
<unary-result>#
|
||||
}
|
||||
|
||||
}
|
||||
public? final? class Y {
|
||||
public? constructor(arr: Array<Int>): super<kotlin.Any>()
|
||||
|
||||
public? final? property arr(val): Array<Int>
|
||||
public? get(): Array<Int>
|
||||
|
||||
}
|
||||
public? final? function test4(y: Y): kotlin.Unit {
|
||||
val x1: <implicit> = {
|
||||
val <unary>: <implicit> = y#.arr#[Int(0)]
|
||||
val <array-set>: <implicit> = y#.arr#
|
||||
<array-set>#[Int(0)] = inc#(<unary>#)
|
||||
<unary>#
|
||||
}
|
||||
|
||||
val x2: <implicit> = {
|
||||
val <unary>: <implicit> = y#.arr#[Int(1)]
|
||||
val <unary-result>: <implicit> = inc#(<unary>#)
|
||||
val <array-set>: <implicit> = y#.arr#
|
||||
<array-set>#[Int(1)] = <unary-result>#
|
||||
<unary-result>#
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo() {
|
||||
val x = 1
|
||||
var y = x + 1
|
||||
val z = y * 2
|
||||
y = y + z
|
||||
val w = y - x
|
||||
return w
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
FILE: variables.kt
|
||||
public? final? function foo(): kotlin.Unit {
|
||||
val x: <implicit> = Int(1)
|
||||
var y: <implicit> = plus#(x#, Int(1))
|
||||
val z: <implicit> = times#(y#, Int(2))
|
||||
y# = plus#(y#, z#)
|
||||
val w: <implicit> = minus#(y#, x#)
|
||||
return@@@foo w#
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fun foo(limit: Int) {
|
||||
var k = 0
|
||||
some@ while (k < limit) {
|
||||
k++
|
||||
println(k)
|
||||
while (k == 13) {
|
||||
k++
|
||||
if (k < limit) break@some
|
||||
if (k > limit) continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun bar(limit: Int) {
|
||||
var k = limit
|
||||
do {
|
||||
k--
|
||||
println(k)
|
||||
} while (k >= 0)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
FILE: while.kt
|
||||
public? final? function foo(limit: Int): kotlin.Unit {
|
||||
var k: <implicit> = Int(0)
|
||||
some@while(<(k#, limit#)) {
|
||||
val <unary>: <implicit> = k#
|
||||
k# = inc#(<unary>#)
|
||||
<unary>#
|
||||
println#(k#)
|
||||
while(==(k#, Int(13))) {
|
||||
val <unary>: <implicit> = k#
|
||||
k# = inc#(<unary>#)
|
||||
<unary>#
|
||||
when () {
|
||||
<(k#, limit#) -> {
|
||||
break@@@[<(k#, limit#)]
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
when () {
|
||||
>(k#, limit#) -> {
|
||||
continue@@@[==(k#, Int(13))]
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public? final? function bar(limit: Int): kotlin.Unit {
|
||||
var k: <implicit> = limit#
|
||||
do {
|
||||
val <unary>: <implicit> = k#
|
||||
k# = dec#(<unary>#)
|
||||
<unary>#
|
||||
println#(k#)
|
||||
}
|
||||
while(>=(k#, Int(0)))
|
||||
}
|
||||
+3
-3
@@ -58,7 +58,7 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
||||
|
||||
protected fun doRawFirTest(filePath: String) {
|
||||
val file = createKtFile(filePath)
|
||||
val firFile = file.toFirFile()
|
||||
val firFile = file.toFirFile(stubMode = false)
|
||||
val firFileDump = StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString()
|
||||
val expectedPath = filePath.replace(".kt", ".txt")
|
||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
|
||||
@@ -71,8 +71,8 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
||||
}
|
||||
}
|
||||
|
||||
protected fun KtFile.toFirFile(): FirFile =
|
||||
RawFirBuilder(object : FirSessionBase() {}).buildFirFile(this)
|
||||
protected fun KtFile.toFirFile(stubMode: Boolean): FirFile =
|
||||
RawFirBuilder(object : FirSessionBase() {}, stubMode).buildFirFile(this)
|
||||
|
||||
private fun FirElement.traverseChildren(result: MutableSet<FirElement> = hashSetOf()): MutableSet<FirElement> {
|
||||
if (!result.add(this)) {
|
||||
|
||||
Generated
+138
@@ -130,5 +130,143 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
|
||||
public void testTypeParameters() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/typeParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("where.kt")
|
||||
public void testWhere() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/declarations/where.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/psi2fir/testData/rawBuilder/expressions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Expressions extends AbstractRawFirBuilderTestCase {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doRawFirTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInExpressions() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/psi2fir/testData/rawBuilder/expressions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("annotated.kt")
|
||||
public void testAnnotated() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/annotated.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAccess.kt")
|
||||
public void testArrayAccess() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/arrayAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAssignment.kt")
|
||||
public void testArrayAssignment() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/arrayAssignment.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("branches.kt")
|
||||
public void testBranches() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/branches.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferences.kt")
|
||||
public void testCallableReferences() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/callableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("calls.kt")
|
||||
public void testCalls() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/calls.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classReference.kt")
|
||||
public void testClassReference() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/classReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("collectionLiterals.kt")
|
||||
public void testCollectionLiterals() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/collectionLiterals.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("destructuring.kt")
|
||||
public void testDestructuring() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/destructuring.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("for.kt")
|
||||
public void testFor() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/for.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericCalls.kt")
|
||||
public void testGenericCalls() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/genericCalls.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("init.kt")
|
||||
public void testInit() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambda.kt")
|
||||
public void testLambda() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/lambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("locals.kt")
|
||||
public void testLocals() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/locals.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("modifications.kt")
|
||||
public void testModifications() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/modifications.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullability.kt")
|
||||
public void testNullability() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/nullability.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleReturns.kt")
|
||||
public void testSimpleReturns() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/simpleReturns.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("super.kt")
|
||||
public void testSuper() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/super.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("these.kt")
|
||||
public void testThese() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/these.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("try.kt")
|
||||
public void testTry() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/try.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeOperators.kt")
|
||||
public void testTypeOperators() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/typeOperators.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unary.kt")
|
||||
public void testUnary() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/unary.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("variables.kt")
|
||||
public void testVariables() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/variables.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("while.kt")
|
||||
public void testWhile() throws Exception {
|
||||
runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/while.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+100
-5
@@ -6,8 +6,19 @@
|
||||
package org.jetbrains.kotlin.fir.builder
|
||||
|
||||
import com.intellij.testFramework.TestDataPath
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAccess
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners
|
||||
import org.junit.runner.RunWith
|
||||
import java.io.File
|
||||
@@ -17,11 +28,19 @@ import kotlin.system.measureNanoTime
|
||||
@RunWith(JUnit3RunnerWithInners::class)
|
||||
class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
|
||||
fun testTotalKotlin() {
|
||||
private fun testTotalKotlinWithGivenMode(stubMode: Boolean) {
|
||||
val root = File(testDataPath)
|
||||
var counter = 0
|
||||
var time = 0L
|
||||
var totalLength = 0
|
||||
var expressionStubs = 0
|
||||
var errorExpressions = 0
|
||||
var normalExpressions = 0
|
||||
var normalStatements = 0
|
||||
var errorDeclarations = 0
|
||||
var normalDeclarations = 0
|
||||
var errorReferences = 0
|
||||
var normalReferences = 0
|
||||
println("BASE PATH: $testDataPath")
|
||||
for (file in root.walkTopDown()) {
|
||||
if (file.isDirectory) continue
|
||||
@@ -31,12 +50,66 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
val ktFile = createKtFile(file.toRelativeString(root))
|
||||
var firFile: FirFile? = null
|
||||
time += measureNanoTime {
|
||||
firFile = ktFile.toFirFile()
|
||||
firFile = ktFile.toFirFile(stubMode)
|
||||
}
|
||||
totalLength += StringBuilder().also { FirRenderer(it).visitFile(firFile!!) }.length
|
||||
counter++
|
||||
firFile?.accept(object : FirVisitorVoid() {
|
||||
override fun visitElement(element: FirElement) {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitErrorExpression(errorExpression: FirErrorExpression) {
|
||||
errorExpressions++
|
||||
println(errorExpression.render())
|
||||
errorExpression.psi?.let { println(it) }
|
||||
}
|
||||
|
||||
override fun visitAccess(access: FirAccess) {
|
||||
val calleeReference = access.calleeReference
|
||||
if (calleeReference is FirErrorNamedReference) {
|
||||
errorReferences++
|
||||
println(calleeReference.errorReason)
|
||||
} else {
|
||||
normalReferences++
|
||||
}
|
||||
super.visitAccess(access)
|
||||
}
|
||||
|
||||
override fun visitExpression(expression: FirExpression) {
|
||||
when (expression) {
|
||||
is FirExpressionStub -> {
|
||||
expressionStubs++
|
||||
if (!stubMode) {
|
||||
println(expression.psi?.text)
|
||||
}
|
||||
}
|
||||
else -> normalExpressions++
|
||||
}
|
||||
expression.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitStatement(statement: FirStatement) {
|
||||
normalStatements++
|
||||
statement.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitErrorDeclaration(errorDeclaration: FirErrorDeclaration) {
|
||||
errorDeclarations++
|
||||
println(errorDeclaration.render())
|
||||
errorDeclaration.psi?.let { println(it) }
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: FirDeclaration) {
|
||||
normalDeclarations++
|
||||
declaration.acceptChildren(this)
|
||||
}
|
||||
})
|
||||
|
||||
} catch (e: Exception) {
|
||||
println("TIME PER FILE: ${(time / counter) * 1e-6} ms, COUNTER: $counter")
|
||||
if (counter > 0) {
|
||||
println("TIME PER FILE: ${(time / counter) * 1e-6} ms, COUNTER: $counter")
|
||||
}
|
||||
println("EXCEPTION in: " + file.toRelativeString(root))
|
||||
throw e
|
||||
}
|
||||
@@ -44,6 +117,28 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
println("SUCCESS!")
|
||||
println("TOTAL LENGTH: $totalLength")
|
||||
println("TIME PER FILE: ${(time / counter) * 1e-6} ms, COUNTER: $counter")
|
||||
println("EXPRESSION STUBS: $expressionStubs")
|
||||
println("ERROR EXPRESSIONS: $errorExpressions")
|
||||
println("NORMAL EXPRESSIONS: $normalExpressions")
|
||||
println("NORMAL STATEMENTS: $normalStatements")
|
||||
println("ERROR DECLARATIONS: $errorDeclarations")
|
||||
println("NORMAL DECLARATIONS: $normalDeclarations")
|
||||
println("ERROR REFERENCES: $errorReferences")
|
||||
println("NORMAL REFERENCES: $normalReferences")
|
||||
if (!stubMode) {
|
||||
assertEquals(0, expressionStubs)
|
||||
}
|
||||
assertEquals(0, errorExpressions)
|
||||
assertEquals(0, errorDeclarations)
|
||||
assertEquals(0, errorReferences)
|
||||
}
|
||||
|
||||
fun testTotalKotlinWithExpressionTrees() {
|
||||
testTotalKotlinWithGivenMode(stubMode = false)
|
||||
}
|
||||
|
||||
fun testTotalKotlinWithDeclarationsOnly() {
|
||||
testTotalKotlinWithGivenMode(stubMode = true)
|
||||
}
|
||||
|
||||
fun testVisitConsistency() {
|
||||
@@ -53,7 +148,7 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
if (file.path.contains("testData") || file.path.contains("resources")) continue
|
||||
if (file.extension != "kt") continue
|
||||
val ktFile = createKtFile(file.toRelativeString(root))
|
||||
val firFile = ktFile.toFirFile()
|
||||
val firFile = ktFile.toFirFile(stubMode = false)
|
||||
try {
|
||||
firFile.checkChildren()
|
||||
} catch (e: Throwable) {
|
||||
@@ -70,7 +165,7 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
if (file.path.contains("testData") || file.path.contains("resources")) continue
|
||||
if (file.extension != "kt") continue
|
||||
val ktFile = createKtFile(file.toRelativeString(root))
|
||||
val firFile = ktFile.toFirFile()
|
||||
val firFile = ktFile.toFirFile(stubMode = false)
|
||||
try {
|
||||
firFile.checkTransformedChildren()
|
||||
} catch (e: Throwable) {
|
||||
|
||||
Reference in New Issue
Block a user