Compare commits

..

2 Commits

Author SHA1 Message Date
Ilya Muradyan
106ea55afc Introduce GetScriptingClassByClassLoader interface
It is needed to override default JVM behaviour
2020-11-28 03:16:04 +03:00
Ilya Muradyan
977d170d11 Fix path for Windows in Fibonacci test 2020-11-28 03:16:04 +03:00
1906 changed files with 24459 additions and 37789 deletions

9
.bunch
View File

@@ -1,4 +1,7 @@
202
201
as41_201
as42
202
203_202
193
as40_193
as41
as42_202

View File

@@ -188,7 +188,7 @@ extra["versions.kotlinx-collections-immutable-jvm"] = immutablesVersion
extra["versions.ktor-network"] = "1.0.1"
if (!project.hasProperty("versions.kotlin-native")) {
extra["versions.kotlin-native"] = "1.4.30-dev-17395"
extra["versions.kotlin-native"] = "1.4.30-dev-17200"
}
val intellijUltimateEnabled by extra(project.kotlinBuildProperties.intellijUltimateEnabled)
@@ -854,8 +854,6 @@ tasks {
register("kaptIdeTest") {
dependsOn(":kotlin-annotation-processing:test")
dependsOn(":kotlin-annotation-processing-base:test")
dependsOn(":kotlin-annotation-processing-cli:test")
}
register("gradleIdeTest") {

View File

@@ -54,12 +54,11 @@ var Project.javaHome: String?
extra["javaHome"] = v
}
fun Project.generator(fqName: String, sourceSet: SourceSet? = null, configure: JavaExec.() -> Unit = {}) = smartJavaExec {
fun Project.generator(fqName: String, sourceSet: SourceSet? = null) = smartJavaExec {
classpath = (sourceSet ?: testSourceSet).runtimeClasspath
mainClass.set(fqName)
workingDir = rootDir
systemProperty("line.separator", "\n")
configure()
}
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {

View File

@@ -269,7 +269,8 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
continue
}
val fullFileText = FileUtil.loadFile(file, true)
val fullFileText =
FileUtil.loadFile(file, true).replace("COROUTINES_PACKAGE", "kotlin.coroutines")
if (fullFileText.contains("// WITH_COROUTINES")) {
if (fullFileText.contains("kotlin.coroutines.experimental")) continue
@@ -316,7 +317,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
}
private fun createTestFiles(file: File, expectedText: String): List<KotlinBaseTest.TestFile> =
CodegenTestCase.createTestFilesFromFile(file, expectedText, false, TargetBackend.JVM)
CodegenTestCase.createTestFilesFromFile(file, expectedText, "kotlin.coroutines", false, TargetBackend.JVM)
companion object {
const val GRADLE_VERSION = "5.6.4" // update GRADLE_SHA_256 on change

View File

@@ -26,13 +26,13 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
public abstract class AbstractClassBuilder implements ClassBuilder {
protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.API_VERSION) {};
public static final RecordComponentVisitor EMPTY_RECORD_VISITOR = new RecordComponentVisitor(Opcodes.API_VERSION) {};
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {};
private String thisName;
@@ -91,16 +91,6 @@ public abstract class AbstractClassBuilder implements ClassBuilder {
return visitor;
}
@NotNull
@Override
public RecordComponentVisitor newRecordComponent(@NotNull String name, @NotNull String desc, @Nullable String signature) {
RecordComponentVisitor visitor = getVisitor().visitRecordComponent(name, desc, signature);
if (visitor == null) {
return EMPTY_RECORD_VISITOR;
}
return visitor;
}
@Override
@NotNull
public JvmSerializationBindings getSerializationBindings() {

View File

@@ -1,158 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SMAPBuilder;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
import java.util.List;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
public abstract class AbstractClassBuilder implements ClassBuilder {
protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.API_VERSION) {};
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {};
private String thisName;
private final JvmSerializationBindings serializationBindings = new JvmSerializationBindings();
private String sourceName;
private String debugInfo;
public static class Concrete extends AbstractClassBuilder {
private final ClassVisitor v;
public Concrete(@NotNull ClassVisitor v) {
this.v = v;
}
@Override
@NotNull
public ClassVisitor getVisitor() {
return v;
}
}
@Override
@NotNull
public FieldVisitor newField(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable Object value
) {
FieldVisitor visitor = getVisitor().visitField(access, name, desc, signature, value);
if (visitor == null) {
return EMPTY_FIELD_VISITOR;
}
return visitor;
}
@Override
@NotNull
public MethodVisitor newMethod(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable String[] exceptions
) {
MethodVisitor visitor = getVisitor().visitMethod(access, name, desc, signature, exceptions);
if (visitor == null) {
return EMPTY_METHOD_VISITOR;
}
return visitor;
}
@Override
@NotNull
public JvmSerializationBindings getSerializationBindings() {
return serializationBindings;
}
@Override
@NotNull
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
return getVisitor().visitAnnotation(desc, visible);
}
@Override
public void done() {
getVisitor().visitSource(sourceName, debugInfo);
getVisitor().visitEnd();
}
@Override
public void defineClass(
@Nullable PsiElement origin,
int version,
int access,
@NotNull String name,
@Nullable String signature,
@NotNull String superName,
@NotNull String[] interfaces
) {
thisName = name;
getVisitor().visit(version, access, name, signature, superName, interfaces);
}
@Override
public void visitSource(@NotNull String name, @Nullable String debug) {
assert sourceName == null || sourceName.equals(name) : "inconsistent file name: " + sourceName + " vs " + name;
sourceName = name;
debugInfo = debug;
}
@Override
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
if (!GENERATE_SMAP) return;
List<FileMapping> fileMappings = smap.getResultMappings();
if (fileMappings.isEmpty()) return;
visitSource(fileMappings.get(0).getName(), SMAPBuilder.INSTANCE.build(fileMappings, backwardsCompatibleSyntax));
}
@Override
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
getVisitor().visitOuterClass(owner, name, desc);
}
@Override
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
getVisitor().visitInnerClass(name, outerName, innerName, access);
}
@Override
@NotNull
public String getThisName() {
assert thisName != null : "This name isn't set";
return thisName;
}
}

View File

@@ -29,8 +29,7 @@ class CallableMethod(
override val generateCalleeType: Type?,
override val returnKotlinType: KotlinType?,
val isInterfaceMethod: Boolean,
private val isDefaultMethodInInterface: Boolean,
private val boxInlineClassBeforeInvoke: Boolean
private val isDefaultMethodInInterface: Boolean
) : Callable {
private val defaultImplMethod: Method by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethod)
@@ -50,9 +49,6 @@ class CallableMethod(
get() = getAsmMethod().argumentTypes
override fun genInvokeInstruction(v: InstructionAdapter) {
if (boxInlineClassBeforeInvoke) {
StackValue.boxInlineClass(dispatchReceiverKotlinType!!, v)
}
v.visitMethodInsn(
invokeOpcode,
owner.internalName,

View File

@@ -19,10 +19,14 @@ package org.jetbrains.kotlin.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
public interface ClassBuilder {
@NotNull
@@ -45,12 +49,6 @@ public interface ClassBuilder {
@Nullable String[] exceptions
);
@NotNull RecordComponentVisitor newRecordComponent(
@NotNull String name,
@NotNull String desc,
@Nullable String signature
);
@NotNull
JvmSerializationBindings getSerializationBindings();

View File

@@ -1,79 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
public interface ClassBuilder {
@NotNull
FieldVisitor newField(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable Object value
);
@NotNull
MethodVisitor newMethod(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable String[] exceptions
);
@NotNull
JvmSerializationBindings getSerializationBindings();
@NotNull
AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible);
void done();
@NotNull
ClassVisitor getVisitor();
void defineClass(
@Nullable PsiElement origin,
int version,
int access,
@NotNull String name,
@Nullable String signature,
@NotNull String superName,
@NotNull String[] interfaces
);
void visitSource(@NotNull String name, @Nullable String debug);
void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax);
void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc);
void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access);
@NotNull
String getThisName();
}

View File

@@ -19,10 +19,14 @@ package org.jetbrains.kotlin.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.FileMapping;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
public abstract class DelegatingClassBuilder implements ClassBuilder {
@NotNull
@@ -54,14 +58,6 @@ public abstract class DelegatingClassBuilder implements ClassBuilder {
return getDelegate().newMethod(origin, access, name, desc, signature, exceptions);
}
@NotNull
@Override
public RecordComponentVisitor newRecordComponent(
@NotNull String name, @NotNull String desc, @Nullable String signature
) {
return getDelegate().newRecordComponent(name, desc, signature);
}
@NotNull
@Override
public JvmSerializationBindings getSerializationBindings() {

View File

@@ -1,118 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.*;
public abstract class DelegatingClassBuilder implements ClassBuilder {
@NotNull
protected abstract ClassBuilder getDelegate();
@NotNull
@Override
public FieldVisitor newField(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable Object value
) {
return getDelegate().newField(origin, access, name, desc, signature, value);
}
@NotNull
@Override
public MethodVisitor newMethod(
@NotNull JvmDeclarationOrigin origin,
int access,
@NotNull String name,
@NotNull String desc,
@Nullable String signature,
@Nullable String[] exceptions
) {
return getDelegate().newMethod(origin, access, name, desc, signature, exceptions);
}
@NotNull
@Override
public JvmSerializationBindings getSerializationBindings() {
return getDelegate().getSerializationBindings();
}
@NotNull
@Override
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
return getDelegate().newAnnotation(desc, visible);
}
@Override
public void done() {
getDelegate().done();
}
@NotNull
@Override
public ClassVisitor getVisitor() {
return getDelegate().getVisitor();
}
@Override
public void defineClass(
@Nullable PsiElement origin,
int version,
int access,
@NotNull String name,
@Nullable String signature,
@NotNull String superName,
@NotNull String[] interfaces
) {
getDelegate().defineClass(origin, version, access, name, signature, superName, interfaces);
}
@Override
public void visitSource(@NotNull String name, @Nullable String debug) {
getDelegate().visitSource(name, debug);
}
@Override
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
getDelegate().visitSMAP(smap, backwardsCompatibleSyntax);
}
@Override
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
getDelegate().visitOuterClass(owner, name, desc);
}
@Override
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
getDelegate().visitInnerClass(name, outerName, innerName, access);
}
@NotNull
@Override
public String getThisName() {
return getDelegate().getThisName();
}
}

View File

@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
import org.jetbrains.kotlin.resolve.JVM_INLINE_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
@@ -56,13 +55,6 @@ class ErasedInlineClassBodyCodegen(
generateUnboxMethod()
generateFunctionsFromAny()
generateSpecializedEqualsStub()
generateJvmInlineAnnotation()
}
private fun generateJvmInlineAnnotation() {
if (descriptor.isInline) {
v.newAnnotation(JVM_INLINE_ANNOTATION_FQ_NAME.topLevelClassAsmType().descriptor, true).visitEnd()
}
}
private fun generateFunctionsFromAny() {

View File

@@ -1221,12 +1221,7 @@ public class FunctionCodegen {
// 'null' because the "could not find expected declaration" error has been already reported in isDefaultNeeded earlier
List<ValueParameterDescriptor> valueParameters =
functionDescriptor.isSuspend()
? CollectionsKt.plus(
CodegenUtil.getFunctionParametersForDefaultValueGeneration(
CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(functionDescriptor), null),
CollectionsKt.last(functionDescriptor.getValueParameters()))
: CodegenUtil.getFunctionParametersForDefaultValueGeneration(functionDescriptor, null);
CodegenUtil.getFunctionParametersForDefaultValueGeneration(functionDescriptor, null);
boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor);
FrameMap frameMap = createFrameMap(state, signature, functionDescriptor.getExtensionReceiverParameter(), valueParameters, isStatic);

View File

@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
@@ -222,10 +221,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
access |= ACC_ENUM;
}
if (JvmAnnotationUtilKt.isJvmRecord(descriptor)) {
access |= ACC_RECORD;
}
v.defineClass(
myClass.getPsiOrParent(),
state.getClassFileVersion(),

View File

@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
@@ -436,10 +435,9 @@ public class PropertyCodegen {
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, new Pair<>(type, name));
if (isBackingFieldOwner) {
String signature = isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor);
FieldVisitor fv = builder.newField(
JvmDeclarationOriginKt.OtherOrigin(propertyDescriptor), modifiers, name, type.getDescriptor(),
signature, defaultValue
isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor), defaultValue
);
if (annotatedField != null) {
@@ -452,10 +450,6 @@ public class PropertyCodegen {
AnnotationCodegen.forField(fv, memberCodegen, state, skipNullabilityAnnotations)
.genAnnotations(annotatedField, type, propertyDescriptor.getType(), null, additionalVisibleAnnotations);
}
if (propertyDescriptor.getContainingDeclaration() instanceof ClassDescriptor && JvmAnnotationUtilKt.isJvmRecord((ClassDescriptor) propertyDescriptor.getContainingDeclaration())) {
builder.newRecordComponent(name, type.getDescriptor(), signature);
}
}
}

View File

