Compare commits

..

1 Commits

Author SHA1 Message Date
Simon Ogorodnik
42d681b8d6 Remove parentClassTypeParameterStackCache from JavaSymbolProvider 2021-02-17 15:39:21 +03:00
742 changed files with 12717 additions and 14720 deletions

View File

@@ -20,9 +20,11 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.mapToIndex
class ArgumentAndDeclIndex(val arg: ResolvedValueArgument, val declIndex: Int)
@@ -68,8 +70,12 @@ abstract class ArgumentGenerator {
generateExpression(declIndex, argument)
}
is DefaultValueArgument -> {
defaultArgs.mark(declIndex)
generateDefault(declIndex, argument)
if (calleeDescriptor?.defaultValueFromJava(declIndex) == true) {
generateDefaultJava(declIndex, argument)
} else {
defaultArgs.mark(declIndex)
generateDefault(declIndex, argument)
}
}
is VarargValueArgument -> {
generateVararg(declIndex, argument)
@@ -97,6 +103,10 @@ abstract class ArgumentGenerator {
throw UnsupportedOperationException("Unsupported vararg value argument #$i: $argument")
}
protected open fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
throw UnsupportedOperationException("Unsupported default java argument #$i: $argument")
}
protected open fun generateOther(i: Int, argument: ResolvedValueArgument) {
throw UnsupportedOperationException("Unsupported value argument #$i: $argument")
}
@@ -106,6 +116,28 @@ abstract class ArgumentGenerator {
}
}
private fun CallableDescriptor.defaultValueFromJava(index: Int): Boolean = DFS.ifAny(
listOf(this),
{ current -> current.original.overriddenDescriptors.map { it.original } },
{ descriptor ->
descriptor.original.overriddenDescriptors.isEmpty() &&
descriptor is JavaCallableMemberDescriptor &&
descriptor.valueParameters[index].declaresDefaultValue()
}
)
fun shouldInvokeDefaultArgumentsStub(resolvedCall: ResolvedCall<*>): Boolean {
val descriptor = resolvedCall.resultingDescriptor
val valueArgumentsByIndex = resolvedCall.valueArgumentsByIndex ?: return false
for (index in valueArgumentsByIndex.indices) {
val resolvedValueArgument = valueArgumentsByIndex[index]
if (resolvedValueArgument is DefaultValueArgument && !descriptor.defaultValueFromJava(index)) {
return true
}
}
return false
}
fun getFunctionWithDefaultArguments(functionDescriptor: FunctionDescriptor): FunctionDescriptor {
if (functionDescriptor.containingDeclaration !is ClassDescriptor) return functionDescriptor
if (functionDescriptor.overriddenDescriptors.isEmpty()) return functionDescriptor
@@ -123,4 +155,4 @@ fun getFunctionWithDefaultArguments(functionDescriptor: FunctionDescriptor): Fun
function.valueParameters.any { valueParameter -> valueParameter.hasDefaultValue() }
}
?: functionDescriptor
}
}

View File

@@ -72,6 +72,12 @@ class CallBasedArgumentGenerator(
callGenerator.putValueIfNeeded(getJvmKotlinType(i), lazyVararg, ValueKind.GENERAL_VARARG, i)
}
override fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
val argumentValue = valueParameters[i].findJavaDefaultArgumentValue(valueParameterTypes[i], codegen.typeMapper)
callGenerator.putValueIfNeeded(getJvmKotlinType(i), argumentValue)
}
override fun reorderArgumentsIfNeeded(args: List<ArgumentAndDeclIndex>) {
callGenerator.reorderArgumentsIfNeeded(args, valueParameterTypes)
}

View File

