Extend compile time checker to check constructors body
This commit is contained in:
committed by
TeamCityServer
parent
cc0bbac354
commit
9b1f11b22b
+27
-5
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
class IrCompileTimeChecker(
|
class IrCompileTimeChecker(
|
||||||
containingDeclaration: IrElement? = null, private val mode: EvaluationMode = EvaluationMode.WITH_ANNOTATIONS
|
containingDeclaration: IrElement? = null, private val mode: EvaluationMode = EvaluationMode.WITH_ANNOTATIONS
|
||||||
) : IrElementVisitor<Boolean, Nothing?> {
|
) : IrElementVisitor<Boolean, Nothing?> {
|
||||||
private val visitedStack = mutableListOf<IrElement?>().apply { if (containingDeclaration != null) add(containingDeclaration) }
|
private val visitedStack = mutableListOf<IrElement>().apply { if (containingDeclaration != null) add(containingDeclaration) }
|
||||||
|
|
||||||
private fun IrElement.asVisited(block: () -> Boolean): Boolean {
|
private fun IrElement.asVisited(block: () -> Boolean): Boolean {
|
||||||
visitedStack += this
|
visitedStack += this
|
||||||
@@ -39,7 +39,7 @@ class IrCompileTimeChecker(
|
|||||||
private fun visitConstructor(expression: IrFunctionAccessExpression): Boolean {
|
private fun visitConstructor(expression: IrFunctionAccessExpression): Boolean {
|
||||||
return when {
|
return when {
|
||||||
!visitValueParameters(expression, null) -> false
|
!visitValueParameters(expression, null) -> false
|
||||||
else -> mode.canEvaluateFunction(expression.symbol.owner)
|
else -> if (mode.canEvaluateBody(expression.symbol.owner)) expression.symbol.owner.body?.accept(this, null) != false else true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ class IrCompileTimeChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitComposite(expression: IrComposite, data: Nothing?): Boolean {
|
override fun visitComposite(expression: IrComposite, data: Nothing?): Boolean {
|
||||||
if (expression.origin == IrStatementOrigin.DESTRUCTURING_DECLARATION) {
|
if (expression.origin == IrStatementOrigin.DESTRUCTURING_DECLARATION || expression.origin == null) {
|
||||||
return visitStatements(expression.statements, data)
|
return visitStatements(expression.statements, data)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -130,7 +130,8 @@ class IrCompileTimeChecker(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression.receiver == null) return expression.symbol.owner.correspondingPropertySymbol?.owner?.isConst == true
|
if (expression.receiver == null)
|
||||||
|
return expression.symbol.owner.correspondingPropertySymbol?.owner?.let { it.isConst || it.backingField?.initializer?.expression is IrConst<*> } == true
|
||||||
|
|
||||||
val property = expression.symbol.owner.correspondingPropertySymbol?.owner
|
val property = expression.symbol.owner.correspondingPropertySymbol?.owner
|
||||||
val owner = expression.symbol.owner
|
val owner = expression.symbol.owner
|
||||||
@@ -146,10 +147,13 @@ class IrCompileTimeChecker(
|
|||||||
val getter = parent.declarations.filterIsInstance<IrProperty>().single { it == property }.getter
|
val getter = parent.declarations.filterIsInstance<IrProperty>().single { it == property }.getter
|
||||||
val isJavaPrimitiveStatic = owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic &&
|
val isJavaPrimitiveStatic = owner.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && owner.isStatic &&
|
||||||
(owner.type.isPrimitiveType() || owner.type.isStringClassType())
|
(owner.type.isPrimitiveType() || owner.type.isStringClassType())
|
||||||
return visitedStack.contains(getter) || isJavaPrimitiveStatic
|
return getter?.let { visitedStack.contains(it) } == true || isJavaPrimitiveStatic
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSetField(expression: IrSetField, data: Nothing?): Boolean {
|
override fun visitSetField(expression: IrSetField, data: Nothing?): Boolean {
|
||||||
|
if (expression.receiver.let { it == null || (it.type.classifierOrNull?.owner as? IrClass)?.isObject == true }) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
//todo check receiver?
|
//todo check receiver?
|
||||||
val property = expression.symbol.owner.correspondingPropertySymbol?.owner
|
val property = expression.symbol.owner.correspondingPropertySymbol?.owner
|
||||||
val parent = expression.symbol.owner.parent as IrDeclarationContainer
|
val parent = expression.symbol.owner.parent as IrDeclarationContainer
|
||||||
@@ -161,10 +165,28 @@ class IrCompileTimeChecker(
|
|||||||
return visitConstructor(expression)
|
return visitConstructor(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Nothing?): Boolean {
|
||||||
|
if (expression.symbol.owner.returnType.isAny()) return true
|
||||||
|
return visitConstructor(expression)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: Nothing?): Boolean {
|
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: Nothing?): Boolean {
|
||||||
return visitConstructor(expression)
|
return visitConstructor(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: Nothing?): Boolean {
|
||||||
|
val irClass = expression.classSymbol.owner
|
||||||
|
val classProperties = irClass.declarations.filterIsInstance<IrProperty>()
|
||||||
|
val anonymousInitializer = irClass.declarations.filterIsInstance<IrAnonymousInitializer>().filter { !it.isStatic }
|
||||||
|
|
||||||
|
|
||||||
|
return anonymousInitializer.all { init -> init.body.accept(this, data) } && classProperties.all {
|
||||||
|
val propertyInitializer = it.backingField?.initializer?.expression
|
||||||
|
if ((propertyInitializer as? IrGetValue)?.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER) return@all true
|
||||||
|
return@all (propertyInitializer?.accept(this, data) != false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitFunctionReference(expression: IrFunctionReference, data: Nothing?): Boolean {
|
override fun visitFunctionReference(expression: IrFunctionReference, data: Nothing?): Boolean {
|
||||||
return expression.asVisited {
|
return expression.asVisited {
|
||||||
mode.canEvaluateFunction(expression.symbol.owner) && expression.symbol.owner.body?.accept(this, data) == true
|
mode.canEvaluateFunction(expression.symbol.owner) && expression.symbol.owner.body?.accept(this, data) == true
|
||||||
|
|||||||
Reference in New Issue
Block a user