@@ -1,680 +0,0 @@
/*
* Copyright 2000-2018 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.codegen;
import com.intellij.psi.PsiElement;
import kotlin.Pair;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
import org.jetbrains.kotlin.codegen.context.MultifileClassFacadeContext;
import org.jetbrains.kotlin.codegen.context.MultifileClassPartContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorFactory;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor;
import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.org.objectweb.asm.FieldVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getDeprecatedAccessFlag;
import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getVisibilityForBackingField;
import static org.jetbrains.kotlin.codegen.FunctionCodegen.processInterfaceMethod;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*;
import static org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND;
import static org.jetbrains.kotlin.fileClasses.JvmFileClassUtilKt.isTopLevelInJvmMultifileClass;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.K_PROPERTY_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmFieldAnnotation;
import static org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt.hasJvmSyntheticAnnotation;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class PropertyCodegen {
private final GenerationState state;
private final ClassBuilder v;
private final FunctionCodegen functionCodegen;
private final KotlinTypeMapper typeMapper;
private final BindingContext bindingContext;
private final FieldOwnerContext context;
private final MemberCodegen<?> memberCodegen;
private final OwnerKind kind;
public PropertyCodegen(
@NotNull FieldOwnerContext context,
@NotNull ClassBuilder v,
@NotNull FunctionCodegen functionCodegen,
@NotNull MemberCodegen<?> memberCodegen
) {
this.state = functionCodegen.state;
this.v = v;
this.functionCodegen = functionCodegen;
this.typeMapper = state.getTypeMapper();
this.bindingContext = state.getBindingContext();
this.context = context;
this.memberCodegen = memberCodegen;
this.kind = context.getContextKind();
}
public void gen(@NotNull KtProperty property) {
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, property);
if (!(variableDescriptor instanceof PropertyDescriptor)) {
throw ExceptionLogger.logDescriptorNotFound(
"Property " + property.getName() + " should have a property descriptor: " + variableDescriptor, property
);
}
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
gen(property, propertyDescriptor, property.getGetter(), property.getSetter());
}
public void genDestructuringDeclaration(@NotNull KtDestructuringDeclarationEntry entry) {
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, entry);
if (!(variableDescriptor instanceof PropertyDescriptor)) {
throw ExceptionLogger.logDescriptorNotFound(
"Destructuring declaration entry" + entry.getName() + " should have a property descriptor: " + variableDescriptor, entry
);
}
if (!UnderscoreUtilKt.isSingleUnderscore(entry)) {
genDestructuringDeclaration((PropertyDescriptor) variableDescriptor);
}
}
public void generateInPackageFacade(@NotNull DeserializedPropertyDescriptor deserializedProperty) {
assert context instanceof MultifileClassFacadeContext : "should be called only for generating facade: " + context;
genBackingFieldAndAnnotations(deserializedProperty);
if (!isConstOrHasJvmFieldAnnotation(deserializedProperty)) {
generateGetter(deserializedProperty, null);
generateSetter(deserializedProperty, null);
}
}
private void gen(
@NotNull KtProperty declaration,
@NotNull PropertyDescriptor descriptor,
@Nullable KtPropertyAccessor getter,
@Nullable KtPropertyAccessor setter
) {
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION ||
kind == OwnerKind.DEFAULT_IMPLS || kind == OwnerKind.ERASED_INLINE_CLASS
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
genBackingFieldAndAnnotations(descriptor);
boolean isDefaultGetterAndSetter = isDefaultAccessor(getter) && isDefaultAccessor(setter);
if (isAccessorNeeded(descriptor, getter, isDefaultGetterAndSetter)) {
generateGetter(descriptor, getter);
}
if (isAccessorNeeded(descriptor, setter, isDefaultGetterAndSetter)) {
generateSetter(descriptor, setter);
}
}
private static boolean isDefaultAccessor(@Nullable KtPropertyAccessor accessor) {
return accessor == null || !accessor.hasBody();
}
private void genDestructuringDeclaration(@NotNull PropertyDescriptor descriptor) {
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DEFAULT_IMPLS
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
genBackingFieldAndAnnotations(descriptor);
generateGetter(descriptor, null);
generateSetter(descriptor, null);
}
private void genBackingFieldAndAnnotations(@NotNull PropertyDescriptor descriptor) {
// Fields and '$annotations' methods for non-private const properties are generated in the multi-file facade
boolean isBackingFieldOwner = descriptor.isConst() && !DescriptorVisibilities.isPrivate(descriptor.getVisibility())
? !(context instanceof MultifileClassPartContext)
: CodegenContextUtil.isImplementationOwner(context, descriptor);
generateBackingField(descriptor, isBackingFieldOwner);
generateSyntheticMethodIfNeeded(descriptor, isBackingFieldOwner);
}
private boolean isAccessorNeeded(
@NotNull PropertyDescriptor descriptor,
@Nullable KtPropertyAccessor accessor,
boolean isDefaultGetterAndSetter
) {
return isAccessorNeeded(descriptor, accessor, isDefaultGetterAndSetter, kind);
}
public static boolean isReferenceablePropertyWithGetter(@NotNull PropertyDescriptor descriptor) {
PsiElement psiElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
KtDeclaration ktDeclaration = psiElement instanceof KtDeclaration ? (KtDeclaration) psiElement : null;
if (ktDeclaration instanceof KtProperty) {
KtProperty ktProperty = (KtProperty) ktDeclaration;
boolean isDefaultGetterAndSetter =
isDefaultAccessor(ktProperty.getGetter()) && isDefaultAccessor(ktProperty.getSetter());
return isAccessorNeeded(descriptor, ktProperty.getGetter(), isDefaultGetterAndSetter, OwnerKind.IMPLEMENTATION);
} else if (ktDeclaration instanceof KtParameter) {
return isAccessorNeeded(descriptor, null, true, OwnerKind.IMPLEMENTATION);
} else {
return isAccessorNeeded(descriptor, null, false, OwnerKind.IMPLEMENTATION);
}
}
/**
* Determines if it's necessary to generate an accessor to the property, i.e. if this property can be referenced via getter/setter
* for any reason
*
* @see JvmCodegenUtil#couldUseDirectAccessToProperty
*/
private static boolean isAccessorNeeded(
@NotNull PropertyDescriptor descriptor,
@Nullable KtPropertyAccessor accessor,
boolean isDefaultGetterAndSetter,
OwnerKind kind
) {
if (isConstOrHasJvmFieldAnnotation(descriptor)) return false;
boolean isDefaultAccessor = isDefaultAccessor(accessor);
// Don't generate accessors for interface properties with default accessors in DefaultImpls
if (kind == OwnerKind.DEFAULT_IMPLS && isDefaultAccessor) return false;
// Delegated or extension properties can only be referenced via accessors
if (descriptor.isDelegated() || descriptor.getExtensionReceiverParameter() != null) return true;
// Companion object properties should have accessors for non-private properties because these properties can be referenced
// via getter/setter. But these accessors getter/setter are not required for private properties that have a default getter
// and setter, in this case, the property can always be accessed through the accessor 'access<property name>$cp' and avoid some
// useless indirection by using others accessors.
if (isCompanionObject(descriptor.getContainingDeclaration())) {
if (DescriptorVisibilities.isPrivate(descriptor.getVisibility()) && isDefaultGetterAndSetter) {
return false;
}
return true;
}
// Non-const properties from multifile classes have accessors regardless of visibility
if (isTopLevelInJvmMultifileClass(descriptor)) return true;
// Private class properties have accessors only in cases when those accessors are non-trivial
if (DescriptorVisibilities.isPrivate(descriptor.getVisibility())) {
return !isDefaultAccessor;
}
// Non-private properties with private setter should not be generated for trivial properties
// as the class will use direct field access instead
//noinspection ConstantConditions
if (accessor != null && accessor.isSetter() && DescriptorVisibilities.isPrivate(descriptor.getSetter().getVisibility())) {
return !isDefaultAccessor;
}
// Non-public API (private and internal) primary vals of inline classes don't have getter
if (InlineClassesUtilsKt.isUnderlyingPropertyOfInlineClass(descriptor) && !descriptor.getVisibility().isPublicAPI()) {
return false;
}
return true;
}
private static boolean areAccessorsNeededForPrimaryConstructorProperty(
@NotNull PropertyDescriptor descriptor,
@NotNull OwnerKind kind
) {
if (hasJvmFieldAnnotation(descriptor)) return false;
if (kind == OwnerKind.ERASED_INLINE_CLASS) return false;
DescriptorVisibility visibility = descriptor.getVisibility();
if (InlineClassesUtilsKt.isInlineClass(descriptor.getContainingDeclaration())) {
return visibility.isPublicAPI();
}
else {
return !DescriptorVisibilities.isPrivate(visibility);
}
}
public void generatePrimaryConstructorProperty(@NotNull PropertyDescriptor descriptor) {
genBackingFieldAndAnnotations(descriptor);
if (areAccessorsNeededForPrimaryConstructorProperty(descriptor, context.getContextKind())) {
generateGetter(descriptor, null);
generateSetter(descriptor, null);
}
}
public void generateConstructorPropertyAsMethodForAnnotationClass(
@NotNull KtParameter parameter,
@NotNull PropertyDescriptor descriptor,
@Nullable FunctionDescriptor expectedAnnotationConstructor
) {
JvmMethodGenericSignature signature = typeMapper.mapAnnotationParameterSignature(descriptor);
Method asmMethod = signature.getAsmMethod();
MethodVisitor mv = v.newMethod(
JvmDeclarationOriginKt.OtherOrigin(parameter, descriptor),
ACC_PUBLIC | ACC_ABSTRACT,
asmMethod.getName(),
asmMethod.getDescriptor(),
signature.getGenericsSignature(),
null
);
PropertyGetterDescriptor getter = descriptor.getGetter();
assert getter != null : "Annotation property should have a getter: " + descriptor;
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, getter, asmMethod);
AnnotationCodegen.forMethod(mv, memberCodegen, state).genAnnotations(getter, asmMethod.getReturnType(), null);
KtExpression defaultValue = loadAnnotationArgumentDefaultValue(parameter, descriptor, expectedAnnotationConstructor);
if (defaultValue != null) {
ConstantValue<?> constant = ExpressionCodegen.getCompileTimeConstant(
defaultValue, bindingContext, true, state.getShouldInlineConstVals());
assert !state.getClassBuilderMode().generateBodies || constant != null
: "Default value for annotation parameter should be compile time value: " + defaultValue.getText();
if (constant != null) {
AnnotationCodegen annotationCodegen = AnnotationCodegen.forAnnotationDefaultValue(mv, memberCodegen, state);
annotationCodegen.generateAnnotationDefaultValue(constant, descriptor.getType());
}
}
mv.visitEnd();
}
private KtExpression loadAnnotationArgumentDefaultValue(
@NotNull KtParameter ktParameter,
@NotNull PropertyDescriptor descriptor,
@Nullable FunctionDescriptor expectedAnnotationConstructor
) {
KtExpression value = ktParameter.getDefaultValue();
if (value != null) return value;
if (expectedAnnotationConstructor != null) {
ValueParameterDescriptor expectedParameter = CollectionsKt.single(
expectedAnnotationConstructor.getValueParameters(), parameter -> parameter.getName().equals(descriptor.getName())
);
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(expectedParameter);
if (!(element instanceof KtParameter)) {
state.getDiagnostics().report(EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(ktParameter));
return null;
}
return ((KtParameter) element).getDefaultValue();
}
return null;
}
private void generateBackingField(@NotNull PropertyDescriptor descriptor, boolean isBackingFieldOwner) {
if (isJvmInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.DEFAULT_IMPLS ||
kind == OwnerKind.ERASED_INLINE_CLASS) {
return;
}
Object defaultValue;
if (descriptor.isDelegated()) {
defaultValue = null;
}
else if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
if (shouldWriteFieldInitializer(descriptor)) {
ConstantValue<?> initializer = descriptor.getCompileTimeInitializer();
defaultValue = initializer == null ? null : initializer.getValue();
}
else {
defaultValue = null;
}
}
else {
return;
}
generateBackingField(descriptor, descriptor.isDelegated(), defaultValue, isBackingFieldOwner);
}
// Annotations on properties are stored in bytecode on an empty synthetic method. This way they're still
// accessible via reflection, and 'deprecated' and 'synthetic' flags prevent this method from being called accidentally
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, boolean isBackingFieldOwner) {
Annotations annotations = descriptor.getAnnotations();
if (annotations.isEmpty()) return;
Method signature = typeMapper.mapSyntheticMethodForPropertyAnnotations(descriptor);
if (kind != OwnerKind.DEFAULT_IMPLS && CodegenContextUtil.isImplementationOwner(context, descriptor)) {
v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, signature);
}
if (isBackingFieldOwner) {
if (!isInterface(context.getContextDescriptor()) ||
processInterfaceMethod(descriptor, kind, false, true, state.getJvmDefaultMode())) {
memberCodegen.generateSyntheticAnnotationsMethod(descriptor, signature, annotations);
}
}
}
private void generateBackingField(
@NotNull PropertyDescriptor propertyDescriptor,
boolean isDelegate,
@Nullable Object defaultValue,
boolean isBackingFieldOwner
) {
FieldDescriptor annotatedField = isDelegate ? propertyDescriptor.getDelegateField() : propertyDescriptor.getBackingField();
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) {
modifiers |= flagAnnotation.getJvmFlag(annotatedField);
}
if (kind == OwnerKind.PACKAGE) {
modifiers |= ACC_STATIC;
}
if (!propertyDescriptor.isLateInit() && (!propertyDescriptor.isVar() || isDelegate)) {
modifiers |= ACC_FINAL;
}
if (hasJvmSyntheticAnnotation(propertyDescriptor)) {
modifiers |= ACC_SYNTHETIC;
}
KotlinType kotlinType = isDelegate ? getDelegateTypeForProperty(propertyDescriptor, bindingContext) : propertyDescriptor.getType();
Type type = typeMapper.mapType(kotlinType);
ClassBuilder builder = v;
FieldOwnerContext backingFieldContext = context;
List<String> additionalVisibleAnnotations = Collections.emptyList();
if (DescriptorAsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor) ) {
modifiers |= ACC_STATIC;
if (DescriptorsJvmAbiUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor)) {
ImplementationBodyCodegen codegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
builder = codegen.v;
backingFieldContext = codegen.context;
if (DescriptorVisibilities.isPrivate(((ClassDescriptor) propertyDescriptor.getContainingDeclaration()).getVisibility())) {
modifiers |= ACC_DEPRECATED;
additionalVisibleAnnotations = Collections.singletonList(CodegenUtilKt.JAVA_LANG_DEPRECATED);
}
}
}
modifiers |= getVisibilityForBackingField(propertyDescriptor, isDelegate);
if (DescriptorAsmUtil.isPropertyWithBackingFieldCopyInOuterClass(propertyDescriptor)) {
ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
parentBodyCodegen.addCompanionObjectPropertyToCopy(propertyDescriptor, defaultValue);
}
String name = backingFieldContext.getFieldName(propertyDescriptor, isDelegate);
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, new Pair<>(type, name));
if (isBackingFieldOwner) {
String signature = isDelegate ? null : typeMapper.mapFieldSignature(kotlinType, propertyDescriptor);
FieldVisitor fv = builder.newField(
JvmDeclarationOriginKt.OtherOrigin(propertyDescriptor), modifiers, name, type.getDescriptor(),
signature, defaultValue
);
if (annotatedField != null) {
// Don't emit nullability annotations for backing field if:
// - backing field is synthetic;
// - property is lateinit (since corresponding field is actually nullable).
boolean skipNullabilityAnnotations =
(modifiers & ACC_SYNTHETIC) != 0 ||
propertyDescriptor.isLateInit();
AnnotationCodegen.forField(fv, memberCodegen, state, skipNullabilityAnnotations)
.genAnnotations(annotatedField, type, propertyDescriptor.getType(), null, additionalVisibleAnnotations);
}
if (propertyDescriptor.getContainingDeclaration() instanceof ClassDescriptor && JvmAnnotationUtilKt.isJvmRecord((ClassDescriptor) propertyDescriptor.getContainingDeclaration())) {
// builder.newRecordComponent(name, type.getDescriptor(), signature);
}
}
}
@NotNull
public static KotlinType getDelegateTypeForProperty(
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull BindingContext bindingContext
) {
ResolvedCall<FunctionDescriptor> provideDelegateResolvedCall =
bindingContext.get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, propertyDescriptor);
KtProperty property = (KtProperty) DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
KtExpression delegateExpression = property != null ? property.getDelegateExpression() : null;
KotlinType delegateType;
if (provideDelegateResolvedCall != null) {
delegateType = provideDelegateResolvedCall.getResultingDescriptor().getReturnType();
}
else if (delegateExpression != null) {
delegateType = bindingContext.getType(delegateExpression);
}
else {
delegateType = null;
}
if (delegateType == null) {
// Delegation convention is unresolved
delegateType = ErrorUtils.createErrorType("Delegate type");
}
return delegateType;
}
private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) {
if (!descriptor.isConst() &&
state.getLanguageVersionSettings().supportsFeature(LanguageFeature.NoConstantValueAttributeForNonConstVals)) {
return false;
}
//final field of primitive or String type
if (!descriptor.isVar()) {
Type type = typeMapper.mapType(descriptor);
return AsmUtil.isPrimitive(type) || "java.lang.String".equals(type.getClassName());
}
return false;
}
private void generateGetter(@NotNull PropertyDescriptor descriptor, @Nullable KtPropertyAccessor getter) {
generateAccessor(
getter,
descriptor.getGetter() != null ? descriptor.getGetter() : DescriptorFactory.createDefaultGetter(
descriptor, Annotations.Companion.getEMPTY()
)
);
}
private void generateSetter(@NotNull PropertyDescriptor descriptor, @Nullable KtPropertyAccessor setter) {
if (!descriptor.isVar()) return;
generateAccessor(
setter,
descriptor.getSetter() != null ? descriptor.getSetter() : DescriptorFactory.createDefaultSetter(
descriptor, Annotations.Companion.getEMPTY(), Annotations.Companion.getEMPTY()
)
);
}
private void generateAccessor(@Nullable KtPropertyAccessor accessor, @NotNull PropertyAccessorDescriptor descriptor) {
if (context instanceof MultifileClassFacadeContext &&
(DescriptorVisibilities.isPrivate(descriptor.getVisibility()) ||
DescriptorAsmUtil.getVisibilityAccessFlag(descriptor) == Opcodes.ACC_PRIVATE)) {
return;
}
FunctionGenerationStrategy strategy;
if (accessor == null || !accessor.hasBody()) {
if (descriptor.getCorrespondingProperty().isDelegated()) {
strategy = new DelegatedPropertyAccessorStrategy(state, descriptor);
}
else {
strategy = new DefaultPropertyAccessorStrategy(state, descriptor);
}
}
else {
strategy = new FunctionGenerationStrategy.FunctionDefault(state, accessor);
}
functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), descriptor, strategy);
}
private static class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
private final PropertyAccessorDescriptor propertyAccessorDescriptor;
public DefaultPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
super(state);
propertyAccessorDescriptor = descriptor;
}
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
InstructionAdapter v = codegen.v;
PropertyDescriptor propertyDescriptor = propertyAccessorDescriptor.getCorrespondingProperty();
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0);
PsiElement jetProperty = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
if (jetProperty instanceof KtProperty || jetProperty instanceof KtParameter) {
codegen.markLineNumber((KtElement) jetProperty, false);
}
if (propertyAccessorDescriptor instanceof PropertyGetterDescriptor) {
Type type = signature.getReturnType();
property.put(type, v);
v.areturn(type);
}
else if (propertyAccessorDescriptor instanceof PropertySetterDescriptor) {
List<ValueParameterDescriptor> valueParameters = propertyAccessorDescriptor.getValueParameters();
assert valueParameters.size() == 1 : "Property setter should have only one value parameter but has " + propertyAccessorDescriptor;
int parameterIndex = codegen.lookupLocalIndex(valueParameters.get(0));
assert parameterIndex >= 0 : "Local index for setter parameter should be positive or zero: " + propertyAccessorDescriptor;
Type type = codegen.typeMapper.mapType(propertyDescriptor);
property.store(StackValue.local(parameterIndex, type), codegen.v);
v.visitInsn(RETURN);
}
else {
throw new IllegalStateException("Unknown property accessor: " + propertyAccessorDescriptor);
}
}
}
public static StackValue invokeDelegatedPropertyConventionMethod(
@NotNull ExpressionCodegen codegen,
@NotNull ResolvedCall<FunctionDescriptor> resolvedCall,
@NotNull StackValue receiver,
@NotNull PropertyDescriptor propertyDescriptor
) {
codegen.tempVariables.put(
resolvedCall.getCall().getValueArguments().get(1).asElement(),
getDelegatedPropertyMetadata(propertyDescriptor, codegen.getBindingContext())
);
return codegen.invokeFunction(resolvedCall, receiver);
}
public static boolean isDelegatedPropertyWithOptimizedMetadata(
@NotNull VariableDescriptorWithAccessors descriptor,
@NotNull BindingContext bindingContext
) {
return Boolean.TRUE == bindingContext.get(DELEGATED_PROPERTY_WITH_OPTIMIZED_METADATA, descriptor);
}
public static @NotNull StackValue getOptimizedDelegatedPropertyMetadataValue() {
return StackValue.constant(null, K_PROPERTY_TYPE);
}
@NotNull
public static StackValue getDelegatedPropertyMetadata(
@NotNull VariableDescriptorWithAccessors descriptor,
@NotNull BindingContext bindingContext
) {
if (isDelegatedPropertyWithOptimizedMetadata(descriptor, bindingContext)) {
return getOptimizedDelegatedPropertyMetadataValue();
}
Type owner = bindingContext.get(DELEGATED_PROPERTY_METADATA_OWNER, descriptor);
assert owner != null : "Delegated property owner not found: " + descriptor;
List<VariableDescriptorWithAccessors> allDelegatedProperties = bindingContext.get(DELEGATED_PROPERTIES_WITH_METADATA, owner);
int index = allDelegatedProperties == null ? -1 : allDelegatedProperties.indexOf(descriptor);
if (index < 0) {
throw new AssertionError("Delegated property not found in " + owner + ": " + descriptor);
}
StackValue.Field array = StackValue.field(
Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none()
);
return StackValue.arrayElement(K_PROPERTY_TYPE, null, array, StackValue.constant(index));
}
private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
private final PropertyAccessorDescriptor propertyAccessorDescriptor;
public DelegatedPropertyAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
super(state);
this.propertyAccessorDescriptor = descriptor;
}
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
InstructionAdapter v = codegen.v;
BindingContext bindingContext = state.getBindingContext();
ResolvedCall<FunctionDescriptor> resolvedCall =
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, propertyAccessorDescriptor);
assert resolvedCall != null : "Resolve call should be recorded for delegate call " + signature.toString();
PropertyDescriptor propertyDescriptor = propertyAccessorDescriptor.getCorrespondingProperty();
StackValue.Property property = codegen.intermediateValueForProperty(propertyDescriptor, true, null, StackValue.LOCAL_0);
StackValue.Property delegate = property.getDelegateOrNull();
assert delegate != null : "No delegate for delegated property: " + propertyDescriptor;
StackValue lastValue = invokeDelegatedPropertyConventionMethod(codegen, resolvedCall, delegate, propertyDescriptor);
Type asmType = signature.getReturnType();
KotlinType kotlinReturnType = propertyAccessorDescriptor.getOriginal().getReturnType();
lastValue.put(asmType, kotlinReturnType, v);
v.areturn(asmType);
}
}
public void genDelegate(@NotNull PropertyDescriptor delegate, @NotNull PropertyDescriptor delegateTo, @NotNull StackValue field) {
ClassDescriptor toClass = (ClassDescriptor) delegateTo.getContainingDeclaration();
PropertyGetterDescriptor getter = delegate.getGetter();
if (getter != null) {
//noinspection ConstantConditions
functionCodegen.genDelegate(getter, delegateTo.getGetter().getOriginal(), toClass, field);
}
PropertySetterDescriptor setter = delegate.getSetter();
if (setter != null) {
//noinspection ConstantConditions
functionCodegen.genDelegate(setter, delegateTo.getSetter().getOriginal(), toClass, field);
}
}
}

View File

@@ -1222,9 +1222,8 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
oldLvt += record
}
method.localVariables.clear()
// Skip `this` for suspend lambda
// Skip `this` for suspend lamdba
val start = if (isForNamedFunction) 0 else 1
val oldLvtNodeToLatestNewLvtNode = mutableMapOf<LocalVariableNode, LocalVariableNode>()
for (variableIndex in start until method.maxLocals) {
if (oldLvt.none { it.index == variableIndex }) continue
var startLabel: LabelNode? = null
@@ -1240,15 +1239,25 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
val endLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode ?: continue
// startLabel can be null in case of parameters
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
// Attempt to extend existing local variable node corresponding to the record in
// the original local variable table.
var recordToExtend: LocalVariableNode? = oldLvtNodeToLatestNewLvtNode[lvtRecord]
if (recordToExtend != null && InsnSequence(recordToExtend.end, startLabel).none { isBeforeSuspendMarker(it) }) {
var recordToExtend: LocalVariableNode? = null
for (record in method.localVariables) {
if (record.name == lvtRecord.name &&
record.desc == lvtRecord.desc &&
record.signature == lvtRecord.signature &&
record.index == lvtRecord.index
) {
if (InsnSequence(record.end, startLabel).none { isBeforeSuspendMarker(it) }) {
recordToExtend = record
break
}
}
}
if (recordToExtend != null) {
recordToExtend.end = endLabel
} else {
val node = LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
method.localVariables.add(node)
oldLvtNodeToLatestNewLvtNode[lvtRecord] = node
method.localVariables.add(
LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
)
}
}
}

View File

@@ -136,7 +136,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
) {
var nodeAndSmap: SMAPAndMethodNode? = null
try {
nodeAndSmap = createInlineMethodNode(mapDefaultSignature, typeArguments, typeSystem)
nodeAndSmap = createInlineMethodNode(
functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler
)
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
} catch (e: CompilationException) {
throw e
@@ -272,8 +274,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
abstract fun extractDefaultLambdas(node: MethodNode): List<DefaultLambda>
abstract fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean
fun generateAndInsertFinallyBlocks(
intoNode: MethodNode,
insertPoints: List<MethodInliner.PointForExternalFinallyBlocks>,
@@ -512,33 +512,38 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
}
internal fun createInlineMethodNode(
callDefault: Boolean,
typeArguments: List<TypeParameterMarker>?,
typeSystem: TypeSystemCommonBackendContext
): SMAPAndMethodNode {
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
if (intrinsic != null) {
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
}
val asmMethod = if (callDefault)
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompiler.contextKind)
else
mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !descriptorIsDeserialized(directMember)) {
val node = sourceCompiler.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
return node
}
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
}
companion object {
internal fun createInlineMethodNode(
functionDescriptor: FunctionDescriptor,
methodOwner: Type,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
typeArguments: List<TypeParameterMarker>?,
typeSystem: TypeSystemCommonBackendContext,
state: GenerationState,
sourceCompilerForInline: SourceCompilerForInline
): SMAPAndMethodNode {
val intrinsic = generateInlineIntrinsic(state, functionDescriptor, typeArguments, typeSystem)
if (intrinsic != null) {
return SMAPAndMethodNode(intrinsic, createDefaultFakeSMAP())
}
val asmMethod = if (callDefault)
state.typeMapper.mapDefaultMethod(functionDescriptor, sourceCompilerForInline.contextKind)
else
mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod)
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
if (!isBuiltInArrayIntrinsic(functionDescriptor) && directMember !is DescriptorWithContainerSource) {
val node = sourceCompilerForInline.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod)
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
return node
}
return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature)
}
internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode {
val directMember = getDirectMemberAndCallableFromObject(functionDescriptor)
assert(directMember is DescriptorWithContainerSource) {
@@ -572,8 +577,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
doCreateMethodNodeFromCompiled(directMember, state, jvmSignature.asmMethod)
else
null
result ?:
throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor")
result ?: throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor")
}
return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP)

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.linkWithLabel
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class InlineCodegenForDefaultBody(
@@ -39,10 +41,8 @@ class InlineCodegenForDefaultBody(
}
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
val nodeAndSmap = PsiInlineCodegen(
codegen, state, function, methodOwner, jvmSignature, TypeParameterMappings(), sourceCompilerForInline
).createInlineMethodNode(
callDefault, null, codegen.typeSystem
val nodeAndSmap = InlineCodegen.createInlineMethodNode(
function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline
)
val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP)

View File

@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getMethodAsmFlags
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
@@ -26,7 +25,6 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlinableParameterExpres
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -210,7 +208,4 @@ class PsiInlineCodegen(
::PsiDefaultLambda
)
}
override fun descriptorIsDeserialized(memberDescriptor: CallableMemberDescriptor): Boolean =
memberDescriptor is DescriptorWithContainerSource
}

View File

@@ -130,9 +130,7 @@ fun <T, R : DefaultLambda> expandMaskConditionsAndUpdateVariableNodes(
node.instructions.insert(position, newInsn)
}
node.localVariables.removeIf {
(it.start in toDelete && it.end in toDelete) || defaultLambdas.contains(it.index)
}
node.localVariables.removeIf { it.start in toDelete && it.end in toDelete }
node.remove(toDelete)

View File