@@ -74,10 +74,7 @@ import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices;
import org.jetbrains.kotlin.resolve.jvm.JvmConstantsKt;
import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
import org.jetbrains.kotlin.resolve.jvm.*;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
@@ -2693,7 +2690,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@NotNull
Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall<?> resolvedCall) {
Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall resolvedCall) {
IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd);
if (intrinsic != null) {
return intrinsic.toCallable(fd, superCall, resolvedCall, this);
@@ -2701,8 +2698,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
fd = SamCodegenUtil.resolveSamAdapter(fd);
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
if (valueArguments != null && valueArguments.stream().anyMatch(it -> it instanceof DefaultValueArgument)) {
if (ArgumentGeneratorKt.shouldInvokeDefaultArgumentsStub(resolvedCall)) {
// When we invoke a function with some arguments mapped as defaults,
// we later reroute this call to an overridden function in a base class that processes the default arguments.
// If the base class is generic, this overridden function can have a different Kotlin signature

View File

@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.annotations.ThrowUtilKt;
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
@@ -1105,7 +1105,7 @@ public class FunctionCodegen {
return Collections.emptyList();
}
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(ThrowUtilKt.JVM_THROWS_ANNOTATION_FQ_NAME);
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(AnnotationUtilKt.JVM_THROWS_ANNOTATION_FQ_NAME);
if (annotation == null) return Collections.emptyList();
Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();

View File

@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
internal class ObjectSuperCallArgumentGenerator(
@@ -64,6 +65,12 @@ internal class ObjectSuperCallArgumentGenerator(
pushDefaultValueOnStack(type, iv)
}
public override fun generateDefaultJava(i: Int, argument: DefaultValueArgument) {
val type = parameters[i].asmType
val value = superValueParameters[i].findJavaDefaultArgumentValue(type, typeMapper)
value.put(type, iv)
}
public override fun generateVararg(i: Int, argument: VarargValueArgument) {
generateSuperCallArgument(i)
}

View File

@@ -5,7 +5,18 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.AsmUtil.unboxPrimitiveTypeOrNull
import org.jetbrains.kotlin.codegen.StackValue.*
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.load.java.Constant
import org.jetbrains.kotlin.load.java.EnumEntry
import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.getDefaultValueFromAnnotation
import org.jetbrains.kotlin.load.java.lexicalCastFrom
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -75,3 +86,40 @@ class FunctionCallStackValue(
resultKotlinType: KotlinType?,
lambda: (v: InstructionAdapter) -> Unit
) : OperationStackValue(resultType, resultKotlinType, lambda)
fun ValueParameterDescriptor.findJavaDefaultArgumentValue(targetType: Type, typeMapper: KotlinTypeMapper): StackValue {
val descriptorWithDefaultValue = DFS.dfs(
listOf(this.original),
{ it.original.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) },
object : DFS.AbstractNodeHandler<ValueParameterDescriptor, ValueParameterDescriptor?>() {
var result: ValueParameterDescriptor? = null
override fun beforeChildren(current: ValueParameterDescriptor?): Boolean {
if (current?.declaresDefaultValue() == true && current.getDefaultValueFromAnnotation() != null) {
result = current
return false
}
return true
}
override fun result(): ValueParameterDescriptor? = result
}
) ?: error("Should be at least one descriptor with default value: $this")
val defaultValue = descriptorWithDefaultValue.getDefaultValueFromAnnotation()
if (defaultValue is NullDefaultValue) {
return constant(null, targetType)
}
val value = (defaultValue as StringDefaultValue).value
val castResult = type.lexicalCastFrom(value) ?: error("Should be checked in frontend")
return when (castResult) {
is EnumEntry -> enumEntry(castResult.descriptor, typeMapper)
is Constant -> {
val unboxedType = unboxPrimitiveTypeOrNull(targetType) ?: targetType
return coercion(constant(castResult.value, unboxedType), targetType, null)
}
}
}

View File

@@ -462,29 +462,6 @@ class AnonymousObjectTransformer(
val indexToFunctionalArgument = transformationInfo.functionalArguments
val capturedParams = HashSet<Int>()
// Possible cases where we need to add each lambda's captures separately:
//
// 1. Top-level object in an inline lambda that is *not* being inlined into another object. In this case, we
// have no choice but to add a separate field for each captured variable. `capturedLambdas` is either empty
// (already have the fields) or contains the parent lambda object (captures used to be read from it, but
// the object will be removed and its contents inlined).
//
// 2. Top-level object in a named inline function. Again, there's no option but to add separate fields.
// `capturedLambdas` contains all lambdas used by this object and nested objects.
//
// 3. Nested object, either in an inline lambda or an inline function. This case has two subcases:
// * The object's captures are passed as separate arguments (e.g. KT-28064 style object that used to be in a lambda);
// we *could* group them into `this$0` now, but choose not to. Lambdas are replaced by their captures to match.
// * The object's captures are already grouped into `this$0`; this includes captured lambda parameters (for objects in
// inline functions) and a reference to the outer object or lambda (for objects in lambdas), so `capturedLambdas` is
// empty anyway.
//
// The only remaining case is a top-level object inside a (crossinline) lambda that is inlined into another object.
// Then, the reference to the soon-to-be-removed lambda class containing the captures (and it exists, or else the object
// would not have needed regeneration in the first place) is simply replaced with a reference to the outer object, and
// that object will contain loose fields for everything we need to capture.
val topLevelInCrossinlineLambda = parentFieldRemapper is InlinedLambdaRemapper && !parentFieldRemapper.parent!!.isRoot
//load captured parameters and patch instruction list
// NB: there is also could be object fields
val toDelete = arrayListOf<AbstractInsnNode>()
@@ -493,12 +470,10 @@ class AnonymousObjectTransformer(
val parameterAload = fieldNode.previous as VarInsnNode
val varIndex = parameterAload.`var`
val functionalArgument = indexToFunctionalArgument[varIndex]
// If an outer `this` is already captured by this object, rename it if any inline lambda will capture
// one of the same type, causing the code below to create a clash. Note that the values can be different.
// TODO: this is only really necessary if there will be a name *and* type clash.
val shouldRename = !topLevelInCrossinlineLambda && isThis0(fieldName) &&
indexToFunctionalArgument.values.any { it is LambdaInfo && it.capturedVars.any { it.fieldName == fieldName } }
val newFieldName = if (shouldRename) addUniqueField(fieldName + INLINE_FUN_THIS_0_SUFFIX) else fieldName
val newFieldName = if (isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToFunctionalArgument.values))
getNewFieldName(fieldName, true)
else
fieldName
val info = capturedParamBuilder.addCapturedParam(
Type.getObjectType(transformationInfo.oldClassName), fieldName, newFieldName,
Type.getType(fieldNode.desc), functionalArgument is LambdaInfo, null
@@ -533,17 +508,35 @@ class AnonymousObjectTransformer(
//For all inlined lambdas add their captured parameters
//TODO: some of such parameters could be skipped - we should perform additional analysis
val allRecapturedParameters = ArrayList<CapturedParamDesc>()
if (!topLevelInCrossinlineLambda) {
val capturedOuterThisTypes = mutableSetOf<String>()
if (parentFieldRemapper !is InlinedLambdaRemapper || parentFieldRemapper.parent!!.isRoot) {
// Possible cases:
//
// 1. Top-level object in an inline lambda that is *not* being inlined into another object. In this case, we
// have no choice but to add a separate field for each captured variable. `capturedLambdas` is either empty
// (already have the fields) or contains the parent lambda object (captures used to be read from it, but
// the object will be removed and its contents inlined).
//
// 2. Top-level object in a named inline function. Again, there's no option but to add separate fields.
// `capturedLambdas` contains all lambdas used by this object and nested objects.
//
// 3. Nested object, either in an inline lambda or an inline function. This case has two subcases:
// * The object's captures are passed as separate arguments (e.g. KT-28064 style object that used to be in a lambda);
// we could group them into `this$0` now, but choose not to. Lambdas are replaced by their captures.
// * The object's captures are already grouped into `this$0`; this includes captured lambda parameters (for objects in
// inline functions) and a reference to the outer object or lambda (for objects in lambdas), so `capturedLambdas` is
// empty and the choice doesn't matter.
//
val alreadyAdded = HashMap<String, CapturedParamInfo>()
for (info in capturedLambdas) {
for (desc in info.capturedVars) {
// Merge all outer `this` of the same type captured by inlined lambdas, since they have to be the same
// object. Outer `this` captured by the original object itself should have been renamed above,
// and can have a different value even if the same type is captured by a lambda.
val recapturedParamInfo = if (isThis0(desc.fieldName))
capturedParamBuilder.addCapturedParam(desc, desc.fieldName, !capturedOuterThisTypes.add(desc.type.className))
else
capturedParamBuilder.addCapturedParam(desc, addUniqueField(desc.fieldName + INLINE_TRANSFORMATION_SUFFIX), false)
val key = desc.fieldName + "$$$" + desc.type.className
val alreadyAddedParam = alreadyAdded[key]
val recapturedParamInfo = capturedParamBuilder.addCapturedParam(
desc,
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
alreadyAddedParam != null
)
if (info is ExpressionLambda && info.isCapturedSuspend(desc)) {
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend
}
@@ -558,6 +551,10 @@ class AnonymousObjectTransformer(
allRecapturedParameters.add(desc)
constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.newFieldName).remapValue = composed
if (isThis0(desc.fieldName)) {
alreadyAdded.put(key, recapturedParamInfo)
}
}
}
} else if (capturedLambdas.isNotEmpty()) {
@@ -582,6 +579,24 @@ class AnonymousObjectTransformer(
return constructorAdditionalFakeParams
}
private fun shouldRenameThis0(parentFieldRemapper: FieldRemapper, values: Collection<FunctionalArgument>): Boolean {
return if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) {
values.any { it is LambdaInfo && it.capturedVars.any { isThis0(it.fieldName) } }
} else false
}
private fun getNewFieldName(oldName: String, originalField: Boolean): String {
if (AsmUtil.CAPTURED_THIS_FIELD == oldName) {
return if (!originalField) {
oldName
} else {
//rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site
addUniqueField(oldName + INLINE_FUN_THIS_0_SUFFIX)
}
}
return addUniqueField(oldName + INLINE_TRANSFORMATION_SUFFIX)
}
private fun addUniqueField(name: String): String {
val existNames = fieldNames.getOrPut(name) { LinkedList() }
val suffix = if (existNames.isEmpty()) "" else "$" + existNames.size
@@ -589,4 +604,7 @@ class AnonymousObjectTransformer(
existNames.add(newName)
return newName
}
private fun isFirstDeclSiteLambdaFieldRemapper(parentRemapper: FieldRemapper): Boolean =
parentRemapper !is RegeneratedLambdaFieldRemapper && parentRemapper !is InlinedLambdaRemapper
}

View File

@@ -204,7 +204,7 @@ class GenerationState private constructor(
val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
val runtimeStringConcat =
if (target.majorVersion >= JvmTarget.JVM_9.majorVersion)
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INDY_WITH_CONSTANTS
configuration.get(JVMConfigurationKeys.STRING_CONCAT) ?: JvmStringConcat.INLINE
else JvmStringConcat.INLINE
val samConversionsScheme = run {

View File

@@ -114,14 +114,6 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
var doNotClearBindingContext: Boolean by FreezableVar(false)
@Argument(
value = "-Xparallel-backend-threads",
description = "When using the IR backend, run lowerings by file in N parallel threads.\n" +
"0 means use a thread per processor core.\n" +
"Default value is 1"
)
var parallelBackendThreads: String by FreezableVar("1")
@Argument(value = "-Xmodule-path", valueDescription = "<path>", description = "Paths where to find Java 9+ modules")
var javaModulePath: String? by NullableStringFreezableVar(null)
@@ -369,9 +361,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
description = """Select code generation scheme for string concatenation.
-Xstring-concat=indy-with-constants Concatenate strings using `invokedynamic` `makeConcatWithConstants`. Requires `-jvm-target 9` or greater.
-Xstring-concat=indy Concatenate strings using `invokedynamic` `makeConcat`. Requires `-jvm-target 9` or greater.
-Xstring-concat=inline Concatenate strings using `StringBuilder`
default: `indy-with-constants` for JVM target 9 or greater, `inline` otherwise"""
-Xstring-concat=inline Concatenate strings using `StringBuilder`"""
)
var stringConcat: String? by NullableStringFreezableVar(JvmStringConcat.INLINE.description)

View File

@@ -88,7 +88,7 @@ fun buildKLib(
configuration = configuration,
allDependencies = allDependencies,
friendDependencies = emptyList(),
irFactory = PersistentIrFactory(), // TODO: IrFactoryImpl?
irFactory = PersistentIrFactory,
outputKlibPath = outputPath,
nopack = true
)

View File

@@ -199,7 +199,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
configuration = config.configuration,
allDependencies = resolvedLibraries,
friendDependencies = friendDependencies,
irFactory = PersistentIrFactory(), // TODO IrFactoryImpl?
irFactory = PersistentIrFactory,
outputKlibPath = outputFile.path,
nopack = arguments.irProduceKlibDir
)

View File

@@ -291,10 +291,6 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
}
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
val nThreadsRaw = arguments.parallelBackendThreads.toIntOrNull() ?: 1
val nThreads = if (nThreadsRaw == 0) Runtime.getRuntime().availableProcessors() else nThreadsRaw
put(CommonConfigurationKeys.PARALLEL_BACKEND_THREADS, nThreads)
}
fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments) {

View File

@@ -50,10 +50,6 @@ object CommonConfigurationKeys {
@JvmField
val USE_FIR_EXTENDED_CHECKERS = CompilerConfigurationKey.create<Boolean>("fir extended checkers")
@JvmField
val PARALLEL_BACKEND_THREADS =
CompilerConfigurationKey.create<Int>("When using the IR backend, run lowerings by file in N parallel threads")
}
var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings

View File

@@ -1484,6 +1484,24 @@ public class FirTypeEnhancementTestGenerated extends AbstractFirTypeEnhancementT
}
}
@TestMetadata("compiler/testData/loadJava/compiledJava/signatureAnnotations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SignatureAnnotations extends AbstractFirTypeEnhancementTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSignatureAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava/compiledJava/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
}
@TestMetadata("StableName.java")
public void testStableName() throws Exception {
runTest("compiler/testData/loadJava/compiledJava/signatureAnnotations/StableName.java");
}
}
@TestMetadata("compiler/testData/loadJava/compiledJava/signaturePropagation")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)

View File

@@ -132,4 +132,67 @@ public class OwnFirTypeEnhancementTestGenerated extends AbstractOwnFirTypeEnhanc
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/enhancement/mapping"), Pattern.compile("^(.+)\\.java$"), null, true);
}
}
@TestMetadata("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SignatureAnnotations extends AbstractOwnFirTypeEnhancementTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInSignatureAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
}
@TestMetadata("DefaultEnum.java")
public void testDefaultEnum() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultEnum.java");
}
@TestMetadata("DefaultLongLiteral.java")
public void testDefaultLongLiteral() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultLongLiteral.java");
}
@TestMetadata("DefaultNull.java")
public void testDefaultNull() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultNull.java");
}
@TestMetadata("DefaultNullAndParameter.java")
public void testDefaultNullAndParameter() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.java");
}
@TestMetadata("DefaultParameter.java")
public void testDefaultParameter() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/DefaultParameter.java");
}
@TestMetadata("EmptyParameterName.java")
public void testEmptyParameterName() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/EmptyParameterName.java");
}
@TestMetadata("ReorderedParameterNames.java")
public void testReorderedParameterNames() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/ReorderedParameterNames.java");
}
@TestMetadata("SameParameterName.java")
public void testSameParameterName() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/SameParameterName.java");
}
@TestMetadata("SpecialCharsParameterName.java")
public void testSpecialCharsParameterName() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.java");
}
@TestMetadata("StaticMethodWithDefaultValue.java")
public void testStaticMethodWithDefaultValue() throws Exception {
runTest("compiler/fir/analysis-tests/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.java");
}
}
}

View File

@@ -65,6 +65,9 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
private fun createEnvironment(content: String): KotlinCoreEnvironment {
val classpath = mutableListOf(getAnnotationsJar(), ForTestCompileRuntime.runtimeJarForTests())
if (InTextDirectivesUtils.isDirectiveDefined(content, "ANDROID_ANNOTATIONS")) {
classpath.add(ForTestCompileRuntime.androidAnnotationsForTests())
}
if (InTextDirectivesUtils.isDirectiveDefined(content, "JVM_ANNOTATIONS")) {
classpath.add(ForTestCompileRuntime.jvmAnnotationsForTests())
}

View File

@@ -1 +1 @@
Most FIR enhancement tests use compiler/testData/loadJava/compiledJava
Most FIR enhancement tests use compiler/testData/loadJava/compilerJava

View File

@@ -0,0 +1,33 @@
public/*package*/ open class A : R|kotlin/Any| {
public open fun a(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(HELLO)) arg: R|ft<@FlexibleNullability Signs, Signs?>!| = R|/Signs.HELLO|): R|ft<@FlexibleNullability Signs, Signs?>!|
public open fun bar(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(X)) arg: R|ft<@FlexibleNullability Signs, Signs?>!| = R|/Signs.X|): R|ft<@FlexibleNullability Signs, Signs?>!|
public open fun baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft<@FlexibleNullability Signs, Signs?>!|): R|ft<@FlexibleNullability Signs, Signs?>!|
public open fun bam(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft<@FlexibleNullability Mixed, Mixed?>!| = R|/Mixed.NOT_ENTRY_EITHER|): R|ft<@FlexibleNullability Mixed, Mixed?>!|
public/*package*/ constructor(): R|A|
}
public final enum class Mixed : R|kotlin/Enum<ft<@FlexibleNullability Mixed, Mixed?>!>| {
public final static enum entry NOT_ENTRY_EITHER: R|@FlexibleNullability Mixed|
public final static fun values(): R|kotlin/Array<Mixed>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|Mixed| {
}
}
public final enum class Signs : R|kotlin/Enum<ft<@FlexibleNullability Signs, Signs?>!>| {
public final static enum entry HELLO: R|@FlexibleNullability Signs|
public final static enum entry WORLD: R|@FlexibleNullability Signs|
public final static field X: R|ft<@FlexibleNullability Signs, Signs?>!|
public final static fun values(): R|kotlin/Array<Signs>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|Signs| {
}
}

View File

@@ -0,0 +1,39 @@
// FILE: Signs.java
// ANDROID_ANNOTATIONS
public enum Signs {
HELLO,
WORLD;
public static final Signs X;
public static final class NOT_ENTRY_EITHER {}
}
// FILE: Mixed.java
public enum Mixed {
NOT_ENTRY_EITHER;
public static final class NOT_ENTRY_EITHER {}
}
// FILE: A.java
import kotlin.annotations.jvm.internal.*;
class A {
public Signs a(@DefaultValue("HELLO") Signs arg) {
return arg;
}
public Signs bar(@DefaultValue("X") Signs arg) {
return arg;
}
public Signs baz(@DefaultValue("NOT_ENTRY_EITHER") Signs arg) {
return arg;
}
public Mixed bam(@DefaultValue("NOT_ENTRY_EITHER") Mixed arg) {
return arg;
}
}

View File

@@ -0,0 +1,24 @@
public open class A : R|kotlin/Any| {
public open fun first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0x1F)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!| = Long(31)): R|kotlin/Unit|
public open fun second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0X1F)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!| = Long(31)): R|kotlin/Unit|
public open fun third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0b1010)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!| = Long(10)): R|kotlin/Unit|
public open fun fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1010)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!| = Long(10)): R|kotlin/Unit|
public constructor(): R|A|
}
public open class B : R|kotlin/Any| {
public open fun first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0x)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!|): R|kotlin/Unit|
public open fun second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0xZZ)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!|): R|kotlin/Unit|
public open fun third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0b)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!|): R|kotlin/Unit|
public open fun fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1234)) value: R|ft<@FlexibleNullability kotlin/Long, kotlin/Long?>!|): R|kotlin/Unit|
public constructor(): R|B|
}

View File

@@ -0,0 +1,36 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void first(@DefaultValue("0x1F") Long value) {
}
public void second(@DefaultValue("0X1F") Long value) {
}
public void third(@DefaultValue("0b1010") Long value) {
}
public void fourth(@DefaultValue("0B1010") Long value) {
}
}
// FILE: B.java
import kotlin.annotations.jvm.internal.*;
public class B {
public void first(@DefaultValue("0x") Long value) {
}
public void second(@DefaultValue("0xZZ") Long value) {
}
public void third(@DefaultValue("0b") Long value) {
}
public void fourth(@DefaultValue("0B1234") Long value) {
}
}

View File

@@ -0,0 +1,14 @@
public open class A : R|kotlin/Any| {
public open fun foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() x: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
public open fun bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() x: R|kotlin/Int| = Null(null)): R|kotlin/Unit|
public constructor(): R|A|
}
public open class B<T : R|ft<kotlin/Any, kotlin/Any?>!|> : R|kotlin/Any| {
public open fun foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() t: R|ft<@FlexibleNullability T, T?>!| = Null(null)): R|kotlin/Unit|
public constructor<T : R|ft<kotlin/Any, kotlin/Any?>!|>(): R|B<T>|
}

View File

@@ -0,0 +1,17 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void foo(@DefaultNull Integer x) {}
public void bar(@DefaultNull int x) {}
}
// FILE: B.java
import kotlin.annotations.jvm.internal.*;
public class B<T> {
public void foo(@DefaultNull T t) { }
}

View File

@@ -0,0 +1,32 @@
public open class A : R|kotlin/Any| {
public open fun foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() i: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
public open fun bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
public open fun bam(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
public open fun baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Int(42)): R|kotlin/Unit|
public constructor(): R|A|
}
public abstract interface AInt : R|kotlin/Any| {
public abstract fun foo(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) i: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Int(42)): R|kotlin/Unit|
public abstract fun bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Null(null)): R|kotlin/Unit|
}
public open class B : R|A| {
public open fun foo(i: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!|): R|kotlin/Unit|
public open fun bar(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Int(42)): R|kotlin/Unit|
public open fun bam(@R|kotlin/annotations/jvm/internal/DefaultNull|() @R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!| = Int(42)): R|kotlin/Unit|
public constructor(): R|B|
}
public open class C : R|A|, R|AInt| {
public constructor(): R|C|
}

View File

@@ -0,0 +1,38 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void foo(@DefaultNull Integer i) {}
public void bar(@DefaultNull Integer a) {}
public void bam(@DefaultNull Integer a) {}
public void baz(@DefaultValue("42") Integer a) {}
}
// FILE: AInt.java
import kotlin.annotations.jvm.internal.*;
public interface AInt {
public void foo(@DefaultValue("42") Integer i) {}
public void bar(@DefaultNull Integer a) {}
}
// FILE: B.java
import kotlin.annotations.jvm.internal.*;
public class B extends A {
public void foo(Integer i) {}
public void bar(@DefaultValue("42") Integer a) {}
public void bam(@DefaultNull @DefaultValue("42") Integer a) {}
}
// FILE: C.java
public class C extends A implements AInt {
}

View File

@@ -0,0 +1,14 @@
public/*package*/ open class A : R|kotlin/Any| {
public open fun first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(hello)) value: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(hello)): R|kotlin/Unit|
public open fun second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(first)) a: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(first), @R|kotlin/annotations/jvm/internal/DefaultValue|(String(second)) b: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(second)): R|kotlin/Unit|
public open fun third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(first)) a: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(first), b: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public open fun fourth(first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|, @R|kotlin/annotations/jvm/internal/DefaultValue|(String(second)) second: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(second)): R|kotlin/Unit|
public open fun wrong(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(hello)) i: R|ft<@FlexibleNullability kotlin/Int, kotlin/Int?>!|): R|kotlin/Unit|
public/*package*/ constructor(): R|A|
}

View File

@@ -0,0 +1,23 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
class A {
public void first(@DefaultValue("hello") String value) {
}
public void second(@DefaultValue("first") String a, @DefaultValue("second") String b) {
}
public void third(@DefaultValue("first") String a, String b) {
}
public void fourth(String first, @DefaultValue("second") String second) {
}
public void wrong(@DefaultValue("hello") Integer i) {
}
}

View File

@@ -0,0 +1,10 @@
public/*package*/ open class A : R|kotlin/Any| {
public open fun emptyName(@R|kotlin/annotations/jvm/internal/ParameterName|(String()) first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|, @R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) second: R|kotlin/Int|): R|kotlin/Unit|
public open fun missingName(@R|kotlin/annotations/jvm/internal/ParameterName|() first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public open fun numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(Int(42)) first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public/*package*/ constructor(): R|A|
}

View File

@@ -0,0 +1,16 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
class A {
public void emptyName(@ParameterName("") String first, @ParameterName("ok") int second) {
}
public void missingName(@ParameterName() String first) {
}
public void numberName(@ParameterName(42) String first) {
}
}

View File

@@ -0,0 +1,6 @@
public open class A : R|kotlin/Any| {
public open fun connect(@R|kotlin/annotations/jvm/internal/ParameterName|(String(host)) host: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|, @R|kotlin/annotations/jvm/internal/ParameterName|(String(port)) port: R|kotlin/Int|): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -0,0 +1,10 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void connect(@ParameterName("host") String host, @ParameterName("port") int port) {
}
}

View File

@@ -0,0 +1,6 @@
public open class A : R|kotlin/Any| {
public open fun same(@R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) first: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|, @R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) second: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -0,0 +1,10 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
public class A {
public void same(@ParameterName("ok") String first, @ParameterName("ok") String second) {
}
}

View File

@@ -0,0 +1,8 @@
public open class A : R|kotlin/Any| {
public open fun dollarName(@R|kotlin/annotations/jvm/internal/ParameterName|(String($)) host: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public open fun numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(String(42)) field: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -0,0 +1,13 @@
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
import kotlin.internal.*;
public class A {
public void dollarName(@ParameterName("$") String host) {
}
public void numberName(@ParameterName("42") String field) {
}
}

View File

@@ -0,0 +1,6 @@
public/*package*/ open class A : R|kotlin/Any| {
public open static fun withDefault(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(OK)) arg: R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!| = String(OK)): R|ft<@FlexibleNullability kotlin/String, kotlin/String?>!|
public/*package*/ constructor(): R|A|
}

View File

@@ -0,0 +1,13 @@
// IGNORE_BACKEND: JS, NATIVE
// FILE: A.java
// ANDROID_ANNOTATIONS
import kotlin.annotations.jvm.internal.*;
class A {
public static String withDefault(@DefaultValue("OK") String arg) {
return arg;
}
}

View File

@@ -3,36 +3,36 @@ object Delegate {
operator fun setValue(instance: Any?, property: Any, value: String) {}
}
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var test: Int
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var kest by Delegate
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var test: Int<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var kest by Delegate<!>
lateinit var good: String
class A {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val fest = "10"
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val fest = "10"<!>
lateinit var mest: String
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var xest: String?
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var nest: Int
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var west: Char
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var qest: Boolean
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var aest: Short
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var hest: Byte
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var jest: Long
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val dest: String
get() = "KEKER"
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var xest: String?<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var nest: Int<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var west: Char<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var qest: Boolean<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var aest: Short<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var hest: Byte<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var jest: Long<!>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit val dest: String
get() = "KEKER"<!>
}
class B<T> {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var best: T
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var best: T<!>
}
class C<K : Any> {
lateinit var pest: K
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var vest: K?
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var vest: K?<!>
}
fun rest() {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var i: Int
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var i: Int<!>
lateinit var a: A
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var b: B<String> = B()
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var b: B<String> = B()<!>
}

View File

@@ -15,7 +15,7 @@ class SomeClass : SomeInterface {
get() = true
set(value) {}
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var fau: Double
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit var fau: Double<!>
}
inline class InlineClass

View File

@@ -16428,6 +16428,42 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("defaultEnum.kt")
public void testDefaultEnum() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultEnum.kt");
}
@Test
@TestMetadata("defaultLongLiteral.kt")
public void testDefaultLongLiteral() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultLongLiteral.kt");
}
@Test
@TestMetadata("defaultNull.kt")
public void testDefaultNull() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNull.kt");
}
@Test
@TestMetadata("defaultNullAndParameter.kt")
public void testDefaultNullAndParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultNullAndParameter.kt");
}
@Test
@TestMetadata("defaultParameter.kt")
public void testDefaultParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/defaultParameter.kt");
}
@Test
@TestMetadata("emptyParameterName.kt")
public void testEmptyParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/emptyParameterName.kt");
}
@Test
@TestMetadata("notNullVarargOverride.kt")
public void testNotNullVarargOverride() throws Exception {
@@ -16439,6 +16475,48 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testNullableVarargOverride() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/nullableVarargOverride.kt");
}
@Test
@TestMetadata("overridesDefaultValue.kt")
public void testOverridesDefaultValue() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesDefaultValue.kt");
}
@Test
@TestMetadata("overridesParameterName.kt")
public void testOverridesParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/overridesParameterName.kt");
}
@Test
@TestMetadata("reorderedParameterNames.kt")
public void testReorderedParameterNames() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/reorderedParameterNames.kt");
}
@Test
@TestMetadata("sameParameterName.kt")
public void testSameParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/sameParameterName.kt");
}
@Test
@TestMetadata("specialCharsParameterName.kt")
public void testSpecialCharsParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/specialCharsParameterName.kt");
}
@Test
@TestMetadata("stableParameterName.kt")
public void testStableParameterName() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/stableParameterName.kt");
}
@Test
@TestMetadata("staticMethodWithDefaultValue.kt")
public void testStaticMethodWithDefaultValue() throws Exception {
runTest("compiler/testData/diagnostics/tests/j+k/signatureAnnotations/staticMethodWithDefaultValue.kt");
}
}
@Nested
@@ -24496,12 +24574,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/sealed/interfaces/inheritorInDifferentModule.kt");
}
@Test
@TestMetadata("sealedFunInterface.kt")
public void testSealedFunInterface() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/interfaces/sealedFunInterface.kt");
}
@Test
@TestMetadata("sealedInterfacesDisabled.kt")
public void testSealedInterfacesDisabled() throws Exception {

View File

@@ -15,6 +15,7 @@ data class DiagnosticData(
val psiType: KType,
val parameters: List<DiagnosticParameter>,
val positioningStrategy: PositioningStrategy,
val group: String?,
)
data class DiagnosticParameter(
@@ -41,7 +42,6 @@ enum class PositioningStrategy(private val strategy: String) {
WHEN_EXPRESSION("WHEN_EXPRESSION"),
IF_EXPRESSION("IF_EXPRESSION"),
VARIANCE_MODIFIER("VARIANCE_MODIFIER"),
LATEINIT_MODIFIER("LATEINIT_MODIFIER"),
;
@@ -54,4 +54,8 @@ enum class PositioningStrategy(private val strategy: String) {
fun DiagnosticData.hasDefaultPositioningStrategy(): Boolean =
positioningStrategy == PositioningStrategy.DEFAULT
positioningStrategy == PositioningStrategy.DEFAULT
data class DiagnosticList(
val diagnostics: List<DiagnosticData>,
)

View File

@@ -1,56 +0,0 @@
/*
* Copyright 2010-2021 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.checkers.generator.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.PrivateForInline
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.typeOf
abstract class DiagnosticGroup @PrivateForInline constructor(val name: String) {
@Suppress("PropertyName")
@PrivateForInline
val _diagnostics = mutableListOf<DiagnosticData>()
@OptIn(PrivateForInline::class)
val diagnostics: List<DiagnosticData>
get() = _diagnostics
@OptIn(PrivateForInline::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> error(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = diagnosticDelegateProvider<E, P>(Severity.ERROR, positioningStrategy, init)
@OptIn(PrivateForInline::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> warning(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = diagnosticDelegateProvider<E, P>(Severity.WARNING, positioningStrategy, init)
@PrivateForInline
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> diagnosticDelegateProvider(
severity: Severity,
positioningStrategy: PositioningStrategy,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = PropertyDelegateProvider<Any?, ReadOnlyProperty<DiagnosticGroup, DiagnosticData>> { _, property ->
val diagnostic = DiagnosticBuilder(
severity,
name = property.name,
sourceElementType = typeOf<E>(),
psiType = typeOf<P>(),
positioningStrategy,
).apply(init).build()
_diagnostics += diagnostic
ReadOnlyProperty { _, _ -> diagnostic }
}
}

View File

@@ -1,69 +0,0 @@
/*
* Copyright 2010-2021 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.checkers.generator.diagnostics
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.PrivateForInline
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.typeOf
abstract class DiagnosticList {
@Suppress("PropertyName")
@PrivateForInline
val _groups = mutableListOf<DiagnosticGroup>()
@OptIn(PrivateForInline::class)
val groups: List<DiagnosticGroup>
get() = _groups
val allDiagnostics: List<DiagnosticData>
get() = groups.flatMap { it.diagnostics }
@OptIn(PrivateForInline::class)
operator fun DiagnosticGroup.provideDelegate(
thisRef: DiagnosticList,
prop: KProperty<*>
): ReadOnlyProperty<DiagnosticList, DiagnosticGroup> {
val group = this
_groups += group
return ReadOnlyProperty { _, _ -> group }
}
}
class DiagnosticBuilder(
private val severity: Severity,
private val name: String,
private val sourceElementType: KType,
private val psiType: KType,
private val positioningStrategy: PositioningStrategy,
) {
@PrivateForInline
val parameters = mutableListOf<DiagnosticParameter>()
@OptIn(PrivateForInline::class, ExperimentalStdlibApi::class)
inline fun <reified T> parameter(name: String) {
if (parameters.size == 3) {
error("Diagnostic cannot have more than 3 parameters")
}
parameters += DiagnosticParameter(
name = name,
type = typeOf<T>()
)
}
@OptIn(PrivateForInline::class)
fun build() = DiagnosticData(
severity,
name,
sourceElementType,
psiType,
parameters,
positioningStrategy,
)
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2010-2021 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.checkers.generator.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.PrivateForInline
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.typeOf
class DiagnosticListBuilder private constructor() {
@PrivateForInline
val diagnostics = mutableListOf<DiagnosticData>()
@PrivateForInline
var currentGroupName: String? = null
@OptIn(PrivateForInline::class)
inline fun group(groupName: String, inner: () -> Unit) {
if (currentGroupName != null) {
error("Groups can not be nested ")
}
currentGroupName = groupName
inner()
currentGroupName = null
}
@OptIn(PrivateForInline::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> error(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = diagnosticDelegateProvider<E, P>(Severity.ERROR, positioningStrategy, init)
@OptIn(PrivateForInline::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> warning(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = diagnosticDelegateProvider<E, P>(Severity.WARNING, positioningStrategy, init)
@PrivateForInline
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified E : FirSourceElement, reified P : PsiElement> diagnosticDelegateProvider(
severity: Severity,
positioningStrategy: PositioningStrategy,
crossinline init: DiagnosticBuilder.() -> Unit = {}
) = PropertyDelegateProvider<Any?, AlwaysReturningUnitPropertyDelegate> { _, property ->
diagnostics += DiagnosticBuilder(
severity,
name = property.name,
sourceElementType = typeOf<E>(),
psiType = typeOf<P>(),
positioningStrategy,
group = currentGroupName,
).apply(init).build()
AlwaysReturningUnitPropertyDelegate
}
@PrivateForInline
object AlwaysReturningUnitPropertyDelegate : ReadOnlyProperty<Any?, Unit> {
override fun getValue(thisRef: Any?, property: KProperty<*>) = Unit
}
@OptIn(PrivateForInline::class)
private fun build() = DiagnosticList(diagnostics)
companion object {
fun buildDiagnosticList(init: DiagnosticListBuilder.() -> Unit) =
DiagnosticListBuilder().apply(init).build()
}
}
class DiagnosticBuilder(
private val severity: Severity,
private val name: String,
private val sourceElementType: KType,
private val psiType: KType,
private val positioningStrategy: PositioningStrategy,
private val group: String?
) {
@PrivateForInline
val parameters = mutableListOf<DiagnosticParameter>()
@OptIn(PrivateForInline::class, ExperimentalStdlibApi::class)
inline fun <reified T> parameter(name: String) {
if (parameters.size == 3) {
error("Diagnostic cannot have more than 3 parameters")
}
parameters += DiagnosticParameter(
name = name,
type = typeOf<T>()
)
}
@OptIn(PrivateForInline::class)
fun build() = DiagnosticData(
severity,
name,
sourceElementType,
psiType,
parameters,
positioningStrategy,
group
)
}

View File

@@ -33,18 +33,19 @@ object ErrorListDiagnosticListRenderer : DiagnosticListRenderer() {
private fun SmartPrinter.printErrorsObject(diagnosticList: DiagnosticList) {
inBracketsWithIndent("object FirErrors") {
for (group in diagnosticList.groups) {
printDiagnosticGroup(group.name, group.diagnostics)
val groups = diagnosticList.diagnostics.groupBy { it.group }
for ((group, diagnostics) in groups) {
printDiagnosticGroup(group, diagnostics)
println()
}
}
}
private fun SmartPrinter.printDiagnosticGroup(
group: String,
group: String?,
diagnostics: List<DiagnosticData>
) {
println("// $group")
println("// ${group ?: "NO GROUP"}")
for (it in diagnostics) {
printDiagnostic(it)
}
@@ -109,7 +110,7 @@ object ErrorListDiagnosticListRenderer : DiagnosticListRenderer() {
@OptIn(ExperimentalStdlibApi::class)
private fun collectImports(diagnosticList: DiagnosticList): Collection<String> = buildSet {
diagnosticList.allDiagnostics.forEach { diagnostic ->
diagnosticList.diagnostics.forEach { diagnostic ->
for (typeArgument in diagnostic.getAllTypeArguments()) {
typeArgument.collectClassNamesTo(this)
}

View File

@@ -25,15 +25,15 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
@OptIn(PrivateForInline::class)
object DIAGNOSTICS_LIST : DiagnosticList() {
val Miscellaneous by object : DiagnosticGroup("Miscellaneous") {
val DIAGNOSTICS_LIST = DiagnosticListBuilder.buildDiagnosticList {
group("Miscellaneous") {
val SYNTAX by error<FirSourceElement, PsiElement>()
val OTHER_ERROR by error<FirSourceElement, PsiElement>()
}
val GENERAL_SYNTAX by object : DiagnosticGroup("General syntax") {
group("General syntax") {
val ILLEGAL_CONST_EXPRESSION by error<FirSourceElement, PsiElement>()
val ILLEGAL_UNDERSCORE by error<FirSourceElement, PsiElement>()
val EXPRESSION_REQUIRED by error<FirSourceElement, PsiElement>()
@@ -44,7 +44,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val DELEGATION_IN_INTERFACE by error<FirSourceElement, PsiElement>()
}
val UNRESOLVED by object : DiagnosticGroup("Unresolved") {
group("Unresolved") {
val HIDDEN by error<FirSourceElement, PsiElement> {
parameter<AbstractFirBasedSymbol<*>>("hidden")
}
@@ -59,7 +59,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val NO_THIS by error<FirSourceElement, PsiElement>()
}
val SUPER by object : DiagnosticGroup("Super") {
group("Super") {
val SUPER_IS_NOT_AN_EXPRESSION by error<FirSourceElement, PsiElement>()
val SUPER_NOT_AVAILABLE by error<FirSourceElement, PsiElement>()
val ABSTRACT_SUPER_CALL by error<FirSourceElement, PsiElement>()
@@ -68,7 +68,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
}
val SUPERTYPES by object : DiagnosticGroup("Supertypes") {
group("Supertypes") {
val TYPE_PARAMETER_AS_SUPERTYPE by error<FirSourceElement, PsiElement>()
val ENUM_AS_SUPERTYPE by error<FirSourceElement, PsiElement>()
val RECURSION_IN_SUPERTYPES by error<FirSourceElement, PsiElement>()
@@ -84,7 +84,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error<FirSourceElement, PsiElement>()
}
val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") {
group(" Constructor problems") {
val CONSTRUCTOR_IN_OBJECT by error<FirSourceElement, KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val CONSTRUCTOR_IN_INTERFACE by error<FirSourceElement, KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val NON_PRIVATE_CONSTRUCTOR_IN_ENUM by error<FirSourceElement, PsiElement>()
@@ -98,7 +98,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val SEALED_CLASS_CONSTRUCTOR_CALL by error<FirSourceElement, PsiElement>()
}
val ANNOTATIONS by object : DiagnosticGroup("Annotations") {
group("Annotations") {
val ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR by error<FirSourceElement, KtExpression>()
val ANNOTATION_ARGUMENT_MUST_BE_CONST by error<FirSourceElement, KtExpression>()
val ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST by error<FirSourceElement, KtExpression>()
@@ -116,7 +116,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val VAR_ANNOTATION_PARAMETER by error<FirSourceElement, KtParameter>(PositioningStrategy.VAL_OR_VAR_NODE)
}
val EXPOSED_VISIBILITY by object : DiagnosticGroup("Exposed visibility") {
group("Exposed visibility group") {
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by exposedVisibilityError<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
val EXPOSED_FUNCTION_RETURN_TYPE by exposedVisibilityError<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
@@ -128,7 +128,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val EXPOSED_TYPE_PARAMETER_BOUND by exposedVisibilityError<KtTypeReference>()
}
val MODIFIERS by object : DiagnosticGroup("Modifiers") {
group("Modifiers") {
val INAPPLICABLE_INFIX_MODIFIER by error<FirSourceElement, PsiElement>()
val REPEATED_MODIFIER by error<FirSourceElement, PsiElement> {
parameter<KtModifierKeywordToken>("modifier")
@@ -148,7 +148,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val REDUNDANT_OPEN_IN_INTERFACE by warning<FirSourceElement, KtModifierListOwner>(PositioningStrategy.OPEN_MODIFIER)
}
val APPLICABILITY by object : DiagnosticGroup("Applicability") {
group("Applicability") {
val NONE_APPLICABLE by error<FirSourceElement, PsiElement> {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
@@ -156,12 +156,12 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val INAPPLICABLE_CANDIDATE by error<FirSourceElement, PsiElement> {
parameter<AbstractFirBasedSymbol<*>>("candidate")
}
val INAPPLICABLE_LATEINIT_MODIFIER by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.LATEINIT_MODIFIER) {
val INAPPLICABLE_LATEINIT_MODIFIER by error<FirSourceElement, PsiElement> {
parameter<String>("reason")
}
}
val AMBIGUIRY by object : DiagnosticGroup("Ambiguity") {
group("Ambiguity") {
val AMBIGUITY by error<FirSourceElement, PsiElement> {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
@@ -170,7 +170,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
}
val TYPES_AND_TYPE_PARAMETERS by object : DiagnosticGroup("Types & type parameters") {
group("Types & type parameters") {
val TYPE_MISMATCH by error<FirSourceElement, PsiElement> {
parameter<ConeKotlinType>("expectedType")
parameter<ConeKotlinType>("actualType")
@@ -203,7 +203,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME)
}
val OVERRIDES by object : DiagnosticGroup("overrides") {
group("overrides") {
val NOTHING_TO_OVERRIDE by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.OVERRIDE_MODIFIER) {
parameter<FirMemberDeclaration>("declaration")
}
@@ -242,7 +242,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
}
val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") {
group("Redeclarations") {
val MANY_COMPANION_OBJECTS by error<FirSourceElement, PsiElement>()
val CONFLICTING_OVERLOADS by error<FirSourceElement, PsiElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
parameter<Collection<AbstractFirBasedSymbol<*>>>("conflictingOverloads")
@@ -253,7 +253,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val ANY_METHOD_IMPLEMENTED_IN_INTERFACE by error<FirSourceElement, PsiElement>()
}
val INVALID_LOCAL_DECLARATIONS by object : DiagnosticGroup("Invalid local declarations") {
group("Invalid local declarations") {
val LOCAL_OBJECT_NOT_ALLOWED by error<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME) {
parameter<Name>("objectName")
}
@@ -262,7 +262,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
}
val FUNCTIONS by object : DiagnosticGroup("Functions") {
group("Functions") {
val ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS by error<FirSourceElement, KtFunction>(PositioningStrategy.MODALITY_MODIFIER) {
parameter<FirMemberDeclaration>("function")
parameter<FirMemberDeclaration>("containingClass") // TODO use FirClass instead of FirMemberDeclaration
@@ -288,7 +288,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val USELESS_VARARG_ON_PARAMETER by warning<FirSourceElement, KtParameter>()
}
val PROPERTIES_ANS_ACCESSORS by object : DiagnosticGroup("Properties & accessors") {
group("Properties & accessors") {
val ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.MODALITY_MODIFIER) {
parameter<FirMemberDeclaration>("property")
parameter<FirMemberDeclaration>("containingClass") // TODO use FirClass instead of FirMemberDeclaration
@@ -314,15 +314,14 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val EXPECTED_PRIVATE_DECLARATION by error<FirSourceElement, KtModifierListOwner>(PositioningStrategy.VISIBILITY_MODIFIER)
}
val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") {
group("Multi-platform projects") {
val EXPECTED_DECLARATION_WITH_BODY by error<FirSourceElement, KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val EXPECTED_PROPERTY_INITIALIZER by error<FirSourceElement, KtExpression>()
// TODO: need to cover `by` as well as delegate expression
val EXPECTED_DELEGATED_PROPERTY by error<FirSourceElement, KtPropertyDelegate>()
}
val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") {
group("Destructuring declaration") {
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error<FirSourceElement, KtDestructuringDeclaration>()
val COMPONENT_FUNCTION_MISSING by error<FirSourceElement, PsiElement> {
parameter<Name>("missingFunctionName")
@@ -340,7 +339,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
// TODO: val COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH by ...
}
val CONTROL_FLOW by object : DiagnosticGroup("Control flow diagnostics") {
group("Control flow diagnostics") {
val UNINITIALIZED_VARIABLE by error<FirSourceElement, PsiElement> {
parameter<FirPropertySymbol>("variable")
}
@@ -355,7 +354,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val WRONG_IMPLIES_CONDITION by warning<FirSourceElement, PsiElement>()
}
val NULLABILITY by object : DiagnosticGroup("Nullability") {
group("Nullability") {
val UNSAFE_CALL by error<FirSourceElement, PsiElement>(PositioningStrategy.DOT_BY_SELECTOR) {
parameter<ConeKotlinType>("receiverType")
}
@@ -375,20 +374,20 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
// TODO: val UNEXPECTED_SAFE_CALL by ...
}
val WHNE_EXPRESSIONS by object : DiagnosticGroup("When expressions") {
group("When expressions") {
val NO_ELSE_IN_WHEN by error<FirSourceElement, KtWhenExpression>(PositioningStrategy.WHEN_EXPRESSION) {
parameter<List<WhenMissingCase>>("missingWhenCases")
}
val INVALID_IF_AS_EXPRESSION by error<FirSourceElement, KtIfExpression>(PositioningStrategy.IF_EXPRESSION)
}
val FUNCTION_CONTRACTS by object : DiagnosticGroup("Function contracts") {
group("Function contracts") {
val ERROR_IN_CONTRACT_DESCRIPTION by error<FirSourceElement, KtElement> {
parameter<String>("reason")
}
}
val EXTENDED_CHECKERS by object : DiagnosticGroup("Extended checkers") {
group("Extended checkers") {
val REDUNDANT_VISIBILITY_MODIFIER by warning<FirSourceElement, KtModifierListOwner>(PositioningStrategy.VISIBILITY_MODIFIER)
val REDUNDANT_MODALITY_MODIFIER by warning<FirSourceElement, KtModifierListOwner>(PositioningStrategy.MODALITY_MODIFIER)
val REDUNDANT_RETURN_UNIT_TYPE by warning<FirSourceElement, PsiTypeElement>()
@@ -408,7 +407,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
}
private inline fun <reified P : PsiElement> DiagnosticGroup.exposedVisibilityError(
private inline fun <reified P : PsiElement> DiagnosticListBuilder.exposedVisibilityError(
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT
) = error<FirSourceElement, P>(positioningStrategy) {
parameter<FirEffectiveVisibility>("elementVisibility")

View File

@@ -91,7 +91,7 @@ object FirErrors {
val SEALED_SUPERTYPE by error0<FirSourceElement, PsiElement>()
val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error0<FirSourceElement, PsiElement>()
// Constructor problems
// Constructor problems
val CONSTRUCTOR_IN_OBJECT by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val CONSTRUCTOR_IN_INTERFACE by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val NON_PRIVATE_CONSTRUCTOR_IN_ENUM by error0<FirSourceElement, PsiElement>()
@@ -119,7 +119,7 @@ object FirErrors {
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by error0<FirSourceElement, KtTypeReference>()
val VAR_ANNOTATION_PARAMETER by error0<FirSourceElement, KtParameter>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
// Exposed visibility
// Exposed visibility group
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, KtNamedDeclaration, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
val EXPOSED_FUNCTION_RETURN_TYPE by error3<FirSourceElement, KtNamedDeclaration, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>(SourceElementPositioningStrategies.DECLARATION_NAME)
val EXPOSED_RECEIVER_TYPE by error3<FirSourceElement, KtTypeReference, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
@@ -140,7 +140,7 @@ object FirErrors {
// Applicability
val NONE_APPLICABLE by error1<FirSourceElement, PsiElement, Collection<AbstractFirBasedSymbol<*>>>()
val INAPPLICABLE_CANDIDATE by error1<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>>()
val INAPPLICABLE_LATEINIT_MODIFIER by error1<FirSourceElement, KtModifierListOwner, String>(SourceElementPositioningStrategies.LATEINIT_MODIFIER)
val INAPPLICABLE_LATEINIT_MODIFIER by error1<FirSourceElement, PsiElement, String>()
// Ambiguity
val AMBIGUITY by error1<FirSourceElement, PsiElement, Collection<AbstractFirBasedSymbol<*>>>()

View File

@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.analysis.cfa
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirClass
@@ -16,12 +15,9 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
class FirControlFlowAnalyzer(
session: FirSession,
declarationCheckers: DeclarationCheckers = session.checkersComponent.declarationCheckers
) {
private val cfaCheckers = declarationCheckers.controlFlowAnalyserCheckers
private val variableAssignmentCheckers = declarationCheckers.variableAssignmentCfaBasedCheckers
class FirControlFlowAnalyzer(session: FirSession) {
private val cfaCheckers = session.checkersComponent.declarationCheckers.controlFlowAnalyserCheckers
private val variableAssignmentCheckers = session.checkersComponent.declarationCheckers.variableAssignmentCfaBasedCheckers
// Currently declaration in analyzeXXX is not used, but it may be useful in future
@Suppress("UNUSED_PARAMETER")

View File

@@ -31,7 +31,7 @@ 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.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.typeCheckerContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
@@ -317,4 +317,4 @@ val FirFunctionCall.isIterator
internal fun throwableClassLikeType(session: FirSession) = session.builtinTypes.throwableType.type
fun ConeKotlinType.isSubtypeOfThrowable(session: FirSession) =
throwableClassLikeType(session).isSupertypeOf(session.typeContext, this.fullyExpandedType(session))
throwableClassLikeType(session).isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))

View File

@@ -26,8 +26,8 @@ import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.utils.addToStdlib.min
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object FirOverrideChecker : FirClassChecker() {
override fun check(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
object FirOverrideChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false

View File

@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.utils.addToStdlib.min
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -62,13 +63,18 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
parameterPairs.mapValues { it.value.coneType }
)
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false
)
parameterPairs.forEach { (proto, actual) ->
if (actual.source == null) {
// inferred types don't report INAPPLICABLE_CANDIDATE for type aliases!
return@forEach
}
if (!satisfiesBounds(proto, actual.coneType, substitutor, context.session.typeContext)) {
if (!satisfiesBounds(proto, actual.coneType, substitutor, typeCheckerContext)) {
reporter.reportOn(actual.source, proto, actual.coneType, context)
return
}
@@ -76,7 +82,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
// we must analyze nested things like
// S<S<K, L>, T<K, L>>()
actual.coneType.safeAs<ConeClassLikeType>()?.let {
val errorOccurred = analyzeTypeParameters(it, context, reporter, context.session.typeContext, actual.source)
val errorOccurred = analyzeTypeParameters(it, context, reporter, typeCheckerContext, actual.source)
if (errorOccurred) {
return
@@ -93,14 +99,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
// typealias A<G> = B<List<G>>
// val a = A<Int>()
when (calleeFir) {
is FirConstructor -> analyzeConstructorCall(expression, substitutor, context.session.typeContext, reporter, context)
is FirConstructor -> analyzeConstructorCall(expression, substitutor, typeCheckerContext, reporter, context)
}
}
private fun analyzeConstructorCall(
functionCall: FirQualifiedAccessExpression,
callSiteSubstitutor: ConeSubstitutor,
typeSystemContext: ConeTypeContext,
typeCheckerContext: AbstractTypeCheckerContext,
reporter: DiagnosticReporter,
context: CheckerContext
) {
@@ -151,7 +157,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
constructorsParameterPairs.forEach { (proto, actual) ->
// just in case
var intersection = typeSystemContext.intersectTypes(
var intersection = typeCheckerContext.intersectTypes(
proto.fir.bounds.map { it.coneType }
).safeAs<ConeKotlinType>() ?: return@forEach
@@ -161,7 +167,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
// substitute Int for G from
// the example above
val target = callSiteSubstitutor.substituteOrSelf(actual)
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeSystemContext, target, intersection)
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
if (!satisfiesBounds) {
reporter.reportOn(functionCall.source, proto, actual, context)
@@ -181,7 +187,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
type: ConeClassLikeType,
context: CheckerContext,
reporter: DiagnosticReporter,
typeSystemContext: ConeTypeContext,
typeCheckerContext: AbstractTypeCheckerContext,
reportTarget: FirSourceElement?
): Boolean {
val prototypeClass = type.lookupTag.toSymbol(context.session)
@@ -212,13 +218,13 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
)
parameterPairs.forEach { (proto, actual) ->
if (!satisfiesBounds(proto, actual.type, substitutor, typeSystemContext)) {
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
// should report on the parameter instead!
reporter.reportOn(reportTarget, proto, actual, context)
return true
}
val errorOccurred = analyzeTypeParameters(actual, context, reporter, typeSystemContext, reportTarget)
val errorOccurred = analyzeTypeParameters(actual, context, reporter, typeCheckerContext, reportTarget)
if (errorOccurred) {
return true
@@ -236,14 +242,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
prototypeSymbol: FirTypeParameterSymbol,
target: ConeKotlinType,
substitutor: ConeSubstitutor,
typeSystemContext: ConeTypeContext
typeCheckerContext: AbstractTypeCheckerContext
): Boolean {
var intersection = typeSystemContext.intersectTypes(
var intersection = typeCheckerContext.intersectTypes(
prototypeSymbol.fir.bounds.map { it.coneType }
).safeAs<ConeKotlinType>() ?: return true
intersection = substitutor.substituteOrSelf(intersection)
return AbstractTypeChecker.isSubtypeOf(typeSystemContext, target, intersection, stubTypesEqualToAnything = false)
return AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
}
private fun DiagnosticReporter.reportOn(

View File

@@ -7,18 +7,13 @@ package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.analysis.cfa.FirControlFlowAnalyzer
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
class ControlFlowAnalysisDiagnosticComponent(
collector: AbstractDiagnosticCollector,
declarationCheckers: DeclarationCheckers = collector.session.checkersComponent.declarationCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
private val controlFlowAnalyzer = FirControlFlowAnalyzer(session, declarationCheckers)
class ControlFlowAnalysisDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
private val controlFlowAnalyzer = FirControlFlowAnalyzer(session)
// ------------------------------- Class initializer -------------------------------

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
@@ -14,9 +13,9 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.*
class DeclarationCheckersDiagnosticComponent(
collector: AbstractDiagnosticCollector,
private val checkers: DeclarationCheckers = collector.session.checkersComponent.declarationCheckers,
collector: AbstractDiagnosticCollector
) : AbstractDiagnosticCollectorComponent(collector) {
private val checkers = session.checkersComponent.declarationCheckers
override fun visitFile(file: FirFile, data: CheckerContext) {
checkers.fileCheckers.check(file, data, reporter)

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
@@ -14,10 +13,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.expressions.*
class ExpressionCheckersDiagnosticComponent(
collector: AbstractDiagnosticCollector,
private val checkers: ExpressionCheckers = collector.session.checkersComponent.expressionCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
private val checkers = session.checkersComponent.expressionCheckers
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) {
checkers.basicExpressionCheckers.check(anonymousFunction, data, reporter)

View File

@@ -14,12 +14,10 @@ object StandardClassIds {
val BASE_KOTLIN_PACKAGE = FqName("kotlin")
val BASE_REFLECT_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("reflect"))
val BASE_COLLECTIONS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("collections"))
private fun String.baseId() = ClassId(BASE_KOTLIN_PACKAGE, Name.identifier(this))
private fun ClassId.unsignedId() = ClassId(BASE_KOTLIN_PACKAGE, Name.identifier("U" + shortClassName.identifier))
private fun String.reflectId() = ClassId(BASE_REFLECT_PACKAGE, Name.identifier(this))
private fun Name.primitiveArrayId() = ClassId(Array.packageFqName, Name.identifier(identifier + Array.shortClassName.identifier))
private fun String.collectionsId() = ClassId(BASE_COLLECTIONS_PACKAGE, Name.identifier(this))
val Nothing = "Nothing".baseId()
val Unit = "Unit".baseId()
@@ -87,25 +85,6 @@ object StandardClassIds {
return "Function$n".baseId()
}
val Iterator = "Iterator".collectionsId()
val Iterable = "Iterable".collectionsId()
val Collection = "Collection".collectionsId()
val List = "List".collectionsId()
val ListIterator = "ListIterator".collectionsId()
val Set = "Set".collectionsId()
val Map = "Map".collectionsId()
val MutableIterator = "MutableIterator".collectionsId()
val MutableIterable = "MutableIterable".collectionsId()
val MutableCollection = "MutableCollection".collectionsId()
val MutableList = "MutableList".collectionsId()
val MutableListIterator = "MutableListIterator".collectionsId()
val MutableSet = "MutableSet".collectionsId()
val MutableMap = "MutableMap".collectionsId()
val MapEntry = Map.createNestedClassId(Name.identifier("Entry"))
val MutableMapEntry = MutableMap.createNestedClassId(Name.identifier("MutableEntry"))
val Suppress = "Suppress".baseId()
}

View File

@@ -82,17 +82,6 @@ object CompilerConeAttributes {
override fun toString(): String = "@UnsafeVariance"
}
val compilerAttributeByClassId: Map<ClassId, ConeAttribute<*>> = mapOf(
Exact.ANNOTATION_CLASS_ID to Exact,
NoInfer.ANNOTATION_CLASS_ID to NoInfer,
EnhancedNullability.ANNOTATION_CLASS_ID to EnhancedNullability,
ExtensionFunctionType.ANNOTATION_CLASS_ID to ExtensionFunctionType,
FlexibleNullability.ANNOTATION_CLASS_ID to FlexibleNullability,
UnsafeVariance.ANNOTATION_CLASS_ID to UnsafeVariance
)
val compilerAttributeByFqName: Map<FqName, ConeAttribute<*>> = compilerAttributeByClassId.mapKeys { it.key.asSingleFqName() }
}
val ConeAttributes.exact: CompilerConeAttributes.Exact? by ConeAttributes.attributeAccessor<CompilerConeAttributes.Exact>()

View File

@@ -9,12 +9,11 @@ import org.jetbrains.kotlin.fir.utils.AttributeArrayOwner
import org.jetbrains.kotlin.fir.utils.Protected
import org.jetbrains.kotlin.fir.utils.TypeRegistry
import org.jetbrains.kotlin.fir.utils.isEmpty
import org.jetbrains.kotlin.types.model.AnnotationMarker
import org.jetbrains.kotlin.utils.addIfNotNull
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass
abstract class ConeAttribute<T : ConeAttribute<T>> : AnnotationMarker {
abstract class ConeAttribute<T : ConeAttribute<T>> {
abstract fun union(other: @UnsafeVariance T?): T?
abstract fun intersect(other: @UnsafeVariance T?): T?
abstract fun isSubtypeOf(other: @UnsafeVariance T?): Boolean
@@ -70,13 +69,6 @@ class ConeAttributes private constructor(attributes: List<ConeAttribute<*>>) : A
return perform(other) { this.intersect(it) }
}
fun remove(attribute: ConeAttribute<*>): ConeAttributes {
if (arrayMap.isEmpty()) return this
val attributes = arrayMap.filter { it != attribute }
if (attributes.size == arrayMap.size) return this
return create(attributes)
}
override fun iterator(): Iterator<ConeAttribute<*>> {
return arrayMap.iterator()
}

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.analysis
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector
@@ -84,7 +83,7 @@ class FirAnalyzerFacade(
fun convertToIr(extensions: GeneratorExtensions): Fir2IrResult {
if (scopeSession == null) runResolution()
val signaturer = JvmIdSignatureDescriptor(JvmManglerDesc())
val signaturer = IdSignatureDescriptor(JvmManglerDesc())
return Fir2IrConverter.createModuleFragment(
session, scopeSession!!, firFiles!!,

View File

@@ -37,7 +37,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
)
override val classCheckers: Set<FirClassChecker> = setOf(
FirOverrideChecker,
FirThrowableSubclassChecker,
)
@@ -52,6 +51,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirLocalEntityNotAllowedChecker,
FirManyCompanionObjectsChecker,
FirMethodOfAnyImplementedInInterfaceChecker,
FirOverrideChecker,
FirPrimaryConstructorRequiredForDataClassChecker,
FirSupertypeInitializedInInterfaceChecker,
FirSupertypeInitializedWithoutPrimaryConstructor,

View File

@@ -30,9 +30,6 @@ import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
@OptIn(SessionConfiguration::class)
fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersionSettings) {
register(FirLanguageSettingsComponent::class, FirLanguageSettingsComponent(languageVersionSettings))
register(InferenceComponents::class, InferenceComponents(this))
register(FirDeclaredMemberScopeProvider::class, FirDeclaredMemberScopeProvider())
register(FirCorrespondingSupertypesCache::class, FirCorrespondingSupertypesCache(this))
register(FirDefaultParametersResolver::class, FirDefaultParametersResolver())
@@ -41,6 +38,8 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.create(this))
register(FirPredicateBasedProvider::class, FirPredicateBasedProvider.create(this))
register(GeneratedClassIndex::class, GeneratedClassIndex.create())
register(FirLanguageSettingsComponent::class, FirLanguageSettingsComponent(languageVersionSettings))
register(InferenceComponents::class, InferenceComponents(this))
}
@OptIn(SessionConfiguration::class)

View File

@@ -220,7 +220,7 @@ class FirBuiltinSymbolProvider(session: FirSession, val kotlinScopeProvider: Kot
isVararg = false
}
}
dispatchReceiverType = classId.defaultType(this@klass.typeParameters.map { it.symbol })
dispatchReceiverType = classId.defaultType(typeParameters.map { it.symbol })
}
)
}

View File

@@ -51,8 +51,6 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.threadLocal
import java.util.concurrent.ConcurrentHashMap
@OptIn(ObsoleteDescriptorBasedAPI::class)
class Fir2IrDeclarationStorage(
@@ -62,28 +60,28 @@ class Fir2IrDeclarationStorage(
private val firProvider = session.firProvider
private val fragmentCache = ConcurrentHashMap<FqName, IrExternalPackageFragment>()
private val fragmentCache = mutableMapOf<FqName, IrExternalPackageFragment>()
private val builtInsFragmentCache = ConcurrentHashMap<FqName, IrExternalPackageFragment>()
private val builtInsFragmentCache = mutableMapOf<FqName, IrExternalPackageFragment>()
private val fileCache = ConcurrentHashMap<FirFile, IrFile>()
private val fileCache = mutableMapOf<FirFile, IrFile>()
private val functionCache = ConcurrentHashMap<FirFunction<*>, IrSimpleFunction>()
private val functionCache = mutableMapOf<FirFunction<*>, IrSimpleFunction>()
private val constructorCache = ConcurrentHashMap<FirConstructor, IrConstructor>()
private val constructorCache = mutableMapOf<FirConstructor, IrConstructor>()
private val initializerCache = ConcurrentHashMap<FirAnonymousInitializer, IrAnonymousInitializer>()
private val initializerCache = mutableMapOf<FirAnonymousInitializer, IrAnonymousInitializer>()
private val propertyCache = ConcurrentHashMap<FirProperty, IrProperty>()
private val propertyCache = mutableMapOf<FirProperty, IrProperty>()
// For pure fields (from Java) only
private val fieldToPropertyCache = ConcurrentHashMap<FirField, IrProperty>()
private val fieldToPropertyCache = mutableMapOf<FirField, IrProperty>()
private val delegatedReverseCache = ConcurrentHashMap<IrDeclaration, FirDeclaration>()
private val delegatedReverseCache = mutableMapOf<IrDeclaration, FirDeclaration>()
private val fieldCache = ConcurrentHashMap<FirField, IrField>()
private val fieldCache = mutableMapOf<FirField, IrField>()
private val localStorage by threadLocal { Fir2IrLocalStorage() }
private val localStorage = Fir2IrLocalStorage()
private val delegatedMemberGenerator = DelegatedMemberGenerator(components)

View File

@@ -12,10 +12,7 @@ import org.jetbrains.kotlin.fir.backend.convertWithOffsets
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.calls.FirFakeArgumentForCallableReference
import org.jetbrains.kotlin.fir.resolve.calls.ResolvedCallArgument
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -32,7 +29,10 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.types.typeOrNull
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
@@ -58,7 +58,7 @@ internal class AdapterGenerator(
function: IrFunction
): Boolean =
needSuspendConversion(type, function) || needCoercionToUnit(type, function) ||
needVarargSpread(callableReferenceAccess)
needVarargSpread(callableReferenceAccess, type, function)
/**
* For example,
@@ -96,11 +96,26 @@ internal class AdapterGenerator(
*
* At the use site, instead of referenced, we can put the adapter: { a, b -> referenced(a, b) }
*/
private fun needVarargSpread(callableReferenceAccess: FirCallableReferenceAccess): Boolean {
private fun needVarargSpread(
callableReferenceAccess: FirCallableReferenceAccess,
type: IrSimpleType,
function: IrFunction
): Boolean {
// Unbound callable reference 'A::foo'
return (callableReferenceAccess.calleeReference as? FirResolvedCallableReference)?.mappedArguments?.any {
it.value is ResolvedCallArgument.VarargArgument || it.value is ResolvedCallArgument.DefaultArgument
} == true
val shift = if (callableReferenceAccess.explicitReceiver is FirResolvedQualifier) 1 else 0
val typeArguments = type.arguments
// Drop the return type from type arguments
val expectedParameterSize = typeArguments.size - 1 - shift
if (expectedParameterSize < function.valueParameters.size) {
return false
}
var hasSpreadCase = false
function.valueParameters.forEachIndexed { index, irValueParameter ->
if (irValueParameter.isVararg && typeArguments[shift + index] == irValueParameter.varargElementType) {
hasSpreadCase = true
}
}
return hasSpreadCase
}
internal fun ConeKotlinType.kFunctionTypeToFunctionType(): IrSimpleType =
@@ -112,7 +127,7 @@ internal class AdapterGenerator(
adapteeSymbol: IrFunctionSymbol,
type: IrSimpleType
): IrExpression {
val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirFunction
val firAdaptee = callableReferenceAccess.toResolvedCallableReference()?.resolvedSymbol?.fir as? FirSimpleFunction
val adaptee = adapteeSymbol.owner
val expectedReturnType = type.arguments.last().typeOrNull
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
@@ -123,7 +138,7 @@ internal class AdapterGenerator(
callableReferenceAccess, startOffset, endOffset, firAdaptee!!, adaptee, type, boundDispatchReceiver, boundExtensionReceiver
)
val irCall = createAdapteeCallForCallableReference(
callableReferenceAccess, firAdaptee, adapteeSymbol, irAdapterFunction, boundDispatchReceiver, boundExtensionReceiver
callableReferenceAccess, adapteeSymbol, irAdapterFunction, boundDispatchReceiver, boundExtensionReceiver
)
irAdapterFunction.body = irFactory.createBlockBody(startOffset, endOffset) {
if (expectedReturnType?.isUnit() == true) {
@@ -164,7 +179,7 @@ internal class AdapterGenerator(
callableReferenceAccess: FirCallableReferenceAccess,
startOffset: Int,
endOffset: Int,
firAdaptee: FirFunction<*>,
firAdaptee: FirSimpleFunction,
adaptee: IrFunction,
type: IrSimpleType,
boundDispatchReceiver: IrExpression?,
@@ -172,7 +187,6 @@ internal class AdapterGenerator(
): IrSimpleFunction {
val returnType = type.arguments.last().typeOrNull!!
val parameterTypes = type.arguments.dropLast(1).map { it.typeOrNull!! }
val firMemberAdaptee = firAdaptee as FirMemberDeclaration
return irFactory.createFunction(
startOffset, endOffset,
IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE,
@@ -181,13 +195,13 @@ internal class AdapterGenerator(
DescriptorVisibilities.LOCAL,
Modality.FINAL,
returnType,
isInline = firMemberAdaptee.isInline,
isExternal = firMemberAdaptee.isExternal,
isTailrec = firMemberAdaptee.isTailRec,
isSuspend = firMemberAdaptee.isSuspend || type.isSuspendFunction(),
isOperator = firMemberAdaptee.isOperator,
isInfix = firMemberAdaptee.isInfix,
isExpect = firMemberAdaptee.isExpect,
isInline = firAdaptee.isInline,
isExternal = firAdaptee.isExternal,
isTailrec = firAdaptee.isTailRec,
isSuspend = firAdaptee.isSuspend || type.isSuspendFunction(),
isOperator = firAdaptee.isOperator,
isInfix = firAdaptee.isInfix,
isExpect = firAdaptee.isExpect,
isFakeOverride = false
).also { irAdapterFunction ->
irAdapterFunction.metadata = FirMetadataSource.Function(firAdaptee)
@@ -254,7 +268,6 @@ internal class AdapterGenerator(
private fun createAdapteeCallForCallableReference(
callableReferenceAccess: FirCallableReferenceAccess,
firAdaptee: FirFunction<*>,
adapteeSymbol: IrFunctionSymbol,
adapterFunction: IrFunction,
boundDispatchReceiver: IrExpression?,
@@ -283,7 +296,6 @@ internal class AdapterGenerator(
}
var adapterParameterIndex = 0
var parameterShift = 0
if (boundDispatchReceiver != null || boundExtensionReceiver != null) {
val receiverValue = IrGetValueImpl(
startOffset, endOffset, adapterFunction.extensionReceiverParameter!!.symbol, IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE
@@ -300,56 +312,50 @@ internal class AdapterGenerator(
)
if (adapteeFunction.extensionReceiverParameter != null) {
irCall.extensionReceiver = adaptedReceiverValue
adapterParameterIndex++
} else {
irCall.dispatchReceiver = adaptedReceiverValue
}
parameterShift++
}
val mappedArguments = (callableReferenceAccess.calleeReference as? FirResolvedCallableReference)?.mappedArguments
fun buildIrGetValueArgument(argument: FirExpression): IrGetValue {
val parameterIndex = (argument as? FirFakeArgumentForCallableReference)?.index ?: adapterParameterIndex
adapterParameterIndex++
return adapterFunction.valueParameters[parameterIndex + parameterShift].toIrGetValue(startOffset, endOffset)
}
adapteeFunction.valueParameters.zip(firAdaptee.valueParameters).mapIndexed { index, (valueParameter, firParameter) ->
when (val mappedArgument = mappedArguments?.get(firParameter)) {
is ResolvedCallArgument.VarargArgument -> {
val valueArgument = if (mappedArgument.arguments.isEmpty()) {
null
adapteeFunction.valueParameters.mapIndexed { index, valueParameter ->
when {
valueParameter.isVararg -> {
if (adapterFunction.valueParameters.size <= index) {
irCall.putValueArgument(index, null)
} else {
val adaptedValueArgument = IrVarargImpl(
startOffset, endOffset,
valueParameter.type, valueParameter.varargElementType!!,
)
for (argument in mappedArgument.arguments) {
val irValueArgument = buildIrGetValueArgument(argument)
adaptedValueArgument.addElement(irValueArgument)
val adaptedValueArgument =
IrVarargImpl(startOffset, endOffset, valueParameter.type, valueParameter.varargElementType!!)
var neitherArrayNorSpread = false
while (adapterParameterIndex < adapterFunction.valueParameters.size) {
val irValueArgument =
adapterFunction.valueParameters[adapterParameterIndex].toIrGetValue(startOffset, endOffset)
if (irValueArgument.type == valueParameter.type) {
adaptedValueArgument.addElement(IrSpreadElementImpl(startOffset, endOffset, irValueArgument))
adapterParameterIndex++
break
} else if (irValueArgument.type == valueParameter.varargElementType) {
adaptedValueArgument.addElement(irValueArgument)
adapterParameterIndex++
} else {
neitherArrayNorSpread = true
break
}
}
if (neitherArrayNorSpread) {
irCall.putValueArgument(index, null)
} else {
irCall.putValueArgument(index, adaptedValueArgument)
}
adaptedValueArgument
}
irCall.putValueArgument(index, valueArgument)
}
ResolvedCallArgument.DefaultArgument -> {
valueParameter.hasDefaultValue() -> {
irCall.putValueArgument(index, null)
}
is ResolvedCallArgument.SimpleArgument -> {
val irValueArgument = buildIrGetValueArgument(mappedArgument.callArgument)
if (valueParameter.isVararg) {
irCall.putValueArgument(
index, IrVarargImpl(
startOffset, endOffset,
valueParameter.type, valueParameter.varargElementType!!,
listOf(IrSpreadElementImpl(startOffset, endOffset, irValueArgument))
)
)
} else {
irCall.putValueArgument(index, irValueArgument)
}
}
null -> {
else -> {
irCall.putValueArgument(
index, adapterFunction.valueParameters[adapterParameterIndex++].toIrGetValue(startOffset, endOffset)
)
}
}
}

View File

@@ -122,6 +122,16 @@ class CallAndReferenceGenerator(
origin
)
}
is IrConstructorSymbol -> {
val constructor = symbol.owner
val klass = constructor.parent as? IrClass
IrFunctionReferenceImpl(
startOffset, endOffset, type, symbol,
typeArgumentsCount = constructor.typeParameters.size + (klass?.typeParameters?.size ?: 0),
valueArgumentsCount = constructor.valueParameters.size,
reflectionTarget = symbol
)
}
is IrFunctionSymbol -> {
assert(type.isFunctionTypeOrSubtype()) {
"Callable reference whose symbol refers to a function should be of functional type."
@@ -134,12 +144,9 @@ class CallAndReferenceGenerator(
generateAdaptedCallableReference(callableReferenceAccess, explicitReceiverExpression, symbol, adaptedType)
}
} else {
val klass = function.parent as? IrClass
val typeArgumentCount = function.typeParameters.size +
if (function is IrConstructor) klass?.typeParameters?.size ?: 0 else 0
IrFunctionReferenceImpl(
startOffset, endOffset, type, symbol,
typeArgumentsCount = typeArgumentCount,
typeArgumentsCount = function.typeParameters.size,
valueArgumentsCount = function.valueParameters.size,
reflectionTarget = symbol
)
@@ -636,7 +643,7 @@ class CallAndReferenceGenerator(
// If the type of the argument is already an explicitly subtype of the type of the parameter, we don't need SAM conversion.
if (argument.typeRef !is FirResolvedTypeRef ||
AbstractTypeChecker.isSubtypeOf(
session.inferenceComponents.ctx.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true),
session.inferenceComponents.ctx,
argument.typeRef.coneType,
parameter.returnTypeRef.coneType,
isFromNullabilityConstraint = true

View File

@@ -2440,12 +2440,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/callableReference/kt37604.kt");
}
@Test
@TestMetadata("kt44483.kt")
public void testKt44483() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/kt44483.kt");
}
@Test
@TestMetadata("nested.kt")
public void testNested() throws Exception {
@@ -19987,12 +19981,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionOnFunctionReference.kt");
}
@Test
@TestMetadata("samExtFunWithCapturingLambda.kt")
public void testSamExtFunWithCapturingLambda() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/samExtFunWithCapturingLambda.kt");
}
@Test
@TestMetadata("simpleFunInterfaceConstructor.kt")
public void testSimpleFunInterfaceConstructor() throws Exception {
@@ -35387,12 +35375,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/reflection/types/classifiersOfBuiltInTypes.kt");
}
@Test
@TestMetadata("equalsForClassAndTypeParameterWithSameFqName.kt")
public void testEqualsForClassAndTypeParameterWithSameFqName() throws Exception {
runTest("compiler/testData/codegen/box/reflection/types/equalsForClassAndTypeParameterWithSameFqName.kt");
}
@Test
@TestMetadata("innerGenericArguments.kt")
public void testInnerGenericArguments() throws Exception {
@@ -37325,6 +37307,94 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/signatureAnnotations")
@TestDataPath("$PROJECT_ROOT")
public class SignatureAnnotations {
@Test
public void testAllFilesPresentInSignatureAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/signatureAnnotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("defaultAndNamedCombination.kt")
public void testDefaultAndNamedCombination() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultAndNamedCombination.kt");
}
@Test
@TestMetadata("defaultBoxTypes.kt")
public void testDefaultBoxTypes() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultBoxTypes.kt");
}
@Test
@TestMetadata("defaultEnumType.kt")
public void testDefaultEnumType() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultEnumType.kt");
}
@Test
@TestMetadata("defaultLongLiteral.kt")
public void testDefaultLongLiteral() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultLongLiteral.kt");
}
@Test
@TestMetadata("defaultMultipleParams.kt")
public void testDefaultMultipleParams() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultMultipleParams.kt");
}
@Test
@TestMetadata("defaultNull.kt")
public void testDefaultNull() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultNull.kt");
}
@Test
@TestMetadata("defaultNullableBoxTypes.kt")
public void testDefaultNullableBoxTypes() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultNullableBoxTypes.kt");
}
@Test
@TestMetadata("defaultOverrides.kt")
public void testDefaultOverrides() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultOverrides.kt");
}
@Test
@TestMetadata("defaultPrimitiveTypes.kt")
public void testDefaultPrimitiveTypes() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultPrimitiveTypes.kt");
}
@Test
@TestMetadata("defaultValueInConstructor.kt")
public void testDefaultValueInConstructor() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultValueInConstructor.kt");
}
@Test
@TestMetadata("defaultWithJavaBase.kt")
public void testDefaultWithJavaBase() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultWithJavaBase.kt");
}
@Test
@TestMetadata("defaultWithKotlinBase.kt")
public void testDefaultWithKotlinBase() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/defaultWithKotlinBase.kt");
}
@Test
@TestMetadata("reorderedParameterNames.kt")
public void testReorderedParameterNames() throws Exception {
runTest("compiler/testData/codegen/box/signatureAnnotations/reorderedParameterNames.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/smap")
@TestDataPath("$PROJECT_ROOT")
@@ -37452,24 +37522,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
}
@Test
@TestMetadata("kt44814.kt")
public void testKt44814() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt44814.kt");
}
@Test
@TestMetadata("kt44932.kt")
public void testKt44932() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt44932.kt");
}
@Test
@TestMetadata("kt44942.kt")
public void testKt44942() throws Exception {
runTest("compiler/testData/codegen/box/smartCasts/kt44942.kt");
}
@Test
@TestMetadata("lambdaArgumentWithoutType.kt")
public void testLambdaArgumentWithoutType() throws Exception {

View File

@@ -647,18 +647,6 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
runTest("compiler/testData/codegen/boxInline/anonymousObject/twoCapturedReceivers/kt8668_3.kt");
}
@Test
@TestMetadata("kt8668_nested.kt")
public void testKt8668_nested() throws Exception {
runTest("compiler/testData/codegen/boxInline/anonymousObject/twoCapturedReceivers/kt8668_nested.kt");
}
@Test
@TestMetadata("kt8668_nested_2.kt")
public void testKt8668_nested_2() throws Exception {
runTest("compiler/testData/codegen/boxInline/anonymousObject/twoCapturedReceivers/kt8668_nested_2.kt");
}
@Test
@TestMetadata("twoDifferentDispatchReceivers.kt")
public void testTwoDifferentDispatchReceivers() throws Exception {

View File

@@ -5080,12 +5080,6 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/stringOperations/concatDynamicIndyDataClass.kt");
}
@Test
@TestMetadata("concatDynamicUnit.kt")
public void testConcatDynamicUnit() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/stringOperations/concatDynamicUnit.kt");
}
@Test
@TestMetadata("concatNotDynamic.kt")
public void testConcatNotDynamic() throws Exception {
@@ -5580,12 +5574,6 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/subjectAny.kt");
}
@Test
@TestMetadata("whenOr.kt")
public void testWhenOr() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/whenEnumOptimization/whenOr.kt");
}
@Test
@TestMetadata("withoutElse.kt")
public void testWithoutElse() throws Exception {

View File

@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.resolveSupertypesInTheAir
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -242,7 +241,9 @@ private fun ConeClassLikeType.mapToCanonicalNoExpansionString(session: FirSessio
} + "[]"
}
with(session.typeContext) {
val context = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = true, session = session)
with(context) {
val typeConstructor = typeConstructor()
typeConstructor.getPrimitiveType()?.let { return JvmPrimitiveType.get(it).wrapperFqName.asString() }
typeConstructor.getPrimitiveArrayType()?.let { return JvmPrimitiveType.get(it).javaKeywordName + "[]" }

View File

@@ -69,7 +69,6 @@ class JavaSymbolProvider(
private val scopeProvider = JavaScopeProvider(::wrapScopeWithJvmMapped, this)
private val facade: KotlinJavaPsiFacade get() = KotlinJavaPsiFacade.getInstance(project)
private val parentClassTypeParameterStackCache = mutableMapOf<FirRegularClassSymbol, JavaTypeParameterStack>()
private fun findClass(
classId: ClassId,
@@ -189,15 +188,12 @@ class JavaSymbolProvider(
if (parentClassSymbol != null) {
val parentStack = parentClassTypeParameterStackCache[parentClassSymbol]
?: (parentClassSymbol.fir as? FirJavaClass)?.javaTypeParameterStack
val parentStack = (parentClassSymbol.fir as? FirJavaClass)?.javaTypeParameterStack
if (parentStack != null) {
javaTypeParameterStack.addStack(parentStack)
}
}
parentClassTypeParameterStackCache[classSymbol] = javaTypeParameterStack
val firJavaClass = createFirJavaClass(javaClass, classSymbol, outerClassId, parentClassSymbol, classId, javaTypeParameterStack)
parentClassTypeParameterStackCache.remove(classSymbol)
firJavaClass.convertSuperTypes(javaClass, javaTypeParameterStack)
firJavaClass.addAnnotationsFrom(this@JavaSymbolProvider.session, javaClass, javaTypeParameterStack)
return firJavaClass

View File

@@ -393,8 +393,6 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
)
}
val classSymbol = session.symbolProvider.getClassLikeSymbolByFqName(classId) as? FirRegularClassSymbol
val mappedTypeArguments = if (isRaw) {
val defaultArgs = (1..classifier.typeParameters.size).map { ConeStarProjection }
@@ -405,10 +403,14 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
} else {
val position = if (isLowerBound) TypeComponentPosition.FLEXIBLE_LOWER else TypeComponentPosition.FLEXIBLE_UPPER
val classSymbol = session.symbolProvider.getClassLikeSymbolByFqName(classId) as? FirRegularClassSymbol
classSymbol?.fir?.createRawArguments(defaultArgs, position) ?: defaultArgs
}
} else {
val typeParameters = runIf(!forTypeParameterBounds && !isForSupertypes) { classSymbol?.fir?.typeParameters } ?: emptyList()
val typeParameters = runIf(!forTypeParameterBounds && !isForSupertypes) {
val classSymbol = session.symbolProvider.getClassLikeSymbolByFqName(classId) as? FirRegularClassSymbol
classSymbol?.fir?.typeParameters
} ?: emptyList()
typeArguments.indices.map { index ->
val argument = typeArguments[index]

View File

@@ -18,6 +18,8 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.declarations.*
import org.jetbrains.kotlin.fir.render
@@ -28,9 +30,12 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
import org.jetbrains.kotlin.load.java.typeEnhancement.*
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.utils.JavaTypeEnhancementState
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -180,26 +185,27 @@ class FirSignatureEnhancement(
enhanceReturnType(firMethod, overriddenMembers, memberContext, predefinedEnhancementInfo)
}
val enhancedValueParameterTypes = mutableListOf<FirResolvedTypeRef>()
val newValueParameterInfo = mutableListOf<EnhanceValueParameterResult>()
for ((index, valueParameter) in firMethod.valueParameters.withIndex()) {
if (hasReceiver && index == 0) continue
enhancedValueParameterTypes += enhanceValueParameterType(
newValueParameterInfo += enhanceValueParameter(
firMethod, overriddenMembers, hasReceiver,
memberContext, predefinedEnhancementInfo, valueParameter as FirJavaValueParameter,
if (hasReceiver) index - 1 else index
)
}
val newValueParameters = firMethod.valueParameters.zip(enhancedValueParameterTypes) { valueParameter, enhancedReturnType ->
val newValueParameters = firMethod.valueParameters.zip(newValueParameterInfo) { valueParameter, newInfo ->
val (newTypeRef, newDefaultValue) = newInfo
buildValueParameter {
source = valueParameter.source
session = this@FirSignatureEnhancement.session
origin = FirDeclarationOrigin.Enhancement
returnTypeRef = enhancedReturnType
returnTypeRef = newTypeRef
this.name = valueParameter.name
symbol = FirVariableSymbol(this.name)
defaultValue = valueParameter.defaultValue
defaultValue = valueParameter.defaultValue ?: newDefaultValue
isCrossinline = valueParameter.isCrossinline
isNoinline = valueParameter.isNoinline
isVararg = valueParameter.isVararg
@@ -292,7 +298,9 @@ class FirSignatureEnhancement(
return signatureParts.type
}
private fun enhanceValueParameterType(
private data class EnhanceValueParameterResult(val typeRef: FirResolvedTypeRef, val defaultValue: FirExpression?)
private fun enhanceValueParameter(
ownerFunction: FirFunction<*>,
overriddenMembers: List<FirCallableMemberDeclaration<*>>,
hasReceiver: Boolean,
@@ -300,7 +308,7 @@ class FirSignatureEnhancement(
predefinedEnhancementInfo: PredefinedFunctionEnhancementInfo?,
ownerParameter: FirJavaValueParameter,
index: Int
): FirResolvedTypeRef {
): EnhanceValueParameterResult {
val signatureParts = ownerFunction.partsForValueParameter(
typeQualifierResolver,
overriddenMembers,
@@ -313,7 +321,13 @@ class FirSignatureEnhancement(
predefinedEnhancementInfo?.parametersInfo?.getOrNull(index),
forAnnotationMember = owner.classKind == ClassKind.ANNOTATION_CLASS
)
return signatureParts.type
val firResolvedTypeRef = signatureParts.type
val defaultValueExpression = when (val defaultValue = ownerParameter.getDefaultValueFromAnnotation()) {
NullDefaultValue -> buildConstExpression(null, ConstantValueKind.Null, null)
is StringDefaultValue -> firResolvedTypeRef.type.lexicalCastFrom(session, defaultValue.value)
null -> null
}
return EnhanceValueParameterResult(firResolvedTypeRef, defaultValueExpression)
}
private fun enhanceReturnType(

View File

@@ -13,6 +13,11 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildQualifiedAccessExpression
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
@@ -26,6 +31,11 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.JavaDefaultQualifiers
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_NULL_FQ_NAME
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME
import org.jetbrains.kotlin.load.java.descriptors.AnnotationDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue
import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
import org.jetbrains.kotlin.load.java.structure.JavaType
import org.jetbrains.kotlin.load.java.typeEnhancement.*
@@ -35,6 +45,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.RawType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.extractRadix
internal class IndexedJavaTypeQualifiers(private val data: Array<JavaTypeQualifiers>) {
@@ -306,6 +317,22 @@ internal fun ConeKotlinType.lexicalCastFrom(session: FirSession, value: String):
}
}
internal fun FirValueParameter.getDefaultValueFromAnnotation(): AnnotationDefaultValue? {
annotations.find { it.classId == DEFAULT_VALUE_ID }
?.arguments?.firstOrNull()
?.safeAs<FirConstExpression<*>>()?.value?.safeAs<String>()
?.let { return StringDefaultValue(it) }
if (annotations.any { it.classId == DEFAULT_NULL_ID }) {
return NullDefaultValue
}
return null
}
private val DEFAULT_VALUE_ID = ClassId.topLevel(DEFAULT_VALUE_FQ_NAME)
private val DEFAULT_NULL_ID = ClassId.topLevel(DEFAULT_NULL_FQ_NAME)
internal fun List<FirAnnotationCall>.computeTypeAttributesForJavaType(): ConeAttributes =
computeTypeAttributes { classId ->
when (classId) {

View File

@@ -6,19 +6,21 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.visibility
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
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.types.ConeInferenceContext
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
val FirSession.typeContext: ConeInferenceContext
get() = inferenceComponents.ctx
val FirSession.typeCheckerContext: ConeTypeCheckerContext
get() = inferenceComponents.ctx
/**
* Returns the list of functions that overridden by given
*/

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2010-2021 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.declarations
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.model.typeConstructor
fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, context: ConeTypeContext): ConeKotlinType? {
val symbol = (this.fullyExpandedType(session) as? ConeLookupTagBasedType)
?.lookupTag
?.toSymbol(session) as? FirRegularClassSymbol
?: return null
symbol.ensureResolved(FirResolvePhase.STATUS, session)
val firClass = symbol.fir
if (!firClass.status.isInline) return null
val constructor = firClass.declarations.singleOrNull { it is FirConstructor && it.isPrimary } as FirConstructor? ?: return null
val valueParameter = constructor.valueParameters.singleOrNull() ?: return null
val unsubstitutedType = valueParameter.returnTypeRef.coneType
val substitutor = createTypeSubstitutorByTypeConstructor(mapOf(this.typeConstructor(context) to this), context)
return substitutor.substituteOrNull(unsubstitutedType)
}

View File

@@ -104,7 +104,6 @@ abstract class AbstractConeCallConflictResolver(
is FirConstructor -> createFlatSignature(call, declaration)
is FirVariable<*> -> createFlatSignature(call, declaration)
is FirClass<*> -> createFlatSignature(call, declaration)
is FirTypeAlias -> createFlatSignature(call, declaration)
else -> error("Not supported: $declaration")
}
}
@@ -164,10 +163,10 @@ abstract class AbstractConeCallConflictResolver(
?: call.argumentMapping?.map { it.value.argumentType() }.orEmpty())
}
private fun createFlatSignature(call: Candidate, klass: FirClassLikeDeclaration<*>): FlatSignature<Candidate> {
private fun createFlatSignature(call: Candidate, klass: FirClass<*>): FlatSignature<Candidate> {
return FlatSignature(
call,
(klass as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
(klass as? FirRegularClass)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
valueParameterTypes = emptyList(),
hasExtensionReceiver = false,
hasVarargs = false,

View File

@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclarati
import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.typeCheckerContext
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
@@ -25,7 +26,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompat
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.model.TypeSystemCommonSuperTypesContext
import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun Candidate.resolveArgumentExpression(
@@ -416,10 +416,7 @@ fun FirExpression.isFunctional(
val returnTypeCompatible =
expectedReturnType is ConeTypeParameterType ||
AbstractTypeChecker.isSubtypeOf(
session.inferenceComponents.ctx.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = true
),
session.inferenceComponents.ctx,
invokeSymbol.fir.returnTypeRef.coneType,
expectedReturnType,
isFromNullabilityConstraint = false
@@ -436,10 +433,7 @@ fun FirExpression.isFunctional(
val expectedParameterType = expectedParameter!!.lowerBoundIfFlexible()
expectedParameterType is ConeTypeParameterType ||
AbstractTypeChecker.isSubtypeOf(
session.inferenceComponents.ctx.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = true
),
session.inferenceComponents.ctx,
invokeParameter.returnTypeRef.coneType,
expectedParameterType,
isFromNullabilityConstraint = false
@@ -494,7 +488,7 @@ internal fun captureFromTypeParameterUpperBoundIfNeeded(
val simplifiedArgumentType = argumentType.lowerBoundIfFlexible() as? ConeTypeParameterType ?: return argumentType
val typeParameter = simplifiedArgumentType.lookupTag.typeParameterSymbol.fir
val context = session.typeContext
val context = session.typeCheckerContext
val chosenSupertype = typeParameter.bounds.map { it.coneType }
.singleOrNull { it.hasSupertypeWithGivenClassId(expectedTypeClassId, context) } ?: return argumentType
@@ -507,7 +501,7 @@ internal fun captureFromTypeParameterUpperBoundIfNeeded(
}
}
private fun ConeKotlinType.hasSupertypeWithGivenClassId(classId: ClassId, context: TypeSystemCommonSuperTypesContext): Boolean {
private fun ConeKotlinType.hasSupertypeWithGivenClassId(classId: ClassId, context: ConeTypeCheckerContext): Boolean {
return with(context) {
anySuperTypeConstructor {
it is ConeClassLikeLookupTag && it.classId == classId

View File

@@ -51,7 +51,8 @@ internal object CheckCallableReferenceExpectedType : CheckerStage() {
}
candidate.resultingTypeForCallableReference = resultingType
candidate.callableReferenceAdaptation = callableReferenceAdaptation
candidate.usesSuspendConversion =
callableReferenceAdaptation?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
candidate.outerConstraintBuilderEffect = fun ConstraintSystemOperation.() {
addOtherSystem(candidate.system.asReadOnlyStorage())
@@ -132,7 +133,7 @@ internal class CallableReferenceAdaptation(
val argumentTypes: Array<ConeKotlinType>,
val coercionStrategy: CoercionStrategy,
val defaults: Int,
val mappedArguments: CallableReferenceMappedArguments,
val mappedArguments: Map<FirValueParameter, ResolvedCallArgument>,
val suspendConversionStrategy: SuspendConversionStrategy
)
@@ -350,7 +351,7 @@ private fun createFakeArgumentsForReference(
}
}
class FirFakeArgumentForCallableReference(
private class FirFakeArgumentForCallableReference(
val index: Int
) : FirExpression() {
override val source: FirSourceElement?

View File

@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.SuspendConversionStrategy
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
@@ -98,13 +97,6 @@ class Candidate(
var resultingTypeForCallableReference: ConeKotlinType? = null
var outerConstraintBuilderEffect: (ConstraintSystemOperation.() -> Unit)? = null
var usesSAM: Boolean = false
internal var callableReferenceAdaptation: CallableReferenceAdaptation? = null
set(value) {
field = value
usesSuspendConversion = value?.suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
}
var usesSuspendConversion: Boolean = false
var argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>? = null

View File

@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.defaultParameterResolver
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.name.Name
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashMap
import kotlin.collections.component1

View File

@@ -1,11 +1,10 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.resolve.calls
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
sealed class ResolvedCallArgument {
@@ -24,6 +23,4 @@ sealed class ResolvedCallArgument {
}
class VarargArgument(override val arguments: List<FirExpression>) : ResolvedCallArgument()
}
typealias CallableReferenceMappedArguments = Map<FirValueParameter, ResolvedCallArgument>
}

View File

@@ -1136,6 +1136,12 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
lhsExitNode.mergeIncomingFlow()
val flow = lhsExitNode.flow
val lhsVariable = variableStorage.getOrCreateVariable(flow, elvisExpression.lhs)
rhsEnterNode.flow = logicSystem.approveStatementsInsideFlow(
flow,
lhsVariable eq null,
shouldForkFlow = true,
shouldRemoveSynthetics = false
)
lhsIsNotNullNode.flow = logicSystem.approveStatementsInsideFlow(
flow,
lhsVariable notEq null,
@@ -1146,14 +1152,6 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
it.addTypeStatement(lhsVariable typeEq any)
}
}
rhsEnterNode.flow = logicSystem.approveStatementsInsideFlow(
flow,
lhsVariable eq null,
shouldForkFlow = true,
shouldRemoveSynthetics = false
).also {
logicSystem.updateAllReceivers(it)
}
}
fun exitElvis(elvisExpression: FirElvisExpression) {

View File

@@ -143,7 +143,7 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
if (types.any { it.isEmpty() }) return mutableSetOf()
val intersectedTypes = types.map {
if (it.size > 1) {
context.intersectTypes(it.toList())
context.intersectTypes(it.toList()) as ConeKotlinType
} else {
assert(it.size == 1) { "We've already checked each set of types is not empty." }
it.single()

View File

@@ -79,7 +79,6 @@ class ControlFlowGraphBuilder {
private val exitsFromCompletedPostponedAnonymousFunctions: MutableList<PostponedLambdaExitNode> = mutableListOf()
private val whenExitNodes: NodeStorage<FirWhenExpression, WhenExitNode> = NodeStorage()
private val whenBranchIndices: Stack<Map<FirWhenBranch, Int>> = stackOf()
private val binaryAndExitNodes: Stack<BinaryAndExitNode> = stackOf()
private val binaryOrExitNodes: Stack<BinaryOrExitNode> = stackOf()
@@ -597,7 +596,6 @@ class ControlFlowGraphBuilder {
val node = createWhenEnterNode(whenExpression)
addNewSimpleNode(node)
whenExitNodes.push(createWhenExitNode(whenExpression))
whenBranchIndices.push(whenExpression.branches.mapIndexed { index, branch -> branch to index }.toMap())
levelCounter++
return node
}
@@ -615,7 +613,6 @@ class ControlFlowGraphBuilder {
lastNodes.push(it)
addEdge(conditionExitNode, it)
}
levelCounter += whenBranchIndices.top().getValue(whenBranch)
return conditionExitNode to branchEnterNode
}
@@ -625,7 +622,6 @@ class ControlFlowGraphBuilder {
popAndAddEdge(node)
val whenExitNode = whenExitNodes.top()
addEdge(node, whenExitNode, propagateDeadness = false)
levelCounter -= whenBranchIndices.top().getValue(whenBranch)
return node
}
@@ -644,7 +640,6 @@ class ControlFlowGraphBuilder {
lastNodes.push(whenExitNode)
dropPostponedLambdasForNonDeterministicCalls()
levelCounter--
whenBranchIndices.pop()
return whenExitNode to syntheticElseBranchNode
}

View File

@@ -18,7 +18,6 @@ import java.util.*
class FirControlFlowGraphRenderVisitor(
builder: StringBuilder,
private val renderLevels: Boolean = false
) : FirVisitorVoid() {
companion object {
private const val EDGE = " -> "
@@ -82,13 +81,7 @@ class FirControlFlowGraphRenderVisitor(
color = BLUE
}
val attributes = mutableListOf<String>()
val label = buildString {
append(node.render().replace("\"", ""))
if (renderLevels) {
append(" [${node.level}]")
}
}
attributes += "label=\"$label\""
attributes += "label=\"${node.render().replace("\"", "")}\""
fun fillColor(color: String) {
attributes += "style=\"filled\""
@@ -225,4 +218,4 @@ private fun ControlFlowGraph.forEachSubGraph(block: (ControlFlowGraph) -> Unit)
block(subGraph)
subGraph.forEachSubGraph(block)
}
}
}

View File

@@ -7,16 +7,14 @@ package org.jetbrains.kotlin.fir.resolve.inference
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
import org.jetbrains.kotlin.resolve.calls.inference.components.*
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.types.AbstractTypeApproximator
@NoMutableState
class InferenceComponents(val session: FirSession) : FirSessionComponent {
val ctx: ConeInferenceContext = object : ConeInferenceContext {
override val session: FirSession
get() = this@InferenceComponents.session
}
val ctx: ConeTypeCheckerContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = true, session)
val approximator: AbstractTypeApproximator = object : AbstractTypeApproximator(ctx) {}
val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx)

View File

@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
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.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
@@ -46,15 +45,16 @@ fun ConeKotlinType.isKMutableProperty(session: FirSession): Boolean {
}
private fun ConeKotlinType.functionClassKind(session: FirSession): FunctionClassKind? {
return classId(session)?.toFunctionClassKind()
}
private fun ClassId.toFunctionClassKind(): FunctionClassKind? {
return FunctionClassKind.byClassNamePrefix(packageFqName, relativeClassName.asString())
val classId = classId(session) ?: return null
return FunctionClassKind.byClassNamePrefix(classId.packageFqName, classId.relativeClassName.asString())
}
fun ConeKotlinType.isBuiltinFunctionalType(session: FirSession): Boolean {
return functionClassKind(session) != null
val kind = functionClassKind(session) ?: return false
return kind == FunctionClassKind.Function ||
kind == FunctionClassKind.KFunction ||
kind == FunctionClassKind.SuspendFunction ||
kind == FunctionClassKind.KSuspendFunction
}
fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
@@ -62,10 +62,6 @@ fun ConeKotlinType.isFunctionalType(session: FirSession): Boolean {
return kind == FunctionClassKind.Function
}
fun ConeClassLikeLookupTag.isBuiltinFunctionalType(): Boolean {
return classId.toFunctionClassKind() != null
}
fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean {
val kind = functionClassKind(session) ?: return false
return kind == FunctionClassKind.SuspendFunction ||

View File

@@ -10,10 +10,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
import org.jetbrains.kotlin.types.model.typeConstructor
abstract class AbstractConeSubstitutor : ConeSubstitutor() {
private fun wrapProjection(old: ConeTypeProjection, newType: ConeKotlinType): ConeTypeProjection {
@@ -166,15 +162,3 @@ data class ConeSubstitutorByMap(val substitution: Map<FirTypeParameterSymbol, Co
return result
}
}
fun createTypeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, ConeKotlinType>, context: ConeTypeContext): ConeSubstitutor {
if (map.isEmpty()) return ConeSubstitutor.Empty
return object : AbstractConeSubstitutor(),
TypeSubstitutorMarker {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
if (type !is ConeLookupTagBasedType && type !is ConeStubType) return null
val new = map[type.typeConstructor(context)] ?: return null
return new.approximateIntegerLiteralType().updateNullabilityIfNeeded(type)
}
}
}

View File

@@ -14,8 +14,10 @@ import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedCallableReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.calls.CallableReferenceAdaptation
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.FirErrorReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.calls.varargElementType
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
@@ -293,7 +295,6 @@ class FirCallCompletionResultsWriterTransformer(
name = calleeReference.name
resolvedSymbol = calleeReference.candidateSymbol
inferredTypeArguments.addAll(computeTypeArgumentTypes(calleeReference.candidate))
mappedArguments = subCandidate.callableReferenceAdaptation?.mappedArguments ?: emptyMap()
},
).transformDispatchReceiver(StoreReceiver, subCandidate.dispatchReceiverExpression())
.transformExtensionReceiver(StoreReceiver, subCandidate.extensionReceiverExpression())

View File

@@ -989,8 +989,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
if (variable.returnTypeRef is FirImplicitTypeRef) {
when {
initializer != null -> {
val unwrappedInitializer = (initializer as? FirExpressionWithSmartcast)?.originalExpression ?: initializer
val expectedType = when (val resultType = unwrappedInitializer.resultType) {
val expectedType = when (val resultType = initializer.resultType) {
is FirImplicitTypeRef -> buildErrorTypeRef {
diagnostic = ConeSimpleDiagnostic("No result type for initializer", DiagnosticKind.InferenceError)
}

View File

@@ -496,8 +496,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
if (baseType !is ConeClassLikeType) return this
val baseFirClass = baseType.lookupTag.toSymbol(session)?.fir ?: return this
val newArguments = if (AbstractTypeChecker.isSubtypeOfClass(
session.typeContext.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true), baseType.lookupTag, type.lookupTag)) {
val newArguments = if (AbstractTypeChecker.isSubtypeOfClass(session.typeCheckerContext, baseType.lookupTag, type.lookupTag)) {
// If actual type of declaration is more specific than bare type then we should just find
// corresponding supertype with proper arguments
with(session.typeContext) {

View File

@@ -13,11 +13,9 @@ import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.name.FqName
private val INVISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
private val VISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
private val DEFAULT_SIMPLE_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultSimpleImportingScope>()
private val PACKAGE_MEMBER = scopeSessionKey<FqName, FirPackageMemberScope>()
private val ALL_IMPORTS = scopeSessionKey<FirFile, ListStorageFirScope>()
private object FirDefaultStarImportingScopeKey : ScopeSessionKey<DefaultImportPriority, FirScope>()
private object FirDefaultSimpleImportingScopeKey : ScopeSessionKey<DefaultImportPriority, FirScope>()
private object FileImportingScopeKey : ScopeSessionKey<FirFile, ListStorageFirScope>()
private class ListStorageFirScope(val result: List<FirScope>) : FirScope()
@@ -27,7 +25,7 @@ fun createImportingScopes(
scopeSession: ScopeSession,
useCaching: Boolean = true
): List<FirScope> = if (useCaching) {
scopeSession.getOrBuild(file, ALL_IMPORTS) {
scopeSession.getOrBuild(file, FileImportingScopeKey) {
ListStorageFirScope(doCreateImportingScopes(file, session, scopeSession))
}.result
} else {
@@ -41,26 +39,17 @@ private fun doCreateImportingScopes(
): List<FirScope> {
return listOf(
// from low priority to high priority
scopeSession.getOrBuild(DefaultImportPriority.LOW, INVISIBLE_DEFAULT_STAR_IMPORT) {
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES, DefaultImportPriority.LOW)
scopeSession.getOrBuild(DefaultImportPriority.LOW, FirDefaultStarImportingScopeKey) {
FirDefaultStarImportingScope(session, scopeSession, priority = DefaultImportPriority.LOW)
},
scopeSession.getOrBuild(DefaultImportPriority.HIGH, INVISIBLE_DEFAULT_STAR_IMPORT) {
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES, DefaultImportPriority.HIGH)
scopeSession.getOrBuild(DefaultImportPriority.HIGH, FirDefaultStarImportingScopeKey) {
FirDefaultStarImportingScope(session, scopeSession, priority = DefaultImportPriority.HIGH)
},
FirExplicitStarImportingScope(file.imports, session, scopeSession, FirImportingScopeFilter.INVISIBLE_CLASSES),
// TODO: invisible classes from current package should go before this point
scopeSession.getOrBuild(DefaultImportPriority.LOW, VISIBLE_DEFAULT_STAR_IMPORT) {
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES, DefaultImportPriority.LOW)
},
scopeSession.getOrBuild(DefaultImportPriority.HIGH, VISIBLE_DEFAULT_STAR_IMPORT) {
FirDefaultStarImportingScope(session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES, DefaultImportPriority.HIGH)
},
FirExplicitStarImportingScope(file.imports, session, scopeSession, FirImportingScopeFilter.MEMBERS_AND_VISIBLE_CLASSES),
scopeSession.getOrBuild(DefaultImportPriority.LOW, DEFAULT_SIMPLE_IMPORT) {
FirExplicitStarImportingScope(file.imports, session, scopeSession),
scopeSession.getOrBuild(DefaultImportPriority.LOW, FirDefaultSimpleImportingScopeKey) {
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.LOW)
},
scopeSession.getOrBuild(DefaultImportPriority.HIGH, DEFAULT_SIMPLE_IMPORT) {
scopeSession.getOrBuild(DefaultImportPriority.HIGH, FirDefaultSimpleImportingScopeKey) {
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.HIGH)
},
scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) {
@@ -71,6 +60,8 @@ private fun doCreateImportingScopes(
)
}
private val PACKAGE_MEMBER = scopeSessionKey<FqName, FirPackageMemberScope>()
fun ConeClassLikeLookupTag.getNestedClassifierScope(session: FirSession, scopeSession: ScopeSession): FirScope? {
val klass = toSymbol(session)?.fir as? FirRegularClass ?: return null
return klass.scopeProvider.getNestedClassifierScope(klass, session, scopeSession)

View File

@@ -6,12 +6,9 @@
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.moduleVisibilityChecker
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedForCalls
@@ -20,90 +17,52 @@ import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.annotations.JVM_THROWS_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.KOTLIN_NATIVE_THROWS_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.annotations.KOTLIN_THROWS_ANNOTATION_FQ_NAME
enum class FirImportingScopeFilter {
ALL, INVISIBLE_CLASSES, MEMBERS_AND_VISIBLE_CLASSES;
fun check(symbol: FirClassLikeSymbol<*>, session: FirSession): Boolean {
if (this == ALL) return true
// TODO: also check DeprecationLevel.HIDDEN and required Kotlin version
val fir = symbol.fir as? FirMemberDeclaration ?: return false
val isVisible = when (fir.status.visibility) {
// When importing from the same module, status may be unknown because the status resolver depends on super types
// to determine visibility for functions, so it may not have finished yet. Since we only care about classes,
// though, "unknown" will always become public anyway.
Visibilities.Unknown -> true
Visibilities.Internal ->
symbol.fir.session == session || session.moduleVisibilityChecker?.isInFriendModule(fir) == true
// All non-`internal` visibilities are either even more restrictive (e.g. `private`) or must not
// be checked in imports (e.g. `protected` may be valid in some use sites).
else -> !fir.status.visibility.mustCheckInImports()
}
return isVisible == (this == MEMBERS_AND_VISIBLE_CLASSES)
}
}
abstract class FirAbstractImportingScope(
session: FirSession,
protected val scopeSession: ScopeSession,
protected val filter: FirImportingScopeFilter,
lookupInFir: Boolean
) : FirAbstractProviderBasedScope(session, lookupInFir) {
private val FirClassLikeSymbol<*>.fullyExpandedSymbol: FirClassSymbol<*>?
get() = when (this) {
is FirTypeAliasSymbol -> fir.expandedConeType?.lookupTag?.toSymbol(session)?.fullyExpandedSymbol
is FirClassSymbol<*> -> this
}
private fun FirClassSymbol<*>.getStaticsScope(): FirScope? =
if (fir.classKind == ClassKind.OBJECT) {
FirObjectImportedCallableScope(
classId, fir.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
)
private fun getStaticsScope(symbol: FirClassLikeSymbol<*>): FirScope? {
if (symbol is FirTypeAliasSymbol) {
val expansionSymbol = symbol.fir.expandedConeType?.lookupTag?.toSymbol(session)
if (expansionSymbol != null) {
return getStaticsScope(expansionSymbol)
}
} else {
fir.scopeProvider.getStaticScope(fir, session, scopeSession)
}
val firClass = (symbol as FirClassSymbol<*>).fir
fun getStaticsScope(classId: ClassId): FirScope? =
provider.getClassLikeSymbolByFqName(classId)?.fullyExpandedSymbol?.getStaticsScope()
protected fun findSingleClassifierSymbolByName(name: Name?, imports: List<FirResolvedImport>): FirClassLikeSymbol<*>? {
var result: FirClassLikeSymbol<*>? = null
for (import in imports) {
val importedName = name ?: import.importedName ?: continue
val classId = import.resolvedClassId?.createNestedClassId(importedName)
?: ClassId.topLevel(import.packageFqName.child(importedName))
val symbol = provider.getClassLikeSymbolByFqName(classId) ?: continue
if (!filter.check(symbol, session)) continue
result = when {
result == null || result == symbol -> symbol
// Importing multiple versions of the same type is normally an ambiguity, but in the case of `kotlin.Throws`,
// it should take precedence over platform-specific variants. This is lifted directly from `LazyImportScope`
// from the old backend; most likely `Throws` predates expect-actual, and this is a backwards compatibility hack.
// TODO: remove redundant versions of `Throws` from the standard library
result.classId.isJvmOrNativeThrows && symbol.classId.isCommonThrows -> symbol
result.classId.isCommonThrows && symbol.classId.isJvmOrNativeThrows -> result
// TODO: if there is an ambiguity at this scope, further scopes should not be checked.
// Doing otherwise causes KT-39073. Also, returning null here instead of an error symbol
// or something produces poor quality diagnostics ("unresolved name" rather than "ambiguity").
else -> return null
return if (firClass.classKind == ClassKind.OBJECT) {
FirObjectImportedCallableScope(
symbol.classId,
firClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
)
} else {
firClass.scopeProvider.getStaticScope(firClass, session, scopeSession)
}
}
return result
return null
}
protected fun processFunctionsByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirNamedFunctionSymbol) -> Unit) {
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
for (import in imports) {
val importedName = name ?: import.importedName ?: continue
val staticsScope = import.resolvedClassId?.let(::getStaticsScope)
if (staticsScope != null) {
staticsScope.processFunctionsByName(importedName, processor)
} else if (importedName.isSpecial || importedName.identifier.isNotEmpty()) {
for (symbol in provider.getTopLevelFunctionSymbols(import.packageFqName, importedName)) {
fun getStaticsScope(classId: ClassId): FirScope? {
val symbol = provider.getClassLikeSymbolByFqName(classId) ?: return null
return getStaticsScope(symbol)
}
protected inline fun processFunctionsByNameWithImport(
name: Name,
import: FirResolvedImport,
crossinline processor: (FirNamedFunctionSymbol) -> Unit
) {
import.resolvedClassId?.let { classId ->
getStaticsScope(classId)?.processFunctionsByName(name) { processor(it) }
} ?: run {
if (name.isSpecial || name.identifier.isNotEmpty()) {
val symbols = provider.getTopLevelFunctionSymbols(import.packageFqName, name)
for (symbol in symbols) {
symbol.ensureResolvedForCalls(session)
processor(symbol)
}
@@ -111,15 +70,17 @@ abstract class FirAbstractImportingScope(
}
}
protected fun processPropertiesByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirVariableSymbol<*>) -> Unit) {
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
for (import in imports) {
val importedName = name ?: import.importedName ?: continue
val staticsScope = import.resolvedClassId?.let(::getStaticsScope)
if (staticsScope != null) {
staticsScope.processPropertiesByName(importedName, processor)
} else if (importedName.isSpecial || importedName.identifier.isNotEmpty()) {
for (symbol in provider.getTopLevelPropertySymbols(import.packageFqName, importedName)) {
protected inline fun processPropertiesByNameWithImport(
name: Name,
import: FirResolvedImport,
crossinline processor: (FirVariableSymbol<*>) -> Unit
) {
import.resolvedClassId?.let { classId ->
getStaticsScope(classId)?.processPropertiesByName(name) { processor(it) }
} ?: run {
if (name.isSpecial || name.identifier.isNotEmpty()) {
val symbols = provider.getTopLevelPropertySymbols(import.packageFqName, name)
for (symbol in symbols) {
symbol.ensureResolvedForCalls(session)
processor(symbol)
}
@@ -127,9 +88,3 @@ abstract class FirAbstractImportingScope(
}
}
}
private val ClassId.isJvmOrNativeThrows: Boolean
get() = asSingleFqName().let { it == JVM_THROWS_ANNOTATION_FQ_NAME || it == KOTLIN_NATIVE_THROWS_ANNOTATION_FQ_NAME }
private val ClassId.isCommonThrows: Boolean
get() = asSingleFqName() == KOTLIN_THROWS_ANNOTATION_FQ_NAME

View File

@@ -8,33 +8,47 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
abstract class FirAbstractSimpleImportingScope(
session: FirSession,
scopeSession: ScopeSession
) : FirAbstractImportingScope(session, scopeSession, FirImportingScopeFilter.ALL, lookupInFir = true) {
) : FirAbstractImportingScope(session, scopeSession, lookupInFir = true) {
// TODO try to hide this
abstract val simpleImports: Map<Name, List<FirResolvedImport>>
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
val imports = simpleImports[name] ?: return
val symbol = findSingleClassifierSymbolByName(null, imports) ?: return
processor(symbol, ConeSubstitutor.Empty)
if (imports.isEmpty()) return
val provider = session.symbolProvider
for (import in imports) {
val importedName = import.importedName ?: continue
val classId =
import.resolvedClassId?.createNestedClassId(importedName)
?: ClassId.topLevel(import.packageFqName.child(importedName))
val symbol = provider.getClassLikeSymbolByFqName(classId) ?: continue
processor(symbol, ConeSubstitutor.Empty)
}
}
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
val imports = simpleImports[name] ?: return
processFunctionsByName(null, imports, processor)
for (import in imports) {
processFunctionsByNameWithImport(import.importedName!!, import, processor)
}
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
val imports = simpleImports[name] ?: return
processPropertiesByName(null, imports, processor)
for (import in imports) {
processPropertiesByNameWithImport(import.importedName!!, import, processor)
}
}
}

View File

@@ -12,14 +12,14 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
abstract class FirAbstractStarImportingScope(
session: FirSession,
scopeSession: ScopeSession,
filter: FirImportingScopeFilter,
lookupInFir: Boolean
) : FirAbstractImportingScope(session, scopeSession, filter, lookupInFir) {
lookupInFir: Boolean = true
) : FirAbstractImportingScope(session, scopeSession, lookupInFir) {
// TODO try to hide this
abstract val starImports: List<FirResolvedImport>
@@ -27,20 +27,35 @@ abstract class FirAbstractStarImportingScope(
private val absentClassifierNames = mutableSetOf<Name>()
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
if ((!name.isSpecial && name.identifier.isEmpty()) || starImports.isEmpty() || name in absentClassifierNames) {
if (starImports.isEmpty() || name in absentClassifierNames) {
return
}
val symbol = findSingleClassifierSymbolByName(name, starImports)
if (symbol != null) {
var empty = true
for (import in starImports) {
val relativeClassName = import.relativeClassName
val classId = when {
!name.isSpecial && name.identifier.isEmpty() -> return
relativeClassName == null -> ClassId(import.packageFqName, name)
else -> ClassId(import.packageFqName, relativeClassName.child(name), false)
}
val symbol = provider.getClassLikeSymbolByFqName(classId) ?: continue
empty = false
processor(symbol, ConeSubstitutor.Empty)
} else {
}
if (empty) {
absentClassifierNames += name
}
}
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) =
processFunctionsByName(name, starImports, processor)
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
for (import in starImports) {
processFunctionsByNameWithImport(name, import, processor)
}
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) =
processPropertiesByName(name, starImports, processor)
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
for (import in starImports) {
processPropertiesByNameWithImport(name, import, processor)
}
}
}

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -24,10 +23,6 @@ class FirClassUseSiteMemberScope(
val seen = mutableSetOf<FirVariableSymbol<*>>()
declaredMemberScope.processPropertiesByName(name) l@{
if (it.isStatic) return@l
if (it is FirPropertySymbol) {
val directOverridden = computeDirectOverridden(it.fir)
this@FirClassUseSiteMemberScope.directOverriddenProperties[it] = directOverridden
}
seen += it
processor(it)
}
@@ -36,18 +31,9 @@ class FirClassUseSiteMemberScope(
val overriddenBy = it.getOverridden(seen)
if (overriddenBy == null) {
processor(it)
} else if (overriddenBy is FirPropertySymbol && it is FirPropertySymbol) {
directOverriddenProperties.getOrPut(overriddenBy) { mutableListOf() }.add(it)
}
}
}
private fun computeDirectOverridden(property: FirProperty): MutableList<FirPropertySymbol> {
val result = mutableListOf<FirPropertySymbol>()
superTypesScope.processPropertiesByName(property.name) l@{ superSymbol ->
if (superSymbol !is FirPropertySymbol) return@l
if (overrideChecker.isOverriddenProperty(property, superSymbol.fir)) {
result.add(superSymbol)
}
}
return result
}
}

View File

@@ -17,9 +17,8 @@ import org.jetbrains.kotlin.name.Name
class FirDefaultStarImportingScope(
session: FirSession,
scopeSession: ScopeSession,
filter: FirImportingScopeFilter,
priority: DefaultImportPriority
) : FirAbstractStarImportingScope(session, scopeSession, filter, lookupInFir = false) {
) : FirAbstractStarImportingScope(session, scopeSession, lookupInFir = false) {
// TODO: put languageVersionSettings into FirSession?
override val starImports = run {
@@ -39,7 +38,6 @@ class FirDefaultStarImportingScope(
}
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
if (name.isSpecial || name.identifier.isNotEmpty()) {
for (import in starImports) {
for (symbol in provider.getTopLevelFunctionSymbols(import.packageFqName, name)) {
@@ -50,7 +48,6 @@ class FirDefaultStarImportingScope(
}
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
if (filter == FirImportingScopeFilter.INVISIBLE_CLASSES) return
if (name.isSpecial || name.identifier.isNotEmpty()) {
for (import in starImports) {
for (symbol in provider.getTopLevelPropertySymbols(import.packageFqName, name)) {

View File

@@ -13,8 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
class FirExplicitStarImportingScope(
imports: List<FirImport>,
session: FirSession,
scopeSession: ScopeSession,
filter: FirImportingScopeFilter
) : FirAbstractStarImportingScope(session, scopeSession, filter, lookupInFir = true) {
scopeSession: ScopeSession
) : FirAbstractStarImportingScope(session, scopeSession) {
override val starImports = imports.filterIsInstance<FirResolvedImport>().filter { it.isAllUnder }
}

View File

@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
@@ -110,8 +109,6 @@ class FirStandardOverrideChecker(session: FirSession) : FirAbstractOverrideCheck
}
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
if (Visibilities.isPrivate(baseDeclaration.visibility)) return false
if (overrideCandidate.valueParameters.size != baseDeclaration.valueParameters.size) return false
val substitutor = buildTypeParametersSubstitutorIfCompatible(overrideCandidate, baseDeclaration) ?: return false
@@ -127,8 +124,6 @@ class FirStandardOverrideChecker(session: FirSession) : FirAbstractOverrideCheck
overrideCandidate: FirCallableMemberDeclaration<*>,
baseDeclaration: FirProperty
): Boolean {
if (Visibilities.isPrivate(baseDeclaration.visibility)) return false
if (overrideCandidate !is FirProperty) return false
val substitutor = buildTypeParametersSubstitutorIfCompatible(overrideCandidate, baseDeclaration) ?: return false
return isEqualReceiverTypes(overrideCandidate.receiverTypeRef, baseDeclaration.receiverTypeRef, substitutor)

View File

@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractTypeChecker
@@ -34,7 +33,7 @@ class FirTypeIntersectionScope private constructor(
private val absentProperties: MutableSet<Name> = mutableSetOf()
private val absentClassifiers: MutableSet<Name> = mutableSetOf()
private val typeCheckerContext = session.typeContext.newBaseTypeCheckerContext(false, false)
private val typeContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = false, session)
private val overriddenSymbols: MutableMap<FirCallableSymbol<*>, Collection<MemberWithBaseScope<out FirCallableSymbol<*>>>> =
mutableMapOf()
@@ -358,7 +357,7 @@ class FirTypeIntersectionScope private constructor(
require(bFir is FirProperty) { "b is " + b.javaClass }
// TODO: if (!OverridingUtil.isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false
return if (aFir.isVar && bFir.isVar) {
AbstractTypeChecker.equalTypes(typeCheckerContext as AbstractTypeCheckerContext, aReturnType, bReturnType)
AbstractTypeChecker.equalTypes(typeContext as AbstractTypeCheckerContext, aReturnType, bReturnType)
} else { // both vals or var vs val: val can't be more specific then var
!(!aFir.isVar && bFir.isVar) && isTypeMoreSpecific(aReturnType, bReturnType)
}
@@ -367,7 +366,7 @@ class FirTypeIntersectionScope private constructor(
}
private fun isTypeMoreSpecific(a: ConeKotlinType, b: ConeKotlinType): Boolean =
AbstractTypeChecker.isSubtypeOf(typeCheckerContext as AbstractTypeCheckerContext, a, b)
AbstractTypeChecker.isSubtypeOf(typeContext as AbstractTypeCheckerContext, a, b)
private fun <D : FirCallableSymbol<*>> findMemberWithMaxVisibility(members: Collection<MemberWithBaseScope<D>>): MemberWithBaseScope<D> {
assert(members.isNotEmpty())

View File

@@ -11,7 +11,7 @@ fun ConeKotlinType.createOutArrayType(nullable: Boolean = false): ConeKotlinType
return ConeKotlinTypeProjectionOut(this).createArrayType(nullable)
}
fun ConeTypeProjection.createArrayType(nullable: Boolean = false): ConeClassLikeType {
fun ConeTypeProjection.createArrayType(nullable: Boolean = false): ConeKotlinType {
if (this is ConeKotlinTypeProjection) {
val type = type.lowerBoundIfFlexible()
if (type is ConeClassLikeType && type.nullability != ConeNullability.NULLABLE) {

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