mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-19 15:51:29 +00:00
Compare commits
1 Commits
spec-tests
...
rr/selezne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3614bdce27 |
@@ -74,7 +74,6 @@ benchmark {
|
||||
param("size", 1000)
|
||||
|
||||
include("CommonCallsBenchmark")
|
||||
include("ControlFlowAnalysisBenchmark")
|
||||
//include("InferenceBaselineCallsBenchmark")
|
||||
}
|
||||
|
||||
@@ -112,9 +111,8 @@ tasks.named("classes") {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<JavaExec>("runBenchmark") {
|
||||
// jmhArgs example: -PjmhArgs='CommonCalls -p size=500 -p isIR=true -p useNI=true -f 1'
|
||||
val jmhArgs = if (project.hasProperty("jmhArgs")) project.property("jmhArgs").toString() else ""
|
||||
/*tasks.register<JavaExec>("runBenchmark") {
|
||||
val jmhArgs: String by project // example: -PjmhArgs='CommonCalls -p size=500 -p isIR=true -p useNI=true -f 1'
|
||||
val resultFilePath = "$buildDir/benchmarks/jmh-result.json"
|
||||
val ideaHome = intellijRootDir().canonicalPath
|
||||
|
||||
@@ -122,6 +120,7 @@ tasks.register<JavaExec>("runBenchmark") {
|
||||
args = mutableListOf("-Didea.home.path=$ideaHome", benchmarkJarPath, "-rf", "json", "-rff", resultFilePath) + jmhArgs.split("\\s".toRegex())
|
||||
main = "-jar"
|
||||
|
||||
|
||||
doLast {
|
||||
if (project.kotlinBuildProperties.isTeamcityBuild) {
|
||||
val jsonArray = com.google.gson.JsonParser.parseString(File(resultFilePath).readText()).asJsonArray
|
||||
@@ -145,4 +144,4 @@ tasks.register<JavaExec>("runBenchmark") {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.benchmarks
|
||||
|
||||
import org.openjdk.jmh.annotations.*
|
||||
import org.openjdk.jmh.infra.Blackhole
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@State(Scope.Benchmark)
|
||||
open class ControlFlowAnalysisBenchmark : AbstractSimpleFileBenchmark() {
|
||||
@Param("1000")
|
||||
private var size: Int = 0
|
||||
|
||||
@Benchmark
|
||||
fun benchmark(bh: Blackhole) {
|
||||
analyzeGreenFile(bh)
|
||||
}
|
||||
|
||||
override fun buildText() =
|
||||
buildString {
|
||||
appendLine("fun test() {")
|
||||
for (i in 0 until size) {
|
||||
appendLine("for (i$i in 0..10) { ")
|
||||
}
|
||||
for (i in 0 until size) {
|
||||
appendLine("}")
|
||||
}
|
||||
appendLine("}")
|
||||
}
|
||||
}
|
||||
131
build.gradle.kts
131
build.gradle.kts
@@ -229,8 +229,6 @@ extra["compilerModules"] = arrayOf(
|
||||
":compiler:frontend.java",
|
||||
":compiler:cli-common",
|
||||
":compiler:ir.tree",
|
||||
":compiler:ir.tree.impl",
|
||||
":compiler:ir.tree.persistent",
|
||||
":compiler:ir.psi2ir",
|
||||
":compiler:ir.backend.common",
|
||||
":compiler:backend.jvm",
|
||||
@@ -723,6 +721,11 @@ tasks {
|
||||
dependsOn(":jps-plugin:test")
|
||||
}
|
||||
|
||||
register("idea-plugin-main-tests") {
|
||||
dependsOn("dist")
|
||||
dependsOn(":idea:test")
|
||||
}
|
||||
|
||||
register("idea-plugin-additional-tests") {
|
||||
dependsOn("dist")
|
||||
dependsOn(
|
||||
@@ -748,6 +751,17 @@ tasks {
|
||||
}
|
||||
}
|
||||
|
||||
register("idea-plugin-tests") {
|
||||
dependsOn("dist")
|
||||
dependsOn(
|
||||
"idea-plugin-main-tests",
|
||||
"idea-plugin-additional-tests"
|
||||
)
|
||||
if (Ide.IJ()) {
|
||||
dependsOn("idea-new-project-wizard-tests")
|
||||
}
|
||||
}
|
||||
|
||||
register("idea-plugin-performance-tests") {
|
||||
dependsOn("dist")
|
||||
dependsOn(
|
||||
@@ -764,21 +778,10 @@ tasks {
|
||||
)
|
||||
}
|
||||
|
||||
register("ideaPluginTest") {
|
||||
dependsOn(
|
||||
"mainIdeTests",
|
||||
"gradleIdeTest",
|
||||
"kaptIdeTest",
|
||||
"miscIdeTests"
|
||||
)
|
||||
}
|
||||
|
||||
register("mainIdeTests") {
|
||||
dependsOn(":idea:test")
|
||||
}
|
||||
|
||||
register("miscIdeTests") {
|
||||
register("plugins-tests") {
|
||||
dependsOn("dist")
|
||||
dependsOn(
|
||||
":kotlin-annotation-processing:test",
|
||||
":kotlin-allopen-compiler-plugin:test",
|
||||
":kotlin-noarg-compiler-plugin:test",
|
||||
":kotlin-sam-with-receiver-compiler-plugin:test",
|
||||
@@ -786,18 +789,30 @@ tasks {
|
||||
":kotlin-annotation-processing-gradle:test",
|
||||
":kotlinx-serialization-compiler-plugin:test",
|
||||
":kotlinx-serialization-ide-plugin:test",
|
||||
":idea:jvm-debugger:jvm-debugger-test:test",
|
||||
"idea-plugin-additional-tests",
|
||||
"jps-tests",
|
||||
":generators:test"
|
||||
":idea:jvm-debugger:jvm-debugger-test:test"
|
||||
)
|
||||
if (Ide.IJ()) {
|
||||
dependsOn("idea-new-project-wizard-tests")
|
||||
}
|
||||
}
|
||||
|
||||
register("kaptIdeTest") {
|
||||
dependsOn(":kotlin-annotation-processing:test")
|
||||
|
||||
register("ideaPluginTest") {
|
||||
dependsOn(
|
||||
"gradleIdeTest",
|
||||
"androidIdeTest",
|
||||
"miscIdeTests"
|
||||
)
|
||||
}
|
||||
|
||||
register("miscIdeTests") {
|
||||
dependsOn(
|
||||
"idea-plugin-tests",
|
||||
"jps-tests",
|
||||
"plugins-tests",
|
||||
":generators:test"
|
||||
)
|
||||
}
|
||||
|
||||
register("androidIdeTest") {
|
||||
dependsOn("android-ide-tests")
|
||||
}
|
||||
|
||||
register("gradleIdeTest") {
|
||||
@@ -807,39 +822,6 @@ tasks {
|
||||
)
|
||||
}
|
||||
|
||||
register("kmmTest", AggregateTest::class) {
|
||||
dependsOn(
|
||||
":idea:idea-gradle:test",
|
||||
":idea:test",
|
||||
":compiler:test",
|
||||
":js:js.tests:test"
|
||||
)
|
||||
if (Ide.IJ193.orHigher())
|
||||
dependsOn(":kotlin-gradle-plugin-integration-tests:test")
|
||||
if (Ide.AS40.orHigher())
|
||||
dependsOn(":kotlin-ultimate:ide:android-studio-native:test")
|
||||
|
||||
testPatternFile = file("tests/mpp/kmm-patterns.csv")
|
||||
}
|
||||
|
||||
register("test") {
|
||||
doLast {
|
||||
throw GradleException("Don't use directly, use aggregate tasks *-check instead")
|
||||
}
|
||||
}
|
||||
|
||||
named("check") {
|
||||
dependsOn("test")
|
||||
}
|
||||
|
||||
named("checkBuild") {
|
||||
if (kotlinBuildProperties.isTeamcityBuild) {
|
||||
doFirst {
|
||||
println("##teamcity[setParameter name='bootstrap.kotlin.version' value='$bootstrapKotlinVersion']")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register("publishIdeArtifacts") {
|
||||
idePluginDependency {
|
||||
dependsOn(
|
||||
@@ -873,6 +855,39 @@ tasks {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
register("kmmTest", AggregateTest::class) {
|
||||
dependsOn(
|
||||
":idea:idea-gradle:test",
|
||||
":idea:test",
|
||||
":compiler:test",
|
||||
":js:js.tests:test"
|
||||
)
|
||||
if (Ide.IJ193.orHigher())
|
||||
dependsOn(":kotlin-gradle-plugin-integration-tests:test")
|
||||
if (Ide.AS40.orHigher())
|
||||
dependsOn(":kotlin-ultimate:ide:android-studio-native:test")
|
||||
|
||||
testPatternFile = file("tests/mpp/kmm-patterns.csv")
|
||||
}
|
||||
|
||||
register("test") {
|
||||
doLast {
|
||||
throw GradleException("Don't use directly, use aggregate tasks *-check instead")
|
||||
}
|
||||
}
|
||||
|
||||
named("check") {
|
||||
dependsOn("test")
|
||||
}
|
||||
|
||||
named("checkBuild") {
|
||||
if (kotlinBuildProperties.isTeamcityBuild) {
|
||||
doFirst {
|
||||
println("##teamcity[setParameter name='bootstrap.kotlin.version' value='$bootstrapKotlinVersion']")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun CopySpec.setExecutablePermissions() {
|
||||
|
||||
@@ -50,9 +50,6 @@ import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getA
|
||||
|
||||
public abstract class AnnotationCodegen {
|
||||
|
||||
private static final String ORG_JETBRAINS_ANNOTATIONS_NOTNULL = Type.getType(NotNull.class).getDescriptor();
|
||||
private static final String ORG_JETBRAINS_ANNOTATIONS_NULLABLE = Type.getType(Nullable.class).getDescriptor();
|
||||
|
||||
public static final class JvmFlagAnnotation {
|
||||
private final FqName fqName;
|
||||
private final int jvmFlag;
|
||||
@@ -123,7 +120,7 @@ public abstract class AnnotationCodegen {
|
||||
@Nullable Type returnType,
|
||||
@Nullable KotlinType typeForTypeAnnotations,
|
||||
@Nullable DeclarationDescriptorWithVisibility parameterContainer,
|
||||
@NotNull List<String> additionalVisibleAnnotations
|
||||
@NotNull List<Class<?>> additionalAnnotations
|
||||
) {
|
||||
if (annotated == null) return;
|
||||
|
||||
@@ -158,9 +155,9 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
for (String annotation : additionalVisibleAnnotations) {
|
||||
generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotation, true);
|
||||
annotationDescriptorsAlreadyPresent.add(annotation);
|
||||
for (Class<?> annotation : additionalAnnotations) {
|
||||
String descriptor = generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotation);
|
||||
annotationDescriptorsAlreadyPresent.add(descriptor);
|
||||
}
|
||||
|
||||
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent, parameterContainer);
|
||||
@@ -251,15 +248,17 @@ public abstract class AnnotationCodegen {
|
||||
if (!TypeUtils.isNullableType(flexibleType.getLowerBound()) && TypeUtils.isNullableType(flexibleType.getUpperBound())) {
|
||||
AnnotationDescriptor notNull = type.getAnnotations().findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION);
|
||||
if (notNull != null) {
|
||||
generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, ORG_JETBRAINS_ANNOTATIONS_NOTNULL, false);
|
||||
generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, NotNull.class);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String annotationDescriptor =
|
||||
TypeUtils.isNullableType(type) ? ORG_JETBRAINS_ANNOTATIONS_NULLABLE : ORG_JETBRAINS_ANNOTATIONS_NOTNULL;
|
||||
generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationDescriptor, false);
|
||||
boolean isNullableType = TypeUtils.isNullableType(type);
|
||||
|
||||
Class<?> annotationClass = isNullableType ? Nullable.class : NotNull.class;
|
||||
|
||||
generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationClass);
|
||||
}
|
||||
|
||||
private static final Map<JvmTarget, Map<KotlinTarget, ElementType>> annotationTargetMaps = new EnumMap<>(JvmTarget.class);
|
||||
@@ -339,14 +338,13 @@ public abstract class AnnotationCodegen {
|
||||
visitor.visitEnd();
|
||||
}
|
||||
|
||||
private void generateAnnotationIfNotPresent(
|
||||
Set<String> annotationDescriptorsAlreadyPresent,
|
||||
String annotationDescriptor,
|
||||
boolean visible
|
||||
) {
|
||||
if (!annotationDescriptorsAlreadyPresent.contains(annotationDescriptor)) {
|
||||
visitAnnotation(annotationDescriptor, visible).visitEnd();
|
||||
@NotNull
|
||||
private String generateAnnotationIfNotPresent(Set<String> annotationDescriptorsAlreadyPresent, Class<?> annotationClass) {
|
||||
String descriptor = Type.getType(annotationClass).getDescriptor();
|
||||
if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) {
|
||||
visitAnnotation(descriptor, false).visitEnd();
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
private static boolean isBareTypeParameterWithNullableUpperBound(@NotNull KotlinType type) {
|
||||
|
||||
@@ -83,8 +83,6 @@ import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class FunctionCodegen {
|
||||
private static final String JAVA_LANG_DEPRECATED = Type.getType(Deprecated.class).getDescriptor();
|
||||
|
||||
public final GenerationState state;
|
||||
private final KotlinTypeMapper typeMapper;
|
||||
private final BindingContext bindingContext;
|
||||
@@ -223,7 +221,7 @@ public class FunctionCodegen {
|
||||
InlineClassDescriptorResolver.isSpecializedEqualsMethod(functionDescriptor);
|
||||
generateMethodAnnotationsIfRequired(
|
||||
functionDescriptor, asmMethod, jvmSignature, mv,
|
||||
isCompatibilityStubInDefaultImpls ? Collections.singletonList(JAVA_LANG_DEPRECATED) : Collections.emptyList(),
|
||||
isCompatibilityStubInDefaultImpls ? Collections.singletonList(Deprecated.class) : Collections.emptyList(),
|
||||
skipNullabilityAnnotations
|
||||
);
|
||||
GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, jvmSignature, state, (flags & ACC_SYNTHETIC) != 0);
|
||||
@@ -287,7 +285,7 @@ public class FunctionCodegen {
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull JvmMethodGenericSignature jvmSignature,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull List<String> additionalVisibleAnnotations,
|
||||
@NotNull List<Class<?>> additionalNoArgAnnotations,
|
||||
boolean skipNullabilityAnnotations
|
||||
) {
|
||||
FunctionDescriptor annotationsOwner;
|
||||
@@ -304,7 +302,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
AnnotationCodegen.forMethod(mv, memberCodegen, state, skipNullabilityAnnotations)
|
||||
.genAnnotations(annotationsOwner, asmMethod.getReturnType(), functionDescriptor.getReturnType(), null, additionalVisibleAnnotations);
|
||||
.genAnnotations(annotationsOwner, asmMethod.getReturnType(), functionDescriptor.getReturnType(), null, additionalNoArgAnnotations);
|
||||
|
||||
generateParameterAnnotations(
|
||||
annotationsOwner, mv, jvmSignature,
|
||||
|
||||
@@ -24,8 +24,6 @@ import org.jetbrains.kotlin.resolve.calls.checkers.isRestrictsSuspensionReceiver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
|
||||
|
||||
|
||||
class JvmRuntimeTypes(
|
||||
module: ModuleDescriptor,
|
||||
@@ -98,14 +96,6 @@ class JvmRuntimeTypes(
|
||||
else
|
||||
descriptor
|
||||
|
||||
if (actualFunctionDescriptor.returnType == null)
|
||||
throw KotlinExceptionWithAttachments(
|
||||
"Return type for function description is null. Super type cannot be calculated." +
|
||||
"initDesc=${descriptor}, actDesc=${actualFunctionDescriptor}, isReleaseCoroutines=${
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||
}"
|
||||
)
|
||||
|
||||
val functionType = createFunctionType(
|
||||
descriptor.builtIns,
|
||||
Annotations.EMPTY,
|
||||
|
||||
@@ -726,7 +726,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
public SourceMapper getOrCreateSourceMapper() {
|
||||
if (sourceMapper == null) {
|
||||
// note: this is used in InlineCodegen and the element is always physical (KtElement) there
|
||||
sourceMapper = new SourceMapper(SourceInfo.Companion.createFromPsi((KtElement)element, getClassName()));
|
||||
sourceMapper = new SourceMapper(SourceInfo.Companion.createInfo((KtElement)element, getClassName()));
|
||||
}
|
||||
return sourceMapper;
|
||||
}
|
||||
|
||||
@@ -21,26 +21,28 @@ import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
|
||||
data class SourceInfo(
|
||||
val sourceFileName: String?,
|
||||
val pathOrCleanFQN: String,
|
||||
val linesInFile: Int
|
||||
) {
|
||||
data class SourceInfo(val source: String, val pathOrCleanFQN: String, val linesInFile: Int) {
|
||||
|
||||
companion object {
|
||||
fun createFromPsi(element: KtElement?, internalClassName: String): SourceInfo {
|
||||
fun createInfo(element: KtElement?, internalClassName: String): SourceInfo {
|
||||
assert(element != null) { "Couldn't create source mapper for null element $internalClassName" }
|
||||
val lineNumbers = CodegenUtil.getLineNumberForElement(element!!.containingFile, true)
|
||||
?: error("Couldn't extract line count in ${element.containingFile}")
|
||||
?: error("Couldn't extract line count in ${element.containingFile}")
|
||||
|
||||
//TODO hack condition for package parts cleaning
|
||||
val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
||||
val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
||||
|
||||
val fileName = element.containingKtFile.name
|
||||
return SourceInfo(fileName, cleanedClassFqName, lineNumbers)
|
||||
return SourceInfo(element.containingKtFile.name, cleanedClassFqName, lineNumbers)
|
||||
}
|
||||
|
||||
fun createInfoForIr(lineNumbers: Int, internalClassName: String, containingFileName: String): SourceInfo {
|
||||
//TODO cut topLevel names
|
||||
// val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
||||
// val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
||||
|
||||
return SourceInfo(containingFileName, internalClassName, lineNumbers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.Position
|
||||
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -27,8 +28,10 @@ import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
@@ -230,7 +233,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
)
|
||||
|
||||
val sourceInfo = sourceMapper.sourceInfo!!
|
||||
val callSite = SourcePosition(codegen.lastLineNumber, sourceInfo.sourceFileName!!, sourceInfo.pathOrCleanFQN)
|
||||
val callSite = SourcePosition(codegen.lastLineNumber, sourceInfo.source, sourceInfo.pathOrCleanFQN)
|
||||
val inliner = MethodInliner(
|
||||
node, parameters, info, FieldRemapper(null, null, parameters), isSameModule,
|
||||
"Method inlining " + sourceCompiler.callElementText,
|
||||
|
||||
@@ -85,14 +85,9 @@ class SourceMapper(val sourceInfo: SourceInfo?) {
|
||||
get() = fileMappings.values.toList()
|
||||
|
||||
init {
|
||||
sourceInfo?.let { sourceInfo ->
|
||||
// If 'sourceFileName' is null, this class doesn't have debug information
|
||||
// (e.g., multi-file class facade with multiple parts).
|
||||
sourceInfo.sourceFileName?.let { sourceFileName ->
|
||||
// Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce fewer ranges.
|
||||
getOrRegisterNewSource(sourceFileName, sourceInfo.pathOrCleanFQN)
|
||||
.mapNewInterval(1, 1, sourceInfo.linesInFile)
|
||||
}
|
||||
sourceInfo?.let {
|
||||
// Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce fewer ranges.
|
||||
getOrRegisterNewSource(it.source, it.pathOrCleanFQN).mapNewInterval(1, 1, it.linesInFile)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,9 +31,6 @@ dependencies {
|
||||
compile(project(":kotlin-util-io"))
|
||||
compile(project(":compiler:ir.serialization.common"))
|
||||
|
||||
// TODO: as soon as cli-jvm is extracted out of this module, move this dependency there
|
||||
compileOnly(project(":compiler:ir.tree.impl"))
|
||||
|
||||
compileOnly(toolsJarApi())
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
compileOnly(intellijDep()) { includeIntellijCoreJarDependencies(project) }
|
||||
|
||||
@@ -6,7 +6,6 @@ plugins {
|
||||
dependencies {
|
||||
compile(project(":compiler:cli"))
|
||||
compile(project(":compiler:ir.serialization.js"))
|
||||
compileOnly(project(":compiler:ir.tree.persistent"))
|
||||
runtimeOnly(project(":kotlin-reflect"))
|
||||
if (Platform[193].orLower()) {
|
||||
compile(intellijDep()) { includeJars("picocontainer", rootProject = rootProject) }
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.cli.common.messages.*
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -88,7 +87,6 @@ fun buildKLib(
|
||||
configuration = configuration,
|
||||
allDependencies = allDependencies,
|
||||
friendDependencies = emptyList(),
|
||||
irFactory = PersistentIrFactory,
|
||||
outputKlibPath = outputPath,
|
||||
nopack = true
|
||||
)
|
||||
|
||||
@@ -24,17 +24,13 @@ import org.jetbrains.kotlin.cli.common.messages.MessageUtil
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
|
||||
import org.jetbrains.kotlin.incremental.js.IncrementalNextRoundChecker
|
||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
|
||||
import org.jetbrains.kotlin.ir.backend.js.*
|
||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
||||
import org.jetbrains.kotlin.js.config.EcmaVersion
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.JsConfig
|
||||
@@ -197,7 +193,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
configuration = config.configuration,
|
||||
allDependencies = resolvedLibraries,
|
||||
friendDependencies = friendDependencies,
|
||||
irFactory = PersistentIrFactory,
|
||||
outputKlibPath = outputKlibPath,
|
||||
nopack = arguments.irProduceKlibDir
|
||||
)
|
||||
|
||||
@@ -71,7 +71,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries
|
||||
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmManglerDesc
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
|
||||
import org.jetbrains.kotlin.modules.Module
|
||||
@@ -379,8 +378,9 @@ object KotlinToJVMBytecodeCompiler {
|
||||
val (moduleFragment, symbolTable, sourceManager, components) =
|
||||
Fir2IrConverter.createModuleFragment(
|
||||
session, resolveTransformer.scopeSession, firFiles,
|
||||
moduleConfiguration.languageVersionSettings, signaturer,
|
||||
JvmGeneratorExtensions(), FirJvmKotlinMangler(session), IrFactoryImpl
|
||||
moduleConfiguration.languageVersionSettings, signaturer = signaturer,
|
||||
generatorExtensions = JvmGeneratorExtensions(),
|
||||
mangler = FirJvmKotlinMangler(session)
|
||||
)
|
||||
|
||||
performanceManager?.notifyIRTranslationFinished(ktFiles.size, codeLines, debugTargetDescription)
|
||||
|
||||
@@ -52,7 +52,7 @@ fun foo() {
|
||||
val piFloat: <!REDUNDANT_EXPLICIT_TYPE!>Float<!> = 3.14f
|
||||
val piDouble: <!REDUNDANT_EXPLICIT_TYPE!>Double<!> = 3.14
|
||||
val charZ: <!REDUNDANT_EXPLICIT_TYPE!>Char<!> = 'z'
|
||||
<!CAN_BE_VAL!>var<!> alpha: <!REDUNDANT_EXPLICIT_TYPE!>Int<!> = 0
|
||||
var alpha: <!REDUNDANT_EXPLICIT_TYPE!>Int<!> = 0
|
||||
}
|
||||
|
||||
fun test(boolean: Boolean) {
|
||||
|
||||
@@ -4,7 +4,7 @@ fun f() {
|
||||
<!REDUNDANT_VISIBILITY_MODIFIER!>internal<!> var foo = 0
|
||||
}
|
||||
LocalClass().foo = 1
|
||||
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> <!CAN_BE_VAL!>var<!> baz = 0
|
||||
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> var baz = 0
|
||||
}
|
||||
|
||||
internal inline fun internal() {
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
fun testDelegator() {
|
||||
var x: Boolean by LocalFreezableVar(true)
|
||||
var y by LocalFreezableVar("")
|
||||
}
|
||||
|
||||
class LocalFreezableVar<T>(private var value: T) {
|
||||
operator fun getValue(thisRef: Nothing?, property: KProperty<*>): T = value
|
||||
|
||||
operator fun setValue(thisRef: Nothing?, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class C
|
||||
operator fun C.plus(a: Any): C = this
|
||||
operator fun C.plusAssign(a: Any) {}
|
||||
|
||||
fun testOperatorAssignment() {
|
||||
val c = C()
|
||||
c += ""
|
||||
<!CAN_BE_VAL!>var<!> c1 = C()
|
||||
<!ASSIGN_OPERATOR_AMBIGUITY!>c1 += ""<!>
|
||||
|
||||
var a = 1
|
||||
a += 12
|
||||
a -= 10
|
||||
}
|
||||
|
||||
|
||||
fun destructuringDeclaration() {
|
||||
<!CAN_BE_VAL!>var<!> (v1, v2) = getPair()
|
||||
print(v1)
|
||||
|
||||
var (v3, v4) = getPair()
|
||||
print(v3)
|
||||
v4 = ""
|
||||
|
||||
var (v5, v6) = getPair()
|
||||
v5 = 1
|
||||
|
||||
var (v7, v8) = getPair()
|
||||
v7 = 2
|
||||
v8 = "42"
|
||||
|
||||
val (a, b, c) = Triple(1, 1, 1)
|
||||
|
||||
<!CAN_BE_VAL!>var<!> (x, y, z) = Triple(1, 1, 1)
|
||||
}
|
||||
|
||||
fun stackOverflowBug() {
|
||||
<!CAN_BE_VAL!>var<!> a: Int
|
||||
a = 1
|
||||
for (i in 1..10)
|
||||
print(i)
|
||||
}
|
||||
|
||||
fun smth(flag: Boolean) {
|
||||
var a = 1
|
||||
|
||||
if (flag) {
|
||||
while (a > 0) {
|
||||
a--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun withAnnotation(p: List<Any>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
<!CAN_BE_VAL!>var<!> v = p as List<String>
|
||||
print(v)
|
||||
}
|
||||
|
||||
fun withReadonlyDeligate() {
|
||||
val s: String by lazy { "Hello!" }
|
||||
s.hashCode()
|
||||
}
|
||||
|
||||
fun getPair(): Pair<Int, String> = Pair(1, "1")
|
||||
|
||||
fun listReceiver(p: List<String>) {}
|
||||
|
||||
fun withInitializer() {
|
||||
var v1 = 1
|
||||
var v2 = 2
|
||||
<!CAN_BE_VAL!>var<!> v3 = 3
|
||||
v1 = 1
|
||||
v2++
|
||||
print(v3)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
var a = 0
|
||||
while (a>0) {
|
||||
a++
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
<!CAN_BE_VAL!>var<!> a: Int
|
||||
val bool = true
|
||||
val b: String
|
||||
|
||||
if (bool) a = 4 else a = 42
|
||||
|
||||
bool = false
|
||||
}
|
||||
|
||||
fun cycles() {
|
||||
var a = 10
|
||||
while (a > 0) {
|
||||
a--
|
||||
}
|
||||
|
||||
val b: Int
|
||||
while (a < 10) {
|
||||
a++
|
||||
b = a
|
||||
}
|
||||
}
|
||||
|
||||
fun assignedTwice(p: Int) {
|
||||
var v: Int
|
||||
v = 0
|
||||
if (p > 0) v = 1
|
||||
}
|
||||
|
||||
fun main(args: Array<String?>) {
|
||||
<!CAN_BE_VAL!>var<!> a: String?
|
||||
|
||||
if (args.size == 1) {
|
||||
a = args[0]
|
||||
}
|
||||
else {
|
||||
a = args.toString()
|
||||
}
|
||||
|
||||
if (a != null && a.equals("cde")) return
|
||||
}
|
||||
|
||||
fun run(f: () -> Unit) = f()
|
||||
|
||||
fun lambda() {
|
||||
var a: Int
|
||||
a = 10
|
||||
|
||||
run {
|
||||
a = 20
|
||||
}
|
||||
}
|
||||
|
||||
fun lambdaInitialization() {
|
||||
<!CAN_BE_VAL!>var<!> a: Int
|
||||
|
||||
run {
|
||||
a = 20
|
||||
}
|
||||
}
|
||||
|
||||
fun notAssignedWhenNotUsed(p: Int) {
|
||||
<!CAN_BE_VAL!>var<!> v: Int
|
||||
if (p > 0) {
|
||||
v = 1
|
||||
print(v)
|
||||
}
|
||||
}
|
||||
|
||||
var global = 1
|
||||
|
||||
class C {
|
||||
var field = 2
|
||||
|
||||
fun foo() {
|
||||
print(field)
|
||||
print(global)
|
||||
}
|
||||
}
|
||||
|
||||
fun withDelegate() {
|
||||
var s: String by Delegates.notNull()
|
||||
s = ""
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
FILE: VariableAssignmentChecker.kt
|
||||
public final fun testDelegator(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Boolean|by R|/LocalFreezableVar.LocalFreezableVar|<R|kotlin/Boolean|>(Boolean(true))
|
||||
lvar y: R|kotlin/String|by R|/LocalFreezableVar.LocalFreezableVar|<R|kotlin/String|>(String())
|
||||
}
|
||||
public final class LocalFreezableVar<T> : R|kotlin/Any| {
|
||||
public constructor<T>(value: R|T|): R|LocalFreezableVar<T>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
private final var value: R|T| = R|<local>/value|
|
||||
private get(): R|T|
|
||||
private set(value: R|T|): R|kotlin/Unit|
|
||||
|
||||
public final operator fun getValue(thisRef: R|kotlin/Nothing?|, property: R|kotlin/reflect/KProperty<*>|): R|T| {
|
||||
^getValue this@R|/LocalFreezableVar|.R|/LocalFreezableVar.value|
|
||||
}
|
||||
|
||||
public final operator fun setValue(thisRef: R|kotlin/Nothing?|, property: R|kotlin/reflect/KProperty<*>|, value: R|T|): R|kotlin/Unit| {
|
||||
this@R|/LocalFreezableVar|.R|/LocalFreezableVar.value| = R|<local>/value|
|
||||
}
|
||||
|
||||
}
|
||||
public final class C : R|kotlin/Any| {
|
||||
public constructor(): R|C| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final operator fun R|C|.plus(a: R|kotlin/Any|): R|C| {
|
||||
^plus this@R|/plus|
|
||||
}
|
||||
public final operator fun R|C|.plusAssign(a: R|kotlin/Any|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun testOperatorAssignment(): R|kotlin/Unit| {
|
||||
lval c: R|C| = R|/C.C|()
|
||||
R|<local>/c|.R|/plusAssign|(String())
|
||||
lvar c1: R|C| = R|/C.C|()
|
||||
ERROR_EXPR(Operator overload ambiguity. Compatible candidates: [/plus, /plusAssign])
|
||||
lvar a: R|kotlin/Int| = Int(1)
|
||||
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(12))
|
||||
R|<local>/a| = R|<local>/a|.R|kotlin/Int.minus|(Int(10))
|
||||
}
|
||||
public final fun destructuringDeclaration(): R|kotlin/Unit| {
|
||||
lval <destruct>: R|kotlin/Pair<kotlin/Int, kotlin/String>| = R|/getPair|()
|
||||
lvar v1: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Pair.component1: R|kotlin/Int|>|()
|
||||
lvar v2: R|kotlin/String| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Pair.component2: R|kotlin/String|>|()
|
||||
R|kotlin/io/print|(R|<local>/v1|)
|
||||
lval <destruct>: R|kotlin/Pair<kotlin/Int, kotlin/String>| = R|/getPair|()
|
||||
lvar v3: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Pair.component1: R|kotlin/Int|>|()
|
||||
lvar v4: R|kotlin/String| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Pair.component2: R|kotlin/String|>|()
|
||||
R|kotlin/io/print|(R|<local>/v3|)
|
||||
R|<local>/v4| = String()
|
||||
lval <destruct>: R|kotlin/Pair<kotlin/Int, kotlin/String>| = R|/getPair|()
|
||||
lvar v5: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Pair.component1: R|kotlin/Int|>|()
|
||||
lvar v6: R|kotlin/String| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Pair.component2: R|kotlin/String|>|()
|
||||
R|<local>/v5| = Int(1)
|
||||
lval <destruct>: R|kotlin/Pair<kotlin/Int, kotlin/String>| = R|/getPair|()
|
||||
lvar v7: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Pair.component1: R|kotlin/Int|>|()
|
||||
lvar v8: R|kotlin/String| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Pair.component2: R|kotlin/String|>|()
|
||||
R|<local>/v7| = Int(2)
|
||||
R|<local>/v8| = String(42)
|
||||
lval <destruct>: R|kotlin/Triple<kotlin/Int, kotlin/Int, kotlin/Int>| = R|kotlin/Triple.Triple|<R|kotlin/Int|, R|kotlin/Int|, R|kotlin/Int|>(Int(1), Int(1), Int(1))
|
||||
lval a: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Triple.component1: R|kotlin/Int|>|()
|
||||
lval b: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Triple.component2: R|kotlin/Int|>|()
|
||||
lval c: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Triple.component3: R|kotlin/Int|>|()
|
||||
lval <destruct>: R|kotlin/Triple<kotlin/Int, kotlin/Int, kotlin/Int>| = R|kotlin/Triple.Triple|<R|kotlin/Int|, R|kotlin/Int|, R|kotlin/Int|>(Int(1), Int(1), Int(1))
|
||||
lvar x: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Triple.component1: R|kotlin/Int|>|()
|
||||
lvar y: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Triple.component2: R|kotlin/Int|>|()
|
||||
lvar z: R|kotlin/Int| = R|<local>/<destruct>|.R|FakeOverride<kotlin/Triple.component3: R|kotlin/Int|>|()
|
||||
}
|
||||
public final fun stackOverflowBug(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int|
|
||||
R|<local>/a| = Int(1)
|
||||
lval <iterator>: R|kotlin/collections/IntIterator| = Int(1).R|kotlin/Int.rangeTo|(Int(10)).R|kotlin/ranges/IntProgression.iterator|()
|
||||
while(R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()) {
|
||||
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|kotlin/collections/IntIterator.next|()
|
||||
R|kotlin/io/print|(R|<local>/i|)
|
||||
}
|
||||
|
||||
}
|
||||
public final fun smth(flag: R|kotlin/Boolean|): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int| = Int(1)
|
||||
when () {
|
||||
R|<local>/flag| -> {
|
||||
while(CMP(>, R|<local>/a|.R|kotlin/Int.compareTo|(Int(0)))) {
|
||||
lval <unary>: R|kotlin/Int| = R|<local>/a|
|
||||
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.dec|()
|
||||
R|<local>/<unary>|
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun withAnnotation(p: R|kotlin/collections/List<kotlin/Any>|): R|kotlin/Unit| {
|
||||
@R|kotlin/Suppress|(vararg(String(UNCHECKED_CAST))) lvar v: R|kotlin/collections/List<kotlin/String>| = (R|<local>/p| as R|kotlin/collections/List<kotlin/String>|)
|
||||
R|kotlin/io/print|(R|<local>/v|)
|
||||
}
|
||||
public final fun withReadonlyDeligate(): R|kotlin/Unit| {
|
||||
lval s: R|kotlin/String|by R|kotlin/lazy|<R|kotlin/String|>(<L> = lazy@fun <anonymous>(): R|kotlin/String| {
|
||||
^ String(Hello!)
|
||||
}
|
||||
)
|
||||
R|<local>/s|.R|kotlin/Any.hashCode|()
|
||||
}
|
||||
public final fun getPair(): R|kotlin/Pair<kotlin/Int, kotlin/String>| {
|
||||
^getPair R|kotlin/Pair.Pair|<R|kotlin/Int|, R|kotlin/String|>(Int(1), String(1))
|
||||
}
|
||||
public final fun listReceiver(p: R|kotlin/collections/List<kotlin/String>|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun withInitializer(): R|kotlin/Unit| {
|
||||
lvar v1: R|kotlin/Int| = Int(1)
|
||||
lvar v2: R|kotlin/Int| = Int(2)
|
||||
lvar v3: R|kotlin/Int| = Int(3)
|
||||
R|<local>/v1| = Int(1)
|
||||
lval <unary>: R|kotlin/Int| = R|<local>/v2|
|
||||
R|<local>/v2| = R|<local>/<unary>|.R|kotlin/Int.inc|()
|
||||
R|<local>/<unary>|
|
||||
R|kotlin/io/print|(R|<local>/v3|)
|
||||
}
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int| = Int(0)
|
||||
while(CMP(>, R|<local>/a|.R|kotlin/Int.compareTo|(Int(0)))) {
|
||||
lval <unary>: R|kotlin/Int| = R|<local>/a|
|
||||
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.inc|()
|
||||
R|<local>/<unary>|
|
||||
}
|
||||
|
||||
}
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int|
|
||||
lval bool: R|kotlin/Boolean| = Boolean(true)
|
||||
lval b: R|kotlin/String|
|
||||
when () {
|
||||
R|<local>/bool| -> {
|
||||
R|<local>/a| = Int(4)
|
||||
}
|
||||
else -> {
|
||||
R|<local>/a| = Int(42)
|
||||
}
|
||||
}
|
||||
|
||||
R|<local>/bool| = Boolean(false)
|
||||
}
|
||||
public final fun cycles(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int| = Int(10)
|
||||
while(CMP(>, R|<local>/a|.R|kotlin/Int.compareTo|(Int(0)))) {
|
||||
lval <unary>: R|kotlin/Int| = R|<local>/a|
|
||||
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.dec|()
|
||||
R|<local>/<unary>|
|
||||
}
|
||||
|
||||
lval b: R|kotlin/Int|
|
||||
while(CMP(<, R|<local>/a|.R|kotlin/Int.compareTo|(Int(10)))) {
|
||||
lval <unary>: R|kotlin/Int| = R|<local>/a|
|
||||
R|<local>/a| = R|<local>/<unary>|.R|kotlin/Int.inc|()
|
||||
R|<local>/<unary>|
|
||||
R|<local>/b| = R|<local>/a|
|
||||
}
|
||||
|
||||
}
|
||||
public final fun assignedTwice(p: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
lvar v: R|kotlin/Int|
|
||||
R|<local>/v| = Int(0)
|
||||
when () {
|
||||
CMP(>, R|<local>/p|.R|kotlin/Int.compareTo|(Int(0))) -> {
|
||||
R|<local>/v| = Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun main(args: R|kotlin/Array<kotlin/String?>|): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/String?|
|
||||
when () {
|
||||
==(R|<local>/args|.R|kotlin/Array.size|, Int(1)) -> {
|
||||
R|<local>/a| = R|<local>/args|.R|FakeOverride<kotlin/Array.get: R|kotlin/String?|>|(Int(0))
|
||||
}
|
||||
else -> {
|
||||
R|<local>/a| = R|<local>/args|.R|kotlin/Any.toString|()
|
||||
}
|
||||
}
|
||||
|
||||
when () {
|
||||
!=(R|<local>/a|, Null(null)) && R|<local>/a|.R|kotlin/Any.equals|(String(cde)) -> {
|
||||
^main Unit
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun run(f: R|() -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
^run R|<local>/f|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
|
||||
}
|
||||
public final fun lambda(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int|
|
||||
R|<local>/a| = Int(10)
|
||||
R|/run|(<L> = run@fun <anonymous>(): R|kotlin/Unit| {
|
||||
R|<local>/a| = Int(20)
|
||||
}
|
||||
)
|
||||
}
|
||||
public final fun lambdaInitialization(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int|
|
||||
R|/run|(<L> = run@fun <anonymous>(): R|kotlin/Unit| {
|
||||
R|<local>/a| = Int(20)
|
||||
}
|
||||
)
|
||||
}
|
||||
public final fun notAssignedWhenNotUsed(p: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
lvar v: R|kotlin/Int|
|
||||
when () {
|
||||
CMP(>, R|<local>/p|.R|kotlin/Int.compareTo|(Int(0))) -> {
|
||||
R|<local>/v| = Int(1)
|
||||
R|kotlin/io/print|(R|<local>/v|)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final var global: R|kotlin/Int| = Int(1)
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
public final class C : R|kotlin/Any| {
|
||||
public constructor(): R|C| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final var field: R|kotlin/Int| = Int(2)
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
R|kotlin/io/print|(this@R|/C|.R|/C.field|)
|
||||
R|kotlin/io/print|(R|/global|)
|
||||
}
|
||||
|
||||
}
|
||||
public final fun withDelegate(): R|kotlin/Unit| {
|
||||
lvar s: R|kotlin/String|by Q|kotlin/properties/Delegates|.R|kotlin/properties/Delegates.notNull|<R|kotlin/String|>()
|
||||
R|<local>/s| = String()
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
fun goo() {
|
||||
var a = 2
|
||||
val b = 4
|
||||
a <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> a + 1 + b
|
||||
a <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> (a + 1)
|
||||
a = a * b + 1
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
FILE: BasicTest.kt
|
||||
public final fun goo(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int| = Int(2)
|
||||
lval b: R|kotlin/Int| = Int(4)
|
||||
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(1)).R|kotlin/Int.plus|(R|<local>/b|)
|
||||
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(1))
|
||||
R|<local>/a| = R|<local>/a|.R|kotlin/Int.times|(R|<local>/b|).R|kotlin/Int.plus|(Int(1))
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
fun foo() {
|
||||
var a = 0
|
||||
a = (a + 1) / 2
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: ComplexExpression.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int| = Int(0)
|
||||
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(1)).R|kotlin/Int.div|(Int(2))
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
fun foo() {
|
||||
var a = 0
|
||||
a += 10 + a
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: OperatorAssignment.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar a: R|kotlin/Int| = Int(0)
|
||||
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(10).R|kotlin/Int.plus|(R|<local>/a|))
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo() {
|
||||
var list1 = java.util.Collections.emptyList<String>()
|
||||
val list2 = listOf("b")
|
||||
list1 = list1 + list2
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE: flexibleTypeBug.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar list1: R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>!>, kotlin/collections/List<ft<kotlin/String, kotlin/String?>!>?>!| = Q|java/util/Collections|.R|java/util/Collections.emptyList|<R|ft<kotlin/String, kotlin/String?>!|>()
|
||||
lval list2: R|kotlin/collections/List<kotlin/String>| = R|kotlin/collections/listOf|<R|kotlin/String|>(String(b))
|
||||
R|<local>/list1| = R|<local>/list1|.R|kotlin/collections/plus|<R|ft<kotlin/String, kotlin/String?>!|>(R|<local>/list2|)
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
x = x / 1 + 1
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: illegalMultipleOperators.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = R|<local>/x|.R|kotlin/Int.div|(Int(1)).R|kotlin/Int.plus|(Int(1))
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
val y = 0
|
||||
x = y / x + 0
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE: illegalMultipleOperatorsMiddle.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
lval y: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = R|<local>/y|.R|kotlin/Int.div|(R|<local>/x|).R|kotlin/Int.plus|(Int(0))
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
x = 1 - x
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: invalidSubtraction.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = Int(1).R|kotlin/Int.minus|(R|<local>/x|)
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo() {
|
||||
var list = listOf(1, 2, 3)
|
||||
// Should not be highlighted because it's the way we use to say explicitly
|
||||
// "yes, we want to re-assign this immutable list"
|
||||
list = list + 4
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: list.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar list: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/Int|>(vararg(Int(1), Int(2), Int(3)))
|
||||
R|<local>/list| = R|<local>/list|.R|kotlin/collections/plus|<R|kotlin/Int|>(Int(4))
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
<!CAN_BE_VAL!>var<!> y = 0
|
||||
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x + y + 5
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE: multipleOperators.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
lvar y: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = R|<local>/x|.R|kotlin/Int.plus|(R|<local>/y|).R|kotlin/Int.plus|(Int(5))
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
<!CAN_BE_VAL!>var<!> y = 0
|
||||
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> y + x + 5
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE: multipleOperatorsRightSideRepeat.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
lvar y: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = R|<local>/y|.R|kotlin/Int.plus|(R|<local>/x|).R|kotlin/Int.plus|(Int(5))
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun foo() {
|
||||
var listVar = mutableListOf(1, 2, 3)
|
||||
// now, Idea hightlights this code like error (cuz listVar
|
||||
// is mutable and listVar + 4 is immutable) and like warning
|
||||
// (cuz can be replaced with +=)
|
||||
listVar = listVar + 4
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: mutableList.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar listVar: R|kotlin/collections/MutableList<kotlin/Int>| = R|kotlin/collections/mutableListOf|<R|kotlin/Int|>(vararg(Int(1), Int(2), Int(3)))
|
||||
R|<local>/listVar| = R|<local>/listVar|.R|kotlin/collections/plus|<R|kotlin/Int|>(Int(4))
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x - 1 - 1
|
||||
|
||||
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x / 1
|
||||
x = 1 / x
|
||||
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> -1 + x
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
FILE: nonCommutativeRepeat.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = R|<local>/x|.R|kotlin/Int.minus|(Int(1)).R|kotlin/Int.minus|(Int(1))
|
||||
R|<local>/x| = R|<local>/x|.R|kotlin/Int.div|(Int(1))
|
||||
R|<local>/x| = Int(1).R|kotlin/Int.div|(R|<local>/x|)
|
||||
R|<local>/x| = Int(1).R|kotlin/Int.unaryMinus|().R|kotlin/Int.plus|(R|<local>/x|)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
val y = 0
|
||||
val z = 0
|
||||
x = y + z
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
FILE: nonRepeatingAssignment.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
lval y: R|kotlin/Int| = Int(0)
|
||||
lval z: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = R|<local>/y|.R|kotlin/Int.plus|(R|<local>/z|)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
class A
|
||||
|
||||
operator fun A.plus(a: A): A = A()
|
||||
operator fun A.plusAssign(a: A){}
|
||||
|
||||
fun foo() {
|
||||
var a1 = A()
|
||||
val a2 = A()
|
||||
a1 = a1 + a2
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
FILE: plusAssignConflict.kt
|
||||
public final class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final operator fun R|A|.plus(a: R|A|): R|A| {
|
||||
^plus R|/A.A|()
|
||||
}
|
||||
public final operator fun R|A|.plusAssign(a: R|A|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar a1: R|A| = R|/A.A|()
|
||||
lval a2: R|A| = R|/A.A|()
|
||||
R|<local>/a1| = R|<local>/a1|.R|/plus|(R|<local>/a2|)
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> 1 + x
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: rightSideRepeat.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = Int(1).R|kotlin/Int.plus|(R|<local>/x|)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
fun foo() {
|
||||
var y = 0
|
||||
val x = 0
|
||||
y <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> y + x
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE: simpleAssign.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar y: R|kotlin/Int| = Int(0)
|
||||
lval x: R|kotlin/Int| = Int(0)
|
||||
R|<local>/y| = R|<local>/y|.R|kotlin/Int.plus|(R|<local>/x|)
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x + 1
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: validAddition.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = R|<local>/x|.R|kotlin/Int.plus|(Int(1))
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
fun foo() {
|
||||
var x = 0
|
||||
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x - 1
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
FILE: validSubtraction.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lvar x: R|kotlin/Int| = Int(0)
|
||||
R|<local>/x| = R|<local>/x|.R|kotlin/Int.minus|(Int(1))
|
||||
}
|
||||
@@ -47,112 +47,4 @@ public class ExtendedFirDiagnosticsTestGenerated extends AbstractExtendedFirDiag
|
||||
public void testRedundantVisibilityModifierChecker() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/RedundantVisibilityModifierChecker.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("VariableAssignmentChecker.kt")
|
||||
public void testVariableAssignmentChecker() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/VariableAssignmentChecker.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class CanBeReplacedWithOperatorAssignment extends AbstractExtendedFirDiagnosticsTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInCanBeReplacedWithOperatorAssignment() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("BasicTest.kt")
|
||||
public void testBasicTest() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/BasicTest.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ComplexExpression.kt")
|
||||
public void testComplexExpression() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/ComplexExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("flexibleTypeBug.kt")
|
||||
public void testFlexibleTypeBug() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/flexibleTypeBug.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("illegalMultipleOperators.kt")
|
||||
public void testIllegalMultipleOperators() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/illegalMultipleOperators.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("illegalMultipleOperatorsMiddle.kt")
|
||||
public void testIllegalMultipleOperatorsMiddle() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/illegalMultipleOperatorsMiddle.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invalidSubtraction.kt")
|
||||
public void testInvalidSubtraction() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/invalidSubtraction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("list.kt")
|
||||
public void testList() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/list.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleOperators.kt")
|
||||
public void testMultipleOperators() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/multipleOperators.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleOperatorsRightSideRepeat.kt")
|
||||
public void testMultipleOperatorsRightSideRepeat() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/multipleOperatorsRightSideRepeat.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("mutableList.kt")
|
||||
public void testMutableList() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/mutableList.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonCommutativeRepeat.kt")
|
||||
public void testNonCommutativeRepeat() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/nonCommutativeRepeat.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonRepeatingAssignment.kt")
|
||||
public void testNonRepeatingAssignment() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/nonRepeatingAssignment.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("OperatorAssignment.kt")
|
||||
public void testOperatorAssignment() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/OperatorAssignment.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssignConflict.kt")
|
||||
public void testPlusAssignConflict() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/plusAssignConflict.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("rightSideRepeat.kt")
|
||||
public void testRightSideRepeat() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/rightSideRepeat.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleAssign.kt")
|
||||
public void testSimpleAssign() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/simpleAssign.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("validAddition.kt")
|
||||
public void testValidAddition() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/validAddition.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("validSubtraction.kt")
|
||||
public void testValidSubtraction() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/canBeReplacedWithOperatorAssignment/validSubtraction.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15514,11 +15514,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/namedArguments/mixedNamedPosition/oldInference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("secondNamed.kt")
|
||||
public void testSecondNamed() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/namedArguments/mixedNamedPosition/secondNamed.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/namedArguments/mixedNamedPosition/simple.kt");
|
||||
@@ -24847,11 +24842,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/varargs/assigningSingleElementsInNamedFormFunDeprecation_before.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inferredNullableArrayAsVararg.kt")
|
||||
public void testInferredNullableArrayAsVararg() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/varargs/inferredNullableArrayAsVararg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt1781.kt")
|
||||
public void testKt1781() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/varargs/kt1781.kt");
|
||||
|
||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.analysis
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
|
||||
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
|
||||
@@ -61,19 +60,15 @@ private class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
|
||||
override val constructorCheckers: List<FirConstructorChecker>
|
||||
get() = _constructorCheckers
|
||||
override val controlFlowAnalyserCheckers: List<FirControlFlowChecker>
|
||||
get() = _controlFlowAnalyserCheckers
|
||||
|
||||
private val _declarationCheckers: MutableList<FirBasicDeclarationChecker> = mutableListOf()
|
||||
private val _memberDeclarationCheckers: MutableList<FirMemberDeclarationChecker> = mutableListOf()
|
||||
private val _constructorCheckers: MutableList<FirConstructorChecker> = mutableListOf()
|
||||
private val _controlFlowAnalyserCheckers: MutableList<FirControlFlowChecker> = mutableListOf()
|
||||
|
||||
fun register(checkers: DeclarationCheckers) {
|
||||
_declarationCheckers += checkers.declarationCheckers
|
||||
_memberDeclarationCheckers += checkers.allMemberDeclarationCheckers
|
||||
_constructorCheckers += checkers.allConstructorCheckers
|
||||
_controlFlowAnalyserCheckers += checkers.controlFlowAnalyserCheckers
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,18 +79,14 @@ private class ComposedExpressionCheckers : ExpressionCheckers() {
|
||||
get() = _qualifiedAccessCheckers
|
||||
override val functionCallCheckers: List<FirFunctionCallChecker>
|
||||
get() = _functionCallCheckers
|
||||
override val variableAssignmentCheckers: List<FirVariableAssignmentChecker>
|
||||
get() = _variableAssignmentCheckers
|
||||
|
||||
private val _expressionCheckers: MutableList<FirBasicExpresionChecker> = mutableListOf()
|
||||
private val _qualifiedAccessCheckers: MutableList<FirQualifiedAccessChecker> = mutableListOf()
|
||||
private val _functionCallCheckers: MutableList<FirFunctionCallChecker> = mutableListOf()
|
||||
private val _variableAssignmentCheckers: MutableList<FirVariableAssignmentChecker> = mutableListOf()
|
||||
|
||||
fun register(checkers: ExpressionCheckers) {
|
||||
_expressionCheckers += checkers.allExpressionCheckers
|
||||
_qualifiedAccessCheckers += checkers.allQualifiedAccessCheckers
|
||||
_functionCallCheckers += checkers.allFunctionCallCheckers
|
||||
_variableAssignmentCheckers += checkers.variableAssignmentCheckers
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.cfa
|
||||
|
||||
import kotlinx.collections.immutable.PersistentMap
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
|
||||
abstract class AbstractFirPropertyInitializationChecker : FirControlFlowChecker() {
|
||||
abstract override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter)
|
||||
|
||||
class PropertyInitializationInfo(
|
||||
map: PersistentMap<FirPropertySymbol, EventOccurrencesRange> = persistentMapOf()
|
||||
) : ControlFlowInfo<PropertyInitializationInfo, FirPropertySymbol, EventOccurrencesRange>(map) {
|
||||
companion object {
|
||||
val EMPTY = PropertyInitializationInfo()
|
||||
}
|
||||
|
||||
override val constructor: (PersistentMap<FirPropertySymbol, EventOccurrencesRange>) -> PropertyInitializationInfo =
|
||||
::PropertyInitializationInfo
|
||||
|
||||
fun merge(other: PropertyInitializationInfo): PropertyInitializationInfo {
|
||||
var result = this
|
||||
for (symbol in keys.union(other.keys)) {
|
||||
val kind1 = this[symbol] ?: EventOccurrencesRange.ZERO
|
||||
val kind2 = other[symbol] ?: EventOccurrencesRange.ZERO
|
||||
result = result.put(symbol, kind1 or kind2)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class LocalPropertyCollector private constructor() : ControlFlowGraphVisitorVoid() {
|
||||
companion object {
|
||||
fun collect(graph: ControlFlowGraph): MutableSet<FirPropertySymbol> {
|
||||
val collector = LocalPropertyCollector()
|
||||
graph.traverse(TraverseDirection.Forward, collector)
|
||||
return collector.symbols
|
||||
}
|
||||
}
|
||||
|
||||
private val symbols: MutableSet<FirPropertySymbol> = mutableSetOf()
|
||||
|
||||
override fun visitNode(node: CFGNode<*>) {}
|
||||
|
||||
override fun visitVariableDeclarationNode(node: VariableDeclarationNode) {
|
||||
symbols += node.fir.symbol
|
||||
}
|
||||
}
|
||||
|
||||
class DataCollector(private val localProperties: Set<FirPropertySymbol>) :
|
||||
ControlFlowGraphVisitor<PropertyInitializationInfo, Collection<PropertyInitializationInfo>>() {
|
||||
override fun visitNode(node: CFGNode<*>, data: Collection<PropertyInitializationInfo>): PropertyInitializationInfo {
|
||||
if (data.isEmpty()) return PropertyInitializationInfo.EMPTY
|
||||
return data.reduce(PropertyInitializationInfo::merge)
|
||||
}
|
||||
|
||||
override fun visitVariableAssignmentNode(
|
||||
node: VariableAssignmentNode,
|
||||
data: Collection<PropertyInitializationInfo>
|
||||
): PropertyInitializationInfo {
|
||||
val dataForNode = visitNode(node, data)
|
||||
val reference = node.fir.lValue as? FirResolvedNamedReference ?: return dataForNode
|
||||
val symbol = reference.resolvedSymbol as? FirPropertySymbol ?: return dataForNode
|
||||
return if (symbol !in localProperties) {
|
||||
dataForNode
|
||||
} else {
|
||||
processVariableWithAssignment(dataForNode, symbol)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitVariableDeclarationNode(
|
||||
node: VariableDeclarationNode,
|
||||
data: Collection<PropertyInitializationInfo>
|
||||
): PropertyInitializationInfo {
|
||||
val dataForNode = visitNode(node, data)
|
||||
return if (node.fir.initializer == null && node.fir.delegate == null) {
|
||||
dataForNode
|
||||
} else {
|
||||
processVariableWithAssignment(dataForNode, node.fir.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
fun getData(graph: ControlFlowGraph) =
|
||||
graph.collectDataForNode(TraverseDirection.Forward, PropertyInitializationInfo.EMPTY, DataCollector(localProperties))
|
||||
|
||||
private fun processVariableWithAssignment(
|
||||
dataForNode: PropertyInitializationInfo,
|
||||
symbol: FirPropertySymbol
|
||||
): PropertyInitializationInfo {
|
||||
val existingKind = dataForNode[symbol] ?: EventOccurrencesRange.ZERO
|
||||
val kind = existingKind + EventOccurrencesRange.EXACTLY_ONCE
|
||||
return dataForNode.put(symbol, kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,17 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.cfa
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
||||
|
||||
class FirControlFlowAnalyzer(session: FirSession) {
|
||||
private val checkers = session.checkersComponent.declarationCheckers.controlFlowAnalyserCheckers
|
||||
class FirControlFlowAnalyzer {
|
||||
private val propertyInitializationAnalyzer = FirPropertyInitializationAnalyzer()
|
||||
|
||||
fun analyzeClassInitializer(klass: FirClass<*>, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (graph.owner != null) return
|
||||
@@ -24,7 +22,7 @@ class FirControlFlowAnalyzer(session: FirSession) {
|
||||
|
||||
fun analyzeFunction(function: FirFunction<*>, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (graph.owner != null) return
|
||||
checkers.forEach { it.analyze(graph, reporter) }
|
||||
propertyInitializationAnalyzer.analyze(graph, reporter)
|
||||
}
|
||||
|
||||
fun analyzePropertyInitializer(property: FirProperty, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
|
||||
@@ -5,24 +5,23 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.cfa
|
||||
|
||||
import kotlinx.collections.immutable.PersistentMap
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.CFGNode
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraphVisitorVoid
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.QualifiedAccessNode
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
|
||||
object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChecker() {
|
||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter) {
|
||||
class FirPropertyInitializationAnalyzer {
|
||||
fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter) {
|
||||
val localProperties = LocalPropertyCollector.collect(graph)
|
||||
// we want to analyze only properties without initializers
|
||||
localProperties.retainAll { it.fir.initializer == null && it.fir.delegate == null }
|
||||
if (localProperties.isEmpty()) return
|
||||
val data = DataCollector(localProperties).getData(graph)
|
||||
val data = graph.collectDataForNode(TraverseDirection.Forward, PropertyInitializationInfo.EMPTY, DataCollector(localProperties))
|
||||
val reporterVisitor = UninitializedPropertyReporter(data, localProperties, reporter)
|
||||
graph.traverse(TraverseDirection.Forward, reporterVisitor)
|
||||
}
|
||||
@@ -46,4 +45,85 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PropertyInitializationInfo(
|
||||
map: PersistentMap<FirPropertySymbol, EventOccurrencesRange> = persistentMapOf()
|
||||
) : ControlFlowInfo<PropertyInitializationInfo, FirPropertySymbol, EventOccurrencesRange>(map) {
|
||||
companion object {
|
||||
val EMPTY = PropertyInitializationInfo()
|
||||
}
|
||||
|
||||
override val constructor: (PersistentMap<FirPropertySymbol, EventOccurrencesRange>) -> PropertyInitializationInfo =
|
||||
::PropertyInitializationInfo
|
||||
|
||||
fun merge(other: PropertyInitializationInfo): PropertyInitializationInfo {
|
||||
var result = this
|
||||
for (symbol in keys.union(other.keys)) {
|
||||
val kind1 = this[symbol] ?: EventOccurrencesRange.ZERO
|
||||
val kind2 = other[symbol] ?: EventOccurrencesRange.ZERO
|
||||
result = result.put(symbol, kind1 or kind2)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private class LocalPropertyCollector private constructor() : ControlFlowGraphVisitorVoid() {
|
||||
companion object {
|
||||
fun collect(graph: ControlFlowGraph): MutableSet<FirPropertySymbol> {
|
||||
val collector = LocalPropertyCollector()
|
||||
graph.traverse(TraverseDirection.Forward, collector)
|
||||
return collector.symbols
|
||||
}
|
||||
}
|
||||
|
||||
private val symbols: MutableSet<FirPropertySymbol> = mutableSetOf()
|
||||
|
||||
override fun visitNode(node: CFGNode<*>) {}
|
||||
|
||||
override fun visitVariableDeclarationNode(node: VariableDeclarationNode) {
|
||||
symbols += node.fir.symbol
|
||||
}
|
||||
}
|
||||
|
||||
private class DataCollector(private val localProperties: Set<FirPropertySymbol>) : ControlFlowGraphVisitor<PropertyInitializationInfo, Collection<PropertyInitializationInfo>>() {
|
||||
override fun visitNode(node: CFGNode<*>, data: Collection<PropertyInitializationInfo>): PropertyInitializationInfo {
|
||||
if (data.isEmpty()) return PropertyInitializationInfo.EMPTY
|
||||
return data.reduce(PropertyInitializationInfo::merge)
|
||||
}
|
||||
|
||||
override fun visitVariableAssignmentNode(
|
||||
node: VariableAssignmentNode,
|
||||
data: Collection<PropertyInitializationInfo>
|
||||
): PropertyInitializationInfo {
|
||||
val dataForNode = visitNode(node, data)
|
||||
val reference = node.fir.lValue as? FirResolvedNamedReference ?: return dataForNode
|
||||
val symbol = reference.resolvedSymbol as? FirPropertySymbol ?: return dataForNode
|
||||
return if (symbol !in localProperties) {
|
||||
dataForNode
|
||||
} else{
|
||||
processVariableWithAssignment(dataForNode, symbol)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitVariableDeclarationNode(
|
||||
node: VariableDeclarationNode,
|
||||
data: Collection<PropertyInitializationInfo>
|
||||
): PropertyInitializationInfo {
|
||||
val dataForNode = visitNode(node, data)
|
||||
return if (node.fir.initializer == null && node.fir.delegate == null) {
|
||||
dataForNode
|
||||
} else {
|
||||
processVariableWithAssignment(dataForNode, node.fir.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processVariableWithAssignment(
|
||||
dataForNode: PropertyInitializationInfo,
|
||||
symbol: FirPropertySymbol
|
||||
): PropertyInitializationInfo {
|
||||
val existingKind = dataForNode[symbol] ?: EventOccurrencesRange.ZERO
|
||||
val kind = existingKind + EventOccurrencesRange.EXACTLY_ONCE
|
||||
return dataForNode.put(symbol, kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.cfa
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
||||
|
||||
abstract class FirControlFlowChecker {
|
||||
abstract fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter)
|
||||
}
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
|
||||
abstract class DeclarationCheckers {
|
||||
companion object {
|
||||
val EMPTY: DeclarationCheckers = object : DeclarationCheckers() {}
|
||||
@@ -15,7 +13,6 @@ abstract class DeclarationCheckers {
|
||||
open val declarationCheckers: List<FirBasicDeclarationChecker> = emptyList()
|
||||
open val memberDeclarationCheckers: List<FirMemberDeclarationChecker> = emptyList()
|
||||
open val constructorCheckers: List<FirConstructorChecker> = emptyList()
|
||||
open val controlFlowAnalyserCheckers: List<FirControlFlowChecker> = emptyList()
|
||||
|
||||
internal val allMemberDeclarationCheckers: List<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + declarationCheckers
|
||||
internal val allConstructorCheckers: List<FirConstructorChecker> get() = constructorCheckers + allMemberDeclarationCheckers
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.FirPropertyInitializationAnalyzer
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
|
||||
object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
override val declarationCheckers: List<FirBasicDeclarationChecker> = listOf(
|
||||
FirAnnotationClassDeclarationChecker,
|
||||
@@ -22,8 +19,4 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
override val constructorCheckers: List<FirConstructorChecker> = listOf(
|
||||
FirConstructorAllowedChecker
|
||||
)
|
||||
|
||||
override val controlFlowAnalyserCheckers: List<FirControlFlowChecker> = listOf(
|
||||
FirPropertyInitializationAnalyzer
|
||||
)
|
||||
}
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extended.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extended.RedundantExplicitTypeChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extended.RedundantModalityModifierChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extended.RedundantReturnUnitType
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extended.RedundantVisibilityModifierChecker
|
||||
|
||||
object ExtendedDeclarationCheckers : DeclarationCheckers() {
|
||||
override val declarationCheckers = listOf(
|
||||
@@ -19,7 +21,4 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() {
|
||||
RedundantExplicitTypeChecker
|
||||
)
|
||||
|
||||
override val controlFlowAnalyserCheckers: List<FirControlFlowChecker> = listOf(
|
||||
VariableAssignmentChecker
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ abstract class ExpressionCheckers {
|
||||
open val expressionCheckers: List<FirBasicExpresionChecker> = emptyList()
|
||||
open val qualifiedAccessCheckers: List<FirQualifiedAccessChecker> = emptyList()
|
||||
open val functionCallCheckers: List<FirFunctionCallChecker> = emptyList()
|
||||
open val variableAssignmentCheckers: List<FirVariableAssignmentChecker> = emptyList()
|
||||
|
||||
internal val allExpressionCheckers get() = expressionCheckers
|
||||
internal val allQualifiedAccessCheckers get() = qualifiedAccessCheckers + allExpressionCheckers
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extended.CanBeReplacedWithOperatorAssignmentChecker
|
||||
|
||||
object ExtendedExpressionCheckers : ExpressionCheckers() {
|
||||
override val variableAssignmentCheckers: List<FirVariableAssignmentChecker> = listOf(
|
||||
CanBeReplacedWithOperatorAssignmentChecker
|
||||
)
|
||||
}
|
||||
@@ -7,16 +7,14 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
|
||||
abstract class FirExpressionChecker<in E : FirStatement> {
|
||||
abstract class FirExpressionChecker<in E : FirExpression> {
|
||||
abstract fun check(functionCall: E, context: CheckerContext, reporter: DiagnosticReporter)
|
||||
}
|
||||
|
||||
typealias FirBasicExpresionChecker = FirExpressionChecker<FirStatement>
|
||||
typealias FirBasicExpresionChecker = FirExpressionChecker<FirExpression>
|
||||
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccessExpression>
|
||||
typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
|
||||
typealias FirVariableAssignmentChecker = FirExpressionChecker<FirVariableAssignment>
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
||||
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.toFirPsiSourceElement
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
|
||||
object CanBeReplacedWithOperatorAssignmentChecker : FirExpressionChecker<FirVariableAssignment>() {
|
||||
override fun check(functionCall: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val lValue = functionCall.lValue
|
||||
if (lValue !is FirResolvedNamedReference) return
|
||||
val operator = functionCall.psi?.children?.getOrNull(1) ?: return
|
||||
if (operator.text != "=") return
|
||||
|
||||
val lValuePsi = lValue.psi as? KtNameReferenceExpression ?: return
|
||||
val rValue = functionCall.rValue as? FirFunctionCall ?: return
|
||||
val rValuePsi = rValue.psi as? KtBinaryExpression ?: return
|
||||
val rValueClassId = rValue.explicitReceiver?.typeRef?.coneType?.classId
|
||||
|
||||
if (rValueClassId !in StandardClassIds.primitiveTypes) return
|
||||
val rValueResolvedSymbol = rValue.toResolvedCallableSymbol() ?: return
|
||||
if (rValueResolvedSymbol.callableId.classId !in StandardClassIds.primitiveTypes) return
|
||||
|
||||
if (rValuePsi.matcher(lValuePsi)) {
|
||||
val operatorStatement = operator.toFirPsiSourceElement()
|
||||
reporter.report(operatorStatement, FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT)
|
||||
}
|
||||
}
|
||||
|
||||
fun KtBinaryExpression.matcher(variable: KtNameReferenceExpression): Boolean {
|
||||
if ((left as? KtNameReferenceExpression)?.getReferencedName() == variable.getReferencedName()) return true
|
||||
if ((right as? KtNameReferenceExpression)?.getReferencedName() == variable.getReferencedName() && isCommutative()) return true
|
||||
|
||||
return if (isCommutative()) {
|
||||
val leftExpression = left as? KtBinaryExpression
|
||||
val rightExpression = right as? KtBinaryExpression
|
||||
|
||||
val isLeftMatch = isHierarchicallyTrue(operationToken, leftExpression?.operationToken)
|
||||
&& leftExpression?.matcher(variable) == true
|
||||
val isRightMatch = isHierarchicallyTrue(operationToken, rightExpression?.operationToken)
|
||||
&& rightExpression?.matcher(variable) == true
|
||||
isLeftMatch or isRightMatch
|
||||
} else {
|
||||
val leftExpression = left as? KtBinaryExpression
|
||||
|
||||
isHierarchicallyTrue(operationToken, leftExpression?.operationToken)
|
||||
&& leftExpression?.matcher(variable) == true
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtBinaryExpression.isCommutative() = this.operationToken == KtTokens.PLUS || this.operationToken == KtTokens.MUL
|
||||
|
||||
private fun isHierarchicallyTrue(currentOperation: IElementType, nextOperation: IElementType?) = currentOperation == nextOperation
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
||||
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.TraverseDirection
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.traverse
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.toFirPsiSourceElement
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
|
||||
|
||||
object VariableAssignmentChecker : AbstractFirPropertyInitializationChecker() {
|
||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter) {
|
||||
val unprocessedProperties = mutableSetOf<FirPropertySymbol>()
|
||||
val propertiesCharacteristics = mutableMapOf<FirPropertySymbol, EventOccurrencesRange>()
|
||||
|
||||
val localProperties = LocalPropertyCollector.collect(graph)
|
||||
if (localProperties.isEmpty()) return
|
||||
|
||||
val data = DataCollector(localProperties).getData(graph)
|
||||
val reporterVisitor = UninitializedPropertyReporter(data, localProperties, unprocessedProperties, propertiesCharacteristics)
|
||||
graph.traverse(TraverseDirection.Forward, reporterVisitor)
|
||||
|
||||
for (property in unprocessedProperties) {
|
||||
if (property.fir.source is FirFakeSourceElement<*>) continue
|
||||
if (property.callableId.callableName.asString() == "<destruct>") continue
|
||||
propertiesCharacteristics[property] = EventOccurrencesRange.ZERO
|
||||
}
|
||||
|
||||
var lastDestructuringSource: FirSourceElement? = null
|
||||
var destructuringCanBeVal = false
|
||||
var lastDestructuredVariables = 0
|
||||
|
||||
for ((symbol, value) in propertiesCharacteristics) {
|
||||
val source = symbol.getValOrVarSource
|
||||
if (symbol.callableId.callableName.asString() == "<destruct>") {
|
||||
lastDestructuringSource = symbol.getValOrVarSource
|
||||
val childrenCount = symbol.fir.psi?.children?.size ?: continue
|
||||
lastDestructuredVariables = childrenCount - 1 // -1 cuz we don't need expression node after equals operator
|
||||
destructuringCanBeVal = true
|
||||
continue
|
||||
}
|
||||
|
||||
if (lastDestructuringSource != null) {
|
||||
// if this is the last variable in destructuring declaration and destructuringCanBeVal == true and it can be val
|
||||
if (lastDestructuredVariables == 1 && destructuringCanBeVal && canBeVal(symbol, value)) {
|
||||
reporter.report(lastDestructuringSource, FirErrors.CAN_BE_VAL)
|
||||
lastDestructuringSource = null
|
||||
} else if (!canBeVal(symbol, value)) {
|
||||
destructuringCanBeVal = false
|
||||
}
|
||||
lastDestructuredVariables--
|
||||
} else if (canBeVal(symbol, value) && symbol.fir.delegate == null ) {
|
||||
reporter.report(source, FirErrors.CAN_BE_VAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun canBeVal(symbol: FirPropertySymbol, value: EventOccurrencesRange) =
|
||||
(value == EventOccurrencesRange.EXACTLY_ONCE
|
||||
|| value == EventOccurrencesRange.AT_MOST_ONCE
|
||||
|| value == EventOccurrencesRange.ZERO
|
||||
) && symbol.fir.isVar
|
||||
|
||||
private class UninitializedPropertyReporter(
|
||||
val data: Map<CFGNode<*>, PropertyInitializationInfo>,
|
||||
val localProperties: Set<FirPropertySymbol>,
|
||||
val unprocessedProperties: MutableSet<FirPropertySymbol>,
|
||||
val propertiesCharacteristics: MutableMap<FirPropertySymbol, EventOccurrencesRange>
|
||||
) : ControlFlowGraphVisitorVoid() {
|
||||
override fun visitNode(node: CFGNode<*>) {}
|
||||
|
||||
override fun visitVariableAssignmentNode(node: VariableAssignmentNode) {
|
||||
val symbol = (node.fir.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirPropertySymbol
|
||||
?: return
|
||||
if (symbol !in localProperties) return
|
||||
unprocessedProperties.remove(symbol)
|
||||
|
||||
val currentCharacteristic = propertiesCharacteristics.getOrDefault(symbol, EventOccurrencesRange.ZERO)
|
||||
propertiesCharacteristics[symbol] = currentCharacteristic.or(data.getValue(node)[symbol] ?: EventOccurrencesRange.ZERO)
|
||||
}
|
||||
|
||||
override fun visitVariableDeclarationNode(node: VariableDeclarationNode) {
|
||||
val symbol = node.fir.symbol
|
||||
if (node.fir.initializer == null && node.fir.delegate == null) {
|
||||
unprocessedProperties.add(symbol)
|
||||
} else {
|
||||
propertiesCharacteristics[symbol] = EventOccurrencesRange.AT_MOST_ONCE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val FirPropertySymbol.getValOrVarSource
|
||||
get() = (fir.psi as? KtProperty)?.valOrVarKeyword?.toFirPsiSourceElement()
|
||||
?: fir.psi?.firstChild?.toFirPsiSourceElement()
|
||||
?: fir.source
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
|
||||
|
||||
class ControlFlowAnalysisDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
private val controlFlowAnalyzer = FirControlFlowAnalyzer(session)
|
||||
private val controlFlowAnalyzer = FirControlFlowAnalyzer()
|
||||
|
||||
// ------------------------------- Class initializer -------------------------------
|
||||
|
||||
|
||||
@@ -79,11 +79,7 @@ class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollect
|
||||
runCheck { checkers.expressionCheckers.check(getClassCall, data, it) }
|
||||
}
|
||||
|
||||
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) {
|
||||
runCheck { checkers.variableAssignmentCheckers.check(variableAssignment, data, it) }
|
||||
}
|
||||
|
||||
private fun <E : FirStatement> List<FirExpressionChecker<E>>.check(expression: E, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
private fun <E : FirExpression> List<FirExpressionChecker<E>>.check(expression: E, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
for (checker in this) {
|
||||
checker.check(expression, context, reporter)
|
||||
}
|
||||
|
||||
@@ -87,6 +87,6 @@ object FirErrors {
|
||||
val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, PsiElement>()
|
||||
val REDUNDANT_RETURN_UNIT_TYPE by warning0<FirSourceElement, PsiTypeElement>()
|
||||
val REDUNDANT_EXPLICIT_TYPE by warning0<FirSourceElement, PsiElement>()
|
||||
val CAN_BE_VAL by warning0<FirSourceElement, PsiElement>()
|
||||
val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning0<FirSourceElement, PsiElement>()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -310,8 +310,7 @@ class FirElementSerializer private constructor(
|
||||
simpleFunction?.isTailRec == true,
|
||||
simpleFunction?.isExternal == true,
|
||||
simpleFunction?.isSuspend == true,
|
||||
simpleFunction?.isExpect == true,
|
||||
true // TODO: supply 'hasStableParameterNames' flag for metadata
|
||||
simpleFunction?.isExpect == true
|
||||
)
|
||||
if (flags != builder.flags) {
|
||||
builder.flags = flags
|
||||
@@ -440,8 +439,7 @@ class FirElementSerializer private constructor(
|
||||
val flags = Flags.getConstructorFlags(
|
||||
constructor.nonSourceAnnotations(session).isNotEmpty(),
|
||||
ProtoEnumFlags.visibility(normalizeVisibility(constructor)),
|
||||
!constructor.isPrimary,
|
||||
true // TODO: supply 'hasStableParameterNames' flag for metadata
|
||||
!constructor.isPrimary
|
||||
)
|
||||
if (flags != builder.flags) {
|
||||
builder.flags = flags
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassPublicSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
@@ -459,7 +461,7 @@ internal fun IrDeclarationParent.declareThisReceiverParameter(
|
||||
return symbolTable.declareValueParameter(
|
||||
startOffset, endOffset, thisOrigin, receiverDescriptor, thisType
|
||||
) { symbol ->
|
||||
symbolTable.irFactory.createValueParameter(
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, thisOrigin, symbol,
|
||||
Name.special("<this>"), -1, thisType,
|
||||
varargElementType = null, isCrossinline = false, isNoinline = false
|
||||
|
||||
@@ -22,11 +22,16 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrEnumEntryImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeAliasImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedEnumEntryDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedTypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedTypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrEnumConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol
|
||||
@@ -190,7 +195,7 @@ class Fir2IrClassifierStorage(
|
||||
preCacheTypeParameters(typeAlias)
|
||||
return typeAlias.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrTypeAlias(signature) { symbol ->
|
||||
val irTypeAlias = irFactory.createTypeAlias(
|
||||
val irTypeAlias = IrTypeAliasImpl(
|
||||
startOffset, endOffset, symbol,
|
||||
typeAlias.name, typeAlias.visibility,
|
||||
typeAlias.expandedTypeRef.toIrType(),
|
||||
@@ -227,10 +232,10 @@ class Fir2IrClassifierStorage(
|
||||
} else {
|
||||
regularClass.modality ?: Modality.FINAL
|
||||
}
|
||||
val signature = if (regularClass.isLocal) null else signatureComposer.composeSignature(regularClass)
|
||||
val signature = signatureComposer.composeSignature(regularClass)
|
||||
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrClass(signature) { symbol ->
|
||||
irFactory.createClass(
|
||||
IrClassImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
origin,
|
||||
@@ -270,10 +275,10 @@ class Fir2IrClassifierStorage(
|
||||
): IrClass {
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val modality = Modality.FINAL
|
||||
val signature = null
|
||||
val signature = signatureComposer.composeSignature(anonymousObject)
|
||||
val result = anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrClass(signature) { symbol ->
|
||||
irFactory.createClass(
|
||||
IrClassImpl(
|
||||
startOffset, endOffset, origin, symbol, name,
|
||||
// NB: for unknown reason, IR uses 'CLASS' kind for simple anonymous objects
|
||||
anonymousObject.classKind.takeIf { it == ClassKind.ENUM_ENTRY } ?: ClassKind.CLASS,
|
||||
@@ -307,7 +312,7 @@ class Fir2IrClassifierStorage(
|
||||
val irTypeParameter = with(typeParameter) {
|
||||
convertWithOffsets { startOffset, endOffset ->
|
||||
symbolTable.declareGlobalTypeParameter(startOffset, endOffset, origin, descriptor) { symbol ->
|
||||
irFactory.createTypeParameter(
|
||||
IrTypeParameterImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
name, if (index < 0) 0 else index,
|
||||
isReified,
|
||||
@@ -388,7 +393,7 @@ class Fir2IrClassifierStorage(
|
||||
return enumEntry.convertWithOffsets { startOffset, endOffset ->
|
||||
val signature = signatureComposer.composeSignature(enumEntry)
|
||||
val result = declareIrEnumEntry(signature) { symbol ->
|
||||
irFactory.createEnumEntry(
|
||||
IrEnumEntryImpl(
|
||||
startOffset, endOffset, origin, symbol, enumEntry.name
|
||||
).apply {
|
||||
declarationStorage.enterScope(this)
|
||||
@@ -407,7 +412,7 @@ class Fir2IrClassifierStorage(
|
||||
// which will be translated via visitor later.
|
||||
} else if (irParent != null && origin == IrDeclarationOrigin.DEFINED) {
|
||||
val constructor = irParent.constructors.first()
|
||||
this.initializerExpression = factory.createExpressionBody(
|
||||
this.initializerExpression = IrExpressionBodyImpl(
|
||||
IrEnumConstructorCallImpl(
|
||||
startOffset, endOffset, irType, constructor.symbol,
|
||||
valueArgumentsCount = constructor.valueParameters.size,
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
|
||||
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
|
||||
@@ -18,11 +17,10 @@ interface Fir2IrComponents {
|
||||
val scopeSession: ScopeSession
|
||||
val symbolTable: SymbolTable
|
||||
val irBuiltIns: IrBuiltIns
|
||||
val irFactory: IrFactory
|
||||
val classifierStorage: Fir2IrClassifierStorage
|
||||
val declarationStorage: Fir2IrDeclarationStorage
|
||||
val typeConverter: Fir2IrTypeConverter
|
||||
val signatureComposer: Fir2IrSignatureComposer
|
||||
val callGenerator: CallAndReferenceGenerator
|
||||
val fakeOverrideGenerator: FakeOverrideGenerator
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer
|
||||
import org.jetbrains.kotlin.fir.signaturer.FirMangler
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
|
||||
@@ -20,7 +19,6 @@ class Fir2IrComponentsStorage(
|
||||
override val scopeSession: ScopeSession,
|
||||
override val symbolTable: SymbolTable,
|
||||
override val irBuiltIns: IrBuiltIns,
|
||||
override val irFactory: IrFactory,
|
||||
mangler: FirMangler
|
||||
) : Fir2IrComponents {
|
||||
override lateinit var classifierStorage: Fir2IrClassifierStorage
|
||||
@@ -30,4 +28,4 @@ class Fir2IrComponentsStorage(
|
||||
override lateinit var fakeOverrideGenerator: FakeOverrideGenerator
|
||||
|
||||
override val signatureComposer = FirBasedSignatureComposer(mangler)
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,10 @@ package org.jetbrains.kotlin.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.backend.evaluate.evaluateConstants
|
||||
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator
|
||||
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
|
||||
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
|
||||
import org.jetbrains.kotlin.fir.backend.evaluate.evaluateConstants
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
@@ -85,9 +85,7 @@ class Fir2IrConverter(
|
||||
irClass: IrClass = classifierStorage.getCachedIrClass(anonymousObject)!!
|
||||
): IrClass {
|
||||
anonymousObject.getPrimaryConstructorIfAny()?.let {
|
||||
irClass.declarations += declarationStorage.createIrConstructor(
|
||||
it, irClass, isLocal = true
|
||||
)
|
||||
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
|
||||
}
|
||||
for (declaration in sortBySynthetic(anonymousObject.declarations)) {
|
||||
if (declaration is FirRegularClass) {
|
||||
@@ -112,9 +110,7 @@ class Fir2IrConverter(
|
||||
irClass: IrClass = classifierStorage.getCachedIrClass(regularClass)!!
|
||||
): IrClass {
|
||||
regularClass.getPrimaryConstructorIfAny()?.let {
|
||||
irClass.declarations += declarationStorage.createIrConstructor(
|
||||
it, irClass, isLocal = regularClass.isLocal
|
||||
)
|
||||
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
|
||||
}
|
||||
for (declaration in sortBySynthetic(regularClass.declarations)) {
|
||||
val irDeclaration = processMemberDeclaration(declaration, regularClass, irClass) ?: continue
|
||||
@@ -147,21 +143,15 @@ class Fir2IrConverter(
|
||||
containingClass: FirClass<*>?,
|
||||
parent: IrDeclarationParent
|
||||
): IrDeclaration? {
|
||||
val isLocal = containingClass != null &&
|
||||
(containingClass !is FirRegularClass || containingClass.isLocal)
|
||||
return when (declaration) {
|
||||
is FirRegularClass -> {
|
||||
processClassMembers(declaration)
|
||||
}
|
||||
is FirSimpleFunction -> {
|
||||
declarationStorage.createIrFunction(
|
||||
declaration, parent, isLocal = isLocal
|
||||
)
|
||||
declarationStorage.createIrFunction(declaration, parent)
|
||||
}
|
||||
is FirProperty -> {
|
||||
declarationStorage.createIrProperty(
|
||||
declaration, parent, isLocal = isLocal
|
||||
)
|
||||
declarationStorage.createIrProperty(declaration, parent)
|
||||
}
|
||||
is FirField -> {
|
||||
if (declaration.isSynthetic) {
|
||||
@@ -171,9 +161,7 @@ class Fir2IrConverter(
|
||||
}
|
||||
}
|
||||
is FirConstructor -> if (!declaration.isPrimary) {
|
||||
declarationStorage.createIrConstructor(
|
||||
declaration, parent as IrClass, isLocal = isLocal
|
||||
)
|
||||
declarationStorage.createIrConstructor(declaration, parent as IrClass)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -199,13 +187,13 @@ class Fir2IrConverter(
|
||||
scopeSession: ScopeSession,
|
||||
firFiles: List<FirFile>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
fakeOverrideMode: FakeOverrideMode = FakeOverrideMode.NORMAL,
|
||||
signaturer: IdSignatureComposer,
|
||||
generatorExtensions: GeneratorExtensions,
|
||||
mangler: FirMangler,
|
||||
irFactory: IrFactory,
|
||||
mangler: FirMangler
|
||||
): Fir2IrResult {
|
||||
val moduleDescriptor = FirModuleDescriptor(session)
|
||||
val symbolTable = SymbolTable(signaturer, irFactory)
|
||||
val symbolTable = SymbolTable(signaturer)
|
||||
val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
|
||||
val typeTranslator = TypeTranslator(
|
||||
symbolTable,
|
||||
@@ -218,7 +206,7 @@ class Fir2IrConverter(
|
||||
val builtIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, symbolTable)
|
||||
FirBuiltinSymbols(builtIns, moduleDescriptor.builtIns, symbolTable)
|
||||
val sourceManager = PsiSourceManager()
|
||||
val components = Fir2IrComponentsStorage(session, scopeSession, symbolTable, builtIns, irFactory, mangler)
|
||||
val components = Fir2IrComponentsStorage(session, scopeSession, symbolTable, builtIns, mangler)
|
||||
val conversionScope = Fir2IrConversionScope()
|
||||
val classifierStorage = Fir2IrClassifierStorage(components)
|
||||
val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor)
|
||||
@@ -247,17 +235,17 @@ class Fir2IrConverter(
|
||||
converter.processClassHeaders(firFile)
|
||||
}
|
||||
val fakeOverrideGenerator = FakeOverrideGenerator(
|
||||
session, scopeSession, classifierStorage, declarationStorage, conversionScope, FakeOverrideMode.NORMAL
|
||||
session, scopeSession, classifierStorage, declarationStorage, conversionScope, fakeOverrideMode
|
||||
)
|
||||
components.fakeOverrideGenerator = fakeOverrideGenerator
|
||||
val fir2irVisitor = Fir2IrVisitor(converter, components, conversionScope)
|
||||
val callGenerator = CallAndReferenceGenerator(components, fir2irVisitor, conversionScope)
|
||||
components.callGenerator = callGenerator
|
||||
declarationStorage.annotationGenerator = AnnotationGenerator(components)
|
||||
for (firFile in firFiles) {
|
||||
converter.processFileAndClassMembers(firFile)
|
||||
}
|
||||
|
||||
val fir2irVisitor = Fir2IrVisitor(converter, components, conversionScope)
|
||||
val callGenerator = CallAndReferenceGenerator(components, fir2irVisitor, conversionScope)
|
||||
components.callGenerator = callGenerator
|
||||
declarationStorage.annotationGenerator = AnnotationGenerator(components)
|
||||
for (firFile in firFiles) {
|
||||
val irFile = firFile.accept(fir2irVisitor, null) as IrFile
|
||||
val fileEntry = sourceManager.getOrCreateFileEntry(firFile.psi as KtFile)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAMES
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
@@ -26,27 +26,20 @@ import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -245,7 +238,7 @@ class Fir2IrDeclarationStorage(
|
||||
symbolTable.declareValueParameter(
|
||||
startOffset, endOffset, origin, descriptor, type
|
||||
) { symbol ->
|
||||
irFactory.createValueParameter(
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, IrDeclarationOrigin.DEFINED, symbol,
|
||||
Name.special("<set-?>"), 0, type,
|
||||
varargElementType = null,
|
||||
@@ -306,9 +299,7 @@ class Fir2IrDeclarationStorage(
|
||||
)
|
||||
}
|
||||
}
|
||||
// See [LocalDeclarationsLowering]: "local function must not have dispatch receiver."
|
||||
val isLocal = function is FirSimpleFunction && function.isLocal
|
||||
if (function !is FirAnonymousFunction && containingClass != null && !isStatic && !isLocal) {
|
||||
if (function !is FirAnonymousFunction && containingClass != null && !isStatic) {
|
||||
dispatchReceiverParameter = declareThisReceiverParameter(
|
||||
symbolTable,
|
||||
thisType = containingClass.thisReceiver?.type ?: error("No this receiver"),
|
||||
@@ -376,8 +367,7 @@ class Fir2IrDeclarationStorage(
|
||||
function: FirFunction<*>,
|
||||
irParent: IrDeclarationParent?,
|
||||
thisReceiverOwner: IrClass? = irParent as? IrClass,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
|
||||
isLocal: Boolean = false
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrSimpleFunction {
|
||||
val simpleFunction = function as? FirSimpleFunction
|
||||
val isLambda = function.source?.elementType == KtNodeTypes.FUNCTION_LITERAL
|
||||
@@ -394,10 +384,10 @@ class Fir2IrDeclarationStorage(
|
||||
val isSuspend =
|
||||
if (isLambda) ((function as FirAnonymousFunction).typeRef as? FirResolvedTypeRef)?.isSuspend == true
|
||||
else simpleFunction?.isSuspend == true
|
||||
val signature = if (isLocal) null else signatureComposer.composeSignature(function)
|
||||
val signature = signatureComposer.composeSignature(function)
|
||||
val created = function.convertWithOffsets { startOffset, endOffset ->
|
||||
val result = declareIrSimpleFunction(signature, simpleFunction?.containerSource) { symbol ->
|
||||
irFactory.createFunction(
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset, updatedOrigin, symbol,
|
||||
name, visibility,
|
||||
simpleFunction?.modality ?: Modality.FINAL,
|
||||
@@ -465,15 +455,14 @@ class Fir2IrDeclarationStorage(
|
||||
fun createIrConstructor(
|
||||
constructor: FirConstructor,
|
||||
irParent: IrClass,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
|
||||
isLocal: Boolean = false
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrConstructor {
|
||||
val isPrimary = constructor.isPrimary
|
||||
classifierStorage.preCacheTypeParameters(constructor)
|
||||
val signature = if (isLocal) null else signatureComposer.composeSignature(constructor)
|
||||
val signature = signatureComposer.composeSignature(constructor)
|
||||
val created = constructor.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrConstructor(signature) { symbol ->
|
||||
irFactory.createConstructor(
|
||||
IrConstructorImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
Name.special("<init>"), constructor.visibility,
|
||||
constructor.returnTypeRef.toIrType(),
|
||||
@@ -515,18 +504,17 @@ class Fir2IrDeclarationStorage(
|
||||
isSetter: Boolean,
|
||||
origin: IrDeclarationOrigin,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
isLocal: Boolean = false
|
||||
endOffset: Int
|
||||
): IrSimpleFunction {
|
||||
val prefix = if (isSetter) "set" else "get"
|
||||
val signature = if (isLocal) null else signatureComposer.composeAccessorSignature(property, isSetter)
|
||||
val signature = signatureComposer.composeAccessorSignature(property, isSetter)
|
||||
return declareIrAccessor(
|
||||
signature,
|
||||
(correspondingProperty.descriptor as? WrappedPropertyDescriptorWithContainerSource)?.containerSource,
|
||||
isGetter = !isSetter
|
||||
) { symbol ->
|
||||
val accessorReturnType = if (isSetter) irBuiltIns.unitType else propertyType
|
||||
irFactory.createFunction(
|
||||
IrFunctionImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
Name.special("<$prefix-${correspondingProperty.name}>"),
|
||||
propertyAccessor?.visibility ?: correspondingProperty.visibility,
|
||||
@@ -586,7 +574,7 @@ class Fir2IrDeclarationStorage(
|
||||
return symbolTable.declareField(
|
||||
startOffset, endOffset, origin, descriptor, inferredType
|
||||
) { symbol ->
|
||||
irFactory.createField(
|
||||
IrFieldImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
name, inferredType,
|
||||
visibility, isFinal = isFinal,
|
||||
@@ -629,14 +617,13 @@ class Fir2IrDeclarationStorage(
|
||||
property: FirProperty,
|
||||
irParent: IrDeclarationParent?,
|
||||
thisReceiverOwner: IrClass? = irParent as? IrClass,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
|
||||
isLocal: Boolean = false
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||
): IrProperty {
|
||||
classifierStorage.preCacheTypeParameters(property)
|
||||
val signature = if (isLocal) null else signatureComposer.composeSignature(property)
|
||||
val signature = signatureComposer.composeSignature(property)
|
||||
return property.convertWithOffsets { startOffset, endOffset ->
|
||||
val result = declareIrProperty(signature, property.containerSource) { symbol ->
|
||||
irFactory.createProperty(
|
||||
IrPropertyImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
property.name, property.visibility, property.modality!!,
|
||||
isVar = property.isVar,
|
||||
@@ -671,7 +658,7 @@ class Fir2IrDeclarationStorage(
|
||||
if (initializer is FirConstExpression<*>) {
|
||||
// TODO: Normally we shouldn't have error type here
|
||||
val constType = initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type
|
||||
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
|
||||
field.initializer = IrExpressionBodyImpl(initializer.toIrConst(constType))
|
||||
}
|
||||
}
|
||||
} else if (delegate != null) {
|
||||
@@ -693,7 +680,7 @@ class Fir2IrDeclarationStorage(
|
||||
getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||
else -> origin
|
||||
},
|
||||
startOffset, endOffset, isLocal
|
||||
startOffset, endOffset
|
||||
)
|
||||
if (property.isVar) {
|
||||
this.setter = createIrPropertyAccessor(
|
||||
@@ -703,7 +690,7 @@ class Fir2IrDeclarationStorage(
|
||||
setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||
else -> origin
|
||||
},
|
||||
startOffset, endOffset, isLocal
|
||||
startOffset, endOffset
|
||||
)
|
||||
}
|
||||
leaveScope(this)
|
||||
@@ -755,7 +742,7 @@ class Fir2IrDeclarationStorage(
|
||||
startOffset, endOffset,
|
||||
origin, descriptor, type
|
||||
) { symbol ->
|
||||
irFactory.createField(
|
||||
IrFieldImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
field.name, type, field.visibility,
|
||||
isFinal = field.modality == Modality.FINAL,
|
||||
@@ -783,7 +770,7 @@ class Fir2IrDeclarationStorage(
|
||||
symbolTable.declareValueParameter(
|
||||
startOffset, endOffset, origin, descriptor, type
|
||||
) { symbol ->
|
||||
irFactory.createValueParameter(
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
valueParameter.name, index, type,
|
||||
if (!valueParameter.isVararg) null
|
||||
@@ -795,7 +782,7 @@ class Fir2IrDeclarationStorage(
|
||||
it != null && (useStubForDefaultValueStub || it !is FirExpressionStub)
|
||||
}
|
||||
) {
|
||||
this.defaultValue = factory.createExpressionBody(
|
||||
this.defaultValue = IrExpressionBodyImpl(
|
||||
IrErrorExpressionImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, type,
|
||||
"Stub expression for default value of ${valueParameter.name}"
|
||||
|
||||
@@ -127,7 +127,7 @@ class Fir2IrVisitor(
|
||||
memberGenerator.convertClassContent(correspondingClass, anonymousObject)
|
||||
}
|
||||
val constructor = correspondingClass.constructors.first()
|
||||
irEnumEntry.initializerExpression = irFactory.createExpressionBody(
|
||||
irEnumEntry.initializerExpression = IrExpressionBodyImpl(
|
||||
IrEnumConstructorCallImpl(
|
||||
startOffset, endOffset, enumEntry.returnTypeRef.toIrType(),
|
||||
constructor.symbol,
|
||||
@@ -144,9 +144,7 @@ class Fir2IrVisitor(
|
||||
val delegatedConstructor = primaryConstructor?.delegatedConstructor
|
||||
if (delegatedConstructor != null) {
|
||||
with(memberGenerator) {
|
||||
irEnumEntry.initializerExpression = irFactory.createExpressionBody(
|
||||
delegatedConstructor.toIrDelegatingConstructorCall()
|
||||
)
|
||||
irEnumEntry.initializerExpression = IrExpressionBodyImpl(delegatedConstructor.toIrDelegatingConstructorCall())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,7 +222,7 @@ class Fir2IrVisitor(
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): IrElement {
|
||||
val irFunction = if (simpleFunction.visibility == Visibilities.LOCAL) {
|
||||
declarationStorage.createIrFunction(
|
||||
simpleFunction, irParent = conversionScope.parent(), isLocal = true
|
||||
simpleFunction, irParent = conversionScope.parent()
|
||||
)
|
||||
} else {
|
||||
declarationStorage.getCachedIrFunction(simpleFunction)!!
|
||||
@@ -239,7 +237,7 @@ class Fir2IrVisitor(
|
||||
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Any?): IrElement {
|
||||
return anonymousFunction.convertWithOffsets { startOffset, endOffset ->
|
||||
val irFunction = declarationStorage.createIrFunction(
|
||||
anonymousFunction, irParent = conversionScope.parent(), isLocal = true
|
||||
anonymousFunction, irParent = conversionScope.parent()
|
||||
)
|
||||
conversionScope.withFunction(irFunction) {
|
||||
memberGenerator.convertFunctionContent(irFunction, anonymousFunction, containingClass = null)
|
||||
@@ -318,20 +316,16 @@ class Fir2IrVisitor(
|
||||
)
|
||||
} else convertToIrExpression(this)
|
||||
|
||||
private fun convertToIrCall(functionCall: FirFunctionCall, annotationMode: Boolean): IrExpression {
|
||||
val explicitReceiverExpression = convertToIrReceiverExpression(
|
||||
functionCall.explicitReceiver, functionCall.calleeReference
|
||||
)
|
||||
return callGenerator.convertToIrCall(functionCall, functionCall.typeRef, explicitReceiverExpression, annotationMode)
|
||||
}
|
||||
|
||||
override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrExpression {
|
||||
val convertibleCall = if (functionCall.toResolvedCallableSymbol()?.fir is FirIntegerOperator) {
|
||||
functionCall.copy().transformSingle(integerApproximator, null)
|
||||
} else {
|
||||
functionCall
|
||||
}
|
||||
return convertToIrCall(functionCall = convertibleCall, annotationMode = false)
|
||||
val explicitReceiverExpression = convertToIrReceiverExpression(
|
||||
functionCall.explicitReceiver, functionCall.calleeReference
|
||||
)
|
||||
return callGenerator.convertToIrCall(convertibleCall, convertibleCall.typeRef, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Any?): IrElement {
|
||||
@@ -519,7 +513,7 @@ class Fir2IrVisitor(
|
||||
return accept(this@Fir2IrVisitor, null) as IrStatement
|
||||
}
|
||||
|
||||
internal fun convertToIrExpression(expression: FirExpression, annotationMode: Boolean = false): IrExpression {
|
||||
internal fun convertToIrExpression(expression: FirExpression): IrExpression {
|
||||
return when (expression) {
|
||||
is FirBlock -> expression.convertToIrExpressionOrBlock()
|
||||
is FirUnitExpression -> expression.convertWithOffsets { startOffset, endOffset ->
|
||||
@@ -528,18 +522,7 @@ class Fir2IrVisitor(
|
||||
this.symbolTable.referenceClass(this.irBuiltIns.builtIns.unit)
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
val unwrappedExpression = if (expression is FirWrappedArgumentExpression) {
|
||||
expression.expression
|
||||
} else {
|
||||
expression
|
||||
}
|
||||
if (annotationMode && unwrappedExpression is FirFunctionCall) {
|
||||
convertToIrCall(unwrappedExpression, annotationMode)
|
||||
} else {
|
||||
expression.accept(this, null) as IrExpression
|
||||
}
|
||||
}
|
||||
else -> expression.accept(this, null) as IrExpression
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,7 +565,7 @@ class Fir2IrVisitor(
|
||||
internal fun convertToIrBlockBody(block: FirBlock): IrBlockBody {
|
||||
return block.convertWithOffsets { startOffset, endOffset ->
|
||||
val irStatements = block.mapToIrStatements()
|
||||
irFactory.createBlockBody(
|
||||
IrBlockBodyImpl(
|
||||
startOffset, endOffset,
|
||||
if (irStatements.isNotEmpty()) {
|
||||
irStatements.filterNotNull().takeIf { it.isNotEmpty() }
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.backend.generators
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
@@ -21,28 +18,21 @@ import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.isFunctional
|
||||
import org.jetbrains.kotlin.fir.resolve.getCorrespondingConstructorReferenceOrNull
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.toArrayOrPrimitiveArrayType
|
||||
import org.jetbrains.kotlin.ir.types.typeOrNull
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
||||
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
|
||||
|
||||
@@ -96,18 +86,12 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
is IrFunctionSymbol -> {
|
||||
val function = symbol.owner
|
||||
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
||||
if (requiresSuspendConversion(type, function)) {
|
||||
val adaptedType = callableReferenceAccess.typeRef.coneType.kFunctionTypeToFunctionType()
|
||||
generateAdaptedCallableReference(callableReferenceAccess, symbol, adaptedType)
|
||||
} else {
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset, endOffset, type, symbol,
|
||||
typeArgumentsCount = function.typeParameters.size,
|
||||
valueArgumentsCount = function.valueParameters.size,
|
||||
reflectionTarget = symbol
|
||||
)
|
||||
}
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset, endOffset, type, symbol,
|
||||
typeArgumentsCount = function.typeParameters.size,
|
||||
valueArgumentsCount = function.valueParameters.size,
|
||||
reflectionTarget = symbol
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
IrErrorCallExpressionImpl(
|
||||
@@ -118,156 +102,6 @@ class CallAndReferenceGenerator(
|
||||
}.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
private fun requiresSuspendConversion(type: IrType, function: IrFunction): Boolean =
|
||||
type.isKSuspendFunction() && !function.isSuspend
|
||||
|
||||
private fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType {
|
||||
val kind =
|
||||
if (isSuspendFunctionType(session)) FunctionClassDescriptor.Kind.SuspendFunction
|
||||
else FunctionClassDescriptor.Kind.Function
|
||||
val functionalTypeId = ClassId(kind.packageFqName, kind.numberedClassName(typeArguments.size - 1))
|
||||
val coneType = ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(functionalTypeId), typeArguments, isNullable = false)
|
||||
return coneType.toIrType() as IrSimpleType
|
||||
}
|
||||
|
||||
private fun generateAdaptedCallableReference(
|
||||
callableReferenceAccess: FirCallableReferenceAccess,
|
||||
adapteeSymbol: IrFunctionSymbol,
|
||||
type: IrSimpleType
|
||||
): IrExpression {
|
||||
val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirSimpleFunction
|
||||
val adaptee = adapteeSymbol.owner
|
||||
// TODO: handle bound receiver, e.g., c::foo
|
||||
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
|
||||
val irAdapterFunction = createAdapterFunctionForSuspendConversion(startOffset, endOffset, firAdaptee!!, adaptee, type)
|
||||
val irCall = createAdapteeCall(callableReferenceAccess, adapteeSymbol, irAdapterFunction)
|
||||
irAdapterFunction.body = irFactory.createBlockBody(startOffset, endOffset) {
|
||||
if (firAdaptee.returnTypeRef.isUnit) {
|
||||
statements.add(irCall)
|
||||
} else {
|
||||
statements.add(IrReturnImpl(startOffset, endOffset, irBuiltIns.nothingType, irAdapterFunction.symbol, irCall))
|
||||
}
|
||||
}
|
||||
|
||||
IrFunctionExpressionImpl(startOffset, endOffset, type, irAdapterFunction, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAdapterFunctionForSuspendConversion(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
firAdaptee: FirSimpleFunction,
|
||||
adaptee: IrFunction,
|
||||
type: IrSimpleType,
|
||||
): IrSimpleFunction {
|
||||
val returnType = type.arguments.last().typeOrNull!!
|
||||
val parameterTypes = type.arguments.dropLast(1).map { it.typeOrNull!! }
|
||||
val adapterFunctionDescriptor = WrappedSimpleFunctionDescriptor()
|
||||
return symbolTable.declareSimpleFunction(adapterFunctionDescriptor) { irAdapterSymbol ->
|
||||
irFactory.createFunction(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE,
|
||||
irAdapterSymbol,
|
||||
adaptee.name,
|
||||
Visibilities.LOCAL,
|
||||
Modality.FINAL,
|
||||
returnType,
|
||||
isInline = firAdaptee.isInline,
|
||||
isExternal = firAdaptee.isExternal,
|
||||
isTailrec = firAdaptee.isTailRec,
|
||||
isSuspend = true,
|
||||
isOperator = firAdaptee.isOperator,
|
||||
isInfix = firAdaptee.isInfix,
|
||||
isExpect = firAdaptee.isExpect,
|
||||
isFakeOverride = false
|
||||
).also { irAdapterFunction ->
|
||||
adapterFunctionDescriptor.bind(irAdapterFunction)
|
||||
irAdapterFunction.metadata = FirMetadataSource.Function(firAdaptee)
|
||||
symbolTable.enterScope(irAdapterFunction)
|
||||
irAdapterFunction.valueParameters += parameterTypes.mapIndexed { index, parameterType ->
|
||||
createAdapterParameter(irAdapterFunction, Name.identifier("p$index"), index, parameterType)
|
||||
}
|
||||
symbolTable.leaveScope(irAdapterFunction)
|
||||
irAdapterFunction.parent = conversionScope.parent()!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAdapterParameter(
|
||||
adapterFunction: IrFunction,
|
||||
name: Name,
|
||||
index: Int,
|
||||
type: IrType
|
||||
): IrValueParameter {
|
||||
val startOffset = adapterFunction.startOffset
|
||||
val endOffset = adapterFunction.endOffset
|
||||
val descriptor = WrappedValueParameterDescriptor()
|
||||
return symbolTable.declareValueParameter(
|
||||
startOffset, endOffset, IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE, descriptor, type
|
||||
) { irAdapterParameterSymbol ->
|
||||
irFactory.createValueParameter(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE,
|
||||
irAdapterParameterSymbol,
|
||||
name,
|
||||
index,
|
||||
type,
|
||||
varargElementType = null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
).also { irAdapterValueParameter ->
|
||||
descriptor.bind(irAdapterValueParameter)
|
||||
irAdapterValueParameter.parent = adapterFunction
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAdapteeCall(
|
||||
callableReferenceAccess: FirCallableReferenceAccess,
|
||||
adapteeSymbol: IrFunctionSymbol,
|
||||
adapterFunction: IrFunction
|
||||
): IrExpression {
|
||||
val adapteeFunction = adapteeSymbol.owner
|
||||
val startOffset = adapteeFunction.startOffset
|
||||
val endOffset = adapteeFunction.endOffset
|
||||
val type = adapteeFunction.returnType
|
||||
val irCall =
|
||||
if (adapteeSymbol is IrConstructorSymbol) {
|
||||
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, adapteeSymbol)
|
||||
} else {
|
||||
IrCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
type,
|
||||
adapteeSymbol,
|
||||
callableReferenceAccess.typeArguments.size,
|
||||
adapteeFunction.valueParameters.size,
|
||||
origin = null,
|
||||
superQualifierSymbol = null
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: handle non-transient, bound dispatch/extension receiver
|
||||
|
||||
adapteeFunction.valueParameters.mapIndexed { index, valueParameter ->
|
||||
when {
|
||||
valueParameter.hasDefaultValue() -> {
|
||||
irCall.putValueArgument(index, null)
|
||||
}
|
||||
valueParameter.isVararg -> {
|
||||
// TODO: handle vararg and spread
|
||||
irCall.putValueArgument(index, null)
|
||||
}
|
||||
else -> {
|
||||
val irValueArgument = adapterFunction.valueParameters[index]
|
||||
irCall.putValueArgument(index, IrGetValueImpl(startOffset, endOffset, irValueArgument.type, irValueArgument.symbol))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return irCall.applyTypeArguments(callableReferenceAccess)
|
||||
}
|
||||
|
||||
private fun FirQualifiedAccess.tryConvertToSamConstructorCall(type: IrType): IrTypeOperatorCall? {
|
||||
val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null
|
||||
val fir = calleeReference.resolvedSymbol.fir
|
||||
@@ -284,8 +118,7 @@ class CallAndReferenceGenerator(
|
||||
fun convertToIrCall(
|
||||
qualifiedAccess: FirQualifiedAccess,
|
||||
typeRef: FirTypeRef,
|
||||
explicitReceiverExpression: IrExpression?,
|
||||
annotationMode: Boolean = false
|
||||
explicitReceiverExpression: IrExpression?
|
||||
): IrExpression {
|
||||
val type = typeRef.toIrType()
|
||||
val samConstructorCall = qualifiedAccess.tryConvertToSamConstructorCall(type)
|
||||
@@ -367,7 +200,7 @@ class CallAndReferenceGenerator(
|
||||
is IrEnumEntrySymbol -> IrGetEnumValueImpl(startOffset, endOffset, type, symbol)
|
||||
else -> generateErrorCallExpression(startOffset, endOffset, qualifiedAccess.calleeReference, type)
|
||||
}
|
||||
}.applyCallArguments(qualifiedAccess as? FirCall, annotationMode)
|
||||
}.applyCallArguments(qualifiedAccess as? FirCall)
|
||||
.applyTypeArguments(qualifiedAccess).applyReceivers(qualifiedAccess, explicitReceiverExpression)
|
||||
}
|
||||
|
||||
@@ -452,7 +285,7 @@ class CallAndReferenceGenerator(
|
||||
)
|
||||
}
|
||||
}
|
||||
}.applyCallArguments(annotationCall, annotationMode = true)
|
||||
}.applyCallArguments(annotationCall)
|
||||
}
|
||||
|
||||
fun convertToGetObject(qualifier: FirResolvedQualifier): IrExpression {
|
||||
@@ -482,7 +315,7 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrExpression.applyCallArguments(call: FirCall?, annotationMode: Boolean): IrExpression {
|
||||
internal fun IrExpression.applyCallArguments(call: FirCall?): IrExpression {
|
||||
if (call == null) return this
|
||||
return when (this) {
|
||||
is IrMemberAccessExpression<*> -> {
|
||||
@@ -500,7 +333,7 @@ class CallAndReferenceGenerator(
|
||||
val argumentMapping = call.argumentMapping
|
||||
if (argumentMapping != null && argumentMapping.isNotEmpty()) {
|
||||
if (valueParameters != null) {
|
||||
return applyArgumentsWithReorderingIfNeeded(call, argumentMapping, valueParameters, annotationMode)
|
||||
return applyArgumentsWithReorderingIfNeeded(call, argumentMapping, valueParameters)
|
||||
}
|
||||
}
|
||||
for ((index, argument) in call.arguments.withIndex()) {
|
||||
@@ -534,11 +367,10 @@ class CallAndReferenceGenerator(
|
||||
call: FirCall,
|
||||
argumentMapping: Map<FirExpression, FirValueParameter>,
|
||||
valueParameters: List<FirValueParameter>,
|
||||
annotationMode: Boolean
|
||||
): IrExpression {
|
||||
// Assuming compile-time constants only inside annotation, we don't need a block to reorder arguments to preserve semantics.
|
||||
// But, we still need to pick correct indices for named arguments.
|
||||
if (!annotationMode &&
|
||||
if (call !is FirAnnotationCall &&
|
||||
needArgumentReordering(argumentMapping.values, valueParameters)
|
||||
) {
|
||||
return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply {
|
||||
@@ -559,21 +391,9 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
} else {
|
||||
for ((argument, parameter) in argumentMapping) {
|
||||
val argumentExpression =
|
||||
visitor.convertToIrExpression(argument, annotationMode)
|
||||
.applySamConversionIfNeeded(argument, parameter)
|
||||
val argumentExpression = visitor.convertToIrExpression(argument).applySamConversionIfNeeded(argument, parameter)
|
||||
putValueArgument(valueParameters.indexOf(parameter), argumentExpression)
|
||||
}
|
||||
if (annotationMode) {
|
||||
for ((index, parameter) in valueParameters.withIndex()) {
|
||||
if (parameter.isVararg && !argumentMapping.containsValue(parameter)) {
|
||||
val elementType = parameter.returnTypeRef.toIrType()
|
||||
putValueArgument(
|
||||
index, IrVarargImpl(-1, -1, elementType, elementType.toArrayOrPrimitiveArrayType(irBuiltIns))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +27,7 @@ import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.constructedClassType
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
import org.jetbrains.kotlin.ir.util.isSetter
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
|
||||
internal class ClassMemberGenerator(
|
||||
private val components: Fir2IrComponents,
|
||||
@@ -127,7 +124,7 @@ internal class ClassMemberGenerator(
|
||||
annotationGenerator.generate(irFunction, firFunction)
|
||||
}
|
||||
if (firFunction is FirConstructor && irFunction is IrConstructor && !parentAsClass.isAnnotationClass && !firFunction.isExpect) {
|
||||
val body = factory.createBlockBody(startOffset, endOffset)
|
||||
val body = IrBlockBodyImpl(startOffset, endOffset)
|
||||
val delegatedConstructor = firFunction.delegatedConstructor
|
||||
if (delegatedConstructor != null) {
|
||||
val irDelegatingConstructorCall = delegatedConstructor.toIrDelegatingConstructorCall()
|
||||
@@ -224,7 +221,7 @@ internal class ClassMemberGenerator(
|
||||
declarationStorage.enterScope(this@initializeBackingField)
|
||||
// NB: initializer can be already converted
|
||||
if (initializer == null && initializerExpression != null) {
|
||||
initializer = irFactory.createExpressionBody(visitor.convertToIrExpression(initializerExpression))
|
||||
initializer = IrExpressionBodyImpl(visitor.convertToIrExpression(initializerExpression))
|
||||
}
|
||||
declarationStorage.leaveScope(this@initializeBackingField)
|
||||
}
|
||||
@@ -250,7 +247,7 @@ internal class ClassMemberGenerator(
|
||||
val fieldSymbol = backingField?.symbol
|
||||
val declaration = this
|
||||
if (fieldSymbol != null) {
|
||||
body = factory.createBlockBody(
|
||||
body = IrBlockBodyImpl(
|
||||
startOffset, endOffset,
|
||||
listOf(
|
||||
if (isSetter) {
|
||||
@@ -350,7 +347,7 @@ internal class ClassMemberGenerator(
|
||||
it.dispatchReceiver = visitor.convertToIrExpression(firDispatchReceiver)
|
||||
}
|
||||
with(callGenerator) {
|
||||
it.applyCallArguments(this@toIrDelegatingConstructorCall, annotationMode = false)
|
||||
it.applyCallArguments(this@toIrDelegatingConstructorCall)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -359,7 +356,7 @@ internal class ClassMemberGenerator(
|
||||
private fun IrValueParameter.setDefaultValue(firValueParameter: FirValueParameter) {
|
||||
val firDefaultValue = firValueParameter.defaultValue
|
||||
if (firDefaultValue != null) {
|
||||
this.defaultValue = factory.createExpressionBody(visitor.convertToIrExpression(firDefaultValue))
|
||||
this.defaultValue = IrExpressionBodyImpl(visitor.convertToIrExpression(firDefaultValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,15 @@
|
||||
package org.jetbrains.kotlin.fir.backend.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
||||
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||
@@ -19,16 +25,20 @@ import org.jetbrains.kotlin.fir.types.impl.FirImplicitBooleanTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitIntTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitStringTypeRef
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -233,12 +243,25 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
|
||||
)
|
||||
}
|
||||
}
|
||||
val signature = if (classId.isLocal) null else components.signatureComposer.composeSignature(firFunction)
|
||||
val signature = components.signatureComposer.composeSignature(firFunction)
|
||||
return components.declarationStorage.declareIrSimpleFunction(signature, null) { symbol ->
|
||||
components.irFactory.createFunction(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, symbol, name, Visibilities.PUBLIC, Modality.OPEN, returnType,
|
||||
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isExpect = false,
|
||||
isFakeOverride = false, isOperator = false, isInfix = false,
|
||||
IrFunctionImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
origin,
|
||||
symbol,
|
||||
name,
|
||||
Visibilities.PUBLIC,
|
||||
Modality.OPEN,
|
||||
returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
isExpect = false,
|
||||
isFakeOverride = false,
|
||||
isOperator = false,
|
||||
isInfix = false
|
||||
).apply {
|
||||
if (otherParameterNeeded) {
|
||||
val irValueParameter = createSyntheticIrParameter(
|
||||
@@ -265,11 +288,23 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
|
||||
private fun createSyntheticIrParameter(irFunction: IrFunction, name: Name, type: IrType, index: Int = 0): IrValueParameter {
|
||||
val descriptor = WrappedValueParameterDescriptor()
|
||||
return components.symbolTable.declareValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor, type
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
origin,
|
||||
descriptor,
|
||||
type
|
||||
) { symbol ->
|
||||
components.irFactory.createValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, symbol, name, index, type, null,
|
||||
isCrossinline = false, isNoinline = false
|
||||
IrValueParameterImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
origin,
|
||||
symbol,
|
||||
name,
|
||||
index,
|
||||
type,
|
||||
null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
)
|
||||
}.apply {
|
||||
parent = irFunction
|
||||
@@ -302,4 +337,4 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
|
||||
fun getComponentIndex(irFunction: IrFunction): Int? =
|
||||
irFunction.name.identifier.substring("component".length).toIntOrNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,14 +23,15 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedTypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
@@ -114,7 +115,7 @@ internal class DelegatedMemberGenerator(
|
||||
} == true
|
||||
lateinit var irTypeSubstitutor: IrTypeSubstitutor
|
||||
val delegateFunction = symbolTable.declareSimpleFunction(descriptor) { symbol ->
|
||||
irFactory.createFunction(
|
||||
IrFunctionImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
origin,
|
||||
@@ -145,7 +146,7 @@ internal class DelegatedMemberGenerator(
|
||||
typeParameters += symbolTable.declareScopedTypeParameter(
|
||||
startOffset, endOffset, origin, parameterDescriptor
|
||||
) { symbol ->
|
||||
irFactory.createTypeParameter(
|
||||
IrTypeParameterImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
origin,
|
||||
@@ -175,7 +176,7 @@ internal class DelegatedMemberGenerator(
|
||||
valueParameters += symbolTable.declareValueParameter(
|
||||
startOffset, endOffset, origin, parameterDescriptor, substedType
|
||||
) { symbol ->
|
||||
irFactory.createValueParameter(
|
||||
IrValueParameterImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
valueParameter.name, valueParameter.index, substedType,
|
||||
null, valueParameter.isCrossinline, valueParameter.isNoinline
|
||||
@@ -215,7 +216,7 @@ internal class DelegatedMemberGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
val body = irFactory.createBlockBody(startOffset, endOffset)
|
||||
val body = IrBlockBodyImpl(startOffset, endOffset)
|
||||
val irCall = IrCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
@@ -281,7 +282,7 @@ internal class DelegatedMemberGenerator(
|
||||
startOffset, endOffset,
|
||||
IrDeclarationOrigin.DELEGATED_MEMBER, descriptor, superProperty.isDelegated
|
||||
) { symbol ->
|
||||
irFactory.createProperty(
|
||||
IrPropertyImpl(
|
||||
startOffset, endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, symbol,
|
||||
superProperty.name, superProperty.visibility,
|
||||
modality,
|
||||
|
||||
@@ -67,7 +67,6 @@ class FakeOverrideGenerator(
|
||||
for (name in superTypesCallableNames) {
|
||||
if (name in processedCallableNames) continue
|
||||
processedCallableNames += name
|
||||
val isLocal = klass !is FirRegularClass || klass.isLocal
|
||||
useSiteMemberScope.processFunctionsByName(name) { functionSymbol ->
|
||||
if (functionSymbol is FirNamedFunctionSymbol) {
|
||||
val originalFunction = functionSymbol.fir
|
||||
@@ -92,8 +91,7 @@ class FakeOverrideGenerator(
|
||||
originalFunction,
|
||||
irParent = this,
|
||||
thisReceiverOwner = declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
||||
origin = origin,
|
||||
isLocal = isLocal
|
||||
origin = origin
|
||||
)
|
||||
// In fake overrides, parent logic is a bit specific, because
|
||||
// parent of *original* function (base class) is used for dispatch receiver,
|
||||
@@ -117,8 +115,7 @@ class FakeOverrideGenerator(
|
||||
fakeOverrideFunction,
|
||||
irParent = this,
|
||||
thisReceiverOwner = declarationStorage.findIrParent(originalFunction) as? IrClass,
|
||||
origin = origin,
|
||||
isLocal = isLocal
|
||||
origin = origin
|
||||
)
|
||||
if (irFunction.returnType.containsErrorType() || irFunction.valueParameters.any { it.type.containsErrorType() }) {
|
||||
return@processFunctionsByName
|
||||
@@ -145,8 +142,7 @@ class FakeOverrideGenerator(
|
||||
?: declarationStorage.createIrProperty(
|
||||
originalProperty, irParent = this,
|
||||
thisReceiverOwner = declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
||||
origin = origin,
|
||||
isLocal = isLocal
|
||||
origin = origin
|
||||
)
|
||||
irProperty.parent = this
|
||||
result += irProperty.withProperty {
|
||||
@@ -166,8 +162,7 @@ class FakeOverrideGenerator(
|
||||
val irProperty = declarationStorage.createIrProperty(
|
||||
fakeOverrideProperty, irParent = this,
|
||||
thisReceiverOwner = declarationStorage.findIrParent(originalProperty) as? IrClass,
|
||||
origin = origin,
|
||||
isLocal = isLocal
|
||||
origin = origin
|
||||
)
|
||||
if (irProperty.backingField?.type?.containsErrorType() == true ||
|
||||
irProperty.getter?.returnType?.containsErrorType() == true
|
||||
|
||||
@@ -25,9 +25,6 @@ abstract class AbstractFir2IrLazyDeclaration<F : FirMemberDeclaration, D : IrSym
|
||||
val fir: F,
|
||||
open val symbol: Fir2IrBindableSymbol<*, D>
|
||||
) : IrElementBase(startOffset, endOffset), IrDeclaration, IrDeclarationParent, Fir2IrComponents by components {
|
||||
override val factory: IrFactory
|
||||
get() = components.irFactory
|
||||
|
||||
internal fun prepareTypeParameters() {
|
||||
typeParameters = fir.typeParameters.mapIndexedNotNull { index, typeParameter ->
|
||||
if (typeParameter !is FirTypeParameter) return@mapIndexedNotNull null
|
||||
|
||||
@@ -14,13 +14,16 @@ import org.jetbrains.kotlin.fir.resolve.buildUseSiteMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.transform
|
||||
import org.jetbrains.kotlin.ir.util.transformIfNeeded
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class Fir2IrLazyClass(
|
||||
@@ -128,20 +131,12 @@ class Fir2IrLazyClass(
|
||||
is FirSimpleFunction -> {
|
||||
if (declaration.name !in processedNames) {
|
||||
processedNames += declaration.name
|
||||
if (fir.classKind == ClassKind.ENUM_CLASS && declaration.isStatic &&
|
||||
declaration.returnTypeRef is FirResolvedTypeRef
|
||||
) {
|
||||
// Handle values() / valueOf() separately
|
||||
// TODO: handle other static functions / properties properly
|
||||
result += declarationStorage.getIrFunctionSymbol(declaration.symbol).owner
|
||||
} else {
|
||||
scope.processFunctionsByName(declaration.name) {
|
||||
if (it is FirNamedFunctionSymbol && it.callableId.classId == fir.symbol.classId) {
|
||||
if (it.isAbstractMethodOfAny()) {
|
||||
return@processFunctionsByName
|
||||
}
|
||||
result += declarationStorage.getIrFunctionSymbol(it).owner
|
||||
scope.processFunctionsByName(declaration.name) {
|
||||
if (it is FirNamedFunctionSymbol && it.callableId.classId == fir.symbol.classId) {
|
||||
if (it.isAbstractMethodOfAny()) {
|
||||
return@processFunctionsByName
|
||||
}
|
||||
result += declarationStorage.getIrFunctionSymbol(it).owner
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,4 +183,19 @@ class Fir2IrLazyClass(
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitClass(this, data)
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
thisReceiver?.accept(visitor, data)
|
||||
typeParameters.forEach { it.accept(visitor, data) }
|
||||
declarations.forEach { it.accept(visitor, data) }
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
thisReceiver = thisReceiver?.transform(transformer, data)
|
||||
typeParameters = typeParameters.transformIfNeeded(transformer, data)
|
||||
declarations.transform { it.transform(transformer, data) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.ir.util.transformIfNeeded
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -112,4 +114,24 @@ class Fir2IrLazyConstructor(
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
return visitor.visitConstructor(this, data)
|
||||
}
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
typeParameters.forEach { it.accept(visitor, data) }
|
||||
|
||||
dispatchReceiverParameter?.accept(visitor, data)
|
||||
extensionReceiverParameter?.accept(visitor, data)
|
||||
valueParameters.forEach { it.accept(visitor, data) }
|
||||
|
||||
body?.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
typeParameters = typeParameters.transformIfNeeded(transformer, data)
|
||||
|
||||
dispatchReceiverParameter = dispatchReceiverParameter?.transform(transformer, data)
|
||||
extensionReceiverParameter = extensionReceiverParameter?.transform(transformer, data)
|
||||
valueParameters = valueParameters.transformIfNeeded(transformer, data)
|
||||
|
||||
body = body?.transform(transformer, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,12 @@ import org.jetbrains.kotlin.fir.symbols.Fir2IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class Fir2IrLazyProperty(
|
||||
@@ -100,7 +103,7 @@ class Fir2IrLazyProperty(
|
||||
if (initializer is FirConstExpression<*>) {
|
||||
// TODO: Normally we shouldn't have error type here
|
||||
val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type }
|
||||
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
|
||||
field.initializer = IrExpressionBodyImpl(initializer.toIrConst(constType))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,4 +153,20 @@ class Fir2IrLazyProperty(
|
||||
override var metadata: MetadataSource?
|
||||
get() = null
|
||||
set(_) = error("We should never need to store metadata of external declarations.")
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
return visitor.visitProperty(this, data)
|
||||
}
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
backingField?.accept(visitor, data)
|
||||
getter?.accept(visitor, data)
|
||||
setter?.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
backingField = backingField?.transform(transformer, data) as? IrField
|
||||
getter = getter?.run { transform(transformer, data) as IrSimpleFunction }
|
||||
setter = setter?.run { transform(transformer, data) as IrSimpleFunction }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.transformIfNeeded
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class Fir2IrLazySimpleFunction(
|
||||
@@ -138,4 +141,28 @@ class Fir2IrLazySimpleFunction(
|
||||
override var metadata: MetadataSource?
|
||||
get() = null
|
||||
set(_) = error("We should never need to store metadata of external declarations.")
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
return visitor.visitSimpleFunction(this, data)
|
||||
}
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
typeParameters.forEach { it.accept(visitor, data) }
|
||||
|
||||
dispatchReceiverParameter?.accept(visitor, data)
|
||||
extensionReceiverParameter?.accept(visitor, data)
|
||||
valueParameters.forEach { it.accept(visitor, data) }
|
||||
|
||||
body?.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
typeParameters = typeParameters.transformIfNeeded(transformer, data)
|
||||
|
||||
dispatchReceiverParameter = dispatchReceiverParameter?.transform(transformer, data)
|
||||
extensionReceiverParameter = extensionReceiverParameter?.transform(transformer, data)
|
||||
valueParameters = valueParameters.transformIfNeeded(transformer, data)
|
||||
|
||||
body = body?.transform(transformer, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,30 +63,30 @@ class FirBasedSignatureComposer(private val mangler: FirMangler) : Fir2IrSignatu
|
||||
|
||||
override fun composeSignature(declaration: FirDeclaration): IdSignature? {
|
||||
if (declaration is FirAnonymousObject || declaration is FirAnonymousFunction) return null
|
||||
val builder = SignatureBuilder()
|
||||
try {
|
||||
declaration.accept(builder)
|
||||
} catch (t: Throwable) {
|
||||
throw IllegalStateException("Error while composing signature for ${declaration.render()}", t)
|
||||
if (declaration is FirMemberDeclaration && declaration.effectiveVisibility == FirEffectiveVisibilityImpl.Local) {
|
||||
return null
|
||||
}
|
||||
return when (declaration) {
|
||||
is FirRegularClass -> {
|
||||
val builder = SignatureBuilder()
|
||||
declaration.accept(builder)
|
||||
return when {
|
||||
declaration is FirRegularClass && declaration.visibility != Visibilities.LOCAL -> {
|
||||
// TODO: private classes are probably not acceptable here too
|
||||
val classId = declaration.classId
|
||||
IdSignature.PublicSignature(
|
||||
classId.packageFqName.asString(), classId.relativeClassName.asString(), builder.hashId, builder.mask
|
||||
)
|
||||
}
|
||||
is FirTypeAlias -> {
|
||||
declaration is FirTypeAlias -> {
|
||||
if (declaration.visibility == Visibilities.PRIVATE) return null
|
||||
val classId = declaration.symbol.classId
|
||||
IdSignature.PublicSignature(
|
||||
classId.packageFqName.asString(), classId.relativeClassName.asString(), builder.hashId, builder.mask
|
||||
)
|
||||
}
|
||||
is FirCallableMemberDeclaration<*> -> {
|
||||
declaration is FirCallableMemberDeclaration<*> -> {
|
||||
if (declaration.visibility == Visibilities.PRIVATE) return null
|
||||
val callableId = declaration.symbol.callableId
|
||||
if (callableId.classId?.isLocal == true) return null
|
||||
IdSignature.PublicSignature(
|
||||
callableId.packageName.asString(), callableId.relativeCallableName.asString(), builder.hashId, builder.mask
|
||||
)
|
||||
|
||||
@@ -61,11 +61,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/annotations/annotationProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationTargets.kt")
|
||||
public void testAnnotationTargets() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/annotationTargets.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationWithKotlinProperty.kt")
|
||||
public void testAnnotationWithKotlinProperty() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/annotationWithKotlinProperty.kt");
|
||||
@@ -15640,11 +15635,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/defaultArgsViaAnonymousObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("deprecatedAnnotation.kt")
|
||||
public void testDeprecatedAnnotation() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/deprecatedAnnotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
|
||||
public void testInheritedFunctionWithDefaultParameters() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedFunctionWithDefaultParameters.kt");
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor
|
||||
import org.jetbrains.kotlin.ir.AbstractIrTextTestCase
|
||||
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmManglerDesc
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFir2IrTextTest : AbstractIrTextTestCase() {
|
||||
@@ -88,11 +87,10 @@ abstract class AbstractFir2IrTextTest : AbstractIrTextTestCase() {
|
||||
return Fir2IrConverter.createModuleFragment(
|
||||
session, resolveTransformer.scopeSession, firFiles,
|
||||
myEnvironment.configuration.languageVersionSettings,
|
||||
signaturer,
|
||||
signaturer = signaturer,
|
||||
// TODO: differentiate JVM resolve from other targets, such as JS resolve.
|
||||
JvmGeneratorExtensions(generateFacades = false),
|
||||
FirJvmKotlinMangler(session),
|
||||
IrFactoryImpl,
|
||||
generatorExtensions = JvmGeneratorExtensions(generateFacades = false),
|
||||
mangler = FirJvmKotlinMangler(session)
|
||||
).irModuleFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1690,24 +1690,6 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/ir/irText/firProblems")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class FirProblems extends AbstractFir2IrTextTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTestWithCustomIgnoreDirective(this::doTest, TargetBackend.ANY, testDataFilePath, "// IGNORE_BACKEND_FIR: ");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInFirProblems() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/firProblems"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("deprecated.kt")
|
||||
public void testDeprecated() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/firProblems/deprecated.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/ir/irText/lambdas")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -96,6 +96,7 @@ private class FirCallArgumentsProcessor(private val function: FirFunction<*>) {
|
||||
if (state == State.VARARG_POSITION) {
|
||||
completeVarargPositionArguments()
|
||||
}
|
||||
state = State.NAMED_ONLY_ARGUMENTS
|
||||
|
||||
processNamedArgument(argument, argumentName)
|
||||
}
|
||||
@@ -136,8 +137,6 @@ private class FirCallArgumentsProcessor(private val function: FirFunction<*>) {
|
||||
addDiagnostic(NamedArgumentNotAllowed(argument, function))
|
||||
}
|
||||
|
||||
val stateAllowsMixedNamedAndPositionArguments = state != State.NAMED_ONLY_ARGUMENTS
|
||||
state = State.NAMED_ONLY_ARGUMENTS
|
||||
val parameter = findParameterByName(argument, name) ?: return
|
||||
|
||||
result[parameter]?.let {
|
||||
@@ -147,7 +146,7 @@ private class FirCallArgumentsProcessor(private val function: FirFunction<*>) {
|
||||
|
||||
result[parameter] = ResolvedCallArgument.SimpleArgument(argument)
|
||||
|
||||
if (stateAllowsMixedNamedAndPositionArguments && parameters.getOrNull(currentPositionedParameterIndex) == parameter) {
|
||||
if (parameters.getOrNull(currentPositionedParameterIndex) == parameter) {
|
||||
state = State.POSITION_ARGUMENTS
|
||||
currentPositionedParameterIndex++
|
||||
}
|
||||
@@ -264,9 +263,7 @@ private class FirCallArgumentsProcessor(private val function: FirFunction<*>) {
|
||||
private val FirExpression.argumentName: Name?
|
||||
get() = (this as? FirNamedArgumentExpression)?.name
|
||||
|
||||
// TODO: handle functions with non-stable parameter names, see also
|
||||
// org.jetbrains.kotlin.fir.serialization.FirElementSerializer.functionProto
|
||||
// org.jetbrains.kotlin.fir.serialization.FirElementSerializer.constructorProto
|
||||
// TODO: handle java functions
|
||||
private val FirFunction<*>.hasStableParameterNames: Boolean
|
||||
get() = true
|
||||
}
|
||||
|
||||
@@ -11,17 +11,18 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.*
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.extractInputOutputTypesFromCallableReferenceExpectedType
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -92,7 +93,7 @@ internal sealed class CheckReceivers : ResolutionStage() {
|
||||
|
||||
override fun Candidate.getReceiverType(): ConeKotlinType? {
|
||||
val callableSymbol = symbol as? FirCallableSymbol<*> ?: return null
|
||||
val callable = with(bodyResolveComponents) { callableSymbol.phasedFir }
|
||||
val callable = callableSymbol.fir
|
||||
val receiverType = callable.receiverTypeRef?.coneType
|
||||
if (receiverType != null) return receiverType
|
||||
val returnTypeRef = callable.returnTypeRef as? FirResolvedTypeRef ?: return null
|
||||
@@ -155,7 +156,7 @@ private fun FirExpression.isSuperReferenceExpression(): Boolean {
|
||||
internal object MapArguments : ResolutionStage() {
|
||||
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
|
||||
val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
|
||||
val function = with(candidate.bodyResolveComponents) { symbol.phasedFir }
|
||||
val function = symbol.fir
|
||||
|
||||
val mapping = mapArguments(callInfo.arguments, function)
|
||||
candidate.argumentMapping = mapping.toArgumentToParameterMapping()
|
||||
@@ -220,18 +221,12 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
|
||||
}
|
||||
|
||||
val returnTypeRef = candidate.bodyResolveComponents.returnTypeCalculator.tryCalculateReturnType(fir)
|
||||
// If the expected type is a suspend function type and the current argument of interest is a function reference, we need to do
|
||||
// "suspend conversion." Here, during resolution, we bypass constraint system by making resulting type be KSuspendFunction.
|
||||
// Then, during conversion, we need to create an adapter function and replace the function reference created here with an adapted
|
||||
// callable reference.
|
||||
// TODO: should refer to LanguageVersionSettings.SuspendConversion
|
||||
val requireSuspendConversion = expectedType?.isSuspendFunctionType(callInfo.session) == true
|
||||
// TODO: handle callable reference with vararg
|
||||
|
||||
val resultingType: ConeKotlinType = when (fir) {
|
||||
is FirFunction -> callInfo.session.createKFunctionType(
|
||||
fir, resultingReceiverType, returnTypeRef,
|
||||
expectedParameterNumberWithReceiver = expectedType?.let { it.typeArguments.size - 1 },
|
||||
isSuspend = (fir as? FirSimpleFunction)?.isSuspend == true || requireSuspendConversion,
|
||||
isSuspend = (fir as? FirSimpleFunction)?.isSuspend == true,
|
||||
expectedReturnType = extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, callInfo.session)?.outputType
|
||||
)
|
||||
is FirVariable<*> -> createKPropertyType(fir, resultingReceiverType, returnTypeRef)
|
||||
@@ -570,4 +565,4 @@ internal object PostponedVariablesInitializerResolutionStage : ResolutionStage()
|
||||
private fun FirValueParameter.hasBuilderInferenceMarker(): Boolean {
|
||||
return this.hasAnnotation(BUILDER_INFERENCE_CLASS_ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.TransformImplicitType
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForLocalClass
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAccessorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
@@ -86,9 +87,9 @@ fun <F : FirClass<F>> F.runContractAndBodiesResolutionForLocalClass(
|
||||
components.session, components.scopeSession,
|
||||
implicitBodyResolveComputationSession,
|
||||
FirResolvePhase.BODY_RESOLVE,
|
||||
outerBodyResolveContext = newContext,
|
||||
implicitTypeOnly = false,
|
||||
returnTypeCalculator,
|
||||
outerBodyResolveContext = newContext
|
||||
returnTypeCalculator
|
||||
)
|
||||
|
||||
val graphBuilder = components.context.dataFlowAnalyzerContext.graphBuilder
|
||||
|
||||
@@ -124,6 +124,7 @@ class FirIntegerOperator @FirImplementationDetail constructor(
|
||||
FirDeclarationOrigin.Synthetic,
|
||||
returnTypeRef,
|
||||
receiverTypeRef,
|
||||
typeParameters = mutableListOf(),
|
||||
valueParameters = mutableListOf(),
|
||||
body = null,
|
||||
status,
|
||||
@@ -132,7 +133,6 @@ class FirIntegerOperator @FirImplementationDetail constructor(
|
||||
kind.operatorName,
|
||||
symbol,
|
||||
annotations = mutableListOf(),
|
||||
typeParameters = mutableListOf(),
|
||||
) {
|
||||
enum class Kind(val unary: Boolean, val operatorName: Name) {
|
||||
PLUS(false, OperatorNameConventions.PLUS),
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.config.JvmAnalysisFlags
|
||||
import org.jetbrains.kotlin.config.JvmDefaultMode
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
@@ -15,21 +14,15 @@ import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
||||
import org.jetbrains.kotlin.resolve.LanguageVersionSettingsProvider
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPrivateApi
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.util.getNonPrivateTraitMembersForDelegation
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
class JvmDefaultChecker(val jvmTarget: JvmTarget, project: Project) : DeclarationChecker {
|
||||
|
||||
private val ideService = LanguageVersionSettingsProvider.getInstance(project)
|
||||
class JvmDefaultChecker(val jvmTarget: JvmTarget) : DeclarationChecker {
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val jvmDefaultMode = context.languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
|
||||
@@ -82,79 +75,46 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget, project: Project) : Declaratio
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!jvmDefaultMode.isEnabled || descriptor !is ClassDescriptor || isInterface(descriptor) || isAnnotationClass(descriptor)) return
|
||||
// JvmDefaults members checks across class hierarchy:
|
||||
// 1. If in old scheme class have implicit override with different signature than overriden method (e.g. generic specialization)
|
||||
// report error because absent of it's can affect library ABI
|
||||
// 2. If it's mixed hierarchy with implicit override in base class and override one in inherited derived interface report error.
|
||||
// Otherwise the implicit class override would be used for dispatching method calls (but not more specialized)
|
||||
val performSpecializationCheck = jvmDefaultMode.isCompatibility && !descriptor.hasJvmDefaultNoCompatibilityAnnotation() &&
|
||||
//TODO: maybe remove this check for JVM compatibility
|
||||
!(descriptor.modality !== Modality.OPEN && descriptor.modality !== Modality.ABSTRACT || descriptor.isEffectivelyPrivateApi)
|
||||
|
||||
//Should we check clash with implicit class member (that comes from old compilation scheme) and specialization for compatibility mode
|
||||
// If specialization check is reported clash one shouldn't be reported
|
||||
if (descriptor.getSuperClassNotAny() == null && !performSpecializationCheck) return
|
||||
|
||||
getNonPrivateTraitMembersForDelegation(
|
||||
descriptor,
|
||||
returnImplNotDelegate = true
|
||||
).filter { (_, actualImplementation) -> actualImplementation.isCompiledToJvmDefaultWithProperMode(jvmDefaultMode) }
|
||||
.forEach { (inheritedMember, actualImplementation) ->
|
||||
if (actualImplementation is FunctionDescriptor && inheritedMember is FunctionDescriptor) {
|
||||
if (checkSpecializationInCompatibilityMode(
|
||||
inheritedMember,
|
||||
actualImplementation,
|
||||
context,
|
||||
declaration,
|
||||
performSpecializationCheck
|
||||
)
|
||||
) {
|
||||
checkPossibleClashMember(inheritedMember, jvmDefaultMode, context, declaration)
|
||||
}
|
||||
} else if (actualImplementation is PropertyDescriptor && inheritedMember is PropertyDescriptor) {
|
||||
val getterImpl = actualImplementation.getter
|
||||
val getterInherited = inheritedMember.getter
|
||||
if (getterImpl == null || getterInherited == null || !jvmDefaultMode.isCompatibility ||
|
||||
checkSpecializationInCompatibilityMode(
|
||||
getterInherited,
|
||||
getterImpl,
|
||||
context,
|
||||
declaration,
|
||||
performSpecializationCheck
|
||||
)
|
||||
) {
|
||||
if (actualImplementation.isVar && inheritedMember.isVar) {
|
||||
val setterImpl = actualImplementation.setter
|
||||
val setterInherited = inheritedMember.setter
|
||||
if (setterImpl != null && setterInherited != null) {
|
||||
if (!checkSpecializationInCompatibilityMode(
|
||||
setterInherited,
|
||||
setterImpl,
|
||||
context,
|
||||
declaration,
|
||||
performSpecializationCheck
|
||||
)
|
||||
) return@forEach
|
||||
} else if (jvmDefaultMode.isCompatibility &&
|
||||
!isInterface(descriptor) &&
|
||||
!isAnnotationClass(descriptor) &&
|
||||
descriptor is ClassDescriptor &&
|
||||
!descriptor.hasJvmDefaultNoCompatibilityAnnotation()
|
||||
) {
|
||||
val modality = descriptor.modality
|
||||
//TODO: maybe remove this check for jvm compatibility
|
||||
if (modality !== Modality.OPEN && modality !== Modality.ABSTRACT || descriptor.isEffectivelyPrivateApi) return
|
||||
for ((inheritedMember, actualImplementation) in getNonPrivateTraitMembersForDelegation(
|
||||
descriptor,
|
||||
returnImplNotDelegate = true
|
||||
)) {
|
||||
if (actualImplementation.isCallableMemberCompiledToJvmDefault(jvmDefaultMode)) {
|
||||
if (actualImplementation is FunctionDescriptor && inheritedMember is FunctionDescriptor) {
|
||||
processMember(inheritedMember, actualImplementation, context, declaration)
|
||||
} else if (actualImplementation is PropertyDescriptor && inheritedMember is PropertyDescriptor) {
|
||||
val getterImpl = actualImplementation.getter
|
||||
val getterInherited = inheritedMember.getter
|
||||
if (getterImpl == null || getterInherited == null || processMember(getterImpl, getterImpl, context, declaration)) {
|
||||
if (actualImplementation.isVar && inheritedMember.isVar) {
|
||||
val setterImpl = actualImplementation.setter
|
||||
val setterInherited = inheritedMember.setter
|
||||
if (setterImpl != null && setterInherited != null) {
|
||||
processMember(setterImpl, setterImpl, context, declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkPossibleClashMember(inheritedMember, jvmDefaultMode, context, declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSpecializationInCompatibilityMode(
|
||||
private fun processMember(
|
||||
inheritedFun: FunctionDescriptor,
|
||||
actualImplementation: FunctionDescriptor,
|
||||
context: DeclarationCheckerContext,
|
||||
declaration: KtDeclaration,
|
||||
performSpecializationCheck: Boolean
|
||||
declaration: KtDeclaration
|
||||
): Boolean {
|
||||
if (!performSpecializationCheck) return true
|
||||
val inheritedSignature = inheritedFun.computeJvmDescriptor(withReturnType = true, withName = false)
|
||||
val originalImplementation = actualImplementation.original
|
||||
val actualSignature = originalImplementation.computeJvmDescriptor(withReturnType = true, withName = false)
|
||||
@@ -172,39 +132,6 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget, project: Project) : Declaratio
|
||||
return true
|
||||
}
|
||||
|
||||
private fun checkPossibleClashMember(
|
||||
inheritedFun: CallableMemberDescriptor,
|
||||
jvmDefaultMode: JvmDefaultMode,
|
||||
context: DeclarationCheckerContext,
|
||||
declaration: KtDeclaration
|
||||
) {
|
||||
val clashMember = findPossibleClashMember(inheritedFun, jvmDefaultMode)
|
||||
if (clashMember != null) {
|
||||
context.trace.report(
|
||||
ErrorsJvm.EXPLICIT_OVERRIDE_REQUIRED_IN_MIXED_MODE.on(
|
||||
declaration,
|
||||
getDirectMember(inheritedFun),
|
||||
getDirectMember(clashMember),
|
||||
jvmDefaultMode.description
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findPossibleClashMember(
|
||||
inheritedFun: CallableMemberDescriptor,
|
||||
jvmDefaultMode: JvmDefaultMode
|
||||
): CallableMemberDescriptor? {
|
||||
val classDescriptor = inheritedFun.containingDeclaration
|
||||
if (classDescriptor !is ClassDescriptor || classDescriptor.getSuperClassNotAny() == null) return null
|
||||
val classMembers =
|
||||
inheritedFun.overriddenDescriptors.filter { !isInterface(it.containingDeclaration) && !isAnnotationClass(it.containingDeclaration) }
|
||||
val implicitDefaultImplsDelegate =
|
||||
classMembers.firstOrNull { getNonPrivateTraitMembersForDelegation(it, true)?.isCompiledToJvmDefaultWithProperMode(jvmDefaultMode) == false }
|
||||
if (implicitDefaultImplsDelegate != null) return implicitDefaultImplsDelegate
|
||||
return classMembers.firstNotNullResult { findPossibleClashMember(it, jvmDefaultMode) }
|
||||
}
|
||||
|
||||
private fun checkJvmDefaultsInHierarchy(descriptor: DeclarationDescriptor, jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||
if (jvmDefaultMode.isEnabled) return true
|
||||
|
||||
@@ -213,16 +140,9 @@ class JvmDefaultChecker(val jvmTarget: JvmTarget, project: Project) : Declaratio
|
||||
return descriptor.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance<CallableMemberDescriptor>()
|
||||
.all { memberDescriptor ->
|
||||
memberDescriptor.kind.isReal || OverridingUtil.filterOutOverridden(memberDescriptor.overriddenDescriptors.toSet()).all {
|
||||
!isInterface(it.containingDeclaration) || !it.isCompiledToJvmDefaultWithProperMode(jvmDefaultMode) || it.modality == Modality.ABSTRACT
|
||||
!isInterface(it.containingDeclaration) || !it.isCompiledToJvmDefault(jvmDefaultMode) || it.modality == Modality.ABSTRACT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.isCompiledToJvmDefaultWithProperMode(compilationDefaultMode: JvmDefaultMode): Boolean {
|
||||
val jvmDefault =
|
||||
if (this is DeserializedDescriptor) compilationDefaultMode else ideService?.getModuleLanguageVersionSettings(module)
|
||||
?.getFlag(JvmAnalysisFlags.jvmDefaultMode) ?: compilationDefaultMode
|
||||
return isCompiledToJvmDefault(jvmDefault)
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user