@@ -6,7 +6,10 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
@@ -41,10 +44,6 @@ fun CallableDescriptor.isGenericParameter(): Boolean {
fun classFileContainsMethod(descriptor: FunctionDescriptor, state: GenerationState, method: Method): Boolean? {
if (descriptor !is DeserializedSimpleFunctionDescriptor) return null
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
return descriptor.overriddenDescriptors.any { classFileContainsMethod(it, state, method) == true }
}
val classId: ClassId = when {
descriptor.containingDeclaration is DeserializedClassDescriptor -> {
(descriptor.containingDeclaration as DeserializedClassDescriptor).classId ?: return null

View File

@@ -8,4 +8,4 @@ package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>>
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>?>

View File

@@ -8,4 +8,4 @@ package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>?>
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>>

View File

@@ -201,7 +201,7 @@ class GenerationState private constructor(
val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
val runtimeStringConcat =
if (target.majorVersion >= JvmTarget.JVM_9.majorVersion)
if (target.bytecodeVersion >= JvmTarget.JVM_9.bytecodeVersion)
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INLINE
else JvmStringConcat.INLINE
@@ -272,10 +272,7 @@ class GenerationState private constructor(
val rootContext: CodegenContext<*> = RootContext(this)
val classFileVersion: Int = run {
val minorVersion = if (configuration.getBoolean(JVMConfigurationKeys.ENABLE_JVM_PREVIEW)) 0xffff else 0
(minorVersion shl 16) + target.majorVersion
}
val classFileVersion: Int = target.bytecodeVersion
val generateParametersMetadata: Boolean = configuration.getBoolean(JVMConfigurationKeys.PARAMETERS_METADATA)

View File

@@ -5,4 +5,4 @@
package org.jetbrains.kotlin.codegen.state
typealias JvmMethodExceptionTypes = Array<out String?>?
typealias JvmMethodExceptionTypes = Array<out String>?

View File

@@ -5,4 +5,4 @@
package org.jetbrains.kotlin.codegen.state
typealias JvmMethodExceptionTypes = Array<out String>?
typealias JvmMethodExceptionTypes = Array<out String?>?

View File

@@ -50,7 +50,6 @@ import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall
import org.jetbrains.kotlin.resolve.BindingContextUtils.isBoxedLocalCapturedInClosure
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -61,7 +60,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.resolve.jvm.JAVA_LANG_RECORD_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.jvm.annotations.isCompiledToJvmDefault
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
@@ -381,8 +379,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
val originalDescriptor = descriptor.original
return CallableMethod(
owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION) }, method, INVOKESPECIAL,
null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false,
boxInlineClassBeforeInvoke = false
null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false
)
}
@@ -405,7 +402,6 @@ class KotlinTypeMapper @JvmOverloads constructor(
val dispatchReceiverKotlinType: KotlinType?
var isInterfaceMember = false
var isDefaultMethodInInterface = false
var boxInlineClassBeforeInvoke = false
if (functionParent is ClassDescriptor) {
val declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor)
@@ -456,15 +452,11 @@ class KotlinTypeMapper @JvmOverloads constructor(
functionDescriptor = descriptor
}
val isFakeOverrideOfJvmDefault = toInlinedErasedClass &&
functionDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
functionDescriptor.overridesJvmDefault()
val isStaticInvocation = !isFakeOverrideOfJvmDefault &&
(isStaticDeclaration(functionDescriptor) && functionDescriptor !is ImportedFromObjectCallableDescriptor<*> ||
isStaticAccessor(functionDescriptor) ||
functionDescriptor.isJvmStaticInObjectOrClassOrInterface() ||
toInlinedErasedClass)
val isStaticInvocation =
isStaticDeclaration(functionDescriptor) && functionDescriptor !is ImportedFromObjectCallableDescriptor<*> ||
isStaticAccessor(functionDescriptor) ||
functionDescriptor.isJvmStaticInObjectOrClassOrInterface() ||
toInlinedErasedClass
when {
isStaticInvocation -> {
invokeOpcode = INVOKESTATIC
@@ -474,13 +466,8 @@ class KotlinTypeMapper @JvmOverloads constructor(
invokeOpcode = INVOKEINTERFACE
isInterfaceMember = true
}
isFakeOverrideOfJvmDefault -> {
invokeOpcode = INVOKEVIRTUAL
boxInlineClassBeforeInvoke = true
}
else -> {
val isPrivateFunInvocation =
DescriptorVisibilities.isPrivate(functionDescriptor.visibility) && !functionDescriptor.isSuspend
val isPrivateFunInvocation = DescriptorVisibilities.isPrivate(functionDescriptor.visibility) && !functionDescriptor.isSuspend
invokeOpcode = if (superCall || isPrivateFunInvocation) INVOKESPECIAL else INVOKEVIRTUAL
isInterfaceMember = false
}
@@ -492,7 +479,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
else
functionDescriptor.original
signature = if (toInlinedErasedClass && !isFakeOverrideOfJvmDefault)
signature = if (toInlinedErasedClass)
mapSignatureForInlineErasedClassSkipGeneric(functionToCall)
else
mapSignature(
@@ -560,18 +547,10 @@ class KotlinTypeMapper @JvmOverloads constructor(
signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType,
calleeType, returnKotlinType,
if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE,
isDefaultMethodInInterface, boxInlineClassBeforeInvoke
isDefaultMethodInInterface
)
}
private fun CallableMemberDescriptor.overridesJvmDefault(): Boolean {
if (kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
return overriddenDescriptors.any { it.overridesJvmDefault() }
}
if (isCompiledToJvmDefault(jvmDefaultMode)) return true
return (containingDeclaration as? JavaClassDescriptor)?.kind == ClassKind.INTERFACE && modality != Modality.ABSTRACT
}
fun mapFunctionName(descriptor: FunctionDescriptor, kind: OwnerKind?): String {
if (descriptor !is JavaCallableMemberDescriptor) {
val platformName = getJvmName(descriptor)
@@ -584,16 +563,10 @@ class KotlinTypeMapper @JvmOverloads constructor(
return when {
descriptor is PropertyAccessorDescriptor -> {
val property = descriptor.correspondingProperty
val containingDeclaration = property.containingDeclaration
if (isAnnotationClass(containingDeclaration) &&
(!property.hasJvmStaticAnnotation() && !descriptor.hasJvmStaticAnnotation())
) {
if (isAnnotationClass(property.containingDeclaration)) {
return property.name.asString()
}
if ((containingDeclaration as? ClassDescriptor)?.hasJavaLangRecordSupertype() == true) return property.name.asString()
val isAccessor = property is AccessorForPropertyDescriptor
val propertyName = if (isAccessor)
(property as AccessorForPropertyDescriptor).accessorSuffix
@@ -628,9 +601,6 @@ class KotlinTypeMapper @JvmOverloads constructor(
}
}
private fun ClassDescriptor.hasJavaLangRecordSupertype() =
typeConstructor.supertypes.any { KotlinBuiltIns.isConstructedFromGivenClass(it, JAVA_LANG_RECORD_FQ_NAME) }
private val shouldMangleByReturnType =
languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses)

View File

@@ -98,9 +98,6 @@ projectTest(parallel = true) {
}
}
val generateTestData by generator("org.jetbrains.kotlin.generators.tests.GenerateCompilerTestDataKt")
val generateTests by generator("org.jetbrains.kotlin.generators.tests.GenerateCompilerTestsKt") {
dependsOn(generateTestData)
}
val generateTests by generator("org.jetbrains.kotlin.generators.tests.GenerateCompilerTestsKt")
testsJar()

View File

@@ -49,7 +49,6 @@ if "%_KOTLIN_RUNNER%"=="1" (
"%_JAVACMD%" %JAVA_OPTS% "-Dkotlin.home=%_KOTLIN_HOME%" -cp "%_KOTLIN_HOME%\lib\kotlin-runner.jar" ^
org.jetbrains.kotlin.runner.Main %KOTLIN_OPTS%
) else (
setlocal EnableDelayedExpansion
SET _ADDITIONAL_CLASSPATH=
if not "%_KOTLIN_TOOL%"=="" (
@@ -57,7 +56,7 @@ if "%_KOTLIN_RUNNER%"=="1" (
)
"%_JAVACMD%" %JAVA_OPTS% -noverify -cp "%_KOTLIN_HOME%\lib\kotlin-preloader.jar" ^
org.jetbrains.kotlin.preloading.Preloader -cp "%_KOTLIN_HOME%\lib\kotlin-compiler.jar!_ADDITIONAL_CLASSPATH!" ^
org.jetbrains.kotlin.preloading.Preloader -cp "%_KOTLIN_HOME%\lib\kotlin-compiler.jar%_ADDITIONAL_CLASSPATH%" ^
%_KOTLIN_COMPILER% %KOTLIN_OPTS%
)

View File

@@ -1,12 +0,0 @@
<idea-plugin>
<id>org.jetbrains.kotlin</id>
<version>1.2</version>
<!-- Don't add more extension points here! Logic in KotlinCoreEnvironment assumes that there is only one EP. -->
<!-- And this file should be removed once 202 is no longer supported -->
<extensionPoints>
<extensionPoint qualifiedName="com.intellij.psi.classFileDecompiler"
interface="com.intellij.psi.compiled.ClassFileDecompilers$Decompiler"
dynamic="true"/>
</extensionPoints>
</idea-plugin>

View File

@@ -418,13 +418,6 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
var useOldInlineClassesManglingScheme: Boolean by FreezableVar(false)
@Argument(
value = "-Xjvm-enable-preview",
description = "Allow using features from Java language that are in preview phase.\n" +
"Works as `--enable-preview` in Java. All class files are marked as preview-generated thus it won't be possible to use them in release environment"
)
var enableJvmPreview: Boolean by FreezableVar(false)
override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
val result = super.configureAnalysisFlags(collector)
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
@@ -445,7 +438,6 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
result[JvmAnalysisFlags.sanitizeParentheses] = sanitizeParentheses
result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError
result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames
result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview
result[AnalysisFlags.reportErrorsOnIrDependencies] = !useIR && !useFir && !allowJvmIrDependencies
result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses
return result

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.common.messages
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
/**
* This class behaviour is the same as [MessageCollector.report] in [AnalyzerWithCompilerReport.reportDiagnostic].
*/
class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
val messageCollector: MessageCollector
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
render,
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
)
}

View File

@@ -17,6 +17,8 @@
package org.jetbrains.kotlin.cli.common.messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.jar.CoreJarVirtualFile;
import com.intellij.openapi.vfs.local.CoreLocalVirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
@@ -51,6 +53,10 @@ public class MessageUtil {
@NotNull
public static String virtualFileToPath(@NotNull VirtualFile virtualFile) {
return toSystemDependentName(virtualFile.getPath());
// Convert path to platform-dependent format when virtualFile is local file.
if (virtualFile instanceof CoreLocalVirtualFile || virtualFile instanceof CoreJarVirtualFile) {
return toSystemDependentName(virtualFile.getPath());
}
return virtualFile.getPath();
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.common.messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils;
import static com.intellij.openapi.util.io.FileUtil.toSystemDependentName;
public class MessageUtil {
private MessageUtil() {}
@Nullable
public static CompilerMessageLocation psiElementToMessageLocation(@Nullable PsiElement element) {
if (element == null) return null;
PsiFile file = element.getContainingFile();
return psiFileToMessageLocation(file, "<no path>", DiagnosticUtils.getLineAndColumnInPsiFile(file, element.getTextRange()));
}
@Nullable
public static CompilerMessageLocation psiFileToMessageLocation(
@NotNull PsiFile file,
@Nullable String defaultValue,
@NotNull PsiDiagnosticUtils.LineAndColumn lineAndColumn
) {
VirtualFile virtualFile = file.getVirtualFile();
String path = virtualFile != null ? virtualFileToPath(virtualFile) : defaultValue;
return CompilerMessageLocation.create(path, lineAndColumn.getLine(), lineAndColumn.getColumn(), lineAndColumn.getLineContent());
}
@NotNull
public static String virtualFileToPath(@NotNull VirtualFile virtualFile) {
return toSystemDependentName(virtualFile.getPath());
}
}

View File

@@ -77,23 +77,15 @@ open class CliBindingTrace @TestOnly constructor() : BindingTraceContext() {
this.kotlinCodeAnalyzer = kotlinCodeAnalyzer
}
@Suppress("UNCHECKED_CAST")
override fun <K, V> get(slice: ReadOnlySlice<K, V>, key: K): V? {
val value = super.get(slice, key)
if (value == null) {
if (key is KtDeclaration) {
// NB: intentional code duplication, see https://youtrack.jetbrains.com/issue/KT-43296
if (BindingContext.FUNCTION === slice) {
if (BindingContext.FUNCTION === slice || BindingContext.VARIABLE === slice) {
if (key is KtDeclaration) {
if (!KtPsiUtil.isLocal(key)) {
kotlinCodeAnalyzer!!.resolveToDescriptor(key)
return super.get(slice, key) as V?
}
}
if (BindingContext.VARIABLE === slice) {
if (!KtPsiUtil.isLocal(key)) {
kotlinCodeAnalyzer!!.resolveToDescriptor(key)
return super.get(slice, key) as V?
return super.get(slice, key)
}
}
}

View File

@@ -40,6 +40,7 @@ public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnviron
registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class);
registerApplicationExtensionPoint(ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class);
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
@@ -51,4 +52,4 @@ public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnviron
protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem();
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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.cli.jvm.compiler;
import com.intellij.DynamicBundle;
import com.intellij.codeInsight.ContainerProvider;
import com.intellij.codeInsight.runner.JavaMainMethodProvider;
import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.lang.MetaLanguage;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.psi.FileContextProvider;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.compiled.ClassFileDecompilers;
import com.intellij.psi.meta.MetaDataContributor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnvironment {
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
KotlinCoreApplicationEnvironment environment = new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
registerExtensionPoints();
return environment;
}
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
super(parentDisposable, unitTestMode);
}
private static void registerExtensionPoints() {
registerApplicationExtensionPoint(DynamicBundle.LanguageBundleEP.EP_NAME, DynamicBundle.LanguageBundleEP.class);
registerApplicationExtensionPoint(FileContextProvider.EP_NAME, FileContextProvider.class);
registerApplicationExtensionPoint(MetaDataContributor.EP_NAME, MetaDataContributor.class);
registerApplicationExtensionPoint(PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class);
registerApplicationExtensionPoint(ClassFileDecompilers.getInstance().EP_NAME, ClassFileDecompilers.Decompiler.class);
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(Extensions.getRootArea());
}
@Nullable
@Override
protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem();
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2010-2019 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.cli.jvm.compiler;
import com.intellij.DynamicBundle;
import com.intellij.codeInsight.ContainerProvider;
import com.intellij.codeInsight.runner.JavaMainMethodProvider;
import com.intellij.core.JavaCoreApplicationEnvironment;
import com.intellij.lang.MetaLanguage;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.psi.FileContextProvider;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.meta.MetaDataContributor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnvironment {
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
KotlinCoreApplicationEnvironment environment = new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
registerExtensionPoints();
return environment;
}
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
super(parentDisposable, unitTestMode);
}
private static void registerExtensionPoints() {
registerApplicationExtensionPoint(DynamicBundle.LanguageBundleEP.EP_NAME, DynamicBundle.LanguageBundleEP.class);
registerApplicationExtensionPoint(FileContextProvider.EP_NAME, FileContextProvider.class);
registerApplicationExtensionPoint(MetaDataContributor.EP_NAME, MetaDataContributor.class);
registerApplicationExtensionPoint(PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class);
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(Extensions.getRootArea());
}
@Nullable
@Override
protected VirtualFileSystem createJrtFileSystem() {
return new CoreJrtFileSystem();
}
}

View File

@@ -33,16 +33,13 @@ import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.ExtensionsArea
import com.intellij.openapi.fileTypes.PlainTextFileType
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.LanguageLevelProjectExtension
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.*
import com.intellij.openapi.vfs.impl.ZipHandler
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiManager
import com.intellij.psi.compiled.ClassFileDecompilers
import com.intellij.psi.impl.JavaClassSupersImpl
import com.intellij.psi.impl.PsiElementFinderImpl
import com.intellij.psi.impl.PsiTreeChangePreprocessor
@@ -252,8 +249,6 @@ class KotlinCoreEnvironment private constructor(
project.putUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY, fun(roots: List<File>) {
updateClasspath(roots.map { JavaSourceRoot(it, null) })
})
LanguageLevelProjectExtension.getInstance(project).languageLevel = LanguageLevel.JDK_15_PREVIEW
}
private fun collectAdditionalSources(project: MockProject) {
@@ -514,11 +509,6 @@ class KotlinCoreEnvironment private constructor(
val applicationEnvironment = KotlinCoreApplicationEnvironment.create(parentDisposable, unitTestMode)
registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/compiler.xml")
// FIX ME WHEN BUNCH 202 REMOVED: this code is required to support compiler bundled to both 202 and 203.
// Please, remove "com.intellij.psi.classFileDecompiler" EP registration once 202 is no longer supported by the compiler
if (!Extensions.getRootArea().hasExtensionPoint("com.intellij.psi.classFileDecompiler")) {
registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/core.xml")
}
registerApplicationServicesForCLI(applicationEnvironment)
registerApplicationServices(applicationEnvironment)
@@ -702,4 +692,4 @@ class KotlinCoreEnvironment private constructor(
}
}
}
}
}

View File

@@ -1,703 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.codeInsight.ExternalAnnotationsManager
import com.intellij.codeInsight.InferredAnnotationsManager
import com.intellij.core.CoreApplicationEnvironment
import com.intellij.core.CoreJavaFileManager
import com.intellij.core.JavaCoreProjectEnvironment
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.lang.java.JavaParserDefinition
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.TransactionGuard
import com.intellij.openapi.application.TransactionGuardImpl
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.extensions.ExtensionsArea
import com.intellij.openapi.fileTypes.PlainTextFileType
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.LanguageLevelProjectExtension
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.*
import com.intellij.openapi.vfs.impl.ZipHandler
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.PsiManager
import com.intellij.psi.compiled.ClassFileDecompilers
import com.intellij.psi.impl.JavaClassSupersImpl
import com.intellij.psi.impl.PsiElementFinderImpl
import com.intellij.psi.impl.PsiTreeChangePreprocessor
import com.intellij.psi.impl.file.impl.JavaFileManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.JavaClassSupers
import com.intellij.util.io.URLUtil
import com.intellij.util.lang.UrlClassLoader
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.FacadeCache
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl
import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
import org.jetbrains.kotlin.cli.common.config.ContentRoot
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.extensions.ScriptEvaluationExtension
import org.jetbrains.kotlin.cli.common.extensions.ShellExtension
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.toBooleanLenient
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.jvm.index.*
import org.jetbrains.kotlin.cli.jvm.javac.JavacWrapperRegistrar
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleResolver
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.extensions.*
import org.jetbrains.kotlin.extensions.internal.CandidateInterceptor
import org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptor
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.js.translate.extensions.JsSyntheticTranslateExtension
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver
import org.jetbrains.kotlin.resolve.extensions.ExtraImportsProviderExtension
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.serialization.DescriptorSerializerPlugin
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.nio.file.FileSystems
import java.util.zip.ZipFile
class KotlinCoreEnvironment private constructor(
val projectEnvironment: JavaCoreProjectEnvironment,
private val initialConfiguration: CompilerConfiguration,
configFiles: EnvironmentConfigFiles
) {
class ProjectEnvironment(
disposable: Disposable,
applicationEnvironment: KotlinCoreApplicationEnvironment
) :
KotlinCoreProjectEnvironment(disposable, applicationEnvironment) {
private var extensionRegistered = false
override fun preregisterServices() {
registerProjectExtensionPoints(project.extensionArea)
}
fun registerExtensionsFromPlugins(configuration: CompilerConfiguration) {
if (!extensionRegistered) {
registerPluginExtensionPoints(project)
registerExtensionsFromPlugins(project, configuration)
extensionRegistered = true
}
}
override fun registerJavaPsiFacade() {
with(project) {
registerService(
CoreJavaFileManager::class.java,
ServiceManager.getService(this, JavaFileManager::class.java) as CoreJavaFileManager
)
registerKotlinLightClassSupport(project)
registerService(ExternalAnnotationsManager::class.java, MockExternalAnnotationsManager())
registerService(InferredAnnotationsManager::class.java, MockInferredAnnotationsManager())
}
super.registerJavaPsiFacade()
}
}
private val sourceFiles = mutableListOf<KtFile>()
private val rootsIndex: JvmDependenciesDynamicCompoundIndex
private val packagePartProviders = mutableListOf<JvmPackagePartProvider>()
private val classpathRootsResolver: ClasspathRootsResolver
private val initialRoots = ArrayList<JavaRoot>()
val configuration: CompilerConfiguration = initialConfiguration.apply { setupJdkClasspathRoots(configFiles) }.copy()
init {
PersistentFSConstants::class.java.getDeclaredField("ourMaxIntellisenseFileSize")
.apply { isAccessible = true }
.setInt(null, FileUtilRt.LARGE_FOR_CONTENT_LOADING)
val project = projectEnvironment.project
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
(projectEnvironment as? ProjectEnvironment)?.registerExtensionsFromPlugins(configuration)
// otherwise consider that project environment is properly configured before passing to the environment
// TODO: consider some asserts to check important extension points
project.registerService(DeclarationProviderFactoryService::class.java, CliDeclarationProviderFactoryService(sourceFiles))
val isJvm = configFiles == EnvironmentConfigFiles.JVM_CONFIG_FILES
project.registerService(ModuleVisibilityManager::class.java, CliModuleVisibilityManagerImpl(isJvm))
registerProjectServicesForCLI(projectEnvironment)
registerProjectServices(projectEnvironment.project)
for (extension in CompilerConfigurationExtension.getInstances(project)) {
extension.updateConfiguration(configuration)
}
sourceFiles += createKtFiles(project)
collectAdditionalSources(project)
sourceFiles.sortBy { it.virtualFile.path }
val jdkHome = configuration.get(JVMConfigurationKeys.JDK_HOME)
val jrtFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JRT_PROTOCOL)
val javaModuleFinder = CliJavaModuleFinder(jdkHome?.path?.let { path ->
jrtFileSystem?.findFileByPath(path + URLUtil.JAR_SEPARATOR)
})
val outputDirectory =
configuration.get(JVMConfigurationKeys.MODULES)?.singleOrNull()?.getOutputDirectory()
?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)?.absolutePath
classpathRootsResolver = ClasspathRootsResolver(
PsiManager.getInstance(project),
messageCollector,
configuration.getList(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES),
this::contentRootToVirtualFile,
javaModuleFinder,
!configuration.getBoolean(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE),
outputDirectory?.let(this::findLocalFile)
)
val (initialRoots, javaModules) =
classpathRootsResolver.convertClasspathRoots(configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS))
this.initialRoots.addAll(initialRoots)
if (!configuration.getBoolean(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK) && messageCollector != null) {
JvmRuntimeVersionsConsistencyChecker.checkCompilerClasspathConsistency(
messageCollector,
configuration,
initialRoots.mapNotNull { (file, type) -> if (type == JavaRoot.RootType.BINARY) file else null }
)
}
val (roots, singleJavaFileRoots) =
initialRoots.partition { (file) -> file.isDirectory || file.extension != JavaFileType.DEFAULT_EXTENSION }
// REPL and kapt2 update classpath dynamically
rootsIndex = JvmDependenciesDynamicCompoundIndex().apply {
addIndex(JvmDependenciesIndexImpl(roots))
updateClasspathFromRootsIndex(this)
}
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
rootsIndex,
packagePartProviders,
SingleJavaFileRootsIndex(singleJavaFileRoots),
configuration.getBoolean(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING)
)
project.registerService(
JavaModuleResolver::class.java,
CliJavaModuleResolver(classpathRootsResolver.javaModuleGraph, javaModules, javaModuleFinder.systemModules.toList())
)
val finderFactory = CliVirtualFileFinderFactory(rootsIndex)
project.registerService(MetadataFinderFactory::class.java, finderFactory)
project.registerService(VirtualFileFinderFactory::class.java, finderFactory)
project.putUserData(APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY, fun(roots: List<File>) {
updateClasspath(roots.map { JavaSourceRoot(it, null) })
})
}
private fun collectAdditionalSources(project: MockProject) {
var unprocessedSources: Collection<KtFile> = sourceFiles
val processedSources = HashSet<KtFile>()
val processedSourcesByExtension = HashMap<CollectAdditionalSourcesExtension, Collection<KtFile>>()
// repeat feeding extensions with sources while new sources a being added
var sourceCollectionIterations = 0
while (unprocessedSources.isNotEmpty()) {
if (sourceCollectionIterations++ > 10) { // TODO: consider using some appropriate global constant
throw IllegalStateException("Unable to collect additional sources in reasonable number of iterations")
}
processedSources.addAll(unprocessedSources)
val allNewSources = ArrayList<KtFile>()
for (extension in CollectAdditionalSourcesExtension.getInstances(project)) {
// do not feed the extension with the sources it returned on the previous iteration
val sourcesToProcess = unprocessedSources - (processedSourcesByExtension[extension] ?: emptyList())
val newSources = extension.collectAdditionalSourcesAndUpdateConfiguration(sourcesToProcess, configuration, project)
if (newSources.isNotEmpty()) {
allNewSources.addAll(newSources)
processedSourcesByExtension[extension] = newSources
}
}
unprocessedSources = allNewSources.filterNot { processedSources.contains(it) }.distinct()
sourceFiles += unprocessedSources
}
}
fun addKotlinSourceRoots(rootDirs: List<File>) {
val roots = rootDirs.map { KotlinSourceRoot(it.absolutePath, isCommon = false) }
sourceFiles += createSourceFilesFromSourceRoots(configuration, project, roots)
}
fun createPackagePartProvider(scope: GlobalSearchScope): JvmPackagePartProvider {
return JvmPackagePartProvider(configuration.languageVersionSettings, scope).apply {
addRoots(initialRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY))
packagePartProviders += this
(ModuleAnnotationsResolver.getInstance(project) as CliModuleAnnotationsResolver).addPackagePartProvider(this)
}
}
private val VirtualFile.javaFiles: List<VirtualFile>
get() = mutableListOf<VirtualFile>().apply {
VfsUtilCore.processFilesRecursively(this@javaFiles) { file ->
if (file.fileType == JavaFileType.INSTANCE) {
add(file)
}
true
}
}
private val allJavaFiles: List<File>
get() = configuration.javaSourceRoots
.mapNotNull(this::findLocalFile)
.flatMap { it.javaFiles }
.map { File(it.canonicalPath) }
fun registerJavac(
javaFiles: List<File> = allJavaFiles,
kotlinFiles: List<KtFile> = sourceFiles,
arguments: Array<String>? = null,
bootClasspath: List<File>? = null,
sourcePath: List<File>? = null
): Boolean {
return JavacWrapperRegistrar.registerJavac(
projectEnvironment.project, configuration, javaFiles, kotlinFiles, arguments, bootClasspath, sourcePath,
LightClassGenerationSupport.getInstance(project), packagePartProviders
)
}
private val applicationEnvironment: CoreApplicationEnvironment
get() = projectEnvironment.environment
val project: Project
get() = projectEnvironment.project
internal fun countLinesOfCode(sourceFiles: List<KtFile>): Int =
sourceFiles.sumBy { sourceFile ->
val text = sourceFile.text
StringUtil.getLineBreakCount(text) + (if (StringUtil.endsWithLineBreak(text)) 0 else 1)
}
private fun updateClasspathFromRootsIndex(index: JvmDependenciesIndex) {
index.indexedRoots.forEach {
projectEnvironment.addSourcesToClasspath(it.file)
}
}
fun updateClasspath(contentRoots: List<ContentRoot>): List<File>? {
// TODO: add new Java modules to CliJavaModuleResolver
val newRoots = classpathRootsResolver.convertClasspathRoots(contentRoots).roots
if (packagePartProviders.isEmpty()) {
initialRoots.addAll(newRoots)
} else {
for (packagePartProvider in packagePartProviders) {
packagePartProvider.addRoots(newRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY))
}
}
return rootsIndex.addNewIndexForRoots(newRoots)?.let { newIndex ->
updateClasspathFromRootsIndex(newIndex)
newIndex.indexedRoots.mapNotNull { (file) ->
VfsUtilCore.virtualToIoFile(VfsUtilCore.getVirtualFileForJar(file) ?: file)
}.toList()
}.orEmpty()
}
private fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? =
when (root) {
is JvmClasspathRoot ->
if (root.file.isFile) findJarRoot(root.file) else findExistingRoot(root, "Classpath entry")
is JvmModulePathRoot ->
if (root.file.isFile) findJarRoot(root.file) else findExistingRoot(root, "Java module root")
is JavaSourceRoot ->
findExistingRoot(root, "Java source root")
else ->
throw IllegalStateException("Unexpected root: $root")
}
internal fun findLocalFile(path: String): VirtualFile? =
applicationEnvironment.localFileSystem.findFileByPath(path)
private fun findExistingRoot(root: JvmContentRoot, rootDescription: String): VirtualFile? {
return findLocalFile(root.file.absolutePath).also {
if (it == null) {
report(STRONG_WARNING, "$rootDescription points to a non-existent location: ${root.file}")
}
}
}
private fun findJarRoot(file: File): VirtualFile? =
applicationEnvironment.jarFileSystem.findFileByPath("$file${URLUtil.JAR_SEPARATOR}")
private fun getSourceRootsCheckingForDuplicates(): List<KotlinSourceRoot> {
val uniqueSourceRoots = hashSetOf<String>()
val result = mutableListOf<KotlinSourceRoot>()
for (root in configuration.kotlinSourceRoots) {
if (!uniqueSourceRoots.add(root.path)) {
report(STRONG_WARNING, "Duplicate source root: ${root.path}")
}
result.add(root)
}
return result
}
fun getSourceFiles(): List<KtFile> = sourceFiles
private fun createKtFiles(project: Project): List<KtFile> =
createSourceFilesFromSourceRoots(configuration, project, getSourceRootsCheckingForDuplicates())
internal fun report(severity: CompilerMessageSeverity, message: String) = configuration.report(severity, message)
companion object {
private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java)
private val APPLICATION_LOCK = Object()
private var ourApplicationEnvironment: KotlinCoreApplicationEnvironment? = null
private var ourProjectCount = 0
@JvmStatic
fun createForProduction(
parentDisposable: Disposable, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles
): KotlinCoreEnvironment {
setupIdeaStandaloneExecution()
val appEnv = getOrCreateApplicationEnvironmentForProduction(parentDisposable, configuration)
val projectEnv = ProjectEnvironment(parentDisposable, appEnv)
val environment = KotlinCoreEnvironment(projectEnv, configuration, configFiles)
synchronized(APPLICATION_LOCK) {
ourProjectCount++
}
return environment
}
@JvmStatic
fun createForProduction(
projectEnvironment: JavaCoreProjectEnvironment, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles
): KotlinCoreEnvironment {
val environment = KotlinCoreEnvironment(projectEnvironment, configuration, configFiles)
if (projectEnvironment.environment == applicationEnvironment) {
// accounting for core environment disposing
synchronized(APPLICATION_LOCK) {
ourProjectCount++
}
}
return environment
}
@TestOnly
@JvmStatic
fun createForTests(
parentDisposable: Disposable, initialConfiguration: CompilerConfiguration, extensionConfigs: EnvironmentConfigFiles
): KotlinCoreEnvironment {
val configuration = initialConfiguration.copy()
// Tests are supposed to create a single project and dispose it right after use
val appEnv = createApplicationEnvironment(parentDisposable, configuration, unitTestMode = true)
val projectEnv = ProjectEnvironment(parentDisposable, appEnv)
return KotlinCoreEnvironment(projectEnv, configuration, extensionConfigs)
}
// used in the daemon for jar cache cleanup
val applicationEnvironment: KotlinCoreApplicationEnvironment? get() = ourApplicationEnvironment
fun getOrCreateApplicationEnvironmentForProduction(
parentDisposable: Disposable, configuration: CompilerConfiguration
): KotlinCoreApplicationEnvironment {
synchronized(APPLICATION_LOCK) {
if (ourApplicationEnvironment == null) {
val disposable = Disposer.newDisposable()
ourApplicationEnvironment = createApplicationEnvironment(disposable, configuration, unitTestMode = false)
ourProjectCount = 0
Disposer.register(disposable, Disposable {
synchronized(APPLICATION_LOCK) {
ourApplicationEnvironment = null
}
})
}
// Disposing of the environment is unsafe in production then parallel builds are enabled, but turning it off universally
// breaks a lot of tests, therefore it is disabled for production and enabled for tests
if (System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY).toBooleanLenient() != true) {
// JPS may run many instances of the compiler in parallel (there's an option for compiling independent modules in parallel in IntelliJ)
// All projects share the same ApplicationEnvironment, and when the last project is disposed, the ApplicationEnvironment is disposed as well
@Suppress("ObjectLiteralToLambda") // Disposer tree depends on identity of disposables.
Disposer.register(parentDisposable, object : Disposable {
override fun dispose() {
synchronized(APPLICATION_LOCK) {
if (--ourProjectCount <= 0) {
disposeApplicationEnvironment()
}
}
}
})
}
return ourApplicationEnvironment!!
}
}
/**
* This method is also used in Gradle after configuration phase finished.
*/
fun disposeApplicationEnvironment() {
synchronized(APPLICATION_LOCK) {
val environment = ourApplicationEnvironment ?: return
ourApplicationEnvironment = null
Disposer.dispose(environment.parentDisposable)
ZipHandler.clearFileAccessorCache()
}
}
private fun createApplicationEnvironment(
parentDisposable: Disposable, configuration: CompilerConfiguration, unitTestMode: Boolean
): KotlinCoreApplicationEnvironment {
val applicationEnvironment = KotlinCoreApplicationEnvironment.create(parentDisposable, unitTestMode)
registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/compiler.xml")
// FIX ME WHEN BUNCH 202 REMOVED: this code is required to support compiler bundled to both 202 and 203.
// Please, remove "com.intellij.psi.classFileDecompiler" EP registration once 202 is no longer supported by the compiler
if (!Extensions.getRootArea().hasExtensionPoint("com.intellij.psi.classFileDecompiler")) {
registerApplicationExtensionPointsAndExtensionsFrom(configuration, "extensions/core.xml")
}
registerApplicationServicesForCLI(applicationEnvironment)
registerApplicationServices(applicationEnvironment)
return applicationEnvironment
}
private fun registerApplicationExtensionPointsAndExtensionsFrom(configuration: CompilerConfiguration, configFilePath: String) {
fun File.hasConfigFile(configFile: String): Boolean =
if (isDirectory) File(this, "META-INF" + File.separator + configFile).exists()
else try {
ZipFile(this).use {
it.getEntry("META-INF/$configFile") != null
}
} catch (e: Throwable) {
false
}
val pluginRoot: File =
configuration.get(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT)?.let(::File)
?: PathUtil.getResourcePathForClass(this::class.java).takeIf { it.hasConfigFile(configFilePath) }
// hack for load extensions when compiler run directly from project directory (e.g. in tests)
?: File("compiler/cli/cli-common/resources").takeIf { it.hasConfigFile(configFilePath) }
?: throw IllegalStateException(
"Unable to find extension point configuration $configFilePath " +
"(cp:\n ${(Thread.currentThread().contextClassLoader as? UrlClassLoader)?.urls?.joinToString("\n ") { it.file }})"
)
CoreApplicationEnvironment.registerExtensionPointAndExtensions(
FileSystems.getDefault().getPath(pluginRoot.path),
configFilePath,
Extensions.getRootArea()
)
}
@JvmStatic
@Suppress("MemberVisibilityCanPrivate") // made public for CLI Android Lint
fun registerPluginExtensionPoints(project: MockProject) {
ExpressionCodegenExtension.registerExtensionPoint(project)
SyntheticResolveExtension.registerExtensionPoint(project)
ClassBuilderInterceptorExtension.registerExtensionPoint(project)
AnalysisHandlerExtension.registerExtensionPoint(project)
PackageFragmentProviderExtension.registerExtensionPoint(project)
StorageComponentContainerContributor.registerExtensionPoint(project)
DeclarationAttributeAltererExtension.registerExtensionPoint(project)
PreprocessedVirtualFileFactoryExtension.registerExtensionPoint(project)
JsSyntheticTranslateExtension.registerExtensionPoint(project)
CompilerConfigurationExtension.registerExtensionPoint(project)
CollectAdditionalSourcesExtension.registerExtensionPoint(project)
ExtraImportsProviderExtension.registerExtensionPoint(project)
IrGenerationExtension.registerExtensionPoint(project)
ScriptEvaluationExtension.registerExtensionPoint(project)
ShellExtension.registerExtensionPoint(project)
TypeResolutionInterceptor.registerExtensionPoint(project)
CandidateInterceptor.registerExtensionPoint(project)
DescriptorSerializerPlugin.registerExtensionPoint(project)
}
internal fun registerExtensionsFromPlugins(project: MockProject, configuration: CompilerConfiguration) {
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
for (registrar in configuration.getList(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)) {
try {
registrar.registerProjectComponents(project, configuration)
} catch (e: AbstractMethodError) {
val message = "The provided plugin ${registrar.javaClass.name} is not compatible with this version of compiler"
// Since the scripting plugin is often discovered in the compiler environment, it is often taken from the incompatible
// location, and in many cases this is not a fatal error, therefore strong warning is generated instead of exception
if (registrar.javaClass.simpleName == "ScriptingCompilerConfigurationComponentRegistrar") {
messageCollector?.report(STRONG_WARNING, "Default scripting plugin is disabled: $message")
} else {
throw IllegalStateException(message, e)
}
}
}
}
private fun registerApplicationServicesForCLI(applicationEnvironment: KotlinCoreApplicationEnvironment) {
// ability to get text from annotations xml files
applicationEnvironment.registerFileType(PlainTextFileType.INSTANCE, "xml")
applicationEnvironment.registerParserDefinition(JavaParserDefinition())
}
// made public for Upsource
@Suppress("MemberVisibilityCanBePrivate")
@JvmStatic
fun registerApplicationServices(applicationEnvironment: KotlinCoreApplicationEnvironment) {
with(applicationEnvironment) {
registerFileType(KotlinFileType.INSTANCE, "kt")
registerFileType(KotlinFileType.INSTANCE, KotlinParserDefinition.STD_SCRIPT_SUFFIX)
registerParserDefinition(KotlinParserDefinition())
application.registerService(KotlinBinaryClassCache::class.java, KotlinBinaryClassCache())
application.registerService(JavaClassSupers::class.java, JavaClassSupersImpl::class.java)
application.registerService(TransactionGuard::class.java, TransactionGuardImpl::class.java)
}
}
@JvmStatic
fun registerProjectExtensionPoints(area: ExtensionsArea) {
CoreApplicationEnvironment.registerExtensionPoint(
area, PsiTreeChangePreprocessor.EP.name, PsiTreeChangePreprocessor::class.java
)
CoreApplicationEnvironment.registerExtensionPoint(area, PsiElementFinder.EP.name, PsiElementFinder::class.java)
IdeaExtensionPoints.registerVersionSpecificProjectExtensionPoints(area)
}
// made public for Upsource
@JvmStatic
@Deprecated("Use registerProjectServices(project) instead.", ReplaceWith("registerProjectServices(projectEnvironment.project)"))
fun registerProjectServices(
projectEnvironment: JavaCoreProjectEnvironment,
@Suppress("UNUSED_PARAMETER") messageCollector: MessageCollector?
) {
registerProjectServices(projectEnvironment.project)
}
// made public for Android Lint
@JvmStatic
fun registerProjectServices(project: MockProject) {
with(project) {
registerService(KotlinJavaPsiFacade::class.java, KotlinJavaPsiFacade(this))
registerService(FacadeCache::class.java, FacadeCache(this))
registerService(ModuleAnnotationsResolver::class.java, CliModuleAnnotationsResolver())
}
}
private fun registerProjectServicesForCLI(@Suppress("UNUSED_PARAMETER") projectEnvironment: JavaCoreProjectEnvironment) {
/**
* Note that Kapt may restart code analysis process, and CLI services should be aware of that.
* Use PsiManager.getModificationTracker() to ensure that all the data you cached is still valid.
*/
}
// made public for Android Lint
@JvmStatic
fun registerKotlinLightClassSupport(project: MockProject) {
with(project) {
val traceHolder = CliTraceHolder()
val cliLightClassGenerationSupport = CliLightClassGenerationSupport(traceHolder, project)
val kotlinAsJavaSupport = CliKotlinAsJavaSupport(this, traceHolder)
registerService(LightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
registerService(CliLightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
registerService(KotlinAsJavaSupport::class.java, kotlinAsJavaSupport)
registerService(CodeAnalyzerInitializer::class.java, traceHolder)
// We don't pass Disposable because in some tests, we manually unregister these extensions, and that leads to LOG.error
// exception from `ExtensionPointImpl.doRegisterExtension`, because the registered extension can no longer be found
// when the project is being disposed.
// For example, see the `unregisterExtension` call in `GenerationUtils.compileFilesUsingFrontendIR`.
// TODO: refactor this to avoid registering unneeded extensions in the first place, and avoid using deprecated API.
@Suppress("DEPRECATION")
PsiElementFinder.EP.getPoint(project).registerExtension(JavaElementFinder(this, kotlinAsJavaSupport))
@Suppress("DEPRECATION")
PsiElementFinder.EP.getPoint(project).registerExtension(PsiElementFinderImpl(this))
}
}
private fun CompilerConfiguration.setupJdkClasspathRoots(configFiles: EnvironmentConfigFiles) {
if (getBoolean(JVMConfigurationKeys.NO_JDK)) return
val jvmTarget = configFiles == EnvironmentConfigFiles.JVM_CONFIG_FILES
if (!jvmTarget) return
val jdkHome = get(JVMConfigurationKeys.JDK_HOME)
val (javaRoot, classesRoots) = if (jdkHome == null) {
val javaHome = File(System.getProperty("java.home"))
put(JVMConfigurationKeys.JDK_HOME, javaHome)
javaHome to PathUtil.getJdkClassesRootsFromCurrentJre()
} else {
jdkHome to PathUtil.getJdkClassesRoots(jdkHome)
}
if (!CoreJrtFileSystem.isModularJdk(javaRoot)) {
if (classesRoots.isEmpty()) {
report(ERROR, "No class roots are found in the JDK path: $javaRoot")
} else {
addJvmSdkRoots(classesRoots)
}
}
}
}
}

