FIR type enhancements: support annotations for default parameter values

Related to KT-29937
This commit is contained in:
Mikhail Glukhikh
2019-03-07 14:05:53 +03:00
parent 5f3a01c25a
commit c708171add
23 changed files with 487 additions and 16 deletions
@@ -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<JavaTypeQualifiers>) {
constructor(size: Int, compute: (Int) -> JavaTypeQualifiers) : this(Array(size) { compute(it) })
@@ -220,7 +231,56 @@ internal fun FirTypeRef.typeArguments(): List<FirTypeProjection> =
internal fun JavaType.typeArguments(): List<JavaType?> = (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<FirEnumEntry>().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<FirJavaField>().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<FirConstExpression<*>>()?.value?.safeAs<String>()
@@ -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<FirResolvedTypeRef>()
val newValueParameterInfo = mutableListOf<EnhanceValueParameterResult>()
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(
@@ -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<Signs, Signs?>|! = R|/Signs.HELLO|): R|ft<Signs, Signs?>|!
public open operator function bar(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(X)) arg: R|ft<Signs, Signs?>|! = R|/Signs.X|): R|ft<Signs, Signs?>|!
public open operator function baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft<Signs, Signs?>|!): R|ft<Signs, Signs?>|!
public open operator function bam(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft<Mixed, Mixed?>|! = R|/Mixed.NOT_ENTRY_EITHER|): R|ft<Mixed, Mixed?>|!
}
public final enum class Mixed : R|java/lang/Enum<Mixed>| {
public final static property NOT_ENTRY_EITHER(val): R|ft<Mixed, Mixed?>|!
public get(): R|ft<Mixed, Mixed?>|!
}
public final enum class Signs : R|java/lang/Enum<Signs>| {
public final static property HELLO(val): R|ft<Signs, Signs?>|!
public get(): R|ft<Signs, Signs?>|!
public final static property WORLD(val): R|ft<Signs, Signs?>|!
public get(): R|ft<Signs, Signs?>|!
public final static property X(val): R|ft<Signs, Signs?>|!
public get(): R|ft<Signs, Signs?>|!
}
@@ -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;
}
}
@@ -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<kotlin/Long, kotlin/Long?>|! = Long(31)): R|kotlin/Unit|
public open operator function second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0X1F)) value: R|ft<kotlin/Long, kotlin/Long?>|! = Long(31)): R|kotlin/Unit|
public open operator function third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0b1010)) value: R|ft<kotlin/Long, kotlin/Long?>|! = Long(10)): R|kotlin/Unit|
public open operator function fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1010)) value: R|ft<kotlin/Long, kotlin/Long?>|! = 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<kotlin/Long, kotlin/Long?>|!): R|kotlin/Unit|
public open operator function second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0xZZ)) value: R|ft<kotlin/Long, kotlin/Long?>|!): R|kotlin/Unit|
public open operator function third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0b)) value: R|ft<kotlin/Long, kotlin/Long?>|!): R|kotlin/Unit|
public open operator function fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1234)) value: R|ft<kotlin/Long, kotlin/Long?>|!): R|kotlin/Unit|
}
@@ -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) {
}
}
@@ -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<kotlin/Int, kotlin/Int?>|! = 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|
}
<T> public open class B : R|java/lang/Object| {
public open operator function foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() t: R|ft<T, T?>|! = Null(null)): R|kotlin/Unit|
}
@@ -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) { }
}
@@ -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<kotlin/Int, kotlin/Int?>|! = Null(null)): R|kotlin/Unit|
public open operator function bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<kotlin/Int, kotlin/Int?>|! = Null(null)): R|kotlin/Unit|
public open operator function bam(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<kotlin/Int, kotlin/Int?>|! = Null(null)): R|kotlin/Unit|
public open operator function baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<kotlin/Int, kotlin/Int?>|! = 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<kotlin/Int, kotlin/Int?>|! = Int(42)): R|kotlin/Unit|
public abstract operator function bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() a: R|ft<kotlin/Int, kotlin/Int?>|! = Null(null)): R|kotlin/Unit|
}
public open class B : R|A| {
public open operator function foo(i: R|ft<kotlin/Int, kotlin/Int?>|!): R|kotlin/Unit|
public open operator function bar(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<kotlin/Int, kotlin/Int?>|! = 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<kotlin/Int, kotlin/Int?>|! = Int(42)): R|kotlin/Unit|
}
public open class C : R|A|, R|AInt| {
}
@@ -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 {
}
@@ -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<kotlin/String, kotlin/String?>|! = String(hello)): R|kotlin/Unit|
public open operator function second(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(first)) a: R|ft<kotlin/String, kotlin/String?>|! = String(first), @R|kotlin/annotations/jvm/internal/DefaultValue|(String(second)) b: R|ft<kotlin/String, kotlin/String?>|! = String(second)): R|kotlin/Unit|
public open operator function third(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(first)) a: R|ft<kotlin/String, kotlin/String?>|! = String(first), b: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
public open operator function fourth(first: R|ft<kotlin/String, kotlin/String?>|!, @R|kotlin/annotations/jvm/internal/DefaultValue|(String(second)) second: R|ft<kotlin/String, kotlin/String?>|! = String(second)): R|kotlin/Unit|
public open operator function wrong(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(hello)) i: R|ft<kotlin/Int, kotlin/Int?>|!): R|kotlin/Unit|
}
@@ -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) {
}
}
@@ -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<kotlin/String, kotlin/String?>|!, @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<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
public open operator function numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(Int(42)) first: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
}
@@ -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) {
}
}
@@ -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<kotlin/String, kotlin/String?>|!, @R|kotlin/annotations/jvm/internal/ParameterName|(String(port)) port: R|kotlin/Int|): R|kotlin/Unit|
}
@@ -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) {
}
}
@@ -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<kotlin/String, kotlin/String?>|!, @R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) second: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
}
@@ -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) {
}
}
@@ -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<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
public open operator function numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(String(42)) field: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
}
@@ -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) {
}
}
@@ -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<kotlin/String, kotlin/String?>|! = String(OK)): R|ft<kotlin/String, kotlin/String?>|!
}
@@ -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;
}
}
@@ -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");
}
}
}