[FIR] Add the new test set to render diagnostics from IR const evaluator
This commit is contained in:
@@ -5,9 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.backend
|
package org.jetbrains.kotlin.fir.backend
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
|
||||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.KtPsiSourceFileLinesMapping
|
import org.jetbrains.kotlin.KtPsiSourceFileLinesMapping
|
||||||
import org.jetbrains.kotlin.KtSourceFileLinesMappingFromLineStartOffsets
|
import org.jetbrains.kotlin.KtSourceFileLinesMappingFromLineStartOffsets
|
||||||
|
import org.jetbrains.kotlin.backend.common.CommonBackendErrors
|
||||||
|
import org.jetbrains.kotlin.backend.common.sourceElement
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||||
@@ -400,8 +403,8 @@ class Fir2IrConverter(
|
|||||||
private fun evaluateConstants(irModuleFragment: IrModuleFragment, fir2IrConfiguration: Fir2IrConfiguration) {
|
private fun evaluateConstants(irModuleFragment: IrModuleFragment, fir2IrConfiguration: Fir2IrConfiguration) {
|
||||||
val firModuleDescriptor = irModuleFragment.descriptor as? FirModuleDescriptor
|
val firModuleDescriptor = irModuleFragment.descriptor as? FirModuleDescriptor
|
||||||
val targetPlatform = firModuleDescriptor?.platform
|
val targetPlatform = firModuleDescriptor?.platform
|
||||||
val languageVersionSettings = firModuleDescriptor?.session?.languageVersionSettings
|
val languageVersionSettings = firModuleDescriptor?.session?.languageVersionSettings ?: return
|
||||||
val intrinsicConstEvaluation = languageVersionSettings?.supportsFeature(LanguageFeature.IntrinsicConstEvaluation) == true
|
val intrinsicConstEvaluation = languageVersionSettings.supportsFeature(LanguageFeature.IntrinsicConstEvaluation) == true
|
||||||
|
|
||||||
val configuration = IrInterpreterConfiguration(
|
val configuration = IrInterpreterConfiguration(
|
||||||
platform = targetPlatform,
|
platform = targetPlatform,
|
||||||
@@ -409,8 +412,19 @@ class Fir2IrConverter(
|
|||||||
)
|
)
|
||||||
val interpreter = IrInterpreter(IrInterpreterEnvironment(irModuleFragment.irBuiltins, configuration))
|
val interpreter = IrInterpreter(IrInterpreterEnvironment(irModuleFragment.irBuiltins, configuration))
|
||||||
val mode = if (intrinsicConstEvaluation) EvaluationMode.ONLY_INTRINSIC_CONST else EvaluationMode.ONLY_BUILTINS
|
val mode = if (intrinsicConstEvaluation) EvaluationMode.ONLY_INTRINSIC_CONST else EvaluationMode.ONLY_BUILTINS
|
||||||
|
val ktDiagnosticReporter = KtDiagnosticReporterWithImplicitIrBasedContext(fir2IrConfiguration.diagnosticReporter, languageVersionSettings)
|
||||||
irModuleFragment.files.forEach {
|
irModuleFragment.files.forEach {
|
||||||
it.transformConst(interpreter, mode, fir2IrConfiguration.evaluatedConstTracker, fir2IrConfiguration.inlineConstTracker)
|
it.transformConst(
|
||||||
|
interpreter,
|
||||||
|
mode,
|
||||||
|
fir2IrConfiguration.evaluatedConstTracker,
|
||||||
|
fir2IrConfiguration.inlineConstTracker,
|
||||||
|
onError = { irFile, element, error ->
|
||||||
|
// We are using exactly this overload of `at` to eliminate differences between PSI and LightTree render
|
||||||
|
ktDiagnosticReporter.at(element.sourceElement(), element, irFile)
|
||||||
|
.report(CommonBackendErrors.EVALUATION_ERROR, error.description)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-6
@@ -24,12 +24,6 @@ public class FirPsiDiagnosticsTestWithJvmIrBackendGenerated extends AbstractFirP
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestMetadata("exceptionFromInterpreter.kt")
|
|
||||||
public void testExceptionFromInterpreter() throws Exception {
|
|
||||||
runTest("compiler/testData/diagnostics/testsWithJvmBackend/exceptionFromInterpreter.kt");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("indirectInlineCycle.kt")
|
@TestMetadata("indirectInlineCycle.kt")
|
||||||
public void testIndirectInlineCycle() throws Exception {
|
public void testIndirectInlineCycle() throws Exception {
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.test.runners.ir;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.test.generators.GenerateCompilerTestsKt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/irInterpreter")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirLightTreeWithInterpreterDiagnosticsTestGenerated extends AbstractFirLightTreeWithInterpreterDiagnosticsTest {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInIrInterpreter() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/irInterpreter"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("exceptionFromInterpreter.kt")
|
||||||
|
public void testExceptionFromInterpreter() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/irInterpreter/exceptionFromInterpreter.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.test.runners.ir;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.test.generators.GenerateCompilerTestsKt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/irInterpreter")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class FirPsiWithInterpreterDiagnosticsTestGenerated extends AbstractFirPsiWithInterpreterDiagnosticsTest {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInIrInterpreter() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/irInterpreter"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("exceptionFromInterpreter.kt")
|
||||||
|
public void testExceptionFromInterpreter() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/irInterpreter/exceptionFromInterpreter.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-8
@@ -6,9 +6,11 @@
|
|||||||
package org.jetbrains.kotlin.resolve.jvm.diagnostics
|
package org.jetbrains.kotlin.resolve.jvm.diagnostics
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
||||||
import org.jetbrains.kotlin.diagnostics.*
|
|
||||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT
|
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT
|
||||||
|
import org.jetbrains.kotlin.diagnostics.error0
|
||||||
|
import org.jetbrains.kotlin.diagnostics.error1
|
||||||
|
import org.jetbrains.kotlin.diagnostics.error2
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.*
|
import org.jetbrains.kotlin.diagnostics.rendering.*
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
|
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
|
||||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||||
@@ -31,9 +33,6 @@ object JvmBackendErrors {
|
|||||||
val SCRIPT_CAPTURING_ENUM by error1<PsiElement, String>()
|
val SCRIPT_CAPTURING_ENUM by error1<PsiElement, String>()
|
||||||
val SCRIPT_CAPTURING_ENUM_ENTRY by error1<PsiElement, String>()
|
val SCRIPT_CAPTURING_ENUM_ENTRY by error1<PsiElement, String>()
|
||||||
|
|
||||||
val EXCEPTION_IN_CONST_VAL_INITIALIZER by error1<PsiElement, String>()
|
|
||||||
val EXCEPTION_IN_CONST_EXPRESSION by warning1<PsiElement, String>()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
RootDiagnosticRendererFactory.registerFactory(KtDefaultJvmErrorMessages)
|
RootDiagnosticRendererFactory.registerFactory(KtDefaultJvmErrorMessages)
|
||||||
}
|
}
|
||||||
@@ -67,8 +66,5 @@ object KtDefaultJvmErrorMessages : BaseDiagnosticRendererFactory() {
|
|||||||
map.put(JvmBackendErrors.SCRIPT_CAPTURING_INTERFACE, "Interface {0} captures the script class instance. Try to use class instead", STRING)
|
map.put(JvmBackendErrors.SCRIPT_CAPTURING_INTERFACE, "Interface {0} captures the script class instance. Try to use class instead", STRING)
|
||||||
map.put(JvmBackendErrors.SCRIPT_CAPTURING_ENUM, "Enum class {0} captures the script class instance. Try to use class or anonymous object instead", STRING)
|
map.put(JvmBackendErrors.SCRIPT_CAPTURING_ENUM, "Enum class {0} captures the script class instance. Try to use class or anonymous object instead", STRING)
|
||||||
map.put(JvmBackendErrors.SCRIPT_CAPTURING_ENUM_ENTRY, "Enum entry {0} captures the script class instance. Try to use class or anonymous object instead", STRING)
|
map.put(JvmBackendErrors.SCRIPT_CAPTURING_ENUM_ENTRY, "Enum entry {0} captures the script class instance. Try to use class or anonymous object instead", STRING)
|
||||||
|
|
||||||
map.put(JvmBackendErrors.EXCEPTION_IN_CONST_VAL_INITIALIZER, "Cannot evaluate constant expression: {0}", STRING)
|
|
||||||
map.put(JvmBackendErrors.EXCEPTION_IN_CONST_EXPRESSION, "Constant expression will throw an exception at runtime: {0}", STRING)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-8
@@ -8,25 +8,18 @@ package org.jetbrains.kotlin.backend.common.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrErrorExpression
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
|
||||||
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||||
import org.jetbrains.kotlin.ir.interpreter.transformer.preprocessForConstTransformer
|
import org.jetbrains.kotlin.ir.interpreter.transformer.preprocessForConstTransformer
|
||||||
import org.jetbrains.kotlin.ir.interpreter.transformer.runConstOptimizations
|
import org.jetbrains.kotlin.ir.interpreter.transformer.runConstOptimizations
|
||||||
import org.jetbrains.kotlin.ir.interpreter.transformer.transformConst
|
|
||||||
|
|
||||||
class ConstEvaluationLowering(
|
class ConstEvaluationLowering(
|
||||||
val context: CommonBackendContext,
|
val context: CommonBackendContext,
|
||||||
private val suppressErrors: Boolean = context.configuration.getBoolean(CommonConfigurationKeys.IGNORE_CONST_OPTIMIZATION_ERRORS),
|
private val suppressErrors: Boolean = context.configuration.getBoolean(CommonConfigurationKeys.IGNORE_CONST_OPTIMIZATION_ERRORS),
|
||||||
configuration: IrInterpreterConfiguration = IrInterpreterConfiguration(printOnlyExceptionMessage = true),
|
configuration: IrInterpreterConfiguration = IrInterpreterConfiguration(printOnlyExceptionMessage = true),
|
||||||
private val onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
|
||||||
private val onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
|
||||||
) : FileLoweringPass {
|
) : FileLoweringPass {
|
||||||
private val interpreter = IrInterpreter(IrInterpreterEnvironment(context.irBuiltIns, configuration), emptyMap())
|
private val interpreter = IrInterpreter(IrInterpreterEnvironment(context.irBuiltIns, configuration), emptyMap())
|
||||||
private val evaluatedConstTracker = context.configuration[CommonConfigurationKeys.EVALUATED_CONST_TRACKER]
|
private val evaluatedConstTracker = context.configuration[CommonConfigurationKeys.EVALUATED_CONST_TRACKER]
|
||||||
@@ -37,7 +30,7 @@ class ConstEvaluationLowering(
|
|||||||
val useFir = context.configuration[CommonConfigurationKeys.USE_FIR] == true
|
val useFir = context.configuration[CommonConfigurationKeys.USE_FIR] == true
|
||||||
val preprocessedFile = if (useFir) irFile else irFile.preprocessForConstTransformer(interpreter, mode)
|
val preprocessedFile = if (useFir) irFile else irFile.preprocessForConstTransformer(interpreter, mode)
|
||||||
preprocessedFile.runConstOptimizations(
|
preprocessedFile.runConstOptimizations(
|
||||||
interpreter, mode, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressErrors
|
interpreter, mode, evaluatedConstTracker, inlineConstTracker, suppressErrors
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.name.NameUtils
|
import org.jetbrains.kotlin.name.NameUtils
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmBackendErrors
|
|
||||||
|
|
||||||
private var patchParentPhases = 0
|
private var patchParentPhases = 0
|
||||||
|
|
||||||
@@ -328,19 +327,7 @@ private val apiVersionIsAtLeastEvaluationPhase = makeIrModulePhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val constEvaluationPhase = makeIrModulePhase<JvmBackendContext>(
|
private val constEvaluationPhase = makeIrModulePhase<JvmBackendContext>(
|
||||||
{
|
::ConstEvaluationLowering,
|
||||||
ConstEvaluationLowering(
|
|
||||||
it,
|
|
||||||
onWarning = { irFile, element, warning ->
|
|
||||||
it.ktDiagnosticReporter.at(element, irFile)
|
|
||||||
.report(JvmBackendErrors.EXCEPTION_IN_CONST_EXPRESSION, warning.description)
|
|
||||||
},
|
|
||||||
onError = { irFile, element, error ->
|
|
||||||
it.ktDiagnosticReporter.at(element, irFile)
|
|
||||||
.report(JvmBackendErrors.EXCEPTION_IN_CONST_VAL_INITIALIZER, error.description)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
name = "ConstEvaluationLowering",
|
name = "ConstEvaluationLowering",
|
||||||
description = "Evaluate functions that are marked as `IntrinsicConstEvaluation`"
|
description = "Evaluate functions that are marked as `IntrinsicConstEvaluation`"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -167,6 +167,8 @@ internal fun IrBuiltIns.emptyArrayConstructor(arrayType: IrType): IrConstructorC
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun IrConst<*>.toConstantValue(): ConstantValue<*> {
|
internal fun IrConst<*>.toConstantValue(): ConstantValue<*> {
|
||||||
|
if (value == null) return NullValue
|
||||||
|
|
||||||
val constType = this.type.makeNotNull().removeAnnotations()
|
val constType = this.type.makeNotNull().removeAnnotations()
|
||||||
return when (this.type.getPrimitiveType()) {
|
return when (this.type.getPrimitiveType()) {
|
||||||
PrimitiveType.BOOLEAN -> BooleanValue(this.value as Boolean)
|
PrimitiveType.BOOLEAN -> BooleanValue(this.value as Boolean)
|
||||||
|
|||||||
+5
-4
@@ -14,7 +14,10 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||||
import org.jetbrains.kotlin.ir.interpreter.checker.*
|
import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterChecker
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterCheckerData
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.checker.IrInterpreterCommonChecker
|
||||||
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterConstGetterPreprocessor
|
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterConstGetterPreprocessor
|
||||||
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterKCallableNamePreprocessor
|
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterKCallableNamePreprocessor
|
||||||
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterPreprocessorData
|
import org.jetbrains.kotlin.ir.interpreter.preprocessor.IrInterpreterPreprocessorData
|
||||||
@@ -58,13 +61,11 @@ fun IrFile.runConstOptimizations(
|
|||||||
mode: EvaluationMode,
|
mode: EvaluationMode,
|
||||||
evaluatedConstTracker: EvaluatedConstTracker? = null,
|
evaluatedConstTracker: EvaluatedConstTracker? = null,
|
||||||
inlineConstTracker: InlineConstTracker? = null,
|
inlineConstTracker: InlineConstTracker? = null,
|
||||||
onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
|
||||||
onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> },
|
|
||||||
suppressExceptions: Boolean = false,
|
suppressExceptions: Boolean = false,
|
||||||
) {
|
) {
|
||||||
val checker = IrInterpreterCommonChecker()
|
val checker = IrInterpreterCommonChecker()
|
||||||
val irConstExpressionTransformer = IrConstAllTransformer(
|
val irConstExpressionTransformer = IrConstAllTransformer(
|
||||||
interpreter, this, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions
|
interpreter, this, mode, checker, evaluatedConstTracker, inlineConstTracker, { _, _, _ -> }, { _, _, _ -> }, suppressExceptions
|
||||||
)
|
)
|
||||||
this.transform(irConstExpressionTransformer, IrConstTransformer.Data())
|
this.transform(irConstExpressionTransformer, IrConstTransformer.Data())
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
/exceptionFromInterpreter.kt:(197,200): error: Cannot evaluate constant expression: / by zero
|
||||||
|
|
||||||
|
/exceptionFromInterpreter.kt:(239,254): error: Cannot evaluate constant expression: marginPrefix must be non-blank string.
|
||||||
|
|
||||||
|
/exceptionFromInterpreter.kt:(305,308): error: Cannot evaluate constant expression: / by zero
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// !RENDER_IR_DIAGNOSTICS_FULL_TEXT
|
||||||
|
// !LANGUAGE: +IntrinsicConstEvaluation
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// !DIAGNOSTICS: -DIVISION_BY_ZERO
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
const val divideByZero = 1 <!EVALUATION_ERROR!>/ 0<!>
|
||||||
|
const val trimMarginException = "123".<!EVALUATION_ERROR!>trimMargin(" ")<!>
|
||||||
|
|
||||||
|
annotation class A(val i: Int, val b: Int)
|
||||||
|
|
||||||
|
@A(1 <!EVALUATION_ERROR!>/ 0<!>, 2)
|
||||||
|
fun foo() {}
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !RENDER_ALL_DIAGNOSTICS_FULL_TEXT
|
|
||||||
// TARGET_BACKEND: JVM_IR
|
|
||||||
// !DIAGNOSTICS: -CONST_VAL_WITH_NON_CONST_INITIALIZER, -DIVISION_BY_ZERO
|
|
||||||
// WITH_STDLIB
|
|
||||||
|
|
||||||
const val divideByZero = <!EXCEPTION_IN_CONST_VAL_INITIALIZER!>1 / 0<!>
|
|
||||||
val disivionByZeroWarn = <!EXCEPTION_IN_CONST_EXPRESSION!>1 / 0<!>
|
|
||||||
const val trimMarginException = "123".<!EXCEPTION_IN_CONST_VAL_INITIALIZER!>trimMargin(" ")<!>
|
|
||||||
|
|
||||||
// TODO must report all these exceptions directly from fir2ir
|
|
||||||
//annotation class A(val i: Int, val b: Int)
|
|
||||||
//
|
|
||||||
//@A(1 / 0, 2)
|
|
||||||
//fun foo() {}
|
|
||||||
-5
@@ -1,5 +0,0 @@
|
|||||||
package
|
|
||||||
|
|
||||||
public val disivionByZeroWarn: kotlin.Int
|
|
||||||
public const val divideByZero: kotlin.Int
|
|
||||||
public const val trimMarginException: kotlin.String
|
|
||||||
-6
@@ -25,12 +25,6 @@ public class DiagnosticsTestWithJvmIrBackendGenerated extends AbstractDiagnostic
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend"), Pattern.compile("^(.+)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJvmBackend"), Pattern.compile("^(.+)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestMetadata("exceptionFromInterpreter.kt")
|
|
||||||
public void testExceptionFromInterpreter() throws Exception {
|
|
||||||
runTest("compiler/testData/diagnostics/testsWithJvmBackend/exceptionFromInterpreter.kt");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("indirectInlineCycle.kt")
|
@TestMetadata("indirectInlineCycle.kt")
|
||||||
public void testIndirectInlineCycle() throws Exception {
|
public void testIndirectInlineCycle() throws Exception {
|
||||||
|
|||||||
+8
-1
@@ -7,8 +7,10 @@ package org.jetbrains.kotlin.test.backend.ir
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.test.FirParser
|
import org.jetbrains.kotlin.test.FirParser
|
||||||
import org.jetbrains.kotlin.test.backend.handlers.AbstractIrHandler
|
import org.jetbrains.kotlin.test.backend.handlers.AbstractIrHandler
|
||||||
|
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives
|
||||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
||||||
import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue
|
import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.FullDiagnosticsRenderer
|
||||||
import org.jetbrains.kotlin.test.frontend.fir.handlers.diagnosticCodeMetaInfos
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.diagnosticCodeMetaInfos
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
import org.jetbrains.kotlin.test.services.*
|
import org.jetbrains.kotlin.test.services.*
|
||||||
@@ -20,6 +22,8 @@ class IrDiagnosticsHandler(testServices: TestServices) : AbstractIrHandler(testS
|
|||||||
private val diagnosticsService: DiagnosticsService
|
private val diagnosticsService: DiagnosticsService
|
||||||
get() = testServices.diagnosticsService
|
get() = testServices.diagnosticsService
|
||||||
|
|
||||||
|
private val fullDiagnosticsRenderer = FullDiagnosticsRenderer(DiagnosticsDirectives.RENDER_IR_DIAGNOSTICS_FULL_TEXT)
|
||||||
|
|
||||||
override fun processModule(module: TestModule, info: IrBackendInput) {
|
override fun processModule(module: TestModule, info: IrBackendInput) {
|
||||||
val diagnosticsByFilePath = info.diagnosticReporter.diagnosticsByFilePath
|
val diagnosticsByFilePath = info.diagnosticReporter.diagnosticsByFilePath
|
||||||
for (currentModule in testServices.moduleStructure.modules) {
|
for (currentModule in testServices.moduleStructure.modules) {
|
||||||
@@ -34,10 +38,13 @@ class IrDiagnosticsHandler(testServices: TestServices) : AbstractIrHandler(testS
|
|||||||
lightTreeEnabled, lightTreeComparingModeEnabled
|
lightTreeEnabled, lightTreeComparingModeEnabled
|
||||||
)
|
)
|
||||||
globalMetadataInfoHandler.addMetadataInfosForFile(file, diagnosticsMetadataInfos)
|
globalMetadataInfoHandler.addMetadataInfosForFile(file, diagnosticsMetadataInfos)
|
||||||
|
fullDiagnosticsRenderer.storeFullDiagnosticRender(module, diagnostics, file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
|
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
|
||||||
|
fullDiagnosticsRenderer.assertCollectedDiagnostics(testServices, ".fir.ir.diag.txt")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+4
@@ -92,4 +92,8 @@ object DiagnosticsDirectives : SimpleDirectivesContainer() {
|
|||||||
val RENDER_ALL_DIAGNOSTICS_FULL_TEXT by directive(
|
val RENDER_ALL_DIAGNOSTICS_FULL_TEXT by directive(
|
||||||
description = "Render both frontend and backend diagnostic texts to .diag.txt"
|
description = "Render both frontend and backend diagnostic texts to .diag.txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val RENDER_IR_DIAGNOSTICS_FULL_TEXT by directive(
|
||||||
|
description = "Render IR diagnostic texts to .ir.diag.txt"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-20
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives
|
|||||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
||||||
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives
|
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives
|
||||||
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
|
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
|
||||||
|
import org.jetbrains.kotlin.test.directives.model.SimpleDirective
|
||||||
import org.jetbrains.kotlin.test.directives.model.singleValue
|
import org.jetbrains.kotlin.test.directives.model.singleValue
|
||||||
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
||||||
import org.jetbrains.kotlin.test.model.TestFile
|
import org.jetbrains.kotlin.test.model.TestFile
|
||||||
@@ -55,6 +56,31 @@ import org.jetbrains.kotlin.test.utils.MultiModuleInfoDumper
|
|||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
||||||
|
|
||||||
|
class FullDiagnosticsRenderer(private val directive: SimpleDirective) {
|
||||||
|
private val dumper: MultiModuleInfoDumper = MultiModuleInfoDumper(moduleHeaderTemplate = "// -- Module: <%s> --")
|
||||||
|
|
||||||
|
fun assertCollectedDiagnostics(testServices: TestServices, expectedExtension: String) {
|
||||||
|
if (dumper.isEmpty()) return
|
||||||
|
val resultDump = dumper.generateResultingDump()
|
||||||
|
val testDataFile = testServices.moduleStructure.originalTestDataFiles.first()
|
||||||
|
val expectedFile = testDataFile.parentFile.resolve("${testDataFile.nameWithoutExtension.removeSuffix(".fir")}$expectedExtension")
|
||||||
|
testServices.assertions.assertEqualsToFile(expectedFile, resultDump)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun storeFullDiagnosticRender(module: TestModule, diagnostics: List<KtDiagnostic>, file: TestFile) {
|
||||||
|
if (directive !in module.directives) return
|
||||||
|
if (diagnostics.isEmpty()) return
|
||||||
|
|
||||||
|
val reportedDiagnostics = diagnostics.sortedBy { it.textRanges.first().startOffset }.map {
|
||||||
|
val severity = AnalyzerWithCompilerReport.convertSeverity(it.severity).toString().toLowerCaseAsciiOnly()
|
||||||
|
val message = RootDiagnosticRendererFactory(it).render(it)
|
||||||
|
"/${file.name}:${it.textRanges.first()}: $severity: $message"
|
||||||
|
}
|
||||||
|
|
||||||
|
dumper.builderForModule(module).appendLine(reportedDiagnostics.joinToString(separator = "\n\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class)
|
||||||
class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(testServices) {
|
class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(testServices) {
|
||||||
private val globalMetadataInfoHandler: GlobalMetadataInfoHandler
|
private val globalMetadataInfoHandler: GlobalMetadataInfoHandler
|
||||||
@@ -69,14 +95,10 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
|||||||
override val additionalServices: List<ServiceRegistrationData> =
|
override val additionalServices: List<ServiceRegistrationData> =
|
||||||
listOf(service(::DiagnosticsService))
|
listOf(service(::DiagnosticsService))
|
||||||
|
|
||||||
private val dumper: MultiModuleInfoDumper = MultiModuleInfoDumper(moduleHeaderTemplate = "// -- Module: <%s> --")
|
private val fullDiagnosticsRenderer = FullDiagnosticsRenderer(DiagnosticsDirectives.RENDER_DIAGNOSTICS_FULL_TEXT)
|
||||||
|
|
||||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
|
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
|
||||||
if (dumper.isEmpty()) return
|
fullDiagnosticsRenderer.assertCollectedDiagnostics(testServices, ".fir.diag.txt")
|
||||||
val resultDump = dumper.generateResultingDump()
|
|
||||||
val testDataFile = testServices.moduleStructure.originalTestDataFiles.first()
|
|
||||||
val expectedFile = testDataFile.parentFile.resolve("${testDataFile.nameWithoutFirExtension}.fir.diag.txt")
|
|
||||||
assertions.assertEqualsToFile(expectedFile, resultDump)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processModule(module: TestModule, info: FirOutputArtifact) {
|
override fun processModule(module: TestModule, info: FirOutputArtifact) {
|
||||||
@@ -109,7 +131,7 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
|||||||
globalMetadataInfoHandler.addMetadataInfosForFile(file, diagnosticsMetadataInfos)
|
globalMetadataInfoHandler.addMetadataInfosForFile(file, diagnosticsMetadataInfos)
|
||||||
collectSyntaxDiagnostics(currentModule, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled, forceRenderArguments)
|
collectSyntaxDiagnostics(currentModule, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled, forceRenderArguments)
|
||||||
collectDebugInfoDiagnostics(currentModule, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled)
|
collectDebugInfoDiagnostics(currentModule, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled)
|
||||||
checkFullDiagnosticRender(module, diagnostics, file)
|
fullDiagnosticsRenderer.storeFullDiagnosticRender(module, diagnostics, file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,19 +362,6 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
|||||||
is FirCallableSymbol<*> -> callableId.asFqNameForDebugInfo().toUnsafe()
|
is FirCallableSymbol<*> -> callableId.asFqNameForDebugInfo().toUnsafe()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkFullDiagnosticRender(module: TestModule, diagnostics: List<KtDiagnostic>, file: TestFile) {
|
|
||||||
if (DiagnosticsDirectives.RENDER_DIAGNOSTICS_FULL_TEXT !in module.directives) return
|
|
||||||
if (diagnostics.isEmpty()) return
|
|
||||||
|
|
||||||
val reportedDiagnostics = diagnostics.sortedBy { it.textRanges.first().startOffset }.map {
|
|
||||||
val severity = AnalyzerWithCompilerReport.convertSeverity(it.severity).toString().toLowerCaseAsciiOnly()
|
|
||||||
val message = RootDiagnosticRendererFactory(it).render(it)
|
|
||||||
"/${file.name}:${it.textRanges.first()}: $severity: $message"
|
|
||||||
}
|
|
||||||
|
|
||||||
dumper.builderForModule(module).appendLine(reportedDiagnostics.joinToString(separator = "\n\n"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<KtDiagnostic>.diagnosticCodeMetaInfos(
|
fun List<KtDiagnostic>.diagnosticCodeMetaInfos(
|
||||||
|
|||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.test.runners.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.test.FirParser
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
|
import org.jetbrains.kotlin.test.backend.ir.IrDiagnosticsHandler
|
||||||
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
|
import org.jetbrains.kotlin.test.builders.irHandlersStep
|
||||||
|
import org.jetbrains.kotlin.test.directives.configureFirParser
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.Fir2IrResultsConverter
|
||||||
|
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
|
||||||
|
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
|
||||||
|
|
||||||
|
abstract class AbstractFirWithInterpreterDiagnosticsTest(val parser: FirParser) : AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JVM_IR) {
|
||||||
|
override fun TestConfigurationBuilder.configuration() {
|
||||||
|
configureFirParser(parser)
|
||||||
|
baseFirDiagnosticTestConfiguration()
|
||||||
|
|
||||||
|
facadeStep(::Fir2IrResultsConverter)
|
||||||
|
irHandlersStep {
|
||||||
|
useHandlers(
|
||||||
|
::IrDiagnosticsHandler
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class AbstractFirPsiWithInterpreterDiagnosticsTest : AbstractFirWithInterpreterDiagnosticsTest(FirParser.Psi)
|
||||||
|
|
||||||
|
open class AbstractFirLightTreeWithInterpreterDiagnosticsTest : AbstractFirWithInterpreterDiagnosticsTest(FirParser.LightTree)
|
||||||
+9
-3
@@ -10,9 +10,7 @@ import org.jetbrains.kotlin.generators.util.TestGeneratorUtil
|
|||||||
import org.jetbrains.kotlin.test.TargetBackend
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
import org.jetbrains.kotlin.test.runners.*
|
import org.jetbrains.kotlin.test.runners.*
|
||||||
import org.jetbrains.kotlin.test.runners.codegen.*
|
import org.jetbrains.kotlin.test.runners.codegen.*
|
||||||
import org.jetbrains.kotlin.test.runners.ir.AbstractClassicJvmIrTextTest
|
import org.jetbrains.kotlin.test.runners.ir.*
|
||||||
import org.jetbrains.kotlin.test.runners.ir.AbstractFirLightTreeJvmIrTextTest
|
|
||||||
import org.jetbrains.kotlin.test.runners.ir.AbstractFirPsiJvmIrTextTest
|
|
||||||
import org.jetbrains.kotlin.test.runners.ir.interpreter.AbstractJvmIrInterpreterAfterFirPsi2IrTest
|
import org.jetbrains.kotlin.test.runners.ir.interpreter.AbstractJvmIrInterpreterAfterFirPsi2IrTest
|
||||||
import org.jetbrains.kotlin.test.runners.ir.interpreter.AbstractJvmIrInterpreterAfterPsi2IrTest
|
import org.jetbrains.kotlin.test.runners.ir.interpreter.AbstractJvmIrInterpreterAfterPsi2IrTest
|
||||||
import org.jetbrains.kotlin.test.utils.CUSTOM_TEST_DATA_EXTENSION_PATTERN
|
import org.jetbrains.kotlin.test.utils.CUSTOM_TEST_DATA_EXTENSION_PATTERN
|
||||||
@@ -321,6 +319,14 @@ fun generateJUnit5CompilerTests(args: Array<String>) {
|
|||||||
model("debug/localVariables")
|
model("debug/localVariables")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass<AbstractFirPsiWithInterpreterDiagnosticsTest> {
|
||||||
|
model("diagnostics/irInterpreter")
|
||||||
|
}
|
||||||
|
|
||||||
|
testClass<AbstractFirLightTreeWithInterpreterDiagnosticsTest> {
|
||||||
|
model("diagnostics/irInterpreter")
|
||||||
|
}
|
||||||
|
|
||||||
testClass<AbstractFirPsiDiagnosticsTestWithJvmIrBackend> {
|
testClass<AbstractFirPsiDiagnosticsTestWithJvmIrBackend> {
|
||||||
model("diagnostics/testsWithJvmBackend", excludedPattern = excludedCustomTestdataPattern)
|
model("diagnostics/testsWithJvmBackend", excludedPattern = excludedCustomTestdataPattern)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user