diff --git a/common-util/src/main/kotlin/com/google/devtools/ksp/common/ErrorTypeUtils.kt b/common-util/src/main/kotlin/com/google/devtools/ksp/common/ErrorTypeUtils.kt new file mode 100644 index 0000000000..70b67fd8b6 --- /dev/null +++ b/common-util/src/main/kotlin/com/google/devtools/ksp/common/ErrorTypeUtils.kt @@ -0,0 +1,24 @@ +package com.google.devtools.ksp.common + +import com.google.devtools.ksp.symbol.KSType +import com.google.devtools.ksp.symbol.KSTypeArgument + +inline fun errorTypeOnInconsistentArguments( + arguments: List, + placeholdersProvider: () -> List, + withCorrectedArguments: (corrected: List) -> KSType, + errorType: (name: String, message: String) -> E, +): E? { + if (arguments.isNotEmpty()) { + val placeholders = placeholdersProvider() + val diff = arguments.size - placeholders.size + if (diff > 0) { + val wouldBeType = withCorrectedArguments(arguments.dropLast(diff)) + return errorType(wouldBeType.toString(), "Unexpected extra $diff type argument(s)") + } else if (diff < 0) { + val wouldBeType = withCorrectedArguments(arguments + placeholders.drop(arguments.size)) + return errorType(wouldBeType.toString(), "Missing ${-diff} type argument(s)") + } + } + return null +} 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 533fb9181b..9a24d49b66 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 @@ -692,7 +692,8 @@ class ResolverImpl( builtIns.arrayType.replace(typeArgs) } else -> { - getClassDeclarationByName(psiType.canonicalText)?.asStarProjectedType() ?: KSErrorType + getClassDeclarationByName(psiType.canonicalText)?.asStarProjectedType() + ?: KSErrorType(psiType.canonicalText) } } } @@ -1054,7 +1055,7 @@ class ResolverImpl( } } // if substitution fails, fallback to the type from the property - return KSErrorType + return KSErrorType.fromReferenceBestEffort(property.type) } internal fun asMemberOf( @@ -1247,7 +1248,7 @@ class ResolverImpl( } // Convert type arguments for Java wildcard, recursively. - private fun KotlinType.toWildcard(mode: TypeMappingMode): KotlinType? { + private fun KotlinType.toWildcard(mode: TypeMappingMode): Result { val parameters = constructor.parameters val arguments = arguments @@ -1257,9 +1258,12 @@ class ResolverImpl( parameter.variance != org.jetbrains.kotlin.types.Variance.INVARIANT && argument.projectionKind != org.jetbrains.kotlin.types.Variance.INVARIANT ) { - // conflicting variances - // TODO: error message - return null + return Result.failure( + IllegalArgumentException( + "Conflicting variance: variance '${parameter.variance.label}' vs projection " + + "'${argument.projectionKind.label}'" + ) + ) } val argMode = mode.updateFromAnnotations(argument.type) @@ -1267,10 +1271,10 @@ class ResolverImpl( val genericMode = argMode.toGenericArgumentMode( getEffectiveVariance(parameter.variance, argument.projectionKind) ) - TypeProjectionImpl(variance, argument.type.toWildcard(genericMode) ?: return null) + TypeProjectionImpl(variance, argument.type.toWildcard(genericMode).getOrElse { return Result.failure(it) }) } - return replace(wildcardArguments) + return Result.success(replace(wildcardArguments)) } private val JVM_SUPPRESS_WILDCARDS_NAME = KSNameImpl.getCached("kotlin.jvm.JvmSuppressWildcards") @@ -1369,19 +1373,24 @@ class ResolverImpl( if (position == RefPosition.SUPER_TYPE && argument.projectionKind != org.jetbrains.kotlin.types.Variance.INVARIANT ) { - // Type projection isn't allowed in immediate arguments to supertypes. - // TODO: error message - return KSTypeReferenceSyntheticImpl.getCached(KSErrorType, null) + val errorType = KSErrorType( + name = type.toString(), + message = "Type projection isn't allowed in immediate arguments to supertypes" + ) + return KSTypeReferenceSyntheticImpl.getCached(errorType, null) } } - val wildcardType = kotlinType.toWildcard(typeMappingMode)?.let { - var candidate: KotlinType = it + val wildcardType = kotlinType.toWildcard(typeMappingMode).let { + var candidate: KotlinType = it.getOrElse { error -> + val errorType = KSErrorType(name = type.toString(), message = error.message) + return KSTypeReferenceSyntheticImpl.getCached(errorType, null) + } for (i in indexes.reversed()) { candidate = candidate.arguments[i].type } getKSTypeCached(candidate) - } ?: KSErrorType + } return KSTypeReferenceSyntheticImpl.getCached(wildcardType, null) } diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt index 4df03abc8e..4ebb7fbc34 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt @@ -62,7 +62,9 @@ import org.jetbrains.kotlin.load.kotlin.getContainingKotlinJvmBinaryClass import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtClassLiteralExpression import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression +import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.resolve.AnnotationResolverImpl import org.jetbrains.kotlin.resolve.BindingContext @@ -161,7 +163,7 @@ private fun ConstantValue.toValue(parent: KSNode): Any? = when (this) { } else classValue.classId.findKSType() is KClassValue.Value.LocalClass -> getKSTypeCached(classValue.type) } - is ErrorValue -> KSErrorType + is ErrorValue -> KSErrorType(toString()) is NullValue -> null else -> value } @@ -211,7 +213,7 @@ fun LazyAnnotationDescriptor.getValueArguments(): Map> { } else if (resolvedArgument is DefaultValueArgument) { valueParameter.name to DefaultConstantValue } else { - c.annotationResolver.getAnnotationArgumentValue(c.trace, valueParameter, resolvedArgument)?.let { value -> + c.annotationResolver.getAnnotationArgumentValue(c.trace, valueParameter, resolvedArgument).let { value -> val argExp = resolvedArgument.arguments.lastOrNull()?.getArgumentExpression() // When some elements are not available, the expected and actual size of an array argument will // be different. In such case, we need to reconstruct the array. @@ -224,17 +226,22 @@ fun LazyAnnotationDescriptor.getValueArguments(): Map> { val bc = ResolverImpl.instance!!.bindingTrace.bindingContext val args = argExp.innerExpressions.map { bc.get(BindingContext.COMPILE_TIME_VALUE, it)?.toConstantValue(value.type) - ?: ErrorValue.create("") + ?: it.asErrorValue() } valueParameter.name to TypedArrayValue(args, value.type) } else { - valueParameter.name to value + valueParameter.name to (value ?: argExp?.asErrorValue() ?: ErrorValue.create("ERROR VALUE")) } - } ?: (valueParameter.name to ErrorValue.create("")) + } } }.toMap() } +private fun KtExpression.asErrorValue(): ErrorValue { + val reprExpr = (this as? KtClassLiteralExpression)?.receiverExpression ?: this + return ErrorValue.create(reprExpr.text) +} + fun AnnotationDescriptor.createKSValueArguments(ownerAnnotation: KSAnnotation): List { val allValueArgs = if (this is LazyAnnotationDescriptor) { this.getValueArguments() @@ -419,14 +426,14 @@ fun ValueParameterDescriptor.getDefaultValue(ownerAnnotation: KSAnnotation): Any if (!this.type.isError) { defaultValue?.convert(this.type)?.toValue(ownerAnnotation) } else { - KSErrorType + KSErrorType.fromKtErrorType(type) } } } is KtParameter -> if (!this.type.isError) { ResolverImpl.instance!!.evaluateConstant(psi.defaultValue, this.type)?.toValue(ownerAnnotation) } else { - KSErrorType + KSErrorType.fromKtErrorType(type) } is PsiAnnotationMethod -> { when (psi.defaultValue) { diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassDeclarationDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassDeclarationDescriptorImpl.kt index e771bddb71..b0ca39976b 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassDeclarationDescriptorImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassDeclarationDescriptorImpl.kt @@ -151,9 +151,7 @@ class KSClassDeclarationDescriptorImpl private constructor(val descriptor: Class } override fun asType(typeArguments: List): KSType = - descriptor.defaultType.replaceTypeArguments(typeArguments)?.let { - getKSTypeCached(it, typeArguments) - } ?: KSErrorType + descriptor.defaultType.replaceTypeArguments(typeArguments) override fun asStarProjectedType(): KSType { return getKSTypeCached(descriptor.defaultType.replaceArgumentsWithStarProjections()) diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaEnumEntryImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaEnumEntryImpl.kt index 7f74e0a912..db0a43188f 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaEnumEntryImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaEnumEntryImpl.kt @@ -17,6 +17,7 @@ package com.google.devtools.ksp.symbol.impl.java +import com.google.devtools.ksp.common.errorTypeOnInconsistentArguments import com.google.devtools.ksp.common.impl.KSNameImpl import com.google.devtools.ksp.common.toKSModifiers import com.google.devtools.ksp.processing.impl.KSObjectCache @@ -96,8 +97,10 @@ class KSClassDeclarationJavaEnumEntryImpl private constructor(val psi: PsiEnumCo // Enum can't have type parameters. override fun asType(typeArguments: List): KSType { - if (typeArguments.isNotEmpty()) - return KSErrorType + errorTypeOnInconsistentArguments( + arguments = typeArguments, placeholdersProvider = ::emptyList, + withCorrectedArguments = ::asType, errorType = ::KSErrorType, + )?.let { error -> return error } return asStarProjectedType() } diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaImpl.kt index 2eb4d01466..b46bed8559 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaImpl.kt @@ -153,17 +153,13 @@ class KSClassDeclarationJavaImpl private constructor(val psi: PsiClass) : } override fun asType(typeArguments: List): KSType { - return descriptor?.let { - it.defaultType.replaceTypeArguments(typeArguments)?.let { - getKSTypeCached(it, typeArguments) - } - } ?: KSErrorType + return descriptor?.defaultType?.replaceTypeArguments(typeArguments) ?: KSErrorType(psi.qualifiedName) } override fun asStarProjectedType(): KSType { return descriptor?.let { getKSTypeCached(it.defaultType.replaceArgumentsWithStarProjections()) - } ?: KSErrorType + } ?: KSErrorType(psi.qualifiedName) } override fun accept(visitor: KSVisitor, data: D): R { diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceJavaImpl.kt index de33ac5da2..ebd6f0c2b9 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceJavaImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceJavaImpl.kt @@ -124,11 +124,13 @@ class KSTypeReferenceJavaImpl private constructor(val psi: PsiType, override val .mapNotNull { (it.annotationType.resolve() as? KSTypeImpl)?.kotlinType?.constructor?.declarationDescriptor?.fqNameSafe } - val resolved = if ((resolvedType.declaration as? KSClassDeclarationDescriptorImpl) - ?.descriptor is NotFoundClasses.MockClassDescriptor - ) { - KSErrorType - } else resolvedType + val resolved = when (val declaration = resolvedType.declaration) { + is KSClassDeclarationDescriptorImpl -> when (val descriptor = declaration.descriptor) { + is NotFoundClasses.MockClassDescriptor -> KSErrorType(descriptor.name.asString()) + else -> resolvedType + } + else -> resolvedType + } val hasNotNull = relatedAnnotations.any { it in NOT_NULL_ANNOTATIONS } val hasNullable = relatedAnnotations.any { it in NULLABLE_ANNOTATIONS } return if (hasNullable && !hasNotNull) { diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceLiteJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceLiteJavaImpl.kt index a62747a618..b5fab32173 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceLiteJavaImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceLiteJavaImpl.kt @@ -47,13 +47,14 @@ class KSTypeReferenceLiteJavaImpl private constructor(val psiElement: PsiElement val type: KSType by lazy { when (psiElement) { is PsiAnnotation -> { - val psiClass = psiElement.nameReferenceElement!!.resolve() as? PsiClass + val nameReferenceElement = psiElement.nameReferenceElement!! + val psiClass = nameReferenceElement.resolve() as? PsiClass psiClass?.let { (psiElement.containingFile as? PsiJavaFile)?.let { ResolverImpl.instance!!.incrementalContext.recordLookup(it, psiClass.qualifiedName!!) } KSClassDeclarationJavaImpl.getCached(psiClass).asStarProjectedType() - } ?: KSErrorType + } ?: KSErrorType(nameReferenceElement.text) } is PsiMethod -> { KSClassDeclarationJavaImpl.getCached(psiElement.containingClass!!).asStarProjectedType() diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassDeclarationImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassDeclarationImpl.kt index 340020fdac..3979da1a4b 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassDeclarationImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassDeclarationImpl.kt @@ -122,9 +122,7 @@ class KSClassDeclarationImpl private constructor(val ktClassOrObject: KtClassOrO } override fun asType(typeArguments: List): KSType { - return descriptor.defaultType.replaceTypeArguments(typeArguments)?.let { - getKSTypeCached(it, typeArguments) - } ?: KSErrorType + return descriptor.defaultType.replaceTypeArguments(typeArguments) } override fun asStarProjectedType(): KSType { diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSErrorType.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSErrorType.kt index 8cf66385e4..9c5e6ef508 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSErrorType.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSErrorType.kt @@ -19,17 +19,32 @@ package com.google.devtools.ksp.symbol.impl.kotlin import com.google.devtools.ksp.symbol.* import com.google.devtools.ksp.symbol.impl.synthetic.KSErrorTypeClassDeclaration +import org.jetbrains.kotlin.types.FlexibleType +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.error.ErrorType +import org.jetbrains.kotlin.types.error.ErrorTypeKind -object KSErrorType : KSType { - override val annotations: Sequence = emptySequence() +class KSErrorType( + val nameHint: String?, +) : KSType { + constructor(name: String, message: String?) : this( + nameHint = listOfNotNull(name, message).takeIf { it.isNotEmpty() }?.joinToString(" % ") + ) - override val arguments: List = emptyList() + override val annotations: Sequence + get() = emptySequence() - override val declaration: KSDeclaration = KSErrorTypeClassDeclaration + override val arguments: List + get() = emptyList() - override val isError: Boolean = true + override val declaration: KSDeclaration + get() = KSErrorTypeClassDeclaration(this) - override val nullability: Nullability = Nullability.NULLABLE + override val isError: Boolean + get() = true + + override val nullability: Nullability + get() = Nullability.NULLABLE override fun isAssignableFrom(that: KSType): Boolean { return false @@ -51,7 +66,8 @@ object KSErrorType : KSType { return this } - override val isMarkedNullable: Boolean = false + override val isMarkedNullable: Boolean + get() = false override fun replace(arguments: List): KSType { return this @@ -61,11 +77,51 @@ object KSErrorType : KSType { return this } - override fun toString(): String { - return "" - } + override fun toString(): String = nameHint?.let { "" } ?: "" + + override val isFunctionType: Boolean + get() = false + + override val isSuspendFunctionType: Boolean + get() = false - override val isFunctionType: Boolean = false + override fun hashCode() = nameHint.hashCode() - override val isSuspendFunctionType: Boolean = false + override fun equals(other: Any?): Boolean { + return this === other || other is KSErrorType && other.nameHint == nameHint + } + + companion object { + fun fromReferenceBestEffort(reference: KSTypeReference?): KSErrorType { + return when (val type = reference?.resolve()) { + is KSErrorType -> type + null -> KSErrorType(reference?.element?.toString()) + else -> KSErrorType(type.toString()) + } + } + + fun fromKtErrorType(ktType: KotlinType): KSErrorType { + // Logic is in sync with `KotlinType.isError` + val errorType: ErrorType = when (val unwrapped = ktType.unwrap()) { + is ErrorType -> unwrapped + is FlexibleType -> unwrapped.delegate as? ErrorType + else -> null + } ?: throw IllegalArgumentException("Not an error type: $ktType") + + val hint = when (errorType.kind) { + // Handle "Unresolved types" group + ErrorTypeKind.UNRESOLVED_TYPE, + ErrorTypeKind.UNRESOLVED_CLASS_TYPE, + ErrorTypeKind.UNRESOLVED_JAVA_CLASS, + ErrorTypeKind.UNRESOLVED_DECLARATION, + ErrorTypeKind.UNRESOLVED_KCLASS_CONSTANT_VALUE, + ErrorTypeKind.UNRESOLVED_TYPE_ALIAS -> errorType.formatParams.first() + + // TODO: Handle more ErrorTypeKinds where it's possible to extract a name for the error type. + else -> errorType.debugMessage + } + + return KSErrorType(hint) + } + } } diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionErrorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionErrorImpl.kt index 5100e367e8..c1f9ee6a05 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionErrorImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionErrorImpl.kt @@ -29,18 +29,19 @@ class KSFunctionErrorImpl( ) : KSFunction { override val isError: Boolean = true - override val returnType: KSType = KSErrorType + override val returnType: KSType + get() = KSErrorType.fromReferenceBestEffort(declaration.returnType) override val parameterTypes: List get() = declaration.parameters.map { - KSErrorType + KSErrorType.fromReferenceBestEffort(it.type) } override val typeParameters: List get() = emptyList() override val extensionReceiverType: KSType? get() = declaration.extensionReceiver?.let { - KSErrorType + KSErrorType.fromReferenceBestEffort(it) } override fun equals(other: Any?): Boolean { diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt index 2aa8ff1b43..8094ab1ced 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt @@ -97,7 +97,7 @@ class KSPropertyDeclarationImpl private constructor(val ktProperty: KtProperty) KSTypeReferenceDeferredImpl.getCached(this) { val desc = propertyDescriptor as? VariableDescriptorWithAccessors if (desc == null) { - KSErrorType + KSErrorType(null /* no info available */) } else { getKSTypeCached(desc.type) } diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt index d4724f06ca..5fff631c6a 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt @@ -95,9 +95,7 @@ class KSTypeImpl private constructor( } override fun replace(arguments: List): KSType { - return kotlinType.replaceTypeArguments(arguments)?.let { - getKSTypeCached(it, arguments, annotations) - } ?: KSErrorType + return kotlinType.replaceTypeArguments(arguments, annotations) } override fun starProjection(): KSType { @@ -136,10 +134,12 @@ fun getKSTypeCached( ksTypeArguments: List? = null, annotations: Sequence = sequenceOf() ): KSType { - return if (kotlinType.isError || - kotlinType.constructor.declarationDescriptor is NotFoundClasses.MockClassDescriptor - ) { - KSErrorType + if (kotlinType.isError) { + return KSErrorType.fromKtErrorType(kotlinType) + } + val descriptor = kotlinType.constructor.declarationDescriptor + return if (descriptor is NotFoundClasses.MockClassDescriptor) { + KSErrorType(descriptor.name.asString()) } else { KSTypeImpl.getCached( kotlinType, diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueParameterImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueParameterImpl.kt index 7dca3f70ca..5a2d0853bf 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueParameterImpl.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueParameterImpl.kt @@ -112,7 +112,8 @@ class KSValueParameterImpl private constructor(val ktParameter: KtParameter) : K override val type: KSTypeReference by lazy { ktParameter.typeReference?.let { KSTypeReferenceImpl.getCached(it) } - ?: findPropertyForAccessor()?.type ?: KSTypeReferenceSyntheticImpl.getCached(KSErrorType, this) + ?: findPropertyForAccessor()?.type + ?: KSTypeReferenceSyntheticImpl.getCached(KSErrorType(null /* no info available */), this) } override val hasDefault: Boolean = ktParameter.hasDefaultValue() diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSErrorTypeClassDeclaration.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSErrorTypeClassDeclaration.kt index 400a03b55d..db96c789ad 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSErrorTypeClassDeclaration.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSErrorTypeClassDeclaration.kt @@ -18,54 +18,73 @@ package com.google.devtools.ksp.symbol.impl.synthetic import com.google.devtools.ksp.common.impl.KSNameImpl -import com.google.devtools.ksp.processing.impl.ResolverImpl import com.google.devtools.ksp.symbol.* +import com.google.devtools.ksp.symbol.impl.kotlin.KSErrorType -object KSErrorTypeClassDeclaration : KSClassDeclaration { - override val annotations: Sequence = emptySequence() +class KSErrorTypeClassDeclaration( + private val type: KSErrorType, +) : KSClassDeclaration { + override val annotations: Sequence + get() = emptySequence() - override val classKind: ClassKind = ClassKind.CLASS + override val classKind: ClassKind + get() = ClassKind.CLASS - override val containingFile: KSFile? = null + override val containingFile: KSFile? + get() = null - override val declarations: Sequence = emptySequence() + override val declarations: Sequence + get() = emptySequence() - override val isActual: Boolean = false + override val isActual: Boolean + get() = false - override val isExpect: Boolean = false + override val isExpect: Boolean + get() = false - override val isCompanionObject: Boolean = false + override val isCompanionObject: Boolean + get() = false - override val location: Location = NonExistLocation + override val location: Location + get() = NonExistLocation - override val parent: KSNode? = null + override val parent: KSNode? + get() = null - override val modifiers: Set = emptySet() + override val modifiers: Set + get() = emptySet() - override val origin: Origin = Origin.SYNTHETIC + override val origin: Origin + get() = Origin.SYNTHETIC - override val packageName: KSName = KSNameImpl.getCached("") + override val packageName: KSName + get() = KSNameImpl.getCached("") - override val parentDeclaration: KSDeclaration? = null + override val parentDeclaration: KSDeclaration? + get() = null - override val primaryConstructor: KSFunctionDeclaration? = null + override val primaryConstructor: KSFunctionDeclaration? + get() = null - override val qualifiedName: KSName? = null + override val qualifiedName: KSName? + get() = null - override val simpleName: KSName = KSNameImpl.getCached("") + override val simpleName: KSName = KSNameImpl.getCached(type.toString()) - override val superTypes: Sequence = emptySequence() + override val superTypes: Sequence + get() = emptySequence() - override val typeParameters: List = emptyList() + override val typeParameters: List + get() = emptyList() override fun getSealedSubclasses(): Sequence = emptySequence() override fun asStarProjectedType(): KSType { - return ResolverImpl.instance!!.builtIns.nothingType + return type } override fun asType(typeArguments: List): KSType { - return ResolverImpl.instance!!.builtIns.nothingType + return type } override fun findActuals(): Sequence { @@ -89,8 +108,15 @@ object KSErrorTypeClassDeclaration : KSClassDeclaration { } override fun toString(): String { - return "Error type synthetic declaration" + return simpleName.asString() } - override val docString = null + override fun equals(other: Any?): Boolean { + return this === other || other is KSErrorTypeClassDeclaration && other.type == type + } + + override fun hashCode(): Int = type.hashCode() + + override val docString + get() = null } diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt index e8ab1fb8ac..47cdb9c256 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt @@ -18,6 +18,7 @@ package com.google.devtools.ksp.symbol.impl import com.google.devtools.ksp.ExceptionMessage import com.google.devtools.ksp.KspExperimental +import com.google.devtools.ksp.common.errorTypeOnInconsistentArguments import com.google.devtools.ksp.common.impl.KSNameImpl import com.google.devtools.ksp.processing.impl.ResolverImpl import com.google.devtools.ksp.symbol.* @@ -136,10 +137,18 @@ fun org.jetbrains.kotlin.types.Variance.toKSVariance(): Variance { private fun KSTypeReference.toKotlinType() = (resolve() as? KSTypeImpl)?.kotlinType -// returns null if error -internal fun KotlinType.replaceTypeArguments(newArguments: List): KotlinType? { - if (newArguments.isNotEmpty() && this.arguments.size != newArguments.size) - return null +// returns KSErrorType if error +internal fun KotlinType.replaceTypeArguments( + newArguments: List, + annotations: Sequence = emptySequence(), +): KSType { + errorTypeOnInconsistentArguments( + arguments = newArguments, + placeholdersProvider = { arguments.map { KSTypeArgumentDescriptorImpl.getCached(it, Origin.SYNTHETIC, null) } }, + withCorrectedArguments = ::replaceTypeArguments, + errorType = ::KSErrorType, + )?.let { error -> return error } + return replace( newArguments.mapIndexed { index, ksTypeArgument -> val variance = when (ksTypeArgument.variance) { @@ -155,11 +164,11 @@ internal fun KotlinType.replaceTypeArguments(newArguments: List) else -> throw IllegalStateException( "Unexpected psi for type argument: ${ksTypeArgument.javaClass}, $ExceptionMessage" ) - }.toKotlinType() ?: return null + }.let { it.toKotlinType() ?: return KSErrorType.fromReferenceBestEffort(it) } TypeProjectionImpl(variance, type) } - ) + ).let { KSTypeImpl.getCached(it, newArguments, annotations) } } internal fun FunctionDescriptor.toKSDeclaration(): KSDeclaration { 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 18ac2faa69..04e0ed55cb 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 @@ -416,14 +416,14 @@ class ResolverAAImpl( }.updateFromParents(ref) } return analyze { - ktType.toWildcard(mode)?.let { + 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 { @@ -832,7 +832,7 @@ class ResolverAAImpl( } } } else { - KSErrorType + return if (resolved.isError) resolved else KSErrorType(resolved.toString()) } } } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/java/KSAnnotationJavaImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/java/KSAnnotationJavaImpl.kt index 10ef120458..dca4868a32 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/java/KSAnnotationJavaImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/java/KSAnnotationJavaImpl.kt @@ -179,18 +179,19 @@ fun calcValue(value: PsiAnnotationMemberValue?): Any? { is PsiPrimitiveType -> { result.boxedTypeName?.let { ResolverAAImpl.instance - .getClassDeclarationByName(result.boxedTypeName!!)?.asStarProjectedType() ?: KSErrorType - } + .getClassDeclarationByName(it)?.asStarProjectedType() + } ?: KSErrorType(result.boxedTypeName) } is PsiArrayType -> { val componentType = when (val component = result.componentType) { - is PsiPrimitiveType -> component.boxedTypeName?.let { + is PsiPrimitiveType -> component.boxedTypeName?.let { boxedTypeName -> ResolverAAImpl.instance - .getClassDeclarationByName(component.boxedTypeName!!)?.asStarProjectedType() - } ?: KSErrorType + .getClassDeclarationByName(boxedTypeName)?.asStarProjectedType() + } ?: KSErrorType(component.boxedTypeName) else -> { ResolverAAImpl.instance - .getClassDeclarationByName(component.canonicalText)?.asStarProjectedType() ?: KSErrorType + .getClassDeclarationByName(component.canonicalText)?.asStarProjectedType() + ?: KSErrorType(component.canonicalText) } } val componentTypeRef = ResolverAAImpl.instance.createKSTypeReferenceFromKSType(componentType) @@ -200,7 +201,8 @@ fun calcValue(value: PsiAnnotationMemberValue?): Any? { } is PsiType -> { ResolverAAImpl.instance - .getClassDeclarationByName(result.canonicalText)?.asStarProjectedType() ?: KSErrorType + .getClassDeclarationByName(result.canonicalText)?.asStarProjectedType() + ?: KSErrorType(result.canonicalText) } is PsiLiteralValue -> { result.value diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationImpl.kt index 06fef7653d..0030d5f088 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationImpl.kt @@ -18,6 +18,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.KSObjectCache +import com.google.devtools.ksp.common.errorTypeOnInconsistentArguments import com.google.devtools.ksp.common.impl.KSNameImpl import com.google.devtools.ksp.common.impl.KSTypeReferenceSyntheticImpl import com.google.devtools.ksp.impl.ResolverAAImpl @@ -124,9 +125,12 @@ class KSClassDeclarationImpl private constructor(internal val ktClassOrObjectSym } override fun asType(typeArguments: List): KSType { - if (typeArguments.isNotEmpty() && typeArguments.size != asStarProjectedType().arguments.size) { - return KSErrorType - } + errorTypeOnInconsistentArguments( + arguments = typeArguments, + placeholdersProvider = { asStarProjectedType().arguments }, + withCorrectedArguments = ::asType, + errorType = ::KSErrorType, + )?.let { error -> return error } return analyze { if (typeArguments.isEmpty()) { typeParameters.map { buildTypeParameterType((it as KSTypeParameterImpl).ktTypeParameterSymbol) } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSErrorType.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSErrorType.kt index 1fae54507f..83e40c4700 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSErrorType.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSErrorType.kt @@ -16,15 +16,17 @@ */ package com.google.devtools.ksp.impl.symbol.kotlin -import com.google.devtools.ksp.symbol.KSAnnotation -import com.google.devtools.ksp.symbol.KSDeclaration -import com.google.devtools.ksp.symbol.KSType -import com.google.devtools.ksp.symbol.KSTypeArgument -import com.google.devtools.ksp.symbol.Nullability +import com.google.devtools.ksp.symbol.* + +class KSErrorType( + private val hint: String?, +) : KSType { + constructor(name: String, message: String?) : this( + hint = listOfNotNull(name, message).takeIf { it.isNotEmpty() }?.joinToString(" % ") + ) -object KSErrorType : KSType { override val declaration: KSDeclaration - get() = KSErrorTypeClassDeclaration + get() = KSErrorTypeClassDeclaration(this) override val nullability: Nullability get() = Nullability.NULLABLE @@ -57,7 +59,25 @@ object KSErrorType : KSType { override val isSuspendFunctionType: Boolean = false - override fun toString(): String { - return "" + override fun toString(): String = hint?.let { "" } ?: "" + + override fun hashCode() = hint.hashCode() + + override fun equals(other: Any?): Boolean { + return this === other || other is KSErrorType && other.hint == hint + } + + companion object { + // As KSTypeImpl can also be `isError`, this function returns a KSType + // TODO: Make return exclusively KSErrorType + fun fromReferenceBestEffort(reference: KSTypeReference?): KSType { + return when (val type = reference?.resolve()) { + is KSErrorType -> type + null -> KSErrorType(hint = reference?.element?.toString()) + else -> { + type.takeIf { it.isError } ?: KSErrorType(hint = type.toString()) + } + } + } } } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSErrorTypeClassDeclaration.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSErrorTypeClassDeclaration.kt index a37498c955..1831ce1bd7 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSErrorTypeClassDeclaration.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSErrorTypeClassDeclaration.kt @@ -18,54 +18,72 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.impl.KSNameImpl -import com.google.devtools.ksp.impl.ResolverAAImpl import com.google.devtools.ksp.symbol.* -object KSErrorTypeClassDeclaration : KSClassDeclaration { - override val annotations: Sequence = emptySequence() +class KSErrorTypeClassDeclaration( + private val type: KSType, +) : KSClassDeclaration { + override val annotations: Sequence + get() = emptySequence() - override val classKind: ClassKind = ClassKind.CLASS + override val classKind: ClassKind + get() = ClassKind.CLASS - override val containingFile: KSFile? = null + override val containingFile: KSFile? + get() = null - override val declarations: Sequence = emptySequence() + override val declarations: Sequence + get() = emptySequence() - override val isActual: Boolean = false + override val isActual: Boolean + get() = false - override val isExpect: Boolean = false + override val isExpect: Boolean + get() = false - override val isCompanionObject: Boolean = false + override val isCompanionObject: Boolean + get() = false - override val location: Location = NonExistLocation + override val location: Location + get() = NonExistLocation - override val parent: KSNode? = null + override val parent: KSNode? + get() = null - override val modifiers: Set = emptySet() + override val modifiers: Set + get() = emptySet() - override val origin: Origin = Origin.SYNTHETIC + override val origin: Origin + get() = Origin.SYNTHETIC - override val packageName: KSName = KSNameImpl.getCached("") + override val packageName: KSName + get() = KSNameImpl.getCached("") - override val parentDeclaration: KSDeclaration? = null + override val parentDeclaration: KSDeclaration? + get() = null - override val primaryConstructor: KSFunctionDeclaration? = null + override val primaryConstructor: KSFunctionDeclaration? + get() = null - override val qualifiedName: KSName? = null + override val qualifiedName: KSName? + get() = null - override val simpleName: KSName = KSNameImpl.getCached("") + override val simpleName: KSName = KSNameImpl.getCached(type.toString()) - override val superTypes: Sequence = emptySequence() + override val superTypes: Sequence + get() = emptySequence() - override val typeParameters: List = emptyList() + override val typeParameters: List + get() = emptyList() override fun getSealedSubclasses(): Sequence = emptySequence() override fun asStarProjectedType(): KSType { - return ResolverAAImpl.instance.builtIns.nothingType + return type } override fun asType(typeArguments: List): KSType { - return ResolverAAImpl.instance.builtIns.nothingType + return type } override fun findActuals(): Sequence { @@ -89,8 +107,15 @@ object KSErrorTypeClassDeclaration : KSClassDeclaration { } override fun toString(): String { - return "Error type synthetic declaration" + return simpleName.asString() } - override val docString = null + override fun equals(other: Any?): Boolean { + return this === other || other is KSErrorTypeClassDeclaration && other.type == type + } + + override fun hashCode(): Int = type.hashCode() * 2 + + override val docString + get() = null } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFunctionErrorImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFunctionErrorImpl.kt index 6dc2f9b94f..d73bc653b8 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFunctionErrorImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFunctionErrorImpl.kt @@ -10,18 +10,19 @@ class KSFunctionErrorImpl( ) : KSFunction { override val isError: Boolean = true - override val returnType: KSType = KSErrorType + override val returnType: KSType + get() = KSErrorType.fromReferenceBestEffort(declaration.returnType) override val parameterTypes: List get() = declaration.parameters.map { - KSErrorType + KSErrorType.fromReferenceBestEffort(it.type) } override val typeParameters: List get() = emptyList() override val extensionReceiverType: KSType? get() = declaration.extensionReceiver?.let { - KSErrorType + KSErrorType.fromReferenceBestEffort(it) } override fun equals(other: Any?): Boolean { diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt index 1460a2668f..4a9b8a3de1 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt @@ -19,6 +19,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.IdKeyPair import com.google.devtools.ksp.common.KSObjectCache +import com.google.devtools.ksp.common.errorTypeOnInconsistentArguments import com.google.devtools.ksp.impl.ResolverAAImpl import com.google.devtools.ksp.impl.recordLookupWithSupertypes import com.google.devtools.ksp.impl.symbol.kotlin.resolved.KSTypeArgumentResolvedImpl @@ -51,11 +52,11 @@ class KSTypeImpl private constructor(internal val type: KtType) : KSType { } } is KtTypeParameterType -> KSTypeParameterImpl.getCached(symbol) - is KtClassErrorType -> KSErrorTypeClassDeclaration + is KtClassErrorType -> KSErrorTypeClassDeclaration(this@KSTypeImpl) is KtFlexibleType -> type.lowerBoundIfFlexible().toDeclaration() is KtDefinitelyNotNullType -> this@toDeclaration.original.toDeclaration() - else -> KSErrorTypeClassDeclaration + else -> KSErrorTypeClassDeclaration(this@KSTypeImpl) } } } @@ -110,12 +111,17 @@ class KSTypeImpl private constructor(internal val type: KtType) : KSType { } override fun replace(arguments: List): KSType { - return type.replace(arguments.map { it.toKtTypeProjection() })?.let { getCached(it) } ?: KSErrorType + errorTypeOnInconsistentArguments( + arguments = arguments, + placeholdersProvider = { type.typeArguments().map { KSTypeArgumentResolvedImpl.getCached(it) } }, + withCorrectedArguments = ::replace, + errorType = ::KSErrorType, + )?.let { error -> return error } + return getCached(type.replace(arguments.map { it.toKtTypeProjection() })) } override fun starProjection(): KSType { - return type.replace(List(type.typeArguments().size) { KtStarTypeProjection(type.token) }) - ?.let { getCached(it) } ?: KSErrorType + return getCached(type.replace(List(type.typeArguments().size) { KtStarTypeProjection(type.token) })) } override fun makeNullable(): KSType { @@ -134,7 +140,8 @@ class KSTypeImpl private constructor(internal val type: KtType) : KSType { get() = type.nullability == KtTypeNullability.NULLABLE override val isError: Boolean - get() = type is KtClassErrorType + // TODO: non exist type returns KtNonErrorClassType, check upstream for KtClassErrorType usage. + get() = type is KtErrorType || type.classifierSymbol() == null override val isFunctionType: Boolean get() = type is KtFunctionalType && !type.isSuspend diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt index f07636784e..d3c3315752 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt @@ -55,6 +55,45 @@ class KSValueArgumentImpl private constructor( override fun toString(): String { return "${name?.asString() ?: ""}:$value" } +// +// private fun KtAnnotationValue.toValue(): Any? = when (this) { +// is KtArrayAnnotationValue -> this.values.map { it.toValue() } +// is KtAnnotationApplicationValue -> KSAnnotationImpl.getCached(this.annotationValue) +// // TODO: Enum entry should return a type, use declaration as a placeholder. +// is KtEnumEntryAnnotationValue -> this.callableId?.classId?.let { +// analyze { +// it.toKtClassSymbol()?.let { +// it.declarations().filterIsInstance().singleOrNull { +// it.simpleName.asString() == this@toValue.callableId?.callableName?.asString() +// } +// } +// } +// } ?: KSErrorType(callableId?.toString()) +// is KtKClassAnnotationValue -> { +// val classDeclaration = when (this) { +// is KtKClassAnnotationValue.KtNonLocalKClassAnnotationValue -> analyze { +// (this@toValue.classId.toKtClassSymbol())?.let { KSClassDeclarationImpl.getCached(it) } +// } +// is KtKClassAnnotationValue.KtLocalKClassAnnotationValue -> analyze { +// this@toValue.ktClass.getNamedClassOrObjectSymbol()?.let { +// KSClassDeclarationImpl.getCached(it) +// } +// } +// is KtKClassAnnotationValue.KtErrorClassAnnotationValue -> null +// } +// classDeclaration?.asStarProjectedType() ?: KSErrorType( +// when (this) { +// is KtKClassAnnotationValue.KtErrorClassAnnotationValue -> unresolvedQualifierName +// is KtKClassAnnotationValue.KtLocalKClassAnnotationValue -> ktClass.run { +// fqName?.asString() ?: name +// } +// is KtKClassAnnotationValue.KtNonLocalKClassAnnotationValue -> classId.asFqNameString() +// } ?: sourcePsi?.text +// ) +// } +// is KtConstantAnnotationValue -> this.constantValue.value +// is KtUnsupportedAnnotationValue -> null +// } override fun defer(): Restorable = Restorable { getCached(namedAnnotationValue, origin) } } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt index 8302876cf5..c1473d2a89 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt @@ -22,13 +22,11 @@ import com.google.devtools.ksp.common.KSObjectCache import com.google.devtools.ksp.impl.recordLookup import com.google.devtools.ksp.impl.symbol.kotlin.Deferrable import com.google.devtools.ksp.impl.symbol.kotlin.KSClassDeclarationImpl -import com.google.devtools.ksp.impl.symbol.kotlin.KSErrorType import com.google.devtools.ksp.impl.symbol.kotlin.KSTypeImpl import com.google.devtools.ksp.impl.symbol.kotlin.KSTypeParameterImpl import com.google.devtools.ksp.impl.symbol.kotlin.Restorable import com.google.devtools.ksp.impl.symbol.kotlin.analyze import com.google.devtools.ksp.impl.symbol.kotlin.annotations -import com.google.devtools.ksp.impl.symbol.kotlin.classifierSymbol import com.google.devtools.ksp.impl.symbol.kotlin.render import com.google.devtools.ksp.impl.symbol.kotlin.toClassifierReference import com.google.devtools.ksp.impl.symbol.kotlin.toLocation @@ -60,16 +58,7 @@ class KSTypeReferenceResolvedImpl private constructor( override fun resolve(): KSType { analyze { recordLookup(ktType, parent) } - // TODO: non exist type returns KtNonErrorClassType, check upstream for KtClassErrorType usage. - return if ( - analyze { - ktType is KtClassErrorType || (ktType.classifierSymbol() == null) - } - ) { - KSErrorType - } else { - KSTypeImpl.getCached(ktType) - } + return KSTypeImpl.getCached(ktType) } override val annotations: Sequence by lazy { 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 7ac911ef75..177aeeacf3 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 @@ -138,8 +138,11 @@ internal fun KtAnnotationValue.render(): String { is KtArrayAnnotationValue -> values.joinToString(",", "{", "}") { it.render() } is KtConstantAnnotationValue -> constantValue.renderAsKotlinConstant() is KtEnumEntryAnnotationValue -> callableId.toString() - // TODO: handle error classes. - is KtKClassAnnotationValue -> "$classId::class" + is KtKClassAnnotationValue -> { + val type = KSTypeImpl.getCached(type) + // KSTypeImpl takes care of the error types, if applicable + if (type.isError) type.toString() else "$type::class" + } is KtUnsupportedAnnotationValue -> throw IllegalStateException("Unsupported annotation value: $this") } } @@ -174,7 +177,8 @@ internal fun KtType.render(inFunctionType: Boolean = false): String { } } } - is KtClassErrorType, is KtTypeErrorType -> "" + is KtClassErrorType -> KSErrorType(qualifiers.joinToString(".") { it.name.asString() }).toString() + is KtTypeErrorType -> KSErrorType(tryRenderAsNonErrorType()).toString() is KtCapturedType -> asStringForDebugging() is KtDefinitelyNotNullType -> original.render(inFunctionType) + " & Any" is KtDynamicType -> "" @@ -640,10 +644,8 @@ internal fun KtType.isAssignableFrom(that: KtType): Boolean { } // TODO: fix flexible type creation once upstream available. -internal fun KtType.replace(newArgs: List): KtType? { - if (newArgs.isNotEmpty() && newArgs.size != this.typeArguments().size) { - return null - } +internal fun KtType.replace(newArgs: List): KtType { + require(newArgs.isEmpty() || newArgs.size == this.typeArguments().size) return analyze { when (val symbol = classifierSymbol()) { is KtClassLikeSymbol -> analysisSession.buildClassType(symbol) { diff --git a/kotlin-analysis-api/testData/annotationValue/java.kt b/kotlin-analysis-api/testData/annotationValue/java.kt index b8859d32f3..738bd07443 100644 --- a/kotlin-analysis-api/testData/annotationValue/java.kt +++ b/kotlin-analysis-api/testData/annotationValue/java.kt @@ -30,7 +30,7 @@ // 42 // Foo // File -// Error type synthetic declaration +// // Array // @Foo // @Suppress diff --git a/kotlin-analysis-api/testData/annotationValue/kotlin.kt b/kotlin-analysis-api/testData/annotationValue/kotlin.kt index 6b55577c2b..277f593625 100644 --- a/kotlin-analysis-api/testData/annotationValue/kotlin.kt +++ b/kotlin-analysis-api/testData/annotationValue/kotlin.kt @@ -30,8 +30,8 @@ // File // Local // Array -// Error type synthetic declaration -// [, Foo] +// +// [, Foo] // @Foo // @Suppress // RGB.G diff --git a/kotlin-analysis-api/testData/replaceWithErrorTypeArgs.kt b/kotlin-analysis-api/testData/replaceWithErrorTypeArgs.kt index f0f76dd8da..36a715e32a 100644 --- a/kotlin-analysis-api/testData/replaceWithErrorTypeArgs.kt +++ b/kotlin-analysis-api/testData/replaceWithErrorTypeArgs.kt @@ -19,84 +19,84 @@ // TEST PROCESSOR: ReplaceWithErrorTypeArgsProcessor // EXPECTED: // KS.star.replace([INVARIANT Int, INVARIANT String]): KS -// KS.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): KS<, > +// KS.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): KS<, > // KS.asType([INVARIANT Int, INVARIANT String]): KS -// KS.asType([INVARIANT NotExist1, INVARIANT NotExist2]): KS<, > +// KS.asType([INVARIANT NotExist1, INVARIANT NotExist2]): KS<, > // KS.asType(emptyList()): KS // KL.star.replace([INVARIANT Int, INVARIANT String]): KL -// KL.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): KL<, > +// KL.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): KL<, > // KL.asType([INVARIANT Int, INVARIANT String]): KL -// KL.asType([INVARIANT NotExist1, INVARIANT NotExist2]): KL<, > +// KL.asType([INVARIANT NotExist1, INVARIANT NotExist2]): KL<, > // KL.asType(emptyList()): KL // JS.star.replace([INVARIANT Int, INVARIANT String]): JS -// JS.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): JS<, > +// JS.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): JS<, > // JS.asType([INVARIANT Int, INVARIANT String]): JS -// JS.asType([INVARIANT NotExist1, INVARIANT NotExist2]): JS<, > +// JS.asType([INVARIANT NotExist1, INVARIANT NotExist2]): JS<, > // JS.asType(emptyList()): JS // JL.star.replace([INVARIANT Int, INVARIANT String]): JL -// JL.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): JL<, > +// JL.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): JL<, > // JL.asType([INVARIANT Int, INVARIANT String]): JL -// JL.asType([INVARIANT NotExist1, INVARIANT NotExist2]): JL<, > +// JL.asType([INVARIANT NotExist1, INVARIANT NotExist2]): JL<, > // JL.asType(emptyList()): JL -// KS1.star.replace([INVARIANT Int, INVARIANT String]): -// KS1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KS1.asType([INVARIANT Int, INVARIANT String]): -// KS1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KS1.star.replace([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// KS1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): > % Unexpected extra 1 type argument(s)> +// KS1.asType([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// KS1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): > % Unexpected extra 1 type argument(s)> // KS1.asType(emptyList()): KS1 -// KL1.star.replace([INVARIANT Int, INVARIANT String]): -// KL1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KL1.asType([INVARIANT Int, INVARIANT String]): -// KL1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KL1.star.replace([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// KL1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): > % Unexpected extra 1 type argument(s)> +// KL1.asType([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// KL1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): > % Unexpected extra 1 type argument(s)> // KL1.asType(emptyList()): KL1 -// JS1.star.replace([INVARIANT Int, INVARIANT String]): -// JS1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JS1.asType([INVARIANT Int, INVARIANT String]): -// JS1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JS1.star.replace([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// JS1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): > % Unexpected extra 1 type argument(s)> +// JS1.asType([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// JS1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): > % Unexpected extra 1 type argument(s)> // JS1.asType(emptyList()): JS1 -// JL1.star.replace([INVARIANT Int, INVARIANT String]): -// JL1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JL1.asType([INVARIANT Int, INVARIANT String]): -// JL1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JL1.star.replace([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// JL1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): > % Unexpected extra 1 type argument(s)> +// JL1.asType([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// JL1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): > % Unexpected extra 1 type argument(s)> // JL1.asType(emptyList()): JL1 -// JSE.star.replace([INVARIANT Int, INVARIANT String]): -// JSE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JSE.asType([INVARIANT Int, INVARIANT String]): -// JSE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JSE.star.replace([INVARIANT Int, INVARIANT String]): +// JSE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JSE.asType([INVARIANT Int, INVARIANT String]): +// JSE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JSE.asType(emptyList()): JSE -// JSE.E.star.replace([INVARIANT Int, INVARIANT String]): -// JSE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JSE.E.asType([INVARIANT Int, INVARIANT String]): -// JSE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JSE.E.star.replace([INVARIANT Int, INVARIANT String]): +// JSE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JSE.E.asType([INVARIANT Int, INVARIANT String]): +// JSE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JSE.E.asType(emptyList()): JSE -// JLE.star.replace([INVARIANT Int, INVARIANT String]): -// JLE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JLE.asType([INVARIANT Int, INVARIANT String]): -// JLE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JLE.star.replace([INVARIANT Int, INVARIANT String]): +// JLE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JLE.asType([INVARIANT Int, INVARIANT String]): +// JLE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JLE.asType(emptyList()): JLE -// JLE.E.star.replace([INVARIANT Int, INVARIANT String]): -// JLE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JLE.E.asType([INVARIANT Int, INVARIANT String]): -// JLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JLE.E.star.replace([INVARIANT Int, INVARIANT String]): +// JLE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JLE.E.asType([INVARIANT Int, INVARIANT String]): +// JLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JLE.E.asType(emptyList()): JLE -// KSE.star.replace([INVARIANT Int, INVARIANT String]): -// KSE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KSE.asType([INVARIANT Int, INVARIANT String]): -// KSE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KSE.star.replace([INVARIANT Int, INVARIANT String]): +// KSE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KSE.asType([INVARIANT Int, INVARIANT String]): +// KSE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KSE.asType(emptyList()): KSE -// KSE.E.star.replace([INVARIANT Int, INVARIANT String]): -// KSE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KSE.E.asType([INVARIANT Int, INVARIANT String]): -// KSE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KSE.E.star.replace([INVARIANT Int, INVARIANT String]): +// KSE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KSE.E.asType([INVARIANT Int, INVARIANT String]): +// KSE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KSE.E.asType(emptyList()): KSE -// KLE.star.replace([INVARIANT Int, INVARIANT String]): -// KLE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KLE.asType([INVARIANT Int, INVARIANT String]): -// KLE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KLE.star.replace([INVARIANT Int, INVARIANT String]): +// KLE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KLE.asType([INVARIANT Int, INVARIANT String]): +// KLE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KLE.asType(emptyList()): KLE -// KLE.E.star.replace([INVARIANT Int, INVARIANT String]): -// KLE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KLE.E.asType([INVARIANT Int, INVARIANT String]): -// KLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KLE.E.star.replace([INVARIANT Int, INVARIANT String]): +// KLE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KLE.E.asType([INVARIANT Int, INVARIANT String]): +// KLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KLE.E.asType(emptyList()): KLE // default type:A // flexible type star:T diff --git a/test-utils/testData/api/annotationValue_java.kt b/test-utils/testData/api/annotationValue_java.kt index c611fe10dc..28e7f27af6 100644 --- a/test-utils/testData/api/annotationValue_java.kt +++ b/test-utils/testData/api/annotationValue_java.kt @@ -28,7 +28,7 @@ // 42 // Foo // File -// Error type synthetic declaration +// // Array // @Foo // @Suppress diff --git a/test-utils/testData/api/annotationValue_kt.kt b/test-utils/testData/api/annotationValue_kt.kt index 8d9bfd4916..00d93f0be9 100644 --- a/test-utils/testData/api/annotationValue_kt.kt +++ b/test-utils/testData/api/annotationValue_kt.kt @@ -26,8 +26,8 @@ // File // Local // Array -// Error type synthetic declaration -// [, Foo] +// +// [, Foo] // @Foo // @Suppress // G diff --git a/test-utils/testData/api/asMemberOf.kt b/test-utils/testData/api/asMemberOf.kt index d96346cccd..bbc4dc89b8 100644 --- a/test-utils/testData/api/asMemberOf.kt +++ b/test-utils/testData/api/asMemberOf.kt @@ -23,7 +23,7 @@ // baseTypeArg1: kotlin.Int!! // baseTypeArg2: kotlin.String? // typePair: kotlin.Pair!! -// errorType: ? +// errorType: ? // extensionProperty: kotlin.String? // returnInt: () -> kotlin.Int!! // returnArg1: () -> kotlin.Int!! @@ -40,7 +40,7 @@ // baseTypeArg1: kotlin.Any? // baseTypeArg2: kotlin.Any? // typePair: kotlin.Pair!! -// errorType: ? +// errorType: ? // extensionProperty: kotlin.Any? // returnInt: () -> kotlin.Int!! // returnArg1: () -> kotlin.Any? @@ -57,7 +57,7 @@ // baseTypeArg1: kotlin.String!! // baseTypeArg2: kotlin.String? // typePair: kotlin.Pair!! -// errorType: ? +// errorType: ? // extensionProperty: kotlin.String? // returnInt: () -> kotlin.Int!! // returnArg1: () -> kotlin.String!! @@ -96,7 +96,7 @@ // intType: kotlin.Int!! // typeArg1: kotlin.String // typeArg2: kotlin.Int -// errorType: ? +// errorType: ? // returnArg1: () -> kotlin.Int // receiveArgs: (kotlin.String, kotlin.Int, kotlin.Int!!) -> kotlin.Unit!! // methodArgType: (JavaBase.methodArgType.BaseTypeArg1, kotlin.Int) -> kotlin.Unit!! @@ -104,7 +104,7 @@ // fileLevelFunction: java.lang.IllegalArgumentException: Cannot call asMemberOf with a function that is not declared in a class or an interface // fileLevelExtensionFunction: java.lang.IllegalArgumentException: Cannot call asMemberOf with a function that is not declared in a class or an interface // fileLevelProperty: java.lang.IllegalArgumentException: Cannot call asMemberOf with a property that is not declared in a class or an interface -// errorType: (?) -> ? +// errorType: (?) -> ? // expected comparison failures // (Base.functionArgType.BaseTypeArg1?) -> kotlin.String? // () -> kotlin.Int!! diff --git a/test-utils/testData/api/multipleround.kt b/test-utils/testData/api/multipleround.kt index 1afec0cc26..e510eb5859 100644 --- a/test-utils/testData/api/multipleround.kt +++ b/test-utils/testData/api/multipleround.kt @@ -18,28 +18,28 @@ // TEST PROCESSOR: MultipleroundProcessor // EXPECTED: // Round 0: -// K : , , , , , -// J : , , , , , +// K : , , , , , +// J : , , , , , // +J.java, +K.kt // Round 1: -// K : I0, , , , , -// J : I0, , , , , +// K : I0, , , , , +// J : I0, , , , , // +I0.kt, J.java, K.kt // Round 2: -// K : I0, I1, , , , -// J : I0, I1, , , , +// K : I0, I1, , , , +// J : I0, I1, , , , // +I1.java, I0.kt, J.java, K.kt // Round 3: -// K : I0, I1, I2, , , -// J : I0, I1, I2, , , +// K : I0, I1, I2, , , +// J : I0, I1, I2, , , // +I2.kt, I0.kt, I1.java, J.java, K.kt // Round 4: -// K : I0, I1, I2, I3, , -// J : I0, I1, I2, I3, , +// K : I0, I1, I2, I3, , +// J : I0, I1, I2, I3, , // +I3.java, I0.kt, I1.java, I2.kt, J.java, K.kt // Round 5: -// K : I0, I1, I2, I3, I4, -// J : I0, I1, I2, I3, I4, +// K : I0, I1, I2, I3, I4, +// J : I0, I1, I2, I3, I4, // +I4.kt, I0.kt, I1.java, I2.kt, I3.java, J.java, K.kt // Round 6: // K : I0, I1, I2, I3, I4, I5 diff --git a/test-utils/testData/api/parameterTypes.kt b/test-utils/testData/api/parameterTypes.kt index 36fb2cdd8e..d102fbdcba 100644 --- a/test-utils/testData/api/parameterTypes.kt +++ b/test-utils/testData/api/parameterTypes.kt @@ -18,9 +18,9 @@ // TEST PROCESSOR: ParameterTypeProcessor // EXPECTED: // a: Int -// b: +// b: // c: -// errorValue: +// errorValue: // v: String // value: Int // END diff --git a/test-utils/testData/api/replaceWithErrorTypeArgs.kt b/test-utils/testData/api/replaceWithErrorTypeArgs.kt index 1ac869ae4b..58555c0c1d 100644 --- a/test-utils/testData/api/replaceWithErrorTypeArgs.kt +++ b/test-utils/testData/api/replaceWithErrorTypeArgs.kt @@ -19,84 +19,84 @@ // TEST PROCESSOR: ReplaceWithErrorTypeArgsProcessor // EXPECTED: // KS.star.replace([INVARIANT Int, INVARIANT String]): KS -// KS.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KS.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): // KS.asType([INVARIANT Int, INVARIANT String]): KS -// KS.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KS.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KS.asType(emptyList()): KS // KL.star.replace([INVARIANT Int, INVARIANT String]): KL -// KL.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KL.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): // KL.asType([INVARIANT Int, INVARIANT String]): KL -// KL.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KL.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KL.asType(emptyList()): KL // JS.star.replace([INVARIANT Int, INVARIANT String]): JS -// JS.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JS.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): // JS.asType([INVARIANT Int, INVARIANT String]): JS -// JS.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JS.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JS.asType(emptyList()): JS // JL.star.replace([INVARIANT Int, INVARIANT String]): JL -// JL.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JL.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): // JL.asType([INVARIANT Int, INVARIANT String]): JL -// JL.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JL.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JL.asType(emptyList()): JL -// KS1.star.replace([INVARIANT Int, INVARIANT String]): -// KS1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KS1.asType([INVARIANT Int, INVARIANT String]): -// KS1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KS1.star.replace([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// KS1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): % Unexpected extra 1 type argument(s)> +// KS1.asType([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// KS1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): % Unexpected extra 1 type argument(s)> // KS1.asType(emptyList()): KS1 -// KL1.star.replace([INVARIANT Int, INVARIANT String]): -// KL1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KL1.asType([INVARIANT Int, INVARIANT String]): -// KL1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KL1.star.replace([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// KL1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): % Unexpected extra 1 type argument(s)> +// KL1.asType([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// KL1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): % Unexpected extra 1 type argument(s)> // KL1.asType(emptyList()): KL1 -// JS1.star.replace([INVARIANT Int, INVARIANT String]): -// JS1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JS1.asType([INVARIANT Int, INVARIANT String]): -// JS1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JS1.star.replace([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// JS1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): % Unexpected extra 1 type argument(s)> +// JS1.asType([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// JS1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): % Unexpected extra 1 type argument(s)> // JS1.asType(emptyList()): JS1 -// JL1.star.replace([INVARIANT Int, INVARIANT String]): -// JL1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JL1.asType([INVARIANT Int, INVARIANT String]): -// JL1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JL1.star.replace([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// JL1.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): % Unexpected extra 1 type argument(s)> +// JL1.asType([INVARIANT Int, INVARIANT String]): % Unexpected extra 1 type argument(s)> +// JL1.asType([INVARIANT NotExist1, INVARIANT NotExist2]): % Unexpected extra 1 type argument(s)> // JL1.asType(emptyList()): JL1 -// JSE.star.replace([INVARIANT Int, INVARIANT String]): -// JSE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JSE.asType([INVARIANT Int, INVARIANT String]): -// JSE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JSE.star.replace([INVARIANT Int, INVARIANT String]): +// JSE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JSE.asType([INVARIANT Int, INVARIANT String]): +// JSE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JSE.asType(emptyList()): JSE -// JSE.E.star.replace([INVARIANT Int, INVARIANT String]): -// JSE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JSE.E.asType([INVARIANT Int, INVARIANT String]): -// JSE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JSE.E.star.replace([INVARIANT Int, INVARIANT String]): +// JSE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JSE.E.asType([INVARIANT Int, INVARIANT String]): +// JSE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JSE.E.asType(emptyList()): JSE.E -// JLE.star.replace([INVARIANT Int, INVARIANT String]): -// JLE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JLE.asType([INVARIANT Int, INVARIANT String]): -// JLE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JLE.star.replace([INVARIANT Int, INVARIANT String]): +// JLE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JLE.asType([INVARIANT Int, INVARIANT String]): +// JLE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JLE.asType(emptyList()): JLE -// JLE.E.star.replace([INVARIANT Int, INVARIANT String]): -// JLE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// JLE.E.asType([INVARIANT Int, INVARIANT String]): -// JLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// JLE.E.star.replace([INVARIANT Int, INVARIANT String]): +// JLE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// JLE.E.asType([INVARIANT Int, INVARIANT String]): +// JLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // JLE.E.asType(emptyList()): JLE.E -// KSE.star.replace([INVARIANT Int, INVARIANT String]): -// KSE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KSE.asType([INVARIANT Int, INVARIANT String]): -// KSE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KSE.star.replace([INVARIANT Int, INVARIANT String]): +// KSE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KSE.asType([INVARIANT Int, INVARIANT String]): +// KSE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KSE.asType(emptyList()): KSE -// KSE.E.star.replace([INVARIANT Int, INVARIANT String]): -// KSE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KSE.E.asType([INVARIANT Int, INVARIANT String]): -// KSE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KSE.E.star.replace([INVARIANT Int, INVARIANT String]): +// KSE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KSE.E.asType([INVARIANT Int, INVARIANT String]): +// KSE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KSE.E.asType(emptyList()): E -// KLE.star.replace([INVARIANT Int, INVARIANT String]): -// KLE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KLE.asType([INVARIANT Int, INVARIANT String]): -// KLE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KLE.star.replace([INVARIANT Int, INVARIANT String]): +// KLE.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KLE.asType([INVARIANT Int, INVARIANT String]): +// KLE.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KLE.asType(emptyList()): KLE -// KLE.E.star.replace([INVARIANT Int, INVARIANT String]): -// KLE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): -// KLE.E.asType([INVARIANT Int, INVARIANT String]): -// KLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): +// KLE.E.star.replace([INVARIANT Int, INVARIANT String]): +// KLE.E.star.replace([INVARIANT NotExist1, INVARIANT NotExist2]): +// KLE.E.asType([INVARIANT Int, INVARIANT String]): +// KLE.E.asType([INVARIANT NotExist1, INVARIANT NotExist2]): // KLE.E.asType(emptyList()): KLE.E // default type:A // flexible type star:(T..T?)