View File

@@ -686,4 +686,4 @@ class KotlinCoreEnvironment private constructor(
}
}
}
}
}

View File

@@ -463,10 +463,6 @@ object KotlinToJVMBytecodeCompiler {
environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) })
}
if (result.additionalClassPathRoots.isNotEmpty()) {
environment.updateClasspath(result.additionalClassPathRoots.map { JvmClasspathRoot(it, false) })
}
if (result.additionalKotlinRoots.isNotEmpty()) {
environment.addKotlinSourceRoots(result.additionalKotlinRoots)
}
@@ -476,8 +472,8 @@ object KotlinToJVMBytecodeCompiler {
// Clear all diagnostic messages
configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]?.clear()
// Repeat analysis with additional source roots generated by compiler plugins.
return repeatAnalysisIfNeeded(analyze(environment), environment)
// Repeat analysis with additional Java roots (kapt generated sources)
return analyze(environment)
}
return result

View File

@@ -12,6 +12,4 @@ fun setupIdeaStandaloneExecution() {
System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000")
System.getProperties().setProperty("ide.hide.excluded.files", "false")
System.getProperties().setProperty("ast.loading.filter", "false")
System.getProperties().setProperty("idea.ignore.disabled.plugins", "true")
System.getProperties().setProperty("idea.home.path", System.getProperty("java.io.tmpdir"))
}

View File

@@ -12,4 +12,6 @@ fun setupIdeaStandaloneExecution() {
System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000")
System.getProperties().setProperty("ide.hide.excluded.files", "false")
System.getProperties().setProperty("ast.loading.filter", "false")
System.getProperties().setProperty("idea.ignore.disabled.plugins", "true")
System.getProperties().setProperty("idea.home.path", System.getProperty("java.io.tmpdir"))
}

View File

