diff options
author | Jiaxiang Chen <jiaxiang@google.com> | 2024-01-31 17:57:50 -0800 |
---|---|---|
committer | KSP Auto Pick <kotlin-symbol-processing@google.com> | 2024-02-27 02:26:58 +0000 |
commit | f7b15c3b2d776eb73aa92f83de647701095d8c44 (patch) | |
tree | d39ddc8f60c40e4ea63344c5d73d4d13218b067b | |
parent | 9d790e07382c370ab8feb165aa2492d75b0d4872 (diff) | |
download | ksp-f7b15c3b2d776eb73aa92f83de647701095d8c44.tar.gz |
implement getJavaWildcard for KSP2
(cherry picked from commit c56396b51282b311e2bf81426599e3b12ff172e8)
6 files changed, 366 insertions, 64 deletions
diff --git a/common-util/src/main/kotlin/com/google/devtools/ksp/common/impl/RefPosition.kt b/common-util/src/main/kotlin/com/google/devtools/ksp/common/impl/RefPosition.kt new file mode 100644 index 00000000..85e9565b --- /dev/null +++ b/common-util/src/main/kotlin/com/google/devtools/ksp/common/impl/RefPosition.kt @@ -0,0 +1,73 @@ +package com.google.devtools.ksp.common.impl + +import com.google.devtools.ksp.symbol.ClassKind +import com.google.devtools.ksp.symbol.KSCallableReference +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSFunctionDeclaration +import com.google.devtools.ksp.symbol.KSNode +import com.google.devtools.ksp.symbol.KSPropertyDeclaration +import com.google.devtools.ksp.symbol.KSPropertyGetter +import com.google.devtools.ksp.symbol.KSReferenceElement +import com.google.devtools.ksp.symbol.KSTypeArgument +import com.google.devtools.ksp.symbol.KSTypeReference + +enum class RefPosition { + PARAMETER_TYPE, + RETURN_TYPE, + SUPER_TYPE +} + +// TODO: Strict mode for catching unhandled cases. +fun findRefPosition(ref: KSTypeReference): RefPosition = when (val parent = ref.parent) { + is KSCallableReference -> when (ref) { + parent.returnType -> RefPosition.RETURN_TYPE + else -> RefPosition.PARAMETER_TYPE + } + is KSFunctionDeclaration -> when (ref) { + parent.returnType -> RefPosition.RETURN_TYPE + else -> RefPosition.PARAMETER_TYPE + } + is KSPropertyGetter -> RefPosition.RETURN_TYPE + is KSPropertyDeclaration -> when (ref) { + parent.type -> RefPosition.RETURN_TYPE + else -> RefPosition.PARAMETER_TYPE + } + is KSClassDeclaration -> RefPosition.SUPER_TYPE + // is KSTypeArgument -> RefPosition.PARAMETER_TYPE + // is KSAnnotation -> RefPosition.PARAMETER_TYPE + // is KSTypeAlias -> RefPosition.PARAMETER_TYPE + // is KSValueParameter -> RefPosition.PARAMETER_TYPE + // is KSTypeParameter -> RefPosition.PARAMETER_TYPE + else -> RefPosition.PARAMETER_TYPE +} + +// Search in self and parents for the first type reference that is not part of a type argument. +fun KSTypeReference.findOuterMostRef(): Pair<KSTypeReference, List<Int>> { + fun KSNode.findParentRef(): KSTypeReference? { + var parent = parent + while (parent != null && parent !is KSTypeReference) + parent = parent.parent + return parent as? KSTypeReference + } + + val fallback = Pair<KSTypeReference, List<Int>>(this, emptyList()) + val indexes = mutableListOf<Int>() + var candidate: KSTypeReference = this + // KSTypeArgument's parent can be either KSReferenceElement or KSType. + while (candidate.parent is KSTypeArgument) { + // If the parent is a KSType, it's a synthetic reference. + // Do nothing and reply on the fallback behavior. + val referenceElement = (candidate.parent!!.parent as? KSReferenceElement) ?: return fallback + indexes.add(referenceElement.typeArguments.indexOf(candidate.parent)) + // In case the program isn't properly structured, fallback. + candidate = referenceElement.findParentRef() ?: return fallback + } + return Pair(candidate, indexes) +} + +fun KSTypeReference.isReturnTypeOfAnnotationMethod(): Boolean { + var candidate = this.parent + while (candidate !is KSClassDeclaration && candidate != null) + candidate = candidate.parent + return (candidate as? KSClassDeclaration)?.classKind == ClassKind.ANNOTATION_CLASS +} diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processing/impl/ResolverImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processing/impl/ResolverImpl.kt index 2efdc42b..2a559dcc 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processing/impl/ResolverImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/processing/impl/ResolverImpl.kt @@ -28,6 +28,10 @@ import com.google.devtools.ksp.common.JVM_VOLATILE_ANNOTATION_FQN import com.google.devtools.ksp.common.extractThrowsAnnotation import com.google.devtools.ksp.common.impl.KSNameImpl import com.google.devtools.ksp.common.impl.KSTypeReferenceSyntheticImpl +import com.google.devtools.ksp.common.impl.RefPosition +import com.google.devtools.ksp.common.impl.findOuterMostRef +import com.google.devtools.ksp.common.impl.findRefPosition +import com.google.devtools.ksp.common.impl.isReturnTypeOfAnnotationMethod import com.google.devtools.ksp.common.javaModifiers import com.google.devtools.ksp.common.memoized import com.google.devtools.ksp.common.visitor.CollectAnnotatedSymbolsVisitor @@ -1232,67 +1236,6 @@ class ResolverImpl( return modifiers } - private enum class RefPosition { - PARAMETER_TYPE, - RETURN_TYPE, - SUPER_TYPE - } - - // Search in self and parents for the first type reference that is not part of a type argument. - private fun KSTypeReference.findOuterMostRef(): Pair<KSTypeReference, List<Int>> { - fun KSNode.findParentRef(): KSTypeReference? { - var parent = parent - while (parent != null && parent !is KSTypeReference) - parent = parent.parent - return parent as? KSTypeReference - } - - val fallback = Pair<KSTypeReference, List<Int>>(this, emptyList()) - val indexes = mutableListOf<Int>() - var candidate: KSTypeReference = this - // KSTypeArgument's parent can be either KSReferenceElement or KSType. - while (candidate.parent is KSTypeArgument) { - // If the parent is a KSType, it's a synthetic reference. - // Do nothing and reply on the fallback behavior. - val referenceElement = (candidate.parent!!.parent as? KSReferenceElement) ?: return fallback - indexes.add(referenceElement.typeArguments.indexOf(candidate.parent)) - // In case the program isn't properly structured, fallback. - candidate = referenceElement.findParentRef() ?: return fallback - } - return Pair(candidate, indexes) - } - - // TODO: Strict mode for catching unhandled cases. - private fun findRefPosition(ref: KSTypeReference): RefPosition = when (val parent = ref.parent) { - is KSCallableReference -> when (ref) { - parent.returnType -> RefPosition.RETURN_TYPE - else -> RefPosition.PARAMETER_TYPE - } - is KSFunctionDeclaration -> when (ref) { - parent.returnType -> RefPosition.RETURN_TYPE - else -> RefPosition.PARAMETER_TYPE - } - is KSPropertyGetter -> RefPosition.RETURN_TYPE - is KSPropertyDeclaration -> when (ref) { - parent.type -> RefPosition.RETURN_TYPE - else -> RefPosition.PARAMETER_TYPE - } - is KSClassDeclaration -> RefPosition.SUPER_TYPE - // is KSTypeArgument -> RefPosition.PARAMETER_TYPE - // is KSAnnotation -> RefPosition.PARAMETER_TYPE - // is KSTypeAlias -> RefPosition.PARAMETER_TYPE - // is KSValueParameter -> RefPosition.PARAMETER_TYPE - // is KSTypeParameter -> RefPosition.PARAMETER_TYPE - else -> RefPosition.PARAMETER_TYPE - } - - private fun KSTypeReference.isReturnTypeOfAnnotationMethod(): Boolean { - var candidate = this.parent - while (candidate !is KSClassDeclaration && candidate != null) - candidate = candidate.parent - return (candidate as? KSClassDeclaration)?.classKind == ClassKind.ANNOTATION_CLASS - } - // Convert type arguments for Java wildcard, recursively. private fun KotlinType.toWildcard(mode: TypeMappingMode): KotlinType? { val parameters = constructor.parameters diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt index 0c9f15ed..a6e640be 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt @@ -29,6 +29,10 @@ import com.google.devtools.ksp.common.JVM_VOLATILE_ANNOTATION_FQN import com.google.devtools.ksp.common.extractThrowsAnnotation import com.google.devtools.ksp.common.impl.KSNameImpl import com.google.devtools.ksp.common.impl.KSTypeReferenceSyntheticImpl +import com.google.devtools.ksp.common.impl.RefPosition +import com.google.devtools.ksp.common.impl.findOuterMostRef +import com.google.devtools.ksp.common.impl.findRefPosition +import com.google.devtools.ksp.common.impl.isReturnTypeOfAnnotationMethod import com.google.devtools.ksp.common.javaModifiers import com.google.devtools.ksp.common.memoized import com.google.devtools.ksp.common.visitor.CollectAnnotatedSymbolsVisitor @@ -57,11 +61,16 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtTypeAliasSymbol import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl import org.jetbrains.kotlin.fir.types.isRaw +import org.jetbrains.kotlin.fir.types.typeContext import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl +import org.jetbrains.kotlin.load.kotlin.TypeMappingMode +import org.jetbrains.kotlin.load.kotlin.getOptimalModeForReturnType +import org.jetbrains.kotlin.load.kotlin.getOptimalModeForValueParameter import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe @@ -357,7 +366,35 @@ class ResolverAAImpl( } override fun getJavaWildcard(reference: KSTypeReference): KSTypeReference { - TODO("Not yet implemented") + val (ref, indexes) = reference.findOuterMostRef() + val type = ref.resolve() + if (type.isError) + return reference + val position = findRefPosition(ref) + val ktType = (type as KSTypeImpl).type + // cast to FIR internal needed due to missing support in AA for type mapping mode + // and corresponding type mapping APIs. + val coneType = (ktType as KtFirType).coneType + val mode = analyze { + val typeContext = analyze { useSiteModule.getFirResolveSession(project).useSiteFirSession.typeContext } + when (position) { + RefPosition.RETURN_TYPE -> typeContext.getOptimalModeForReturnType( + coneType, + reference.isReturnTypeOfAnnotationMethod() + ) + RefPosition.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE + RefPosition.PARAMETER_TYPE -> typeContext.getOptimalModeForValueParameter(coneType) + }.updateFromParents(ref) + } + return analyze { + ktType.toWildcard(mode)?.let { + var candidate: KtType = it + for (i in indexes.reversed()) { + candidate = candidate.typeArguments()[i].type!! + } + KSTypeReferenceSyntheticImpl.getCached(KSTypeImpl.getCached(candidate), null) + } + } ?: reference } override fun getJvmCheckedException(accessor: KSPropertyAccessor): Sequence<KSType> { diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt index a3c38cb3..5b711bc6 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt @@ -40,27 +40,33 @@ import org.jetbrains.kotlin.analysis.api.components.buildClassType import org.jetbrains.kotlin.analysis.api.components.buildTypeParameterType import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirValueParameterSymbol +import org.jetbrains.kotlin.analysis.api.fir.types.KtFirType import org.jetbrains.kotlin.analysis.api.lifetime.KtAlwaysAccessibleLifetimeToken import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers import org.jetbrains.kotlin.analysis.api.types.* import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap +import org.jetbrains.kotlin.codegen.state.JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME +import org.jetbrains.kotlin.codegen.state.JVM_WILDCARD_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.java.JavaVisibilities import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.toFirExpression import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.types.isAny import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotationVisitor import org.jetbrains.kotlin.load.java.structure.impl.classFiles.ClassifierResolutionContext +import org.jetbrains.kotlin.load.kotlin.TypeMappingMode import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.getEffectiveVariance import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.org.objectweb.asm.AnnotationVisitor import org.jetbrains.org.objectweb.asm.ClassReader @@ -566,3 +572,133 @@ internal fun KtType.replace(newArgs: List<KtTypeProjection>): KtType? { } } } +internal fun getVarianceForWildcard( + parameter: KtTypeParameterSymbol, + projection: KtTypeProjection, + mode: TypeMappingMode +): Variance { + val projectionKind = if (projection is KtTypeArgumentWithVariance) { + projection.variance + } else { + Variance.INVARIANT + } + val parameterVariance = parameter.variance + if (parameterVariance == Variance.INVARIANT) { + return projectionKind + } + if (mode.skipDeclarationSiteWildcards) { + return Variance.INVARIANT + } + if (projectionKind == Variance.INVARIANT || projectionKind == parameterVariance) { + if (mode.skipDeclarationSiteWildcardsIfPossible && projection !is KtStarTypeProjection) { + val coneType = (projection.type as KtFirType).coneType + // TODO: fix most precise covariant argument case. + if (parameterVariance == Variance.OUT_VARIANCE) { + return Variance.INVARIANT + } + if (parameterVariance == Variance.IN_VARIANCE && coneType.isAny) { + return Variance.INVARIANT + } + } + return parameterVariance + } + return Variance.OUT_VARIANCE +} + +internal fun KtType.toWildcard(mode: TypeMappingMode): KtType { + val parameters = this.classifierSymbol()?.typeParameters ?: emptyList() + val args = this.typeArguments() + return analyze { + when (this@toWildcard) { + is KtClassType -> { + // TODO: missing annotations from original type. + buildClassType(this@toWildcard.expandedClassSymbol!!) { + parameters.zip(args).map { (param, arg) -> + val argMode = mode.updateFromAnnotations(arg.type) + val variance = getVarianceForWildcard(param, arg, argMode) + val genericMode = argMode.toGenericArgumentMode( + getEffectiveVariance( + param.variance, + (arg as? KtTypeArgumentWithVariance)?.variance ?: Variance.INVARIANT + ) + ) + val argType = + arg.type ?: analysisSession.builtinTypes.ANY.withNullability(KtTypeNullability.NULLABLE) + argument(argType.toWildcard(genericMode), variance) + } + nullability = this@toWildcard.nullability + } + } + is KtTypeParameterType -> { + buildTypeParameterType(this@toWildcard.symbol) + } + else -> throw IllegalStateException("Unexpected type ${this@toWildcard}") + } + } +} + +internal fun TypeMappingMode.suppressJvmWildcards( + suppress: Boolean +): TypeMappingMode { + return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( + skipDeclarationSiteWildcards = suppress, + isForAnnotationParameter = isForAnnotationParameter, + needInlineClassWrapping = needInlineClassWrapping, + mapTypeAliases = mapTypeAliases + ) +} +internal fun TypeMappingMode.updateFromParents( + ref: KSTypeReference +): TypeMappingMode { + return ref.findJvmSuppressWildcards()?.let { + this.suppressJvmWildcards(it) + } ?: this +} + +internal fun KSTypeReference.findJvmSuppressWildcards(): Boolean? { + var candidate: KSNode? = this + while (candidate != null) { + if ((candidate is KSTypeReference || candidate is KSDeclaration)) { + (candidate as KSAnnotated).annotations.singleOrNull { + it.annotationType.resolve().declaration.qualifiedName?.asString()?.equals( + JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME.asString() + ) == true + }?.let { it.arguments.singleOrNull { it.name?.asString() == "suppress" } }?.let { + return it.value as? Boolean + } + } + candidate = candidate.parent + } + return null +} + +internal fun TypeMappingMode.updateFromAnnotations( + type: KtType? +): TypeMappingMode { + if (type == null) { + return this + } + type.annotations().firstOrNull { + it.annotationType.resolve().declaration.qualifiedName?.asString() + ?.equals(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME.asString()) == true + }?.let { + it.arguments.firstOrNull { it.name?.asString() == "suppress" }?.let { + (it.value as? Boolean)?.let { return suppressJvmWildcards(it) } ?: return this + } + } + return if (type.annotations().any { + it.annotationType.resolve().declaration.qualifiedName?.asString() + ?.equals(JVM_WILDCARD_ANNOTATION_FQ_NAME.asString()) == true + } + ) { + TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( + skipDeclarationSiteWildcards = false, + isForAnnotationParameter = isForAnnotationParameter, + fallbackMode = this, + needInlineClassWrapping = needInlineClassWrapping, + mapTypeAliases = mapTypeAliases + ) + } else { + this + } +} diff --git a/kotlin-analysis-api/testData/javaWildcards2.kt b/kotlin-analysis-api/testData/javaWildcards2.kt new file mode 100644 index 00000000..068dd3cc --- /dev/null +++ b/kotlin-analysis-api/testData/javaWildcards2.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2024 Google LLC + * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// WITH_RUNTIME +// TEST PROCESSOR: JavaWildcard2Processor +// EXPECTED: +// MyEnum : Enum<MyEnum> +// <init> : MyEnum +// values : Array<MyEnum> +// value : String +// valueOf : MyEnum +// entries : EnumEntries<MyEnum> +// entries.getter() : EnumEntries<MyEnum> +// VarianceSubjectSuppressed : Any +// R : Any? +// propWithFinalType : String +// propWithFinalType.getter() : String +// <set-?> : String +// propWithOpenType : Number +// propWithOpenType.getter() : Number +// <set-?> : Number +// propWithFinalGeneric : List<String> +// propWithFinalGeneric.getter() : List<String> +// <set-?> : List<String> +// propWithOpenGeneric : List<Number> +// propWithOpenGeneric.getter() : List<Number> +// <set-?> : List<Number> +// propWithTypeArg : R +// propWithTypeArg.getter() : R +// <set-?> : R +// propWithTypeArgGeneric : List<R> +// propWithTypeArgGeneric.getter() : List<R> +// <set-?> : List<R> +// propWithOpenTypeButSuppressAnnotation : Number +// propWithOpenTypeButSuppressAnnotation.getter() : Number +// <set-?> : Number +// list2 : List<Any?> +// list1 : List<Any?> +// list3 : List<R> +// listTypeArg : List<R> +// list4 : List<Number> +// listTypeArgNumber : List<Number> +// list5 : List<String> +// listTypeArgString : List<String> +// list6 : List<MyEnum> +// listTypeArgEnum : List<MyEnum> +// list7 : List<out String> +// explicitJvmWildcard : List<out String> +// list8 : List<Number> +// explicitJvmSuppressWildcard_OnType : List<Number> +// list9 : List<Number> +// explicitJvmSuppressWildcard_OnType2 : List<Number> +// starList : List<Any?> +// typeArgList : List<R> +// numberList : List<Number> +// stringList : List<String> +// enumList : List<MyEnum> +// jvmWildcard : List<out String> +// suppressJvmWildcard : List<Number> +// <init> : VarianceSubjectSuppressed<Any?> +// R : Any? +// END + +enum class MyEnum() + +@JvmSuppressWildcards +class VarianceSubjectSuppressed<R>( + starList: List<*>, + typeArgList: List<R>, + numberList: List<Number>, + stringList: List<String>, + enumList: List<MyEnum>, + jvmWildcard: List<@JvmWildcard String>, + suppressJvmWildcard: List<@JvmSuppressWildcards Number> +) { + var propWithFinalType: String = "" + var propWithOpenType: Number = 3 + var propWithFinalGeneric: List<String> = TODO() + var propWithOpenGeneric: List<Number> = TODO() + var propWithTypeArg: R = TODO() + var propWithTypeArgGeneric: List<R> = TODO() + @JvmSuppressWildcards + var propWithOpenTypeButSuppressAnnotation: Number = 3 + fun list1(list2: List<*>): List<*> { TODO() } + fun listTypeArg(list3: List<R>): List<R> { TODO() } + fun listTypeArgNumber(list4: List<Number>): List<Number> { TODO() } + fun listTypeArgString(list5: List<String>): List<String> { TODO() } + fun listTypeArgEnum(list6: List<MyEnum>): List<MyEnum> { TODO() } + fun explicitJvmWildcard( + list7: List<@JvmWildcard String> + ): List<@JvmWildcard String> { TODO() } + + fun explicitJvmSuppressWildcard_OnType( + list8: List<@JvmSuppressWildcards Number> + ): List<@JvmSuppressWildcards Number> { TODO() } + + fun explicitJvmSuppressWildcard_OnType2( + list9: @JvmSuppressWildcards List<Number> + ): @JvmSuppressWildcards List<Number> { TODO() } +} diff --git a/test-utils/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt b/test-utils/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt index 37301f62..9d6bbc8e 100644 --- a/test-utils/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt +++ b/test-utils/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt @@ -352,11 +352,10 @@ class KSPAATest : AbstractKSPAATest() { runTest("../test-utils/testData/api/javaTypes2.kt") } - @Disabled @TestMetadata("javaWildcards2.kt") @Test fun testJavaWildcards2() { - runTest("../test-utils/testData/api/javaWildcards2.kt") + runTest("../kotlin-analysis-api/testData/javaWildcards2.kt") } @TestMetadata("lateinitProperties.kt") |