diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt index e083461aef7..837d69284be 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt @@ -6,26 +6,35 @@ package org.jetbrains.kotlin.fir.java.enhancement import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirCallableMember -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.resolvedFqName +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl +import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl import org.jetbrains.kotlin.fir.java.createTypeParameterSymbol +import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass +import org.jetbrains.kotlin.fir.java.declarations.FirJavaField import org.jetbrains.kotlin.fir.java.toConeProjection import org.jetbrains.kotlin.fir.java.toNotNullConeKotlinType import org.jetbrains.kotlin.fir.java.types.FirJavaTypeRef +import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl +import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.constructType +import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toTypeProjection import org.jetbrains.kotlin.fir.service +import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol +import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl +import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.descriptors.AnnotationDefaultValue import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue @@ -34,9 +43,11 @@ import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.typeEnhancement.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import org.jetbrains.kotlin.utils.extractRadix internal class IndexedJavaTypeQualifiers(private val data: Array) { constructor(size: Int, compute: (Int) -> JavaTypeQualifiers) : this(Array(size) { compute(it) }) @@ -220,7 +231,56 @@ internal fun FirTypeRef.typeArguments(): List = internal fun JavaType.typeArguments(): List = (this as? JavaClassifierType)?.typeArguments.orEmpty() -fun FirValueParameter.getDefaultValueFromAnnotation(): AnnotationDefaultValue? { +internal fun ConeKotlinType.lexicalCastFrom(session: FirSession, value: String): FirExpression? { + val lookupTagBasedType = when (this) { + is ConeLookupTagBasedType -> this + is ConeFlexibleType -> return lowerBound.lexicalCastFrom(session, value) + else -> return null + } + val lookupTag = lookupTagBasedType.lookupTag + val firElement = (lookupTag.toSymbol(session) as? FirBasedSymbol<*>)?.fir + if (firElement is FirRegularClass && firElement.classKind == ClassKind.ENUM_CLASS) { + val name = Name.identifier(value) + val firEnumEntry = firElement.declarations.filterIsInstance().find { it.name == name } + + return if (firEnumEntry != null) FirQualifiedAccessExpressionImpl(session, null).apply { + calleeReference = FirSimpleNamedReference( + session, null, name // TODO: , firEnumEntry.symbol + ) + } else if (firElement is FirJavaClass) { + val firStaticProperty = firElement.declarations.filterIsInstance().find { + it.isStatic && it.modality == Modality.FINAL && it.name == name + } + if (firStaticProperty != null) { + FirQualifiedAccessExpressionImpl(session, null).apply { + calleeReference = FirResolvedCallableReferenceImpl( + session, null, name, firStaticProperty.symbol as ConeCallableSymbol + ) + } + } else null + } else null + } + + if (lookupTag !is ConeClassLikeLookupTag) return null + val classId = lookupTag.classId + if (classId.packageFqName != FqName("kotlin")) return null + + val (number, radix) = extractRadix(value) + return when (classId.relativeClassName.asString()) { + "Boolean" -> FirConstExpressionImpl(session, null, IrConstKind.Boolean, value.toBoolean()) + "Char" -> FirConstExpressionImpl(session, null, IrConstKind.Char, value.singleOrNull() ?: return null) + "Byte" -> FirConstExpressionImpl(session, null, IrConstKind.Byte, number.toByteOrNull(radix) ?: return null) + "Short" -> FirConstExpressionImpl(session, null, IrConstKind.Short, number.toShortOrNull(radix) ?: return null) + "Int" -> FirConstExpressionImpl(session, null, IrConstKind.Int, number.toIntOrNull(radix) ?: return null) + "Long" -> FirConstExpressionImpl(session, null, IrConstKind.Long, number.toLongOrNull(radix) ?: return null) + "Float" -> FirConstExpressionImpl(session, null, IrConstKind.Float, value.toFloatOrNull() ?: return null) + "Double" -> FirConstExpressionImpl(session, null, IrConstKind.Double, value.toDoubleOrNull() ?: return null) + "String" -> FirConstExpressionImpl(session, null, IrConstKind.String, value) + else -> null + } +} + +internal fun FirValueParameter.getDefaultValueFromAnnotation(): AnnotationDefaultValue? { annotations.find { it.resolvedFqName == JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME } ?.arguments?.firstOrNull() ?.safeAs>()?.value?.safeAs() diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt index 0f33d026e24..e8eebe9a3a2 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt @@ -9,14 +9,14 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.* import org.jetbrains.kotlin.fir.expressions.FirAnnotationContainer +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.impl.FirConstExpressionImpl import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor import org.jetbrains.kotlin.fir.java.declarations.FirJavaField import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod import org.jetbrains.kotlin.fir.java.declarations.FirJavaValueParameter +import org.jetbrains.kotlin.fir.java.enhancement.* import org.jetbrains.kotlin.fir.java.enhancement.EnhancementSignatureParts -import org.jetbrains.kotlin.fir.java.enhancement.FirAnnotationTypeQualifierResolver -import org.jetbrains.kotlin.fir.java.enhancement.FirJavaEnhancementContext -import org.jetbrains.kotlin.fir.java.enhancement.copyWithNewDefaultTypeQualifiers import org.jetbrains.kotlin.fir.java.types.FirJavaTypeRef import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction @@ -28,7 +28,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver +import org.jetbrains.kotlin.load.java.descriptors.NullDefaultValue +import org.jetbrains.kotlin.load.java.descriptors.StringDefaultValue import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType import org.jetbrains.kotlin.load.java.typeEnhancement.PREDEFINED_FUNCTION_ENHANCEMENT_INFO_BY_SIGNATURE import org.jetbrains.kotlin.load.java.typeEnhancement.PredefinedFunctionEnhancementInfo @@ -130,10 +133,10 @@ class JavaClassEnhancementScope( enhanceReturnType(firMethod, memberContext, predefinedEnhancementInfo) } - val newValueParameterTypeRefs = mutableListOf() + val newValueParameterInfo = mutableListOf() for ((index, valueParameter) in firMethod.valueParameters.withIndex()) { - newValueParameterTypeRefs += enhanceValueParameterType( + newValueParameterInfo += enhanceValueParameter( firMethod, memberContext, predefinedEnhancementInfo, valueParameter as FirJavaValueParameter, index ) } @@ -145,12 +148,13 @@ class JavaClassEnhancementScope( ).apply { status = firMethod.status as FirDeclarationStatusImpl annotations += firMethod.annotations - valueParameters += firMethod.valueParameters.zip(newValueParameterTypeRefs) { valueParameter, newTypeRef -> + valueParameters += firMethod.valueParameters.zip(newValueParameterInfo) { valueParameter, newInfo -> + val (newTypeRef, newDefaultValue) = newInfo with(valueParameter) { FirValueParameterImpl( this@JavaClassEnhancementScope.session, psi, this.name, newTypeRef, - defaultValue, isCrossinline, isNoinline, isVararg + defaultValue ?: newDefaultValue, isCrossinline, isNoinline, isVararg ).apply { annotations += valueParameter.annotations } @@ -200,20 +204,29 @@ class JavaClassEnhancementScope( return signatureParts.type } - private fun enhanceValueParameterType( + private data class EnhanceValueParameterResult(val typeRef: FirResolvedTypeRef, val defaultValue: FirExpression?) + + private fun enhanceValueParameter( ownerFunction: FirCallableMember, memberContext: FirJavaEnhancementContext, predefinedEnhancementInfo: PredefinedFunctionEnhancementInfo?, ownerParameter: FirJavaValueParameter, index: Int - ): FirResolvedTypeRef { + ): EnhanceValueParameterResult { val signatureParts = ownerFunction.partsForValueParameter( typeQualifierResolver, parameterContainer = ownerParameter, methodContext = memberContext, typeInSignature = TypeInSignature.ValueParameter(index) ).enhance(session, jsr305State, predefinedEnhancementInfo?.parametersInfo?.getOrNull(index)) - return signatureParts.type + val firResolvedTypeRef = signatureParts.type + val defaultValue = ownerParameter.getDefaultValueFromAnnotation() + val defaultValueExpression = when (defaultValue) { + NullDefaultValue -> FirConstExpressionImpl(session, null, IrConstKind.Null, null) + is StringDefaultValue -> firResolvedTypeRef.type.lexicalCastFrom(session, defaultValue.value) + null -> null + } + return EnhanceValueParameterResult(firResolvedTypeRef, defaultValueExpression) } private fun enhanceReturnType( diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultEnum.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultEnum.fir.txt new file mode 100644 index 00000000000..335430aedf5 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultEnum.fir.txt @@ -0,0 +1,26 @@ +public/*package*/ open class A : R|java/lang/Object| { + public open operator function a(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(HELLO)) arg: R|ft|! = R|/Signs.HELLO|): R|ft|! + + public open operator function bar(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(X)) arg: R|ft|! = R|/Signs.X|): R|ft|! + + public open operator function baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft|!): R|ft|! + + public open operator function bam(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft|! = R|/Mixed.NOT_ENTRY_EITHER|): R|ft|! + +} +public final enum class Mixed : R|java/lang/Enum| { + public final static property NOT_ENTRY_EITHER(val): R|ft|! + public get(): R|ft|! + +} +public final enum class Signs : R|java/lang/Enum| { + public final static property HELLO(val): R|ft|! + public get(): R|ft|! + + public final static property WORLD(val): R|ft|! + public get(): R|ft|! + + public final static property X(val): R|ft|! + public get(): R|ft|! + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultEnum.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultEnum.java new file mode 100644 index 00000000000..b8fbb6fb186 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultEnum.java @@ -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; + } + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultLongLiteral.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultLongLiteral.fir.txt new file mode 100644 index 00000000000..d6dde5ab68f --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultLongLiteral.fir.txt @@ -0,0 +1,20 @@ +public open class A : R|java/lang/Object| { + public open operator function first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0x1F)) value: R|ft|! = Long(31)): R|kotlin/Unit| + + public open operator function second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0X1F)) value: R|ft|! = Long(31)): R|kotlin/Unit| + + public open operator function third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0b1010)) value: R|ft|! = Long(10)): R|kotlin/Unit| + + public open operator function fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1010)) value: R|ft|! = Long(10)): R|kotlin/Unit| + +} +public open class B : R|java/lang/Object| { + public open operator function first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0x)) value: R|ft|!): R|kotlin/Unit| + + public open operator function second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0xZZ)) value: R|ft|!): R|kotlin/Unit| + + public open operator function third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0b)) value: R|ft|!): R|kotlin/Unit| + + public open operator function fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1234)) value: R|ft|!): R|kotlin/Unit| + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultLongLiteral.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultLongLiteral.java new file mode 100644 index 00000000000..3e1c6e89950 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultLongLiteral.java @@ -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) { + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNull.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNull.fir.txt new file mode 100644 index 00000000000..b4e2bff58e7 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNull.fir.txt @@ -0,0 +1,10 @@ +public open class A : R|java/lang/Object| { + public open operator function foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() x: R|ft|! = Null(null)): R|kotlin/Unit| + + public open operator function bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() x: R|kotlin/Int| = Null(null)): R|kotlin/Unit| + +} + public open class B : R|java/lang/Object| { + public open operator function foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() t: R|ft|! = Null(null)): R|kotlin/Unit| + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNull.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNull.java new file mode 100644 index 00000000000..d3f0372f4cc --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNull.java @@ -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 { + public void foo(@DefaultNull T t) { } +} + diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.fir.txt new file mode 100644 index 00000000000..9cf4b2bf429 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.fir.txt @@ -0,0 +1,26 @@ +public open class A : R|java/lang/Object| { + public open operator function foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() i: R|ft|! = Null(null)): R|kotlin/Unit| + + public open operator function bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft|! = Null(null)): R|kotlin/Unit| + + public open operator function bam(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft|! = Null(null)): R|kotlin/Unit| + + public open operator function baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft|! = Int(42)): R|kotlin/Unit| + +} +public abstract interface AInt : R|java/lang/Object| { + public abstract operator function foo(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) i: R|ft|! = Int(42)): R|kotlin/Unit| + + public abstract operator function bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft|! = Null(null)): R|kotlin/Unit| + +} +public open class B : R|A| { + public open operator function foo(i: R|ft|!): R|kotlin/Unit| + + public open operator function bar(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft|! = Int(42)): R|kotlin/Unit| + + public open operator function bam(@R|kotlin/annotations/jvm/internal/DefaultNull|() @R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft|! = Int(42)): R|kotlin/Unit| + +} +public open class C : R|A|, R|AInt| { +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.java new file mode 100644 index 00000000000..c80e59df91b --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.java @@ -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 { +} + diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultParameter.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultParameter.fir.txt new file mode 100644 index 00000000000..c714b41ccef --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultParameter.fir.txt @@ -0,0 +1,12 @@ +public/*package*/ open class A : R|java/lang/Object| { + public open operator function first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(hello)) value: R|ft|! = String(hello)): R|kotlin/Unit| + + public open operator function second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(first)) a: R|ft|! = String(first), @R|kotlin/annotations/jvm/internal/DefaultValue|(String(second)) b: R|ft|! = String(second)): R|kotlin/Unit| + + public open operator function third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(first)) a: R|ft|! = String(first), b: R|ft|!): R|kotlin/Unit| + + public open operator function fourth(first: R|ft|!, @R|kotlin/annotations/jvm/internal/DefaultValue|(String(second)) second: R|ft|! = String(second)): R|kotlin/Unit| + + public open operator function wrong(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(hello)) i: R|ft|!): R|kotlin/Unit| + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultParameter.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultParameter.java new file mode 100644 index 00000000000..2e92dd18d6b --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultParameter.java @@ -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) { + } +} + + diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/EmptyParameterName.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/EmptyParameterName.fir.txt new file mode 100644 index 00000000000..a3bd371afb0 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/EmptyParameterName.fir.txt @@ -0,0 +1,8 @@ +public/*package*/ open class A : R|java/lang/Object| { + public open operator function emptyName(@R|kotlin/annotations/jvm/internal/ParameterName|(String()) first: R|ft|!, @R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) second: R|kotlin/Int|): R|kotlin/Unit| + + public open operator function missingName(@R|kotlin/annotations/jvm/internal/ParameterName|() first: R|ft|!): R|kotlin/Unit| + + public open operator function numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(Int(42)) first: R|ft|!): R|kotlin/Unit| + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/EmptyParameterName.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/EmptyParameterName.java new file mode 100644 index 00000000000..7e3d6ba9e0e --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/EmptyParameterName.java @@ -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) { + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/ReorderedParameterNames.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/ReorderedParameterNames.fir.txt new file mode 100644 index 00000000000..11b07f99b0b --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/ReorderedParameterNames.fir.txt @@ -0,0 +1,4 @@ +public open class A : R|java/lang/Object| { + public open operator function connect(@R|kotlin/annotations/jvm/internal/ParameterName|(String(host)) host: R|ft|!, @R|kotlin/annotations/jvm/internal/ParameterName|(String(port)) port: R|kotlin/Int|): R|kotlin/Unit| + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/ReorderedParameterNames.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/ReorderedParameterNames.java new file mode 100644 index 00000000000..f971eb9150d --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/ReorderedParameterNames.java @@ -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) { + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SameParameterName.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SameParameterName.fir.txt new file mode 100644 index 00000000000..7308f1fcffa --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SameParameterName.fir.txt @@ -0,0 +1,4 @@ +public open class A : R|java/lang/Object| { + public open operator function same(@R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) first: R|ft|!, @R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) second: R|ft|!): R|kotlin/Unit| + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SameParameterName.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SameParameterName.java new file mode 100644 index 00000000000..d610459e082 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SameParameterName.java @@ -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) { + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.fir.txt new file mode 100644 index 00000000000..e77c281e6b5 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.fir.txt @@ -0,0 +1,6 @@ +public open class A : R|java/lang/Object| { + public open operator function dollarName(@R|kotlin/annotations/jvm/internal/ParameterName|(String($)) host: R|ft|!): R|kotlin/Unit| + + public open operator function numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(String(42)) field: R|ft|!): R|kotlin/Unit| + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.java new file mode 100644 index 00000000000..36bc004a9b3 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.java @@ -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) { + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.fir.txt b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.fir.txt new file mode 100644 index 00000000000..c98350c4cea --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.fir.txt @@ -0,0 +1,4 @@ +public/*package*/ open class A : R|java/lang/Object| { + public open static operator function withDefault(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(OK)) arg: R|ft|! = String(OK)): R|ft|! + +} diff --git a/compiler/fir/resolve/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.java b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.java new file mode 100644 index 00000000000..3301ae534b2 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.java @@ -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; + } +} + diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/OwnFirTypeEnhancementTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/OwnFirTypeEnhancementTestGenerated.java index c6a4a2e43da..a558c736590 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/OwnFirTypeEnhancementTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/OwnFirTypeEnhancementTestGenerated.java @@ -114,4 +114,67 @@ public class OwnFirTypeEnhancementTestGenerated extends AbstractOwnFirTypeEnhanc } } } + + @TestMetadata("compiler/fir/resolve/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, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInSignatureAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/enhancement/signatureAnnotations"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true); + } + + @TestMetadata("DefaultEnum.java") + public void testDefaultEnum() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultEnum.java"); + } + + @TestMetadata("DefaultLongLiteral.java") + public void testDefaultLongLiteral() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultLongLiteral.java"); + } + + @TestMetadata("DefaultNull.java") + public void testDefaultNull() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNull.java"); + } + + @TestMetadata("DefaultNullAndParameter.java") + public void testDefaultNullAndParameter() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultNullAndParameter.java"); + } + + @TestMetadata("DefaultParameter.java") + public void testDefaultParameter() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/DefaultParameter.java"); + } + + @TestMetadata("EmptyParameterName.java") + public void testEmptyParameterName() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/EmptyParameterName.java"); + } + + @TestMetadata("ReorderedParameterNames.java") + public void testReorderedParameterNames() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/ReorderedParameterNames.java"); + } + + @TestMetadata("SameParameterName.java") + public void testSameParameterName() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/SameParameterName.java"); + } + + @TestMetadata("SpecialCharsParameterName.java") + public void testSpecialCharsParameterName() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/SpecialCharsParameterName.java"); + } + + @TestMetadata("StaticMethodWithDefaultValue.java") + public void testStaticMethodWithDefaultValue() throws Exception { + runTest("compiler/fir/resolve/testData/enhancement/signatureAnnotations/StaticMethodWithDefaultValue.java"); + } + } }