diff --git a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt index 706db0d2fc..b99d853154 100644 --- a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt +++ b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt @@ -592,6 +592,12 @@ class KSPCompilerPluginTest : AbstractKSPCompilerPluginTest() { runTest("../test-utils/testData/api/typeArgumentVariance.kt") } + @TestMetadata("typeComparison2.kt") + @Test + fun testTypeComparison2() { + runTest("../test-utils/testData/api/typeComparison2.kt") + } + @TestMetadata("typeComposure.kt") @Test fun testTypeComposure() { 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 d38ea21022..ff00bf8b6c 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 @@ -131,7 +131,9 @@ class KSClassDeclarationImpl private constructor(internal val ktClassOrObjectSym errorType = ::KSErrorType, )?.let { error -> return error } return analyze { + ktClassOrObjectSymbol.tryResolveToTypePhase() if (typeArguments.isEmpty()) { + // Resolving a class symbol also resolves its type parameters. typeParameters.map { buildTypeParameterType((it as KSTypeParameterImpl).ktTypeParameterSymbol) } .let { typeParameterTypes -> buildClassType(ktClassOrObjectSymbol) { @@ -150,7 +152,7 @@ class KSClassDeclarationImpl private constructor(internal val ktClassOrObjectSym override fun asStarProjectedType(): KSType { return analyze { KSTypeImpl.getCached( - useSiteSession.buildClassType(ktClassOrObjectSymbol) { + useSiteSession.buildClassType(ktClassOrObjectSymbol.tryResolveToTypePhase()) { var current: KSNode? = this@KSClassDeclarationImpl while (current is KSClassDeclarationImpl) { current.ktClassOrObjectSymbol.typeParameters.forEach { 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 c06c1649a8..af735619c0 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 @@ -32,15 +32,14 @@ import com.google.devtools.ksp.symbol.* import com.intellij.psi.PsiElement import com.intellij.psi.PsiJavaFile import com.intellij.psi.impl.compiled.ClsMemberImpl -import org.jetbrains.kotlin.analysis.api.KaExperimentalApi -import org.jetbrains.kotlin.analysis.api.KaImplementationDetail -import org.jetbrains.kotlin.analysis.api.KaNonPublicApi -import org.jetbrains.kotlin.analysis.api.KaSession -import org.jetbrains.kotlin.analysis.api.analyze -import org.jetbrains.kotlin.analysis.api.annotations.* +import org.jetbrains.kotlin.analysis.api.* +import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotated +import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotation +import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotationValue import org.jetbrains.kotlin.analysis.api.components.KaSubstitutorBuilder import org.jetbrains.kotlin.analysis.api.fir.KaSymbolByFirBuilder import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter +import org.jetbrains.kotlin.analysis.api.fir.symbols.KaFirSymbol import org.jetbrains.kotlin.analysis.api.fir.symbols.KaFirValueParameterSymbol import org.jetbrains.kotlin.analysis.api.fir.types.KaFirFunctionType import org.jetbrains.kotlin.analysis.api.fir.types.KaFirType @@ -56,6 +55,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.symbols.markers.KaDeclarationContainerSymbol import org.jetbrains.kotlin.analysis.api.types.* import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.getTargetType import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirArrayLiteral @@ -65,14 +65,8 @@ import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack import org.jetbrains.kotlin.fir.java.toFirExpression import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.symbols.SymbolInternals -import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.ConeErrorType -import org.jetbrains.kotlin.fir.types.ConeFlexibleType -import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType -import org.jetbrains.kotlin.fir.types.abbreviatedType -import org.jetbrains.kotlin.fir.types.classId -import org.jetbrains.kotlin.fir.types.coneType -import org.jetbrains.kotlin.fir.types.isAny +import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase +import org.jetbrains.kotlin.fir.types.* 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.JavaUnknownAnnotationArgumentImpl @@ -89,11 +83,7 @@ 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 -import org.jetbrains.org.objectweb.asm.ClassVisitor -import org.jetbrains.org.objectweb.asm.MethodVisitor -import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.* internal val ktSymbolOriginToOrigin = mapOf( KaSymbolOrigin.JAVA_SOURCE to Origin.JAVA, @@ -703,7 +693,7 @@ internal fun KaType.convertToKotlinType(): KaType { ?: declaration } else declaration return analyze { - buildClassType(base) { + buildClassType(base.tryResolveToTypePhase()) { this@convertToKotlinType.typeArguments().forEach { typeProjection -> if (typeProjection is KaTypeArgumentWithVariance) { argument(typeProjection.type.convertToKotlinType(), typeProjection.variance) @@ -731,7 +721,7 @@ internal fun KaType.isAssignableFrom(that: KaType): Boolean { internal fun KaType.replace(newArgs: List): KaType { require(newArgs.isEmpty() || newArgs.size == this.typeArguments().size) return analyze { - when (val symbol = classifierSymbol()) { + when (val symbol = classifierSymbol().tryResolveToTypePhase()) { is KaClassLikeSymbol -> useSiteSession.buildClassType(symbol) { newArgs.forEach { arg -> argument(arg) } nullability = this@replace.nullability @@ -784,7 +774,7 @@ internal fun KaType.toWildcard(mode: TypeMappingMode): KtType { when (this@toWildcard) { is KaClassType -> { // TODO: missing annotations from original type. - buildClassType(this@toWildcard.expandedSymbol!!) { + buildClassType(this@toWildcard.expandedSymbol!!.tryResolveToTypePhase()) { parameters.zip(args).map { (param, arg) -> val argMode = mode.updateFromAnnotations(arg.type) val variance = getVarianceForWildcard(param, arg, argMode) @@ -802,7 +792,7 @@ internal fun KaType.toWildcard(mode: TypeMappingMode): KtType { } } is KaTypeParameterType -> { - buildTypeParameterType(this@toWildcard.symbol) + buildTypeParameterType(this@toWildcard.symbol.tryResolveToTypePhase()) } else -> throw IllegalStateException("Unexpected type ${this@toWildcard}") } @@ -879,3 +869,8 @@ internal fun KaFunctionType.abbreviatedSymbol(): KaTypeAliasSymbol? { val classId = (this as? KaFirFunctionType)?.coneType?.abbreviatedType?.classId ?: return null return classId.toTypeAlias() } + +fun T.tryResolveToTypePhase(): T { + (this as? KaFirSymbol<*>)?.firSymbol?.lazyResolveToPhase(FirResolvePhase.TYPES) + return this +} diff --git a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt index cff122e393..283d0a2711 100644 --- a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt +++ b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt @@ -625,6 +625,12 @@ class KSPAATest : AbstractKSPAATest() { runTest("../test-utils/testData/api/typeComposure.kt") } + @TestMetadata("typeComparison2.kt") + @Test + fun testTypeComparison2() { + runTest("../test-utils/testData/api/typeComparison2.kt") + } + @TestMetadata("typeParameterReference.kt") @Test fun testTypeParameterReference() { diff --git a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/TypeComparison2Processor.kt b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/TypeComparison2Processor.kt new file mode 100644 index 0000000000..32d1760771 --- /dev/null +++ b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/TypeComparison2Processor.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2020 Google LLC + * Copyright 2010-2020 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. + */ + +package com.google.devtools.ksp.processor + +import com.google.devtools.ksp.getClassDeclarationByName +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.symbol.* + +open class TypeComparison2Processor : AbstractTestProcessor() { + val results = mutableListOf() + + override fun process(resolver: Resolver): List { + resolver.getClassDeclarationByName("StyleBuilder")!!.let { cls -> + val typeOne = cls.asType(emptyList()) + val typeTwo = cls.asType(emptyList()) + results.add("${typeOne == typeTwo}") + } + return emptyList() + } + + override fun toResult(): List { + return results + } +} diff --git a/test-utils/testData/api/typeComparison2.kt b/test-utils/testData/api/typeComparison2.kt new file mode 100644 index 0000000000..6e931345bf --- /dev/null +++ b/test-utils/testData/api/typeComparison2.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Google LLC + * Copyright 2010-2020 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: TypeComparison2Processor +// EXPECTED: +// true +// END + +// FILE: A.kt +class StyleApplier +class StyleBuilder, out A : StyleApplier<*, *>> +class KotlinSubject { + fun subject_1(builder: StyleBuilder<*, *>) { + } +}