@@ -39,7 +39,7 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
}
val jvmTarget = get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
if (jvmTarget.majorVersion < JvmTarget.JVM_1_8.majorVersion) {
if (jvmTarget.bytecodeVersion < JvmTarget.JVM_1_8.bytecodeVersion) {
val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
if (jvmDefaultMode.forAllMethodsWithBody) {
messageCollector.report(
@@ -53,7 +53,7 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
val runtimeStringConcat = JvmStringConcat.fromString(arguments.stringConcat!!)
if (runtimeStringConcat != null) {
put(JVMConfigurationKeys.STRING_CONCAT, runtimeStringConcat)
if (jvmTarget.majorVersion < JvmTarget.JVM_9.majorVersion && runtimeStringConcat != JvmStringConcat.INLINE) {
if (jvmTarget.bytecodeVersion < JvmTarget.JVM_9.bytecodeVersion && runtimeStringConcat != JvmStringConcat.INLINE) {
messageCollector.report(
WARNING,
"`-Xstring-concat=${arguments.stringConcat}` does nothing with JVM target `${jvmTarget.description}`."
@@ -232,12 +232,6 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule)
put(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS, arguments.useOldSpilledVarTypeAnalysis)
put(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME, arguments.useOldInlineClassesManglingScheme)
put(JVMConfigurationKeys.ENABLE_JVM_PREVIEW, arguments.enableJvmPreview)
if (arguments.enableJvmPreview) {
getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
.report(INFO, "Using preview Java language features")
}
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
}
@@ -248,4 +242,4 @@ fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments)
?.toTypedArray()
?.filterNot { it.isEmpty() }
?.let { put(JVMConfigurationKeys.KLIB_PATHS, it) }
}
}

View File

@@ -140,7 +140,4 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> USE_OLD_INLINE_CLASSES_MANGLING_SCHEME =
CompilerConfigurationKey.create("Use old, 1.4 version of inline classes mangling scheme");
public static final CompilerConfigurationKey<Boolean> ENABLE_JVM_PREVIEW =
CompilerConfigurationKey.create("Enable Java language preview features");
}

View File

@@ -33,9 +33,6 @@ object JvmAnalysisFlags {
@JvmStatic
val disableUltraLightClasses by AnalysisFlag.Delegates.Boolean
@JvmStatic
val enableJvmPreview by AnalysisFlag.Delegates.Boolean
private object Delegates {
object JavaTypeEnhancementStateWarnByDefault {
operator fun provideDelegate(instance: Any?, property: KProperty<*>): AnalysisFlag.Delegate<JavaTypeEnhancementState> =

View File

@@ -19,21 +19,32 @@ package org.jetbrains.kotlin.config
import org.jetbrains.kotlin.platform.TargetPlatformVersion
import org.jetbrains.org.objectweb.asm.Opcodes
enum class JvmTarget(
override val description: String,
val majorVersion: Int,
) : TargetPlatformVersion {
JVM_1_6("1.6", Opcodes.V1_6),
JVM_1_8("1.8", Opcodes.V1_8),
JVM_9("9", Opcodes.V9),
JVM_10("10", Opcodes.V10),
JVM_11("11", Opcodes.V11),
JVM_12("12", Opcodes.V12),
JVM_13("13", Opcodes.V12 + 1),
JVM_14("14", Opcodes.V12 + 2),
JVM_15("15", Opcodes.V12 + 3),
enum class JvmTarget(override val description: String) : TargetPlatformVersion {
JVM_1_6("1.6"),
JVM_1_8("1.8"),
JVM_9("9"),
JVM_10("10"),
JVM_11("11"),
JVM_12("12"),
JVM_13("13"),
JVM_14("14"),
JVM_15("15"),
;
val bytecodeVersion: Int by lazy {
when (this) {
JVM_1_6 -> Opcodes.V1_6
JVM_1_8 -> Opcodes.V1_8
JVM_9 -> Opcodes.V9
JVM_10 -> Opcodes.V10
JVM_11 -> Opcodes.V11
JVM_12 -> Opcodes.V12
JVM_13 -> Opcodes.V12 + 1
JVM_14 -> Opcodes.V12 + 2
JVM_15 -> Opcodes.V12 + 3
}
}
companion object {
@JvmField
val DEFAULT = JVM_1_6
@@ -41,14 +52,14 @@ enum class JvmTarget(
@JvmStatic
fun fromString(string: String) = values().find { it.description == string }
fun getDescription(majorVersion: Int): String {
val platformDescription = values().find { it.majorVersion == majorVersion }?.description ?: when (majorVersion) {
fun getDescription(bytecodeVersion: Int): String {
val platformDescription = values().find { it.bytecodeVersion == bytecodeVersion }?.description ?: when (bytecodeVersion) {
Opcodes.V1_7 -> "1.7"
else -> null
}
return if (platformDescription != null) "JVM target $platformDescription"
else "JVM bytecode version $majorVersion"
else "JVM bytecode version $bytecodeVersion"
}
}
}

View File

@@ -28,7 +28,7 @@ public final class Test : R|kotlin/Any| {
}
@R|kotlin/jvm/JvmInline|() public final inline class Z : R|kotlin/Any| {
public final inline class Z : R|kotlin/Any| {
public open operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean|
public open fun hashCode(): R|kotlin/Int|
@@ -41,4 +41,3 @@ public final class Test : R|kotlin/Any| {
public constructor(x: R|kotlin/Int|): R|test/Z|
}

View File

@@ -1,4 +1,4 @@
@R|kotlin/jvm/JvmInline|() public final inline class Z : R|kotlin/Any| {
public final inline class Z : R|kotlin/Any| {
public open operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean|
public open fun hashCode(): R|kotlin/Int|
@@ -11,4 +11,3 @@
@R|kotlin/PublishedApi|() internal constructor(value: R|kotlin/Int|): R|test/Z|
}

View File

@@ -40,6 +40,6 @@ public final const val s: R|kotlin/Short| = Short(20000)
public final const val s1: R|kotlin/Short| = Short(1)
public get(): R|kotlin/Short|
public final const val str: R|kotlin/String| = String(:))
public final const val str: R|kotlin/String|
public get(): R|kotlin/String|

View File

@@ -3,11 +3,11 @@ interface Some {
open fun bar() {}
open val x: Int
open val y = <!PROPERTY_INITIALIZER_IN_INTERFACE!>1<!>
open val y = 1
open val z get() = 1
open var xx: Int
open var yy = <!PROPERTY_INITIALIZER_IN_INTERFACE!>1<!>
open var yy = 1
open var zz: Int
set(value) {
field = value

View File

@@ -1,44 +0,0 @@
interface CommonBackendContext
interface PhaserState<Data> {
var depth: Int
}
interface PhaseConfig {
val needProfiling: Boolean
}
inline fun <R, D> PhaserState<D>.downlevel(nlevels: Int, block: () -> R): R {
depth += nlevels
val result = block()
depth -= nlevels
return result
}
interface CompilerPhase<in Context : CommonBackendContext, Input, Output> {
fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output
}
class NamedCompilerPhase<in Context : CommonBackendContext, Data>(
private val lower: CompilerPhase<Context, Data, Data>
) : CompilerPhase<Context, Data, Data> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, input: Data): Data {
// Expected: output: Data, Actual: output: Data?
val output = if (phaseConfig.needProfiling) {
runAndProfile(phaseConfig, phaserState, context, input)
} else {
phaserState.downlevel(1) {
lower.invoke(phaseConfig, phaserState, context, input)
}
}
runAfter(phaseConfig, phaserState, context, output)
}
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, output: Data) {
}
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, source: Data): Data {
}
}

View File

@@ -1,55 +0,0 @@
FILE: compilerPhase.kt
public abstract interface CommonBackendContext : R|kotlin/Any| {
}
public abstract interface PhaserState<Data> : R|kotlin/Any| {
public abstract var depth: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
}
public abstract interface PhaseConfig : R|kotlin/Any| {
public abstract val needProfiling: R|kotlin/Boolean|
public get(): R|kotlin/Boolean|
}
public final inline fun <R, D> R|PhaserState<D>|.downlevel(nlevels: R|kotlin/Int|, block: R|() -> R|): R|R| {
this@R|/downlevel|.R|/PhaserState.depth| = this@R|/downlevel|.R|/PhaserState.depth|.R|kotlin/Int.plus|(R|<local>/nlevels|)
lval result: R|R| = R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|R|>|()
this@R|/downlevel|.R|/PhaserState.depth| = this@R|/downlevel|.R|/PhaserState.depth|.R|kotlin/Int.minus|(R|<local>/nlevels|)
^downlevel R|<local>/result|
}
public abstract interface CompilerPhase<in Context : R|CommonBackendContext|, Input, Output> : R|kotlin/Any| {
public abstract fun invoke(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Input>|, context: R|Context|, input: R|Input|): R|Output|
}
public final class NamedCompilerPhase<in Context : R|CommonBackendContext|, Data> : R|CompilerPhase<Context, Data, Data>| {
public constructor<in Context : R|CommonBackendContext|, Data>(lower: R|CompilerPhase<Context, Data, Data>|): R|NamedCompilerPhase<Context, Data>| {
super<R|kotlin/Any|>()
}
private final val lower: R|CompilerPhase<Context, Data, Data>| = R|<local>/lower|
private get(): R|CompilerPhase<Context, Data, Data>|
public final override fun invoke(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, input: R|Data|): R|Data| {
lval output: R|Data| = when () {
R|<local>/phaseConfig|.R|/PhaseConfig.needProfiling| -> {
this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.runAndProfile|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/input|)
}
else -> {
R|<local>/phaserState|.R|/downlevel|<R|Data|, R|Data|>(Int(1), <L> = downlevel@fun <anonymous>(): R|Data| <kind=UNKNOWN> {
^ this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.lower|.R|SubstitutionOverride</CompilerPhase.invoke: R|Data|>|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/input|)
}
)
}
}
this@R|/NamedCompilerPhase|.R|/NamedCompilerPhase.runAfter|(R|<local>/phaseConfig|, R|<local>/phaserState|, R|<local>/context|, R|<local>/output|)
}
private final fun runAfter(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, output: R|Data|): R|kotlin/Unit| {
}
private final fun runAndProfile(phaseConfig: R|PhaseConfig|, phaserState: R|PhaserState<Data>|, context: R|Context|, source: R|Data|): R|Data| {
}
}

View File

@@ -1,20 +0,0 @@
// FILE: AliasFor.java
public @interface AliasFor {
@AliasFor(value = "attribute")
String value() default "";
@AliasFor(value = "value")
String attribute() default "";
}
// FILE: Service.java
public @interface Service {
@AliasFor(value = "component")
String value() default "";
}
// FILE: Annotated.kt
@Service(value = "Your")
class My

View File

@@ -1,7 +0,0 @@
FILE: Annotated.kt
@R|Service|(value = String(Your)) public final class My : R|kotlin/Any| {
public constructor(): R|My| {
super<R|kotlin/Any|>()
}
}

View File

@@ -1,12 +0,0 @@
// Extracted from ReflectKotlinClass.kt
private val TYPES_ELIGIBLE_FOR_SIMPLE_VISIT = setOf<Class<*>>(
// Primitives
java.lang.Integer::class.java, java.lang.Character::class.java, java.lang.Byte::class.java, java.lang.Long::class.java,
java.lang.Short::class.java, java.lang.Boolean::class.java, java.lang.Double::class.java, java.lang.Float::class.java,
// Arrays of primitives
IntArray::class.java, CharArray::class.java, ByteArray::class.java, LongArray::class.java,
ShortArray::class.java, BooleanArray::class.java, DoubleArray::class.java, FloatArray::class.java,
// Others
Class::class.java, String::class.java
)

View File

@@ -1,3 +0,0 @@
FILE: TypesEligibleForSimpleVisit.kt
private final val TYPES_ELIGIBLE_FOR_SIMPLE_VISIT: R|kotlin/collections/Set<java/lang/Class<*>>| = R|kotlin/collections/setOf|<R|java/lang/Class<*>|>(vararg(<getClass>(Q|java/lang/Integer|).R|kotlin/jvm/java|<R|java/lang/Integer|>, <getClass>(Q|java/lang/Character|).R|kotlin/jvm/java|<R|java/lang/Character|>, <getClass>(Q|java/lang/Byte|).R|kotlin/jvm/java|<R|java/lang/Byte|>, <getClass>(Q|java/lang/Long|).R|kotlin/jvm/java|<R|java/lang/Long|>, <getClass>(Q|java/lang/Short|).R|kotlin/jvm/java|<R|java/lang/Short|>, <getClass>(Q|java/lang/Boolean|).R|kotlin/jvm/java|<R|java/lang/Boolean|>, <getClass>(Q|java/lang/Double|).R|kotlin/jvm/java|<R|java/lang/Double|>, <getClass>(Q|java/lang/Float|).R|kotlin/jvm/java|<R|java/lang/Float|>, <getClass>(Q|kotlin/IntArray|).R|kotlin/jvm/java|<R|kotlin/IntArray|>, <getClass>(Q|kotlin/CharArray|).R|kotlin/jvm/java|<R|kotlin/CharArray|>, <getClass>(Q|kotlin/ByteArray|).R|kotlin/jvm/java|<R|kotlin/ByteArray|>, <getClass>(Q|kotlin/LongArray|).R|kotlin/jvm/java|<R|kotlin/LongArray|>, <getClass>(Q|kotlin/ShortArray|).R|kotlin/jvm/java|<R|kotlin/ShortArray|>, <getClass>(Q|kotlin/BooleanArray|).R|kotlin/jvm/java|<R|kotlin/BooleanArray|>, <getClass>(Q|kotlin/DoubleArray|).R|kotlin/jvm/java|<R|kotlin/DoubleArray|>, <getClass>(Q|kotlin/FloatArray|).R|kotlin/jvm/java|<R|kotlin/FloatArray|>, <getClass>(Q|java/lang/Class|).R|kotlin/jvm/java|<R|java/lang/Class<*>|>, <getClass>(Q|kotlin/String|).R|kotlin/jvm/java|<R|kotlin/String|>))
private get(): R|kotlin/collections/Set<java/lang/Class<*>>|

View File

@@ -2024,11 +2024,6 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("compilerPhase.kt")
public void testCompilerPhase() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.kt");
}
@TestMetadata("complexLambdaWithTypeVariableAsExpectedType.kt")
public void testComplexLambdaWithTypeVariableAsExpectedType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/complexLambdaWithTypeVariableAsExpectedType.kt");
@@ -2084,11 +2079,6 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/questionableSmartCast.kt");
}
@TestMetadata("recursiveNamedAnnotation.kt")
public void testRecursiveNamedAnnotation() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.kt");
}
@TestMetadata("safeCallInvoke.kt")
public void testSafeCallInvoke() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/safeCallInvoke.kt");

View File

@@ -2024,11 +2024,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("compilerPhase.kt")
public void testCompilerPhase() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.kt");
}
@TestMetadata("complexLambdaWithTypeVariableAsExpectedType.kt")
public void testComplexLambdaWithTypeVariableAsExpectedType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/complexLambdaWithTypeVariableAsExpectedType.kt");
@@ -2084,11 +2079,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/problems/questionableSmartCast.kt");
}
@TestMetadata("recursiveNamedAnnotation.kt")
public void testRecursiveNamedAnnotation() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.kt");
}
@TestMetadata("safeCallInvoke.kt")
public void testSafeCallInvoke() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/safeCallInvoke.kt");

View File

@@ -1239,11 +1239,6 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/receiverResolutionInLambda.kt");
}
@TestMetadata("TypesEligibleForSimpleVisit.kt")
public void testTypesEligibleForSimpleVisit() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/TypesEligibleForSimpleVisit.kt");
}
@TestMetadata("weakHashMap.kt")
public void testWeakHashMap() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/weakHashMap.kt");

View File

@@ -10659,16 +10659,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/captureTypeOnlyOnTopLevel.kt");
}
@TestMetadata("capturedFlexibleIntersectionTypesWithDifferentBounds.kt")
public void testCapturedFlexibleIntersectionTypesWithDifferentBounds() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentBounds.kt");
}
@TestMetadata("capturedFlexibleIntersectionTypesWithDifferentConstructors.kt")
public void testCapturedFlexibleIntersectionTypesWithDifferentConstructors() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedFlexibleIntersectionTypesWithDifferentConstructors.kt");
}
@TestMetadata("capturedType.kt")
public void testCapturedType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.kt");
@@ -12917,11 +12907,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassesInsideAnnotations.kt");
}
@TestMetadata("innerClassInsideInlineClass.kt")
public void testInnerClassInsideInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/innerClassInsideInlineClass.kt");
}
@TestMetadata("lateinitInlineClasses.kt")
public void testLateinitInlineClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/lateinitInlineClasses.kt");
@@ -12957,11 +12942,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt");
}
@TestMetadata("varPropertyWithInlineClassReceiver.kt")
public void testVarPropertyWithInlineClassReceiver() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/varPropertyWithInlineClassReceiver.kt");
}
@TestMetadata("varargsOnParametersOfInlineClassType.kt")
public void testVarargsOnParametersOfInlineClassType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.kt");
@@ -19071,11 +19051,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.kt");
}
@TestMetadata("resolveCollectionLiteralInsideLambda.kt")
public void testResolveCollectionLiteralInsideLambda() throws Exception {
runTest("compiler/testData/diagnostics/tests/regressions/resolveCollectionLiteralInsideLambda.kt");
}
@TestMetadata("resolveSubclassOfList.kt")
public void testResolveSubclassOfList() throws Exception {
runTest("compiler/testData/diagnostics/tests/regressions/resolveSubclassOfList.kt");
@@ -20768,16 +20743,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenWithElse.kt");
}
@TestMetadata("ExhaustiveWithFreedom.kt")
public void testExhaustiveWithFreedom() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt");
}
@TestMetadata("inheritorInDifferentModule.kt")
public void testInheritorInDifferentModule() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/inheritorInDifferentModule.kt");
}
@TestMetadata("Local.kt")
public void testLocal() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/Local.kt");
@@ -20788,21 +20753,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/sealed/LocalSealed.kt");
}
@TestMetadata("MultipleFiles_enabled.kt")
public void testMultipleFiles_enabled() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/MultipleFiles_enabled.kt");
}
@TestMetadata("NestedSealed.kt")
public void testNestedSealed() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/NestedSealed.kt");
}
@TestMetadata("NestedSealedWithoutRestrictions.kt")
public void testNestedSealedWithoutRestrictions() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/NestedSealedWithoutRestrictions.kt");
}
@TestMetadata("NeverConstructed.kt")
public void testNeverConstructed() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/NeverConstructed.kt");
@@ -20902,34 +20857,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
public void testWithInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/WithInterface.kt");
}
@TestMetadata("compiler/testData/diagnostics/tests/sealed/interfaces")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Interfaces extends AbstractFirOldFrontendDiagnosticsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInInterfaces() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/sealed/interfaces"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("inheritorInDifferentModule.kt")
public void testInheritorInDifferentModule() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/interfaces/inheritorInDifferentModule.kt");
}
@TestMetadata("sealedInterfacesDisabled.kt")
public void testSealedInterfacesDisabled() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/interfaces/sealedInterfacesDisabled.kt");
}
@TestMetadata("simpleSealedInterface.kt")
public void testSimpleSealedInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/interfaces/simpleSealedInterface.kt");
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/secondaryConstructors")

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
@@ -200,11 +201,6 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/explicitMetadata.kt");
}
@TestMetadata("jvmRecordWithoutJdk15.kt")
public void testJvmRecordWithoutJdk15() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmRecordWithoutJdk15.kt");
}
@TestMetadata("JvmSyntheticOnDelegate.kt")
public void testJvmSyntheticOnDelegate() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/JvmSyntheticOnDelegate.kt");
@@ -1658,6 +1654,10 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInCoroutines() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@@ -1783,8 +1783,8 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
@TestMetadata("noDefaultCoroutineImports.kt")
public void testNoDefaultCoroutineImports() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/noDefaultCoroutineImports.kt");
public void testNoDefaultCoroutineImports_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/noDefaultCoroutineImports.kt", "kotlin.coroutines");
}
@TestMetadata("nonLocalSuspension.kt")
@@ -1813,8 +1813,8 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
@TestMetadata("suspendApplicability.kt")
public void testSuspendApplicability() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendApplicability.kt");
public void testSuspendApplicability_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendApplicability.kt", "kotlin.coroutines");
}
@TestMetadata("suspendConflictsWithNoSuspend.kt")
@@ -1843,8 +1843,8 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
@TestMetadata("suspendCovarianJavaOverride.kt")
public void testSuspendCovarianJavaOverride() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCovarianJavaOverride.kt");
public void testSuspendCovarianJavaOverride_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCovarianJavaOverride.kt", "kotlin.coroutines");
}
@TestMetadata("suspendDestructuring.kt")
@@ -1863,23 +1863,23 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
@TestMetadata("suspendFunctions.kt")
public void testSuspendFunctions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctions.kt");
public void testSuspendFunctions_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctions.kt", "kotlin.coroutines");
}
@TestMetadata("suspendJavaImplementationFromDifferentClass.kt")
public void testSuspendJavaImplementationFromDifferentClass() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendJavaImplementationFromDifferentClass.kt");
public void testSuspendJavaImplementationFromDifferentClass_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendJavaImplementationFromDifferentClass.kt", "kotlin.coroutines");
}
@TestMetadata("suspendJavaOverrides.kt")
public void testSuspendJavaOverrides() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendJavaOverrides.kt");
public void testSuspendJavaOverrides_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendJavaOverrides.kt", "kotlin.coroutines");
}
@TestMetadata("suspendLambda.kt")
public void testSuspendLambda() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendLambda.kt");
public void testSuspendLambda_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendLambda.kt", "kotlin.coroutines");
}
@TestMetadata("suspendOverridability.kt")
@@ -1940,6 +1940,10 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInCallableReference() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/callableReference"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@@ -1955,8 +1959,8 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
@TestMetadata("property.kt")
public void testProperty() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/callableReference/property.kt");
public void testProperty_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/callableReference/property.kt", "kotlin.coroutines");
}
@TestMetadata("suspendConversionForCallableReferences.kt")
@@ -2256,68 +2260,72 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInInlineCrossinline() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("inlineOrdinaryOfCrossinlineOrdinary.kt")
public void testInlineOrdinaryOfCrossinlineOrdinary() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineOrdinary.kt");
public void testInlineOrdinaryOfCrossinlineOrdinary_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineOrdinary.kt", "kotlin.coroutines");
}
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineSuspend.kt");
public void testInlineOrdinaryOfCrossinlineSuspend_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineSuspend.kt", "kotlin.coroutines");
}
@TestMetadata("inlineOrdinaryOfNoinlineOrdinary.kt")
public void testInlineOrdinaryOfNoinlineOrdinary() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfNoinlineOrdinary.kt");
public void testInlineOrdinaryOfNoinlineOrdinary_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfNoinlineOrdinary.kt", "kotlin.coroutines");
}
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfNoinlineSuspend.kt");
public void testInlineOrdinaryOfNoinlineSuspend_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfNoinlineSuspend.kt", "kotlin.coroutines");
}
@TestMetadata("inlineOrdinaryOfOrdinary.kt")
public void testInlineOrdinaryOfOrdinary() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfOrdinary.kt");
public void testInlineOrdinaryOfOrdinary_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfOrdinary.kt", "kotlin.coroutines");
}
@TestMetadata("inlineOrdinaryOfSuspend.kt")
public void testInlineOrdinaryOfSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfSuspend.kt");
public void testInlineOrdinaryOfSuspend_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfSuspend.kt", "kotlin.coroutines");
}
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfCrossinlineOrdinary.kt");
public void testInlineSuspendOfCrossinlineOrdinary_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfCrossinlineOrdinary.kt", "kotlin.coroutines");
}
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfCrossinlineSuspend.kt");
public void testInlineSuspendOfCrossinlineSuspend_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfCrossinlineSuspend.kt", "kotlin.coroutines");
}
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfNoinlineOrdinary.kt");
public void testInlineSuspendOfNoinlineOrdinary_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfNoinlineOrdinary.kt", "kotlin.coroutines");
}
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfNoinlineSuspend.kt");
public void testInlineSuspendOfNoinlineSuspend_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfNoinlineSuspend.kt", "kotlin.coroutines");
}
@TestMetadata("inlineSuspendOfOrdinary.kt")
public void testInlineSuspendOfOrdinary() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfOrdinary.kt");
public void testInlineSuspendOfOrdinary_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfOrdinary.kt", "kotlin.coroutines");
}
@TestMetadata("inlineSuspendOfSuspend.kt")
public void testInlineSuspendOfSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfSuspend.kt");
public void testInlineSuspendOfSuspend_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfSuspend.kt", "kotlin.coroutines");
}
}
@@ -2357,28 +2365,32 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInRestrictSuspension() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("allMembersAllowed.kt")
public void testAllMembersAllowed() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/allMembersAllowed.kt");
public void testAllMembersAllowed_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/allMembersAllowed.kt", "kotlin.coroutines");
}
@TestMetadata("extensions.kt")
public void testExtensions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/extensions.kt");
public void testExtensions_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/extensions.kt", "kotlin.coroutines");
}
@TestMetadata("memberExtension.kt")
public void testMemberExtension() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/memberExtension.kt");
public void testMemberExtension_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/memberExtension.kt", "kotlin.coroutines");
}
@TestMetadata("notRelatedFun.kt")
public void testNotRelatedFun() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/notRelatedFun.kt");
public void testNotRelatedFun_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/notRelatedFun.kt", "kotlin.coroutines");
}
@TestMetadata("outerYield_1_2.kt")
@@ -2392,18 +2404,18 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
@TestMetadata("sameInstance.kt")
public void testSameInstance() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/sameInstance.kt");
public void testSameInstance_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/sameInstance.kt", "kotlin.coroutines");
}
@TestMetadata("simpleForbidden.kt")
public void testSimpleForbidden() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/simpleForbidden.kt");
public void testSimpleForbidden_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/simpleForbidden.kt", "kotlin.coroutines");
}
@TestMetadata("wrongEnclosingFunction.kt")
public void testWrongEnclosingFunction() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/wrongEnclosingFunction.kt");
public void testWrongEnclosingFunction_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension/wrongEnclosingFunction.kt", "kotlin.coroutines");
}
}
@@ -2498,13 +2510,17 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInTailCalls() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/tailCalls"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("forbidden.kt")
public void testForbidden() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/tailCalls/forbidden.kt");
public void testForbidden_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/tailCalls/forbidden.kt", "kotlin.coroutines");
}
@TestMetadata("localFunctions.kt")
@@ -2528,13 +2544,13 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
@TestMetadata("tryCatch.kt")
public void testTryCatch() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/tailCalls/tryCatch.kt");
public void testTryCatch_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/tailCalls/tryCatch.kt", "kotlin.coroutines");
}
@TestMetadata("valid.kt")
public void testValid() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/tailCalls/valid.kt");
public void testValid_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/diagnostics/testsWithStdLib/coroutines/tailCalls/valid.kt", "kotlin.coroutines");
}
}
}

View File

@@ -2024,11 +2024,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("compilerPhase.kt")
public void testCompilerPhase() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/compilerPhase.kt");
}
@TestMetadata("complexLambdaWithTypeVariableAsExpectedType.kt")
public void testComplexLambdaWithTypeVariableAsExpectedType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/complexLambdaWithTypeVariableAsExpectedType.kt");
@@ -2084,11 +2079,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/problems/questionableSmartCast.kt");
}
@TestMetadata("recursiveNamedAnnotation.kt")
public void testRecursiveNamedAnnotation() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/recursiveNamedAnnotation.kt");
}
@TestMetadata("safeCallInvoke.kt")
public void testSafeCallInvoke() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/safeCallInvoke.kt");

View File

@@ -116,7 +116,7 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
return targetFile
}
}
}, ""
)
environment = createEnvironment(content)
val virtualFiles = srcFiles.map {

View File

@@ -0,0 +1,41 @@
/*
* 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
import com.intellij.psi.tree.IElementType
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.fir.*
fun FirSourceElement.getChild(type: IElementType, index: Int = 0, depth: Int = -1): FirSourceElement? {
return getChild(setOf(type), index, depth)
}
fun FirSourceElement.getChild(types: TokenSet, index: Int = 0, depth: Int = -1): FirSourceElement? {
return getChild(types.types.toSet(), index, depth)
}
fun FirSourceElement.getChild(types: Set<IElementType>, index: Int = 0, depth: Int = -1): FirSourceElement? {
return when (this) {
is FirPsiSourceElement<*> -> {
getChild(types, index, depth)
}
is FirLightSourceElement -> {
getChild(types, index, depth)
}
else -> null
}
}
private fun FirPsiSourceElement<*>.getChild(types: Set<IElementType>, index: Int, depth: Int): FirSourceElement? {
val visitor = PsiElementFinderByType(types, index, depth)
return visitor.find(psi)?.toFirPsiSourceElement()
}
private fun FirLightSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int): FirSourceElement? {
val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth)
return visitor.find(lighterASTNode)?.toFirLightSourceElement(treeStructure)
}

View File

@@ -112,7 +112,7 @@ class PropertyInitializationInfoCollector(private val localProperties: Set<FirPr
}
fun getData(graph: ControlFlowGraph) =
graph.collectDataForNode(
graph.collectPathAwareDataForNode(
TraverseDirection.Forward,
PathAwarePropertyInitializationInfo.EMPTY,
this
@@ -128,14 +128,15 @@ class PropertyInitializationInfoCollector(private val localProperties: Set<FirPr
}
internal fun <P : PathAwareControlFlowInfo<P, S>, S : ControlFlowInfo<S, K, EventOccurrencesRange>, K : Any> addRange(
pathAwareInfo: P,
info: P,
key: K,
range: EventOccurrencesRange,
constructor: (PersistentMap<EdgeLabel, S>) -> P
): P {
var resultMap = persistentMapOf<EdgeLabel, S>()
// before: { |-> { p1 |-> PI1 }, l1 |-> { p2 |-> PI2 } }
for ((label, dataPerLabel) in pathAwareInfo) {
for (label in info.keys) {
val dataPerLabel = info[label]!!
val existingKind = dataPerLabel[key] ?: EventOccurrencesRange.ZERO
val kind = existingKind + range
resultMap = resultMap.put(label, dataPerLabel.put(key, kind))

View File

@@ -31,12 +31,14 @@ fun ControlFlowGraph.traverse(
traverse(direction, visitor, null)
}
// ---------------------- Path-sensitive data collection -----------------------
// --------------------- Path-insensitive data collection ----------------------
// TODO: Deprecate and make all existing checkers path-sensitive
fun <I : ControlFlowInfo<I, K, V>, K : Any, V : Any> ControlFlowGraph.collectDataForNode(
direction: TraverseDirection,
initialInfo: I,
visitor: ControlFlowGraphVisitor<I, Collection<Pair<EdgeLabel, I>>>
visitor: ControlFlowGraphVisitor<I, Collection<I>>
): Map<CFGNode<*>, I> {
val nodeMap = LinkedHashMap<CFGNode<*>, I>()
val startNode = getEnterNode(direction)
@@ -53,7 +55,7 @@ fun <I : ControlFlowInfo<I, K, V>, K : Any, V : Any> ControlFlowGraph.collectDat
private fun <I : ControlFlowInfo<I, K, V>, K : Any, V : Any> ControlFlowGraph.collectDataForNodeInternal(
direction: TraverseDirection,
initialInfo: I,
visitor: ControlFlowGraphVisitor<I, Collection<Pair<EdgeLabel, I>>>,
visitor: ControlFlowGraphVisitor<I, Collection<I>>,
nodeMap: MutableMap<CFGNode<*>, I>,
changed: MutableMap<CFGNode<*>, Boolean>
) {
@@ -66,6 +68,56 @@ private fun <I : ControlFlowInfo<I, K, V>, K : Any, V : Any> ControlFlowGraph.co
TraverseDirection.Forward -> node.previousCfgNodes
TraverseDirection.Backward -> node.followingCfgNodes
}
val previousData = previousNodes.mapNotNull { nodeMap[it] }
val data = nodeMap[node]
val newData = node.accept(visitor, previousData)
val hasChanged = newData != data
changed[node] = hasChanged
if (hasChanged) {
nodeMap[node] = newData
}
if (direction == TraverseDirection.Forward && node is CFGNodeWithCfgOwner<*>) {
node.subGraphs.forEach { it.collectDataForNodeInternal(direction, initialInfo, visitor, nodeMap, changed) }
}
}
}
// ---------------------- Path-sensitive data collection -----------------------
// TODO: Once migration is done, get rid of "PathAware" from util names
fun <I : ControlFlowInfo<I, K, V>, K : Any, V : Any> ControlFlowGraph.collectPathAwareDataForNode(
direction: TraverseDirection,
initialInfo: I,
visitor: ControlFlowGraphVisitor<I, Collection<Pair<EdgeLabel, I>>>
): Map<CFGNode<*>, I> {
val nodeMap = LinkedHashMap<CFGNode<*>, I>()
val startNode = getEnterNode(direction)
nodeMap[startNode] = initialInfo
val changed = mutableMapOf<CFGNode<*>, Boolean>()
do {
collectPathAwareDataForNodeInternal(direction, initialInfo, visitor, nodeMap, changed)
} while (changed.any { it.value })
return nodeMap
}
private fun <I : ControlFlowInfo<I, K, V>, K : Any, V : Any> ControlFlowGraph.collectPathAwareDataForNodeInternal(
direction: TraverseDirection,
initialInfo: I,
visitor: ControlFlowGraphVisitor<I, Collection<Pair<EdgeLabel, I>>>,
nodeMap: MutableMap<CFGNode<*>, I>,
changed: MutableMap<CFGNode<*>, Boolean>
) {
val nodes = getNodesInOrder(direction)
for (node in nodes) {
if (direction == TraverseDirection.Backward && node is CFGNodeWithCfgOwner<*>) {
node.subGraphs.forEach { it.collectPathAwareDataForNodeInternal(direction, initialInfo, visitor, nodeMap, changed) }
}
val previousNodes = when (direction) {
TraverseDirection.Forward -> node.previousCfgNodes
TraverseDirection.Backward -> node.followingCfgNodes
}
// One noticeable different against the path-unaware version is, here, we pair the control-flow info with the label.
val previousData =
previousNodes.mapNotNull {
@@ -84,7 +136,7 @@ private fun <I : ControlFlowInfo<I, K, V>, K : Any, V : Any> ControlFlowGraph.co
nodeMap[node] = newData
}
if (direction == TraverseDirection.Forward && node is CFGNodeWithCfgOwner<*>) {
node.subGraphs.forEach { it.collectDataForNodeInternal(direction, initialInfo, visitor, nodeMap, changed) }
node.subGraphs.forEach { it.collectPathAwareDataForNodeInternal(direction, initialInfo, visitor, nodeMap, changed) }
}
}
}

View File

@@ -80,7 +80,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
}
}
val invocationData = graph.collectDataForNode(
val invocationData = graph.collectPathAwareDataForNode(
TraverseDirection.Forward,
PathAwareLambdaInvocationInfo.EMPTY,
InvocationDataCollector(functionalTypeEffects.keys.filterTo(mutableSetOf()) { it !in leakedSymbols })
@@ -89,9 +89,9 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
for ((symbol, effectDeclaration) in functionalTypeEffects) {
graph.exitNode.previousCfgNodes.forEach { node ->
val requiredRange = effectDeclaration.kind
val pathAwareInfo = invocationData.getValue(node)
for (info in pathAwareInfo.values) {
if (investigate(info, symbol, requiredRange, function, reporter)) {
val info = invocationData.getValue(node)
for (label in info.keys) {
if (investigate(info.getValue(label), symbol, requiredRange, function, reporter)) {
// To avoid duplicate reports, stop investigating remaining paths once reported.
break
}

View File

@@ -49,8 +49,8 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
if (symbol !in localProperties) return
if (symbol.fir.isLateInit) return
val pathAwareInfo = data.getValue(node)
for (info in pathAwareInfo.values) {
if (investigate(info, symbol, node)) {
for (label in pathAwareInfo.keys) {
if (investigate(pathAwareInfo[label]!!, symbol, node)) {
// To avoid duplicate reports, stop investigating remaining paths if the property is not initialized at any path.
break
}

View File

@@ -12,9 +12,6 @@ import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSymbolOwner
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
@@ -28,7 +25,6 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -153,7 +149,7 @@ fun FirSymbolOwner<*>.getContainingClass(context: CheckerContext): FirClassLikeD
* Returns the FirClassLikeDeclaration the type alias is pointing
* to provided `this` is a FirTypeAlias. Returns this otherwise.
*/
fun FirClassLikeDeclaration<*>.followAlias(session: FirSession): FirClassLikeDeclaration<*> {
fun FirClassLikeDeclaration<*>.followAlias(session: FirSession): FirClassLikeDeclaration<*>? {
return this.safeAs<FirTypeAlias>()
?.expandedTypeRef
?.firClassLike(session)
@@ -254,21 +250,20 @@ fun FirMemberDeclaration.implicitModality(context: CheckerContext): Modality {
}
val klass = context.findClosestClassOrObject() ?: return Modality.FINAL
val source = source ?: return Modality.FINAL
val tree = source.treeStructure
if (tree.overrideModifier(source.lighterASTNode) != null) {
val klassModalityTokenType = klass.source?.let { tree.modalityModifier(it.lighterASTNode)?.tokenType }
if (klassModalityTokenType == KtTokens.ABSTRACT_KEYWORD ||
klassModalityTokenType == KtTokens.OPEN_KEYWORD ||
klassModalityTokenType == KtTokens.SEALED_KEYWORD
) {
val modifiers = this.modifierListOrNull() ?: return Modality.FINAL
if (modifiers.contains(KtTokens.OVERRIDE_KEYWORD)) {
val klassModifiers = klass.modifierListOrNull()
if (klassModifiers != null && klassModifiers.run {
contains(KtTokens.ABSTRACT_KEYWORD) || contains(KtTokens.OPEN_KEYWORD) || contains(KtTokens.SEALED_KEYWORD)
}) {
return Modality.OPEN
}
}
if (klass is FirRegularClass
if (
klass is FirRegularClass
&& klass.classKind == ClassKind.INTERFACE
&& tree.visibilityModifier(source.lighterASTNode)?.tokenType != KtTokens.PRIVATE_KEYWORD
&& !modifiers.contains(KtTokens.PRIVATE_KEYWORD)
) {
return if (this.hasBody()) Modality.OPEN else Modality.ABSTRACT
}
@@ -276,6 +271,8 @@ fun FirMemberDeclaration.implicitModality(context: CheckerContext): Modality {
return Modality.FINAL
}
private fun FirDeclaration.modifierListOrNull() = this.source.getModifierList()?.modifiers?.map { it.token }
private fun FirDeclaration.hasBody(): Boolean = when (this) {
is FirSimpleFunction -> this.body != null && this.body !is FirEmptyExpressionBlock
is FirProperty -> this.setter?.body !is FirEmptyExpressionBlock? || this.getter?.body !is FirEmptyExpressionBlock?

View File

@@ -0,0 +1,77 @@
/*
* 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
import com.intellij.lang.ASTNode
import com.intellij.lang.LighterASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.TokenSet
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtModifierListOwner
sealed class FirModifierList {
abstract val modifiers: List<FirModifier<*>>
}
fun FirSourceElement?.getModifierList(): FirModifierList? {
return when (this) {
null -> null
is FirPsiSourceElement<*> -> (psi as? KtModifierListOwner)?.modifierList?.let { FirPsiModifierList(it) }
is FirLightSourceElement -> {
val modifierListNode = lighterASTNode.getChildren(treeStructure).find { it?.tokenType == KtNodeTypes.MODIFIER_LIST }
?: return null
FirLightModifierList(modifierListNode, treeStructure)
}
}
}
private val MODIFIER_KEYWORD_SET = TokenSet.orSet(KtTokens.SOFT_KEYWORDS, TokenSet.create(KtTokens.IN_KEYWORD, KtTokens.FUN_KEYWORD))
class FirPsiModifierList(val modifierList: KtModifierList) : FirModifierList() {
override val modifiers: List<FirPsiModifier>
get() = modifierList.node.getChildren(MODIFIER_KEYWORD_SET).map { node ->
FirPsiModifier(node, node.elementType as KtModifierKeywordToken)
}
}
class FirLightModifierList(val modifierList: LighterASTNode, val tree: FlyweightCapableTreeStructure<LighterASTNode>) : FirModifierList() {
override val modifiers: List<FirLightModifier>
get() {
val modifierNodes = modifierList.getChildren(tree)
return modifierNodes.filterNotNull()
.filter { it.tokenType is KtModifierKeywordToken }
.map { FirLightModifier(it, it.tokenType as KtModifierKeywordToken, tree) }
}
}
sealed class FirModifier<Node : Any>(val node: Node, val token: KtModifierKeywordToken)
class FirPsiModifier(
node: ASTNode,
token: KtModifierKeywordToken
) : FirModifier<ASTNode>(node, token)
class FirLightModifier(
node: LighterASTNode,
token: KtModifierKeywordToken,
val tree: FlyweightCapableTreeStructure<LighterASTNode>
) : FirModifier<LighterASTNode>(node, token)
val FirModifier<*>.psi: PsiElement? get() = (this as? FirPsiModifier)?.node?.psi
val FirModifier<*>.lightNode: LighterASTNode? get() = (this as? FirLightModifier)?.node
val FirModifier<*>.source: FirSourceElement?
get() = when (this) {
is FirPsiModifier -> psi?.toFirPsiSourceElement()
is FirLightModifier -> node.toFirLightSourceElement(tree)
}

View File

@@ -1,120 +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.declaration
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.extended.report
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
// See old FE's [DeclarationsChecker]
object FirMemberPropertyChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass) {
return
}
for (member in declaration.declarations) {
if (member is FirProperty) {
checkProperty(declaration, member, reporter)
}
}
}
private fun checkProperty(containingDeclaration: FirRegularClass, property: FirProperty, reporter: DiagnosticReporter) {
if (inInterface(containingDeclaration) &&
property.visibility == Visibilities.Private &&
!property.isAbstract &&
(property.getter == null || property.getter is FirDefaultPropertyAccessor)
) {
property.source?.let { source ->
reporter.report(source, FirErrors.PRIVATE_PROPERTY_IN_INTERFACE)
}
}
if (property.isAbstract) {
if (!containingDeclaration.isAbstract && !containingDeclaration.isSealed && !inEnumClass(containingDeclaration)) {
property.source?.let { source ->
reporter.report(source, FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS)
return
}
}
if (property.delegate != null) {
property.delegate!!.source?.let {
if (inInterface(containingDeclaration)) {
reporter.report(FirErrors.DELEGATED_PROPERTY_IN_INTERFACE.on(it, property.delegate!!))
} else {
reporter.report(FirErrors.ABSTRACT_DELEGATED_PROPERTY.on(it, property.delegate!!))
}
}
}
checkAccessor(property.getter, property.delegate) { src, symbol ->
reporter.report(FirErrors.ABSTRACT_PROPERTY_WITH_GETTER.on(src, symbol))
}
checkAccessor(property.setter, property.delegate) { src, symbol ->
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
reporter.report(FirErrors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY.on(src, symbol))
} else {
reporter.report(FirErrors.ABSTRACT_PROPERTY_WITH_SETTER.on(src, symbol))
}
}
}
checkPropertyInitializer(containingDeclaration, property, reporter)
if (property.isOpen) {
checkAccessor(property.setter, property.delegate) { src, symbol ->
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
reporter.report(FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY.on(src, symbol))
}
}
}
}
private fun checkPropertyInitializer(containingDeclaration: FirRegularClass, property: FirProperty, reporter: DiagnosticReporter) {
property.initializer?.source?.let {
if (property.isAbstract) {
reporter.report(FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER.on(it, property.initializer!!))
} else if (inInterface(containingDeclaration)) {
reporter.report(FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE.on(it, property.initializer!!))
}
}
if (property.isAbstract) {
if (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) {
property.source?.let {
reporter.report(FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(it, property.symbol))
}
}
}
}
private fun checkAccessor(
accessor: FirPropertyAccessor?,
delegate: FirExpression?,
report: (FirSourceElement, FirPropertyAccessorSymbol) -> Unit,
) {
if (accessor != null && accessor !is FirDefaultPropertyAccessor && accessor.hasBody && delegate == null) {
accessor.source?.let {
report.invoke(it, accessor.symbol)
}
}
}
private fun inInterface(containingDeclaration: FirRegularClass): Boolean =
containingDeclaration.classKind == ClassKind.INTERFACE
private fun inEnumClass(containingDeclaration: FirRegularClass): Boolean =
containingDeclaration.classKind == ClassKind.ENUM_CLASS
}

View File

@@ -5,22 +5,19 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import com.intellij.lang.ASTNode
import com.intellij.lang.LighterASTNode
import com.intellij.psi.tree.TokenSet
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifier
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifierList
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
import org.jetbrains.kotlin.fir.analysis.checkers.source
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtModifierListOwner
object FirModifierChecker : FirBasicDeclarationChecker() {
@@ -115,8 +112,7 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
val firstToken = firstModifier.token
val secondToken = secondModifier.token
when (val compatibilityType = deduceCompatibilityType(firstToken, secondToken)) {
CompatibilityType.COMPATIBLE -> {
}
CompatibilityType.COMPATIBLE -> {}
CompatibilityType.REPEATED ->
if (reportedNodes.add(secondModifier)) reporter.reportRepeatedModifier(secondModifier, secondToken)
CompatibilityType.REDUNDANT_2_TO_1 ->
@@ -174,94 +170,35 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
if (!isDeclarationMappedToSourceCorrectly(declaration, source)) return
if (context.containingDeclarations.last() is FirDefaultPropertyAccessor) return
val modifierList = with(FirModifierList) { source.getModifierList() }
val modifierList = source.getModifierList()
modifierList?.let { checkModifiers(it, declaration, reporter) }
}
private fun DiagnosticReporter.reportRepeatedModifier(
modifier: FirModifier<*>, keyword: KtModifierKeywordToken
) {
report(FirErrors.REPEATED_MODIFIER.on(modifier.source, keyword))
val source = modifier.source
source?.let { report(FirErrors.REPEATED_MODIFIER.on(it, keyword)) }
}
private fun DiagnosticReporter.reportRedundantModifier(
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
) {
report(FirErrors.REDUNDANT_MODIFIER.on(modifier.source, firstKeyword, secondKeyword))
val source = modifier.source
source?.let { report(FirErrors.REDUNDANT_MODIFIER.on(it, firstKeyword, secondKeyword)) }
}
private fun DiagnosticReporter.reportDeprecatedModifierPair(
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
) {
report(FirErrors.DEPRECATED_MODIFIER_PAIR.on(modifier.source, firstKeyword, secondKeyword))
val source = modifier.source
source?.let { report(FirErrors.DEPRECATED_MODIFIER_PAIR.on(it, firstKeyword, secondKeyword)) }
}
private fun DiagnosticReporter.reportIncompatibleModifiers(
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
) {
report(FirErrors.INCOMPATIBLE_MODIFIERS.on(modifier.source, firstKeyword, secondKeyword))
}
private sealed class FirModifierList {
abstract val modifiers: List<FirModifier<*>>
class FirPsiModifierList(val modifierList: KtModifierList) : FirModifierList() {
override val modifiers: List<FirModifier.FirPsiModifier>
get() = modifierList.node.getChildren(MODIFIER_KEYWORD_SET).map { node ->
FirModifier.FirPsiModifier(node, node.elementType as KtModifierKeywordToken)
}
}
class FirLightModifierList(
val modifierList: LighterASTNode,
val tree: FlyweightCapableTreeStructure<LighterASTNode>
) : FirModifierList() {
override val modifiers: List<FirModifier.FirLightModifier>
get() {
val modifierNodes = modifierList.getChildren(tree)
return modifierNodes.filterNotNull()
.filter { it.tokenType is KtModifierKeywordToken }
.map { FirModifier.FirLightModifier(it, it.tokenType as KtModifierKeywordToken, tree) }
}
}
companion object {
fun FirSourceElement?.getModifierList(): FirModifierList? {
return when (this) {
null -> null
is FirPsiSourceElement<*> -> (psi as? KtModifierListOwner)?.modifierList?.let { FirPsiModifierList(it) }
is FirLightSourceElement -> {
val modifierListNode = lighterASTNode.getChildren(treeStructure).find { it?.tokenType == KtNodeTypes.MODIFIER_LIST }
?: return null
FirLightModifierList(modifierListNode, treeStructure)
}
}
}
}
}
private val MODIFIER_KEYWORD_SET = TokenSet.orSet(SOFT_KEYWORDS, TokenSet.create(IN_KEYWORD, FUN_KEYWORD))
sealed class FirModifier<Node : Any>(val node: Node, val token: KtModifierKeywordToken) {
class FirPsiModifier(
node: ASTNode,
token: KtModifierKeywordToken
) : FirModifier<ASTNode>(node, token) {
override val source: FirSourceElement
get() = node.psi.toFirPsiSourceElement()
}
class FirLightModifier(
node: LighterASTNode,
token: KtModifierKeywordToken,
val tree: FlyweightCapableTreeStructure<LighterASTNode>
) : FirModifier<LighterASTNode>(node, token) {
override val source: FirSourceElement
get() = node.toFirLightSourceElement(tree)
}
abstract val source: FirSourceElement
val source = modifier.source
source?.let { report(FirErrors.INCOMPATIBLE_MODIFIERS.on(it, firstKeyword, secondKeyword)) }
}
}

View File

@@ -51,7 +51,7 @@ object FirTypeMismatchOnOverrideChecker : FirRegularClassChecker() {
private fun FirTypeScope.retrieveDirectOverriddenOf(function: FirSimpleFunction): List<FirFunctionSymbol<*>> {
processFunctionsByName(function.name) {}
return getDirectOverriddenFunctions(function.symbol)
return getDirectOverriddenFunctions(function.symbol as FirNamedFunctionSymbol)
}
private fun FirTypeScope.retrieveDirectOverriddenOf(property: FirProperty): List<FirPropertySymbol> {

View File

@@ -5,12 +5,22 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import com.intellij.lang.LighterASTNode
import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes.TYPE_ARGUMENT_LIST
import org.jetbrains.kotlin.fir.FirLightSourceElement
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtTypeArgumentList
object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessChecker() {
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -19,13 +29,36 @@ object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessChecker()
val explicitReceiver = expression.explicitReceiver
if (explicitReceiver is FirResolvedQualifier && explicitReceiver.symbol == null) {
if (explicitReceiver.typeArguments.isNotEmpty()) {
if (explicitReceiver.source?.hasAnyArguments() == true) {
reporter.report(explicitReceiver.source)
return
}
}
}
private fun FirSourceElement.hasAnyArguments(): Boolean {
val localPsi = this.psi
val localLight = this.lighterASTNode
if (localPsi != null && localPsi !is PsiErrorElement) {
return localPsi.hasAnyArguments()
} else if (this is FirLightSourceElement) {
return localLight.hasAnyArguments(this.treeStructure)
}
return false
}
private fun PsiElement.hasAnyArguments(): Boolean {
val children = this.children // this is a method call and it collects children
return children.size > 1 && children[1] is KtTypeArgumentList
}
private fun LighterASTNode.hasAnyArguments(tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean {
val children = getChildren(tree)
return children.count { it != null } > 1 && children[1]?.tokenType == TYPE_ARGUMENT_LIST
}
private fun DiagnosticReporter.report(source: FirSourceElement?) {
source?.let {
report(FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.on(it))

View File

@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirOperation
import org.jetbrains.kotlin.fir.expressions.FirStatement
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.lexer.KtTokens
object ArrayEqualityCanBeReplacedWithEquals : FirBasicExpressionChecker() {
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -27,6 +29,7 @@ object ArrayEqualityCanBeReplacedWithEquals : FirBasicExpressionChecker() {
if (left.typeRef.coneType.classId != StandardClassIds.Array) return
if (right.typeRef.coneType.classId != StandardClassIds.Array) return
reporter.report(expression.source, ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS)
val source = expression.source?.getChild(setOf(KtTokens.EQEQ, KtTokens.EXCLEQ))
reporter.report(source, ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS)
}
}

View File

@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecke
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
@@ -58,7 +59,8 @@ object CanBeReplacedWithOperatorAssignmentChecker : FirExpressionChecker<FirVari
}
if (needToReport) {
reporter.report(expression.source, FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT)
val source = expression.source?.getChild(setOf(KtTokens.EQ))
reporter.report(source, FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT)
}
}

View File

@@ -12,9 +12,11 @@ import org.jetbrains.kotlin.fir.analysis.cfa.*
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.getChild
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.lexer.KtTokens
object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
override fun analyze(
@@ -40,7 +42,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
var lastDestructuredVariables = 0
for ((symbol, value) in propertiesCharacteristics) {
val source = symbol.fir.source
val source = symbol.fir.source?.getChild(setOf(KtTokens.VAL_KEYWORD, KtTokens.VAR_KEYWORD), depth = 1)
if (symbol.isDestructuring) {
lastDestructuringSource = source
lastDestructuredVariables = symbol.getDestructuringChildrenCount() ?: continue
@@ -95,11 +97,15 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
}
}
private fun FirPropertySymbol.getDestructuringChildrenCount(): Int? {
val source = fir.source ?: return null
return source.lighterASTNode.getChildren(source.treeStructure).count {
it?.tokenType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY
private fun FirPropertySymbol.getDestructuringChildrenCount(): Int? = when (fir.source) {
is FirPsiSourceElement<*> -> fir.psi?.children?.size?.minus(1) // -1 cuz we don't need expression node after equals operator
is FirLightSourceElement -> {
val source = fir.source as FirLightSourceElement
val tree = (fir.source as FirLightSourceElement).treeStructure
val children = source.lighterASTNode.getChildren(tree)
children.filter { it?.tokenType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY }.size
}
else -> null
}
private val FirPropertySymbol.isDestructuring

View File

@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirLightSourceElement
import org.jetbrains.kotlin.fir.FirPsiSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
@@ -15,11 +17,14 @@ import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -66,10 +71,10 @@ object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
}
}
is FirNamedReference -> {
if (!type.hasSameNameWithoutModifiers(initializer.name)) return
if (typeReference.text != initializer.name.identifier) return
}
is FirFunctionCall -> {
if (!type.hasSameNameWithoutModifiers(initializer.calleeReference.name)) return
if (typeReference.text != initializer.calleeReference.name.asString()) return
}
is FirGetClassCall -> {
return
@@ -86,12 +91,23 @@ object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
reporter.report(declaration.returnTypeRef.source, FirErrors.REDUNDANT_EXPLICIT_TYPE)
}
private val FirTypeRef.text: String?
get() {
return when (source) {
is FirPsiSourceElement<*> -> {
source.psi?.text
}
is FirLightSourceElement -> {
source?.lighterASTNode?.toString()
}
else -> null
}
}
private fun ConeKotlinType.isSame(other: ClassId?): Boolean {
if (this.nullability.isNullable) return false
if (this.type.classId == other) return true
return false
}
private fun ConeKotlinType.hasSameNameWithoutModifiers(name: Name): Boolean =
this is ConeClassLikeType && lookupTag.name == name && typeArguments.isEmpty() && !isMarkedNullable
}

View File

@@ -11,17 +11,17 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.implicitModality
import org.jetbrains.kotlin.fir.analysis.checkers.toToken
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.modality
object RedundantModalityModifierChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
val source = declaration.source
if (source?.kind is FirFakeSourceElementKind) return
if (declaration.source?.kind is FirFakeSourceElementKind) return
val modality = declaration.modality ?: return
if (
@@ -29,10 +29,11 @@ object RedundantModalityModifierChecker : FirMemberDeclarationChecker() {
&& (context.containingDeclarations.last() as? FirClass<*>)?.classKind == ClassKind.INTERFACE
) return
if (source != null && source.treeStructure.modalityModifier(source.lighterASTNode) == null) return
val implicitModality = declaration.implicitModality(context)
if (modality != implicitModality) return
reporter.report(source, REDUNDANT_MODALITY_MODIFIER)
val modalityModifierSource = declaration.source?.getChild(modality.toToken(), depth = 2)
reporter.report(modalityModifierSource, REDUNDANT_MODALITY_MODIFIER)
}
}

View File

@@ -16,31 +16,34 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
object RedundantVisibilityModifierChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
val source = declaration.source ?: return
if (declaration is FirConstructor && source.kind is FirFakeSourceElementKind) return
if (source is FirFakeSourceElement<*>) return
if (declaration is FirConstructor && declaration.source?.kind is FirFakeSourceElementKind) return
if (declaration.source is FirFakeSourceElement<*>) return
if (
declaration !is FirMemberDeclaration
&& !(declaration is FirPropertyAccessor && declaration.visibility == context.containingPropertyVisibility)
) return
val visibilityModifier = source.treeStructure.visibilityModifier(source.lighterASTNode)
val explicitVisibility = (visibilityModifier?.tokenType as? KtModifierKeywordToken)?.toVisibilityOrNull()
val modifiers = declaration.source.getModifierList()
val visibilityModifier = when (modifiers) {
is FirPsiModifierList -> modifiers.modifierList.getVisibility()
is FirLightModifierList -> modifiers.modifiers.visibilityOrNull()
else -> null
} ?: return
val implicitVisibility = declaration.implicitVisibility(context)
val containingMemberDeclaration = context.findClosest<FirMemberDeclaration>()
val redundantVisibility = when {
explicitVisibility == implicitVisibility -> implicitVisibility
explicitVisibility == Visibilities.Internal &&
visibilityModifier == implicitVisibility -> implicitVisibility
modifiers?.modifiers.hasModifier(KtTokens.INTERNAL_KEYWORD) &&
containingMemberDeclaration.let { decl ->
decl != null && decl.isLocalMember
decl != null && (decl.isLocalMember || modifiers?.modifiers.hasModifier(KtTokens.PRIVATE_KEYWORD))
} -> Visibilities.Internal
else -> return
}
@@ -48,12 +51,12 @@ object RedundantVisibilityModifierChecker : FirBasicDeclarationChecker() {
if (
redundantVisibility == Visibilities.Public
&& declaration is FirProperty
&& source.treeStructure.overrideModifier(source.lighterASTNode) != null
&& modifiers?.modifiers.hasModifier(KtTokens.OVERRIDE_KEYWORD)
&& declaration.isVar
&& declaration.setter?.visibility == Visibilities.Public
) return
reporter.report(source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER)
reporter.report(declaration.source?.getChild(KtTokens.VISIBILITY_MODIFIERS), FirErrors.REDUNDANT_VISIBILITY_MODIFIER)
}
private fun FirDeclaration.implicitVisibility(context: CheckerContext): Visibility {
@@ -123,4 +126,10 @@ object RedundantVisibilityModifierChecker : FirBasicDeclarationChecker() {
private val CheckerContext.containingPropertyVisibility
get() = (this.containingDeclarations.last() as? FirProperty)?.visibility
private fun List<FirLightModifier>.visibilityOrNull() =
firstOrNull { it.token.toVisibilityOrNull() != null }?.token?.toVisibilityOrNull()
private fun List<FirModifier<*>>?.hasModifier(token: KtModifierKeywordToken) = this != null && any { it.token == token }
}

View File

@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentMapOf
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.FirSymbolOwner
import org.jetbrains.kotlin.fir.analysis.cfa.*
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
@@ -17,17 +17,16 @@ import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
import org.jetbrains.kotlin.fir.analysis.checkers.isIterator
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
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.lexer.KtTokens
object UnusedChecker : FirControlFlowChecker() {
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, checkerContext: CheckerContext) {
if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(checkerContext)?.takeIf {
!it.symbol.classId.isLocal
} != null
) return
if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(checkerContext)?.takeIf { !it.symbol.classId.isLocal }!= null) return
val properties = LocalPropertyCollector.collect(graph)
if (properties.isEmpty()) return
@@ -36,53 +35,43 @@ object UnusedChecker : FirControlFlowChecker() {
}
class CfaVisitor(
val data: Map<CFGNode<*>, PathAwareVariableStatusInfo>,
val data: Map<CFGNode<*>, VariableStatusInfo>,
val reporter: DiagnosticReporter
) : ControlFlowGraphVisitorVoid() {
override fun visitNode(node: CFGNode<*>) {}
override fun visitVariableAssignmentNode(node: VariableAssignmentNode) {
val variableSymbol = (node.fir.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol ?: return
val dataPerNode = data[node] ?: return
for (dataPerLabel in dataPerNode.values) {
val data = dataPerLabel[variableSymbol] ?: continue
if (data == VariableStatus.ONLY_WRITTEN_NEVER_READ) {
// todo: report case like "a += 1" where `a` `doesn't writes` different way (special for Idea)
val source = node.fir.lValue.source
reporter.report(source, FirErrors.ASSIGNED_VALUE_IS_NEVER_READ)
// To avoid duplicate reports, stop investigating remaining paths once reported.
break
}
val data = data[node]?.get(variableSymbol) ?: return
if (data == VariableStatus.ONLY_WRITTEN_NEVER_READ) {
// todo: report case like "a += 1" where `a` `doesn't writes` different way (special for Idea)
val source = node.fir.lValue.source
reporter.report(source, FirErrors.ASSIGNED_VALUE_IS_NEVER_READ)
}
}
override fun visitVariableDeclarationNode(node: VariableDeclarationNode) {
val variableSymbol = node.fir.symbol
if (variableSymbol.isLoopIterator) return
val dataPerNode = data[node] ?: return
for (dataPerLabel in dataPerNode.values) {
val data = dataPerLabel[variableSymbol] ?: continue
val data = data[node]?.get(variableSymbol) ?: return
val variableSource = variableSymbol.fir.source.takeIf { it?.elementType != KtNodeTypes.DESTRUCTURING_DECLARATION }
when {
data == VariableStatus.UNUSED -> {
if ((node.fir.initializer as? FirFunctionCall)?.isIterator != true) {
reporter.report(variableSource, FirErrors.UNUSED_VARIABLE)
break
}
}
data.isRedundantInit -> {
val source = variableSymbol.fir.initializer?.source
reporter.report(source, FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT)
break
}
data == VariableStatus.ONLY_WRITTEN_NEVER_READ -> {
reporter.report(variableSource, FirErrors.VARIABLE_NEVER_READ)
break
}
else -> {
when {
data == VariableStatus.UNUSED -> {
if ((node.fir.initializer as? FirFunctionCall)?.isIterator != true) {
val source = variableSymbol.identifierSource
reporter.report(source, FirErrors.UNUSED_VARIABLE)
}
}
data.isRedundantInit -> {
val source = variableSymbol.fir.initializer?.source
reporter.report(source, FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT)
}
data == VariableStatus.ONLY_WRITTEN_NEVER_READ -> {
val source = variableSymbol.identifierSource
reporter.report(source, FirErrors.VARIABLE_NEVER_READ)
}
else -> {
}
}
}
}
@@ -133,102 +122,72 @@ object UnusedChecker : FirControlFlowChecker() {
}
class PathAwareVariableStatusInfo(
map: PersistentMap<EdgeLabel, VariableStatusInfo> = persistentMapOf()
) : PathAwareControlFlowInfo<PathAwareVariableStatusInfo, VariableStatusInfo>(map) {
companion object {
val EMPTY = PathAwareVariableStatusInfo(persistentMapOf(NormalPath to VariableStatusInfo.EMPTY))
}
override val constructor: (PersistentMap<EdgeLabel, VariableStatusInfo>) -> PathAwareVariableStatusInfo =
::PathAwareVariableStatusInfo
override val empty: () -> PathAwareVariableStatusInfo =
::EMPTY
}
private class ValueWritesWithoutReading(
private val localProperties: Set<FirPropertySymbol>
) : ControlFlowGraphVisitor<PathAwareVariableStatusInfo, Collection<Pair<EdgeLabel, PathAwareVariableStatusInfo>>>() {
fun getData(graph: ControlFlowGraph): Map<CFGNode<*>, PathAwareVariableStatusInfo> {
return graph.collectDataForNode(TraverseDirection.Backward, PathAwareVariableStatusInfo.EMPTY, this)
) : ControlFlowGraphVisitor<VariableStatusInfo, Collection<VariableStatusInfo>>() {
fun getData(graph: ControlFlowGraph): Map<CFGNode<*>, VariableStatusInfo> {
return graph.collectDataForNode(TraverseDirection.Backward, VariableStatusInfo.EMPTY, this)
}
override fun visitNode(
node: CFGNode<*>,
data: Collection<Pair<EdgeLabel, PathAwareVariableStatusInfo>>
): PathAwareVariableStatusInfo {
if (data.isEmpty()) return PathAwareVariableStatusInfo.EMPTY
return data.map { (label, info) -> info.applyLabel(node, label) }
.reduce(PathAwareVariableStatusInfo::merge)
override fun visitNode(node: CFGNode<*>, data: Collection<VariableStatusInfo>): VariableStatusInfo {
if (data.isEmpty()) return VariableStatusInfo.EMPTY
return data.reduce(VariableStatusInfo::merge)
}
override fun visitVariableDeclarationNode(
node: VariableDeclarationNode,
data: Collection<Pair<EdgeLabel, PathAwareVariableStatusInfo>>
): PathAwareVariableStatusInfo {
override fun visitVariableDeclarationNode(node: VariableDeclarationNode, data: Collection<VariableStatusInfo>): VariableStatusInfo {
val dataForNode = visitNode(node, data)
if (node.fir.source?.kind is FirFakeSourceElementKind) return dataForNode
val symbol = node.fir.symbol
return update(dataForNode, symbol) { prev ->
when (prev) {
null -> {
VariableStatus.UNUSED
}
VariableStatus.ONLY_WRITTEN_NEVER_READ, VariableStatus.WRITTEN_AFTER_READ -> {
if (node.fir.initializer != null && prev.isRead) {
prev.isRedundantInit = true
prev
} else if (node.fir.initializer != null) {
VariableStatus.ONLY_WRITTEN_NEVER_READ
} else {
null
}
}
VariableStatus.READ -> {
VariableStatus.READ
}
else -> {
null
return when (dataForNode[symbol]) {
null -> {
dataForNode.put(symbol, VariableStatus.UNUSED)
}
VariableStatus.ONLY_WRITTEN_NEVER_READ, VariableStatus.WRITTEN_AFTER_READ -> {
if (node.fir.initializer != null && dataForNode[symbol]?.isRead == true) {
val newData = dataForNode[symbol] ?: VariableStatus.UNUSED
newData.isRedundantInit = true
dataForNode.put(symbol, newData)
} else if (node.fir.initializer != null) {
dataForNode.put(symbol, VariableStatus.ONLY_WRITTEN_NEVER_READ)
} else {
dataForNode
}
}
VariableStatus.READ -> {
dataForNode.put(symbol, VariableStatus.READ)
}
else -> {
dataForNode
}
}
}
override fun visitVariableAssignmentNode(
node: VariableAssignmentNode,
data: Collection<Pair<EdgeLabel, PathAwareVariableStatusInfo>>
): PathAwareVariableStatusInfo {
override fun visitVariableAssignmentNode(node: VariableAssignmentNode, data: Collection<VariableStatusInfo>): VariableStatusInfo {
val dataForNode = visitNode(node, data)
val reference = node.fir.lValue as? FirResolvedNamedReference ?: return dataForNode
val symbol = reference.resolvedSymbol as? FirPropertySymbol ?: return dataForNode
return update(dataForNode, symbol) update@{ prev ->
val toPut = when {
symbol !in localProperties -> {
null
}
prev == VariableStatus.READ -> {
VariableStatus.WRITTEN_AFTER_READ
}
prev == VariableStatus.WRITTEN_AFTER_READ -> {
VariableStatus.ONLY_WRITTEN_NEVER_READ
}
else -> {
VariableStatus.ONLY_WRITTEN_NEVER_READ.merge(prev ?: VariableStatus.UNUSED)
}
val toPut = when {
symbol !in localProperties -> {
null
}
dataForNode[symbol] == VariableStatus.READ -> {
VariableStatus.WRITTEN_AFTER_READ
}
dataForNode[symbol] == VariableStatus.WRITTEN_AFTER_READ -> {
VariableStatus.ONLY_WRITTEN_NEVER_READ
}
else -> {
VariableStatus.ONLY_WRITTEN_NEVER_READ.merge(dataForNode[symbol] ?: VariableStatus.UNUSED)
}
toPut ?: return@update null
toPut.isRead = prev?.isRead ?: false
toPut
}
toPut ?: return dataForNode
toPut.isRead = dataForNode[symbol]?.isRead ?: false
return dataForNode.put(symbol, toPut)
}
override fun visitQualifiedAccessNode(
node: QualifiedAccessNode,
data: Collection<Pair<EdgeLabel, PathAwareVariableStatusInfo>>
): PathAwareVariableStatusInfo {
override fun visitQualifiedAccessNode(node: QualifiedAccessNode, data: Collection<VariableStatusInfo>): VariableStatusInfo {
val dataForNode = visitNode(node, data)
if (node.fir.source?.kind is FirFakeSourceElementKind) return dataForNode
val reference = node.fir.calleeReference as? FirResolvedNamedReference ?: return dataForNode
@@ -238,29 +197,13 @@ object UnusedChecker : FirControlFlowChecker() {
val status = VariableStatus.READ
status.isRead = true
return update(dataForNode, symbol) { status }
}
private fun update(
pathAwareInfo: PathAwareVariableStatusInfo,
symbol: FirPropertySymbol,
updater: (VariableStatus?) -> VariableStatus?,
): PathAwareVariableStatusInfo {
var resultMap = persistentMapOf<EdgeLabel, VariableStatusInfo>()
var changed = false
for ((label, dataPerLabel) in pathAwareInfo) {
val v = updater.invoke(dataPerLabel[symbol])
if (v != null) {
resultMap = resultMap.put(label, dataPerLabel.put(symbol, v))
changed = true
} else {
resultMap = resultMap.put(label, dataPerLabel)
}
}
return if (changed) PathAwareVariableStatusInfo(resultMap) else pathAwareInfo
return dataForNode.put(symbol, status)
}
}
private val FirPropertySymbol.isLoopIterator
get() = fir.initializer?.source?.kind == FirFakeSourceElementKind.DesugaredForLoop
private val FirPropertySymbol.identifierSource: FirSourceElement?
get() = fir.source?.getChild(KtTokens.IDENTIFIER, 0, 1)
}

View File

@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.fir.FirEffectiveVisibility
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
@@ -149,23 +147,6 @@ object FirErrors {
val LOCAL_OBJECT_NOT_ALLOWED by error1<FirSourceElement, KtNamedDeclaration, Name>(SourceElementPositioningStrategies.DECLARATION_NAME)
val LOCAL_INTERFACE_NOT_ALLOWED by error1<FirSourceElement, KtNamedDeclaration, Name>(SourceElementPositioningStrategies.DECLARATION_NAME)
// Properties & accessors
val ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS by error0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
val PRIVATE_PROPERTY_IN_INTERFACE by error0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val ABSTRACT_PROPERTY_WITH_INITIALIZER by error1<FirSourceElement, PsiElement, FirExpression>()
val PROPERTY_INITIALIZER_IN_INTERFACE by error1<FirSourceElement, PsiElement, FirExpression>()
val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error1<FirSourceElement, PsiElement, FirPropertySymbol>()
val ABSTRACT_DELEGATED_PROPERTY by error1<FirSourceElement, PsiElement, FirExpression>()
val DELEGATED_PROPERTY_IN_INTERFACE by error1<FirSourceElement, PsiElement, FirExpression>()
// TODO: val ACCESSOR_FOR_DELEGATED_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
val ABSTRACT_PROPERTY_WITH_GETTER by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
val ABSTRACT_PROPERTY_WITH_SETTER by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
val PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
// Control flow diagnostics
val UNINITIALIZED_VARIABLE by error1<FirSourceElement, PsiElement, FirPropertySymbol>()
val WRONG_INVOCATION_KIND by warning3<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>, EventOccurrencesRange, EventOccurrencesRange>()
@@ -173,20 +154,20 @@ object FirErrors {
val WRONG_IMPLIES_CONDITION by error0<FirSourceElement, PsiElement>()
// Extended checkers group
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, PsiElement>()
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 REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE by warning0<FirSourceElement, PsiElement>()
val CAN_BE_VAL by warning0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
val CAN_BE_VAL by warning0<FirSourceElement, PsiElement>()
val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning0<FirSourceElement, PsiElement>()
val REDUNDANT_CALL_OF_CONVERSION_METHOD by warning0<FirSourceElement, PsiElement>()
val ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
val ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS by warning0<FirSourceElement, PsiElement>()
val EMPTY_RANGE by warning0<FirSourceElement, PsiElement>()
val REDUNDANT_SETTER_PARAMETER_TYPE by warning0<FirSourceElement, PsiElement>()
val UNUSED_VARIABLE by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
val UNUSED_VARIABLE by warning0<FirSourceElement, PsiElement>()
val ASSIGNED_VALUE_IS_NEVER_READ by warning0<FirSourceElement, PsiElement>()
val VARIABLE_INITIALIZER_IS_REDUNDANT by warning0<FirSourceElement, PsiElement>()
val VARIABLE_NEVER_READ by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
val VARIABLE_NEVER_READ by warning0<FirSourceElement, PsiElement>()
val USELESS_CALL_ON_NOT_NULL by warning0<FirSourceElement, PsiElement>()
}

View File

@@ -14,8 +14,6 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.MODALITY_MODIFIERS
import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
object LightTreePositioningStrategies {
@@ -144,32 +142,6 @@ object LightTreePositioningStrategies {
return super.mark(node, tree)
}
}
private class ModifierSetBasedLightTreePositioningStrategy(private val modifierSet: TokenSet) : LightTreePositioningStrategy() {
override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> {
tree.findChildByType(node, modifierSet)?.let { return markElement(it, tree) }
tree.nameIdentifier(node)?.let { return markElement(it, tree) }
return when (node.tokenType) {
KtNodeTypes.OBJECT_DECLARATION -> {
markElement(tree.objectKeyword(node)!!, tree)
}
KtNodeTypes.PROPERTY_ACCESSOR -> {
markElement(tree.accessorNamePlaceholder(node), tree)
}
else -> markElement(node, tree)
}
}
}
val VISIBILITY_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(VISIBILITY_MODIFIERS)
val MODALITY_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(MODALITY_MODIFIERS)
val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> {
return markElement(tree.operationReference(node) ?: node, tree)
}
}
}
fun FirSourceElement.hasValOrVar(): Boolean =
@@ -190,9 +162,6 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.initKeyword(node: Ligh
private fun FlyweightCapableTreeStructure<LighterASTNode>.nameIdentifier(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.IDENTIFIER)
private fun FlyweightCapableTreeStructure<LighterASTNode>.operationReference(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtNodeTypes.OPERATION_REFERENCE)
private fun FlyweightCapableTreeStructure<LighterASTNode>.rightParenthesis(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.RPAR)
@@ -202,15 +171,6 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.objectKeyword(node: Li
private fun FlyweightCapableTreeStructure<LighterASTNode>.valOrVarKeyword(node: LighterASTNode): LighterASTNode? =
findChildByType(node, VAL_VAR_TOKEN_SET)
internal fun FlyweightCapableTreeStructure<LighterASTNode>.visibilityModifier(declaration: LighterASTNode): LighterASTNode? =
modifierList(declaration)?.let { findChildByType(it, VISIBILITY_MODIFIERS) }
internal fun FlyweightCapableTreeStructure<LighterASTNode>.modalityModifier(declaration: LighterASTNode): LighterASTNode? =
modifierList(declaration)?.let { findChildByType(it, MODALITY_MODIFIERS) }
internal fun FlyweightCapableTreeStructure<LighterASTNode>.overrideModifier(declaration: LighterASTNode): LighterASTNode? =
modifierList(declaration)?.let { findChildByType(it, KtTokens.OVERRIDE_KEYWORD) }
private fun FlyweightCapableTreeStructure<LighterASTNode>.accessorNamePlaceholder(node: LighterASTNode): LighterASTNode =
findChildByType(node, KtTokens.GET_KEYWORD) ?: findChildByType(node, KtTokens.SET_KEYWORD)!!

View File

@@ -32,19 +32,4 @@ object SourceElementPositioningStrategies {
LightTreePositioningStrategies.DECLARATION_SIGNATURE,
PositioningStrategies.DECLARATION_SIGNATURE
)
val VISIBILITY_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.VISIBILITY_MODIFIER,
PositioningStrategies.VISIBILITY_MODIFIER
)
val MODALITY_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.MODALITY_MODIFIER,
PositioningStrategies.MODALITY_MODIFIER
)
val OPERATOR = SourceElementPositioningStrategy(
LightTreePositioningStrategies.OPERATOR,
PositioningStrategies.OPERATOR
)
}

View File

@@ -43,7 +43,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
FirTypeMismatchOnOverrideChecker,
FirMemberPropertyChecker,
)
override val constructorCheckers: Set<FirConstructorChecker> = setOf(

View File

@@ -20,21 +20,24 @@ import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerial
class FirConstDeserializer(
val session: FirSession,
private val binaryClass: KotlinJvmBinaryClass? = null
private val partSource: KotlinJvmBinaryClass? = null,
private val facadeSource: KotlinJvmBinaryClass? = null
) {
private val constantCache = mutableMapOf<CallableId, FirExpression>()
companion object {
private val constantCache = mutableMapOf<CallableId, FirExpression>()
}
fun loadConstant(propertyProto: ProtoBuf.Property, callableId: CallableId, nameResolver: NameResolver): FirExpression? {
if (!Flags.HAS_CONSTANT.get(propertyProto.flags)) return null
constantCache[callableId]?.let { return it }
if (binaryClass == null) {
if (facadeSource == null && partSource == null) {
val value = propertyProto.getExtensionOrNull(BuiltInSerializerProtocol.compileTimeValue) ?: return null
return buildFirConstant(value, null, value.type.name, nameResolver)?.apply { constantCache[callableId] = this }
}
binaryClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
(facadeSource ?: partSource)!!.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor? = null
override fun visitField(name: Name, desc: String, initializer: Any?): KotlinJvmBinaryClass.AnnotationVisitor? {
@@ -57,11 +60,11 @@ class FirConstDeserializer(
"CHAR", "C" -> buildConstExpression(null, FirConstKind.Char, ((protoValue?.intValue ?: sourceValue) as Number).toChar())
"SHORT", "S" -> buildConstExpression(null, FirConstKind.Short, ((protoValue?.intValue ?: sourceValue) as Number).toShort())
"INT", "I" -> buildConstExpression(null, FirConstKind.Int, protoValue?.intValue?.toInt() ?: sourceValue as Int)
"LONG", "J" -> buildConstExpression(null, FirConstKind.Long, protoValue?.intValue ?: sourceValue as Long)
"FLOAT", "F" -> buildConstExpression(null, FirConstKind.Float, protoValue?.floatValue ?: sourceValue as Float)
"DOUBLE", "D" -> buildConstExpression(null, FirConstKind.Double, protoValue?.doubleValue ?: sourceValue as Double)
"LONG", "J" -> buildConstExpression(null, FirConstKind.Long, (protoValue?.intValue ?: sourceValue) as Long)
"FLOAT", "F" -> buildConstExpression(null, FirConstKind.Float, (protoValue?.floatValue ?: sourceValue) as Float)
"DOUBLE", "D" -> buildConstExpression(null, FirConstKind.Double, (protoValue?.doubleValue ?: sourceValue) as Double)
"BOOLEAN", "Z" -> buildConstExpression(null, FirConstKind.Boolean, (protoValue?.intValue?.toInt() ?: sourceValue) != 0)
"STRING", "Ljava/lang/String;" -> buildConstExpression(
"STRING", "Ljava/lang/String" -> buildConstExpression(
null, FirConstKind.String, protoValue?.stringValue?.let { nameResolver.getString(it) } ?: sourceValue as String
)
else -> null

View File

@@ -228,6 +228,14 @@ class FirBuiltinSymbolProvider(session: FirSession, val kotlinScopeProvider: Kot
}
}
// Find the symbol for "invoke" in the function class
private fun FunctionClassKind.getInvoke(arity: Int): FirNamedFunctionSymbol? {
val functionClass = getClassLikeSymbolByFqName(classId(arity)) ?: return null
val invoke =
functionClass.fir.declarations.find { it is FirSimpleFunction && it.name == OperatorNameConventions.INVOKE } ?: return null
return (invoke as FirSimpleFunction).symbol as? FirNamedFunctionSymbol
}
private fun FunctionClassKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
@FirSymbolProviderInternals
@@ -301,5 +309,13 @@ class FirBuiltinSymbolProvider(session: FirSession, val kotlinScopeProvider: Kot
memberDeserializer.loadFunction(it).symbol
}
}
fun getAllCallableNames(): Set<Name> {
return packageProto.`package`.functionList.mapTo(mutableSetOf()) { nameResolver.getName(it.name) }
}
fun getAllClassNames(): Set<Name> {
return classDataFinder.allClassIds.mapTo(mutableSetOf()) { it.shortClassName }
}
}
}

View File

@@ -205,6 +205,9 @@ class FirElementSerializer private constructor(
var hasGetter = false
var hasSetter = false
//val compileTimeConstant = property.compileTimeInitializer
val hasConstant = false // TODO: compileTimeConstant != null && compileTimeConstant !is NullValue
val hasAnnotations = property.nonSourceAnnotations(session).isNotEmpty()
// TODO: hasAnnotations(descriptor) || hasAnnotations(descriptor.backingField) || hasAnnotations(descriptor.delegateField)
@@ -244,7 +247,6 @@ class FirElementSerializer private constructor(
}
}
val hasConstant = property.isConst // TODO: this is only correct with LanguageFeature.NoConstantValueAttributeForNonConstVals
val flags = Flags.getPropertyFlags(
hasAnnotations,
ProtoEnumFlags.visibility(normalizeVisibility(property)),

View File

@@ -14,14 +14,14 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.ir.util.*
@@ -86,17 +86,8 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext<JvmSignatur
typeContext.hasNothingInNonContravariantPosition(type)
}
private fun FirClassLikeSymbol<*>.toRegularClassSymbol(): FirRegularClassSymbol? = when (this) {
is FirRegularClassSymbol -> this
is FirTypeAliasSymbol -> {
val expandedType = fir.expandedTypeRef.coneType.fullyExpandedType(session) as? ConeClassLikeType
expandedType?.lookupTag?.toSymbol(session) as? FirRegularClassSymbol
}
else -> null
}
private fun ConeClassLikeType.buildPossiblyInnerType(): PossiblyInnerConeType? =
buildPossiblyInnerType(lookupTag.toSymbol(session)?.toRegularClassSymbol(), 0)
buildPossiblyInnerType(lookupTag.toSymbol(session) as? FirRegularClassSymbol?, 0)
private fun ConeClassLikeType.parentClassOrNull(): FirRegularClassSymbol? {
val parentClassId = classId?.outerClassId ?: return null

View File

@@ -140,27 +140,26 @@ fun FirReference.toSymbolForCall(
}
}
private fun FirCallableSymbol<*>.toSymbolForCall(declarationStorage: Fir2IrDeclarationStorage, preferGetter: Boolean): IrSymbol? =
when (this) {
is FirFunctionSymbol<*> -> declarationStorage.getIrFunctionSymbol(this)
is SyntheticPropertySymbol -> {
(fir as? FirSyntheticProperty)?.let { syntheticProperty ->
val delegateSymbol = if (preferGetter) {
syntheticProperty.getter.delegate.symbol
} else {
syntheticProperty.setter?.delegate?.symbol
?: throw AssertionError("Written synthetic property must have a setter")
}
delegateSymbol.unwrapCallRepresentative().toSymbolForCall(declarationStorage, preferGetter)
} ?: declarationStorage.getIrPropertySymbol(this)
}
is FirPropertySymbol -> declarationStorage.getIrPropertySymbol(this)
is FirFieldSymbol -> declarationStorage.getIrFieldSymbol(this)
is FirBackingFieldSymbol -> declarationStorage.getIrBackingFieldSymbol(this)
is FirDelegateFieldSymbol<*> -> declarationStorage.getIrBackingFieldSymbol(this)
is FirVariableSymbol<*> -> declarationStorage.getIrValueSymbol(this)
else -> null
private fun FirCallableSymbol<*>.toSymbolForCall(declarationStorage: Fir2IrDeclarationStorage, preferGetter: Boolean): IrSymbol? = when (this) {
is FirFunctionSymbol<*> -> declarationStorage.getIrFunctionSymbol(this)
is SyntheticPropertySymbol -> {
(fir as? FirSyntheticProperty)?.let { syntheticProperty ->
val delegateSymbol = if (preferGetter) {
syntheticProperty.getter.delegate.symbol
} else {
syntheticProperty.setter?.delegate?.symbol
?: throw AssertionError("Written synthetic property must have a setter")
}
delegateSymbol.unwrapCallRepresentative().toSymbolForCall(declarationStorage, preferGetter)
} ?: declarationStorage.getIrPropertySymbol(this)
}
is FirPropertySymbol -> declarationStorage.getIrPropertySymbol(this)
is FirFieldSymbol -> declarationStorage.getIrFieldSymbol(this)
is FirBackingFieldSymbol -> declarationStorage.getIrBackingFieldSymbol(this)
is FirDelegateFieldSymbol<*> -> declarationStorage.getIrBackingFieldSymbol(this)
is FirVariableSymbol<*> -> declarationStorage.getIrValueSymbol(this)
else -> null
}
fun FirConstExpression<*>.getIrConstKind(): IrConstKind<*> = when (kind) {
FirConstKind.IntegerLiteral -> {
@@ -251,7 +250,7 @@ internal fun FirSimpleFunction.generateOverriddenFunctionSymbols(
scope.processFunctionsByName(name) {}
val overriddenSet = mutableSetOf<IrSimpleFunctionSymbol>()
scope.processDirectlyOverriddenFunctions(symbol) {
if (it.fir.visibility == Visibilities.Private) {
if ((it.fir as FirSimpleFunction).visibility == Visibilities.Private) {
return@processDirectlyOverriddenFunctions ProcessorAction.NEXT
}
@@ -339,8 +338,7 @@ internal fun IrDeclarationParent.declareThisReceiverParameter(
symbolTable.irFactory.createValueParameter(
startOffset, endOffset, thisOrigin, symbol,
Name.special("<this>"), UNDEFINED_PARAMETER_INDEX, thisType,
varargElementType = null, isCrossinline = false, isNoinline = false,
isHidden = false, isAssignable = false
varargElementType = null, isCrossinline = false, isNoinline = false, isAssignable = false
).apply {
this.parent = this@declareThisReceiverParameter
receiverDescriptor.bind(this)

View File

@@ -269,8 +269,7 @@ class Fir2IrDeclarationStorage(
startOffset, endOffset, IrDeclarationOrigin.DEFINED, symbol,
Name.special("<set-?>"), 0, type,
varargElementType = null,
isCrossinline = false, isNoinline = false,
isHidden = false, isAssignable = false
isCrossinline = false, isNoinline = false, isAssignable = false
).apply {
this.parent = parent
descriptor.bind(this)
@@ -405,7 +404,9 @@ class Fir2IrDeclarationStorage(
factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction
): IrSimpleFunction {
if (signature == null) {
val descriptor = WrappedSimpleFunctionDescriptor()
val descriptor =
if (containerSource != null) WrappedFunctionDescriptorWithContainerSource()
else WrappedSimpleFunctionDescriptor()
return symbolTable.declareSimpleFunction(descriptor, factory).apply { descriptor.bind(this) }
}
return symbolTable.declareSimpleFunction(signature, { Fir2IrSimpleFunctionSymbol(signature, containerSource) }, factory)
@@ -686,7 +687,9 @@ class Fir2IrDeclarationStorage(
factory: (IrPropertySymbol) -> IrProperty
): IrProperty {
if (signature == null) {
val descriptor = WrappedPropertyDescriptor()
val descriptor =
if (containerSource != null) WrappedPropertyDescriptorWithContainerSource()
else WrappedPropertyDescriptor()
return symbolTable.declareProperty(0, 0, IrDeclarationOrigin.DEFINED, descriptor, isDelegated = false, factory).apply {
descriptor.bind(this)
}
@@ -896,8 +899,7 @@ class Fir2IrDeclarationStorage(
valueParameter.name, index, type,
if (!valueParameter.isVararg) null
else valueParameter.returnTypeRef.coneType.arrayElementType()?.toIrType(typeContext),
isCrossinline = valueParameter.isCrossinline, isNoinline = valueParameter.isNoinline,
isHidden = false, isAssignable = false
valueParameter.isCrossinline, valueParameter.isNoinline
).apply {
descriptor.bind(this)
if (valueParameter.defaultValue.let {

View File

@@ -266,7 +266,6 @@ internal class AdapterGenerator(
varargElementType = null,
isCrossinline = false,
isNoinline = false,
isHidden = false,
isAssignable = false
).also { irAdapterValueParameter ->
descriptor.bind(irAdapterValueParameter)
@@ -400,8 +399,8 @@ internal class AdapterGenerator(
return this
}
val expectedType = parameter?.returnTypeRef?.coneType ?: return this
// Expect the expected type to be a suspend functional type.
if (!expectedType.isSuspendFunctionType(session)) {
// Expect the expected type to be a suspend functional type, and the argument type is not a suspend functional type.
if (!expectedType.isSuspendFunctionType(session) || argument.typeRef.coneType.isSuspendFunctionType(session)) {
return this
}
val expectedFunctionalType = expectedType.suspendFunctionTypeToFunctionType(session)
@@ -424,17 +423,22 @@ internal class AdapterGenerator(
private fun findInvokeSymbol(expectedFunctionalType: ConeClassLikeType, argument: FirExpression): IrSimpleFunctionSymbol? {
val argumentType = argument.typeRef.coneType
val argumentTypeWithInvoke = argumentType.findSubtypeOfNonSuspendFunctionalType(session, expectedFunctionalType) ?: return null
return if (argumentTypeWithInvoke.isBuiltinFunctionalType(session)) {
(argumentTypeWithInvoke as? ConeClassLikeType)?.findBaseInvokeSymbol(session, scopeSession)
} else {
argumentTypeWithInvoke.findContributedInvokeSymbol(
session, scopeSession, expectedFunctionalType, shouldCalculateReturnTypesOfFakeOverrides = true
)
}?.let {
declarationStorage.getIrFunctionSymbol(it) as? IrSimpleFunctionSymbol
// To avoid any remaining exotic types, e.g., intersection type, like it(FunctionN..., SuspendFunctionN...)
if (argumentType !is ConeClassLikeType) {
return null
}
if (argumentType.isSubtypeOfFunctionalType(session, expectedFunctionalType)) {
return if (argumentType.isBuiltinFunctionalType(session)) {
argumentType.findBaseInvokeSymbol(session, scopeSession)
} else {
argumentType.findContributedInvokeSymbol(session, scopeSession, expectedFunctionalType, shouldCalculateReturnTypesOfFakeOverrides = true)
}?.let {
declarationStorage.getIrFunctionSymbol(it) as? IrSimpleFunctionSymbol
}
}
return null
}
private fun createAdapterFunctionForArgument(

View File

@@ -7,14 +7,14 @@ package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.useSiteTargetsFromMetaAnnotation
import org.jetbrains.kotlin.fir.declarations.hasMetaAnnotationUseSiteTargets
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.util.isPropertyField
import org.jetbrains.kotlin.ir.util.isSetter
/**
@@ -36,73 +36,80 @@ class AnnotationGenerator(private val components: Fir2IrComponents) : Fir2IrComp
irContainer.annotations = firContainer.annotations.toIrAnnotations()
}
private fun FirAnnotationCall.target(applicable: List<AnnotationUseSiteTarget>): AnnotationUseSiteTarget? =
useSiteTarget ?: applicable.firstOrNull(useSiteTargetsFromMetaAnnotation(session)::contains)
companion object {
// Priority order: constructor parameter (if applicable) -> property -> field. So, for example, if `A`
// can be attached to all three, then in a declaration like
// class C(@A val x: Int) { @A val y = 1 }
// the parameter `x` and the property `y` will have the annotation, while the property `x` and both backing fields will not.
private val propertyTargets = listOf(AnnotationUseSiteTarget.PROPERTY, AnnotationUseSiteTarget.FIELD)
private val constructorPropertyTargets = listOf(AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER) + propertyTargets
private val delegatedPropertyTargets = propertyTargets + listOf(AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD)
}
// TODO: third argument should be whether this parameter is a property declaration (though this probably makes no difference)
fun generate(irValueParameter: IrValueParameter, firValueParameter: FirValueParameter, isInConstructor: Boolean) {
if (isInConstructor) {
irValueParameter.annotations += firValueParameter.annotations
.filter { it.target(constructorPropertyTargets) == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER }
irValueParameter.annotations +=
firValueParameter.annotations
.filter {
// TODO: for `null` use-site, refer to targets on the meta annotation
it.useSiteTarget == null || !isInConstructor || it.useSiteTarget == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
}
.toIrAnnotations()
} else {
irValueParameter.annotations += firValueParameter.annotations.toIrAnnotations()
}
}
private fun FirAnnotationCall.targetsField(): Boolean =
// Check if the annotation has a field-targeting meta annotation, e.g., @Target(FIELD)
hasMetaAnnotationUseSiteTargets(session, AnnotationUseSiteTarget.FIELD, AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD)
fun generate(irProperty: IrProperty, property: FirProperty) {
val applicableTargets = when {
property.source?.kind == FirFakeSourceElementKind.PropertyFromParameter -> constructorPropertyTargets
irProperty.isDelegated -> delegatedPropertyTargets
else -> propertyTargets
}
irProperty.annotations += property.annotations
.filter { it.target(applicableTargets) == AnnotationUseSiteTarget.PROPERTY }
.toIrAnnotations()
irProperty.annotations +=
property.annotations
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY ||
// NB: annotation with null use-site should be landed on the property (ahead of field),
// unless it has FIELD target on the meta annotation, like @Target(FIELD)
(it.useSiteTarget == null && !it.targetsField())
}
.toIrAnnotations()
}
fun generate(irField: IrField, property: FirProperty) {
val irProperty = irField.correspondingPropertySymbol?.owner ?: throw AssertionError("$irField is not a property field")
val applicableTargets = when {
property.source?.kind == FirFakeSourceElementKind.PropertyFromParameter -> constructorPropertyTargets
irProperty.isDelegated -> delegatedPropertyTargets
else -> propertyTargets
assert(irField.isPropertyField) {
"$irField is not a property field."
}
irField.annotations += property.annotations.filter {
val target = it.target(applicableTargets)
target == AnnotationUseSiteTarget.FIELD || target == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
}.toIrAnnotations()
irField.annotations +=
property.annotations
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.FIELD ||
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD ||
(it.useSiteTarget == null && it.targetsField())
}
.toIrAnnotations()
}
fun generate(propertyAccessor: IrFunction, property: FirProperty) {
assert(propertyAccessor.isPropertyAccessor) { "$propertyAccessor is not a property accessor." }
assert(propertyAccessor.isPropertyAccessor) {
"$propertyAccessor is not a property accessor."
}
if (propertyAccessor.isSetter) {
propertyAccessor.annotations += property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_SETTER }
.toIrAnnotations()
val parameter = propertyAccessor.valueParameters.single()
parameter.annotations += property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.SETTER_PARAMETER }
.toIrAnnotations()
propertyAccessor.annotations +=
property.annotations
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_SETTER
}
.toIrAnnotations()
propertyAccessor.valueParameters.singleOrNull()?.annotations =
propertyAccessor.valueParameters.singleOrNull()?.annotations?.plus(
property.annotations
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.SETTER_PARAMETER
}
.toIrAnnotations()
)!!
} else {
propertyAccessor.annotations += property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_GETTER }
.toIrAnnotations()
}
propertyAccessor.extensionReceiverParameter?.let { receiver ->
receiver.annotations += property.annotations
.filter { it.useSiteTarget == AnnotationUseSiteTarget.RECEIVER }
.toIrAnnotations()
propertyAccessor.annotations +=
property.annotations
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_GETTER
}
.toIrAnnotations()
}
propertyAccessor.extensionReceiverParameter?.annotations =
propertyAccessor.extensionReceiverParameter?.annotations?.plus(
property.annotations
.filter {
it.useSiteTarget == AnnotationUseSiteTarget.RECEIVER
}
.toIrAnnotations()
)!!
}
}

View File

@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.references.FirDelegateFieldReference
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.calls.getExpectedTypeForSAMConversion
import org.jetbrains.kotlin.fir.resolve.calls.isFunctional
@@ -446,14 +445,8 @@ class CallAndReferenceGenerator(
is FirDelegatedConstructorCall -> call.calleeReference
is FirAnnotationCall -> call.calleeReference
else -> null
}
val function = if (calleeReference == FirReferencePlaceholderForResolvedAnnotations) {
val coneClassLikeType = (call as FirAnnotationCall).annotationTypeRef.coneTypeSafe<ConeClassLikeType>()
val firClass = (coneClassLikeType?.lookupTag?.toSymbol(session) as? FirRegularClassSymbol)?.fir
firClass?.declarations?.filterIsInstance<FirConstructor>()?.firstOrNull()
} else {
((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir
}
} as? FirResolvedNamedReference
val function = (calleeReference?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir
val valueParameters = function?.valueParameters
val argumentMapping = call.argumentMapping
if (argumentMapping != null && (annotationMode || argumentMapping.isNotEmpty())) {
@@ -566,13 +559,11 @@ class CallAndReferenceGenerator(
}
}
with(adapterGenerator) {
if (parameter?.returnTypeRef is FirResolvedTypeRef) {
// Java type case (from annotations)
irArgument = irArgument.applySuspendConversionIfNeeded(argument, parameter)
irArgument = irArgument.applySamConversionIfNeeded(argument, parameter)
}
irArgument = irArgument.applySuspendConversionIfNeeded(argument, parameter)
}
return irArgument.applyAssigningArrayElementsToVarargInNamedForm(argument, parameter)
return irArgument
.applySamConversionIfNeeded(argument, parameter)
.applyAssigningArrayElementsToVarargInNamedForm(argument, parameter)
}
private fun IrExpression.applySamConversionIfNeeded(

Some files were not shown because too many files have changed in this diff Show More