diff --git a/compiler/container/src/org/jetbrains/kotlin/container/Resolve.kt b/compiler/container/src/org/jetbrains/kotlin/container/Resolve.kt index 208bc621fa6..d475f9ab0a5 100644 --- a/compiler/container/src/org/jetbrains/kotlin/container/Resolve.kt +++ b/compiler/container/src/org/jetbrains/kotlin/container/Resolve.kt @@ -48,7 +48,7 @@ class MethodBinding(val method: Method, val argumentDescriptors: List): List = argumentDescriptors.map { it.getValue() } fun Class<*>.bindToConstructor(context: ValueResolveContext): ConstructorBinding { - val constructorInfo = getInfo().constructorInfo!! + val constructorInfo = getInfo().constructorInfo ?: error("No constructor for $this: ${getInfo()}") val candidate = constructorInfo.constructor return ConstructorBinding(candidate, candidate.bindArguments(constructorInfo.parameters, context)) } diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/library/test/A.java b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/library/test/A.java new file mode 100644 index 00000000000..e7ecddace55 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/library/test/A.java @@ -0,0 +1,7 @@ +package test; + +public interface A { + @interface Anno { + String value(); + } +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/library/test/B.java b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/library/test/B.java new file mode 100644 index 00000000000..e4f4e174fe0 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/library/test/B.java @@ -0,0 +1,7 @@ +package test; + +@A.Anno("B") +public interface B { + @A.Anno("foo") + T foo(T t); +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/output.txt new file mode 100644 index 00000000000..a0aba9318ad --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/output.txt @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/source.kt new file mode 100644 index 00000000000..399fe7e8ab1 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyJavaNestedAnnotation/source.kt @@ -0,0 +1,8 @@ +package c + +import test.B + +// There should be _no_ error despite the fact that B and B#foo are annotated with an annotation which cannot be resolved +fun bar(b: B) { + b.foo("") +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/library/a.kt new file mode 100644 index 00000000000..2cb3794ad4c --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/library/a.kt @@ -0,0 +1,6 @@ +package a + +interface A { + @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER) + annotation class Anno(val value: String) +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/library/b.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/library/b.kt new file mode 100644 index 00000000000..fdac61bc93d --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/library/b.kt @@ -0,0 +1,9 @@ +package b + +import a.A + +@A.Anno("B") +interface B { + @A.Anno("foo") + fun <@A.Anno("T") T> foo(t: T) = t +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/output.txt new file mode 100644 index 00000000000..a0aba9318ad --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/output.txt @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/source.kt new file mode 100644 index 00000000000..ad564297819 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/missingDependencyNestedAnnotation/source.kt @@ -0,0 +1,8 @@ +package c + +import b.B + +// There should be _no_ error despite the fact that B and B#foo are annotated with an annotation which cannot be resolved +fun bar(b: B) { + b.foo("") +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java index 1942612c39b..777406eeb7e 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java @@ -52,6 +52,7 @@ import org.jetbrains.org.objectweb.asm.ClassReader; import org.jetbrains.org.objectweb.asm.ClassVisitor; import org.jetbrains.org.objectweb.asm.ClassWriter; import org.jetbrains.org.objectweb.asm.Opcodes; +import org.junit.Assert; import java.io.BufferedOutputStream; import java.io.File; @@ -83,7 +84,8 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { @NotNull private File compileLibrary(@NotNull String sourcePath, @NotNull File... extraClassPath) { File result = new File(tmpdir, sourcePath + ".jar"); - compileKotlin(sourcePath, result, extraClassPath); + Pair output = compileKotlin(sourcePath, result, extraClassPath); + Assert.assertEquals(normalizeOutput(new Pair("", ExitCode.OK)), normalizeOutput(output)); return result; } @@ -298,6 +300,10 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { doTestBrokenKotlinLibrary("library", "a/A.class"); } + public void testMissingDependencyNestedAnnotation() throws Exception { + doTestBrokenKotlinLibrary("library", "a/A$Anno.class"); + } + public void testMissingDependencyConflictingLibraries() throws Exception { File library1 = copyJarFileWithoutEntry(compileLibrary("library1"), "a/A.class", "a/A$Inner.class", "a/AA.class", "a/AA$Inner.class"); @@ -318,6 +324,10 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { KotlinTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), normalizeOutput(output)); } + public void testMissingDependencyJavaNestedAnnotation() throws Exception { + doTestBrokenJavaLibrary("library", "test/A$Anno.class"); + } + /*test source mapping generation when source info is absent*/ public void testInlineFunWithoutDebugInfo() throws Exception { compileKotlin("sourceInline.kt", tmpdir); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt index 405b9d52a66..f89a21f02ac 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaAnnotationDescriptor.kt @@ -16,10 +16,9 @@ package org.jetbrains.kotlin.load.java.lazy.descriptors -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils @@ -27,6 +26,7 @@ import org.jetbrains.kotlin.load.java.components.TypeUsage import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.types.toAttributes import org.jetbrains.kotlin.load.java.structure.* +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.JavaToKotlinClassMap @@ -34,7 +34,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass -import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.serialization.deserialization.findNonGenericClassAcrossDependencies import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.utils.keysToMapExceptNulls @@ -51,7 +51,8 @@ class LazyJavaAnnotationDescriptor( val fqName = fqName() ?: return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation") val annotationClass = JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(fqName) ?: javaAnnotation.resolve()?.let { javaClass -> c.components.moduleClassResolver.resolveClass(javaClass) } - annotationClass?.defaultType ?: createTypeForMissingDependencies(fqName) + ?: createTypeForMissingDependencies(fqName) + annotationClass.defaultType } private val source = c.components.sourceElementFactory.source(javaAnnotation) @@ -151,13 +152,8 @@ class LazyJavaAnnotationDescriptor( } private fun createTypeForMissingDependencies(fqName: FqName) = - ErrorUtils.createErrorTypeWithCustomConstructor( - "[Missing annotation class: $fqName]", - ClassDescriptorImpl( - EmptyPackageFragmentDescriptor(c.module, fqName.parent()), fqName.shortName(), Modality.FINAL, - ClassKind.ANNOTATION_CLASS, listOf(c.module.builtIns.anyType), SourceElement.NO_SOURCE - ).apply { - initialize(MemberScope.Empty, emptySet(), null) - }.typeConstructor + c.module.findNonGenericClassAcrossDependencies( + ClassId.topLevel(fqName), + c.components.deserializedDescriptorResolver.components.notFoundClasses ) } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt index 4a723d7e342..f0fd3eb5157 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt @@ -30,23 +30,20 @@ import org.jetbrains.kotlin.resolve.constants.AnnotationValue import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.serialization.ProtoBuf -import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer -import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter -import org.jetbrains.kotlin.serialization.deserialization.NameResolver -import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.storage.StorageManager -import org.jetbrains.kotlin.types.ErrorUtils import java.util.* class BinaryClassAnnotationAndConstantLoaderImpl( private val module: ModuleDescriptor, + private val notFoundClasses: NotFoundClasses, storageManager: StorageManager, kotlinClassFinder: KotlinClassFinder, errorReporter: ErrorReporter ) : AbstractBinaryClassAnnotationAndConstantLoader, AnnotationWithTarget>( storageManager, kotlinClassFinder, errorReporter ) { - private val annotationDeserializer = AnnotationDeserializer(module) + private val annotationDeserializer = AnnotationDeserializer(module, notFoundClasses) private val factory = ConstantValueFactory(module.builtIns) override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor = @@ -167,7 +164,6 @@ class BinaryClassAnnotationAndConstantLoaderImpl( } private fun resolveClass(classId: ClassId): ClassDescriptor { - return module.findClassAcrossModuleDependencies(classId) - ?: ErrorUtils.createErrorClass(classId.asSingleFqName().asString()) + return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses) } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt index 4acaf5d1a87..c99decc0a13 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt @@ -19,10 +19,7 @@ package org.jetbrains.kotlin.load.kotlin import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider -import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory -import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents -import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter -import org.jetbrains.kotlin.serialization.deserialization.LocalClassResolverImpl +import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.storage.StorageManager // This class is needed only for easier injection: exact types of needed components are specified in the constructor here. @@ -33,6 +30,7 @@ class DeserializationComponentsForJava( classDataFinder: JavaClassDataFinder, annotationAndConstantLoader: BinaryClassAnnotationAndConstantLoaderImpl, packageFragmentProvider: LazyJavaPackageFragmentProvider, + notFoundClasses: NotFoundClasses, errorReporter: ErrorReporter, lookupTracker: LookupTracker ) { @@ -42,7 +40,8 @@ class DeserializationComponentsForJava( val localClassResolver = LocalClassResolverImpl() components = DeserializationComponents( storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, localClassResolver, - errorReporter, lookupTracker, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, JavaTypeCapabilitiesLoader, + errorReporter, lookupTracker, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, + notFoundClasses, JavaTypeCapabilitiesLoader, additionalSupertypes = BuiltInClassesAreSerializableOnJvm(moduleDescriptor) ) localClassResolver.setDeserializationComponents(components) diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt index 5d82c45c2d2..582f3282449 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.platform.JvmBuiltIns import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents import org.jetbrains.kotlin.serialization.deserialization.LocalClassResolver +import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses import org.jetbrains.kotlin.storage.LockBasedStorageManager class RuntimeModuleData private constructor(val deserialization: DeserializationComponents, val packageFacadeProvider: RuntimePackagePartProvider) { @@ -65,10 +66,13 @@ class RuntimeModuleData private constructor(val deserialization: Deserialization LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module)) val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider) val javaClassDataFinder = JavaClassDataFinder(reflectKotlinClassFinder, deserializedDescriptorResolver) - val binaryClassAnnotationAndConstantLoader = BinaryClassAnnotationAndConstantLoaderImpl(module, storageManager, reflectKotlinClassFinder, RuntimeErrorReporter) + val notFoundClasses = NotFoundClasses(storageManager, module) + val binaryClassAnnotationAndConstantLoader = BinaryClassAnnotationAndConstantLoaderImpl( + module, notFoundClasses, storageManager, reflectKotlinClassFinder, RuntimeErrorReporter + ) val deserializationComponentsForJava = DeserializationComponentsForJava( storageManager, module, javaClassDataFinder, binaryClassAnnotationAndConstantLoader, - lazyJavaPackageFragmentProvider, RuntimeErrorReporter, LookupTracker.DO_NOTHING + lazyJavaPackageFragmentProvider, notFoundClasses, RuntimeErrorReporter, LookupTracker.DO_NOTHING ) singleModuleClassResolver.resolver = javaDescriptorResolver deserializedDescriptorResolver.setComponents(deserializationComponentsForJava) diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/builtInsPackageFragmentProvider.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/builtInsPackageFragmentProvider.kt index 82641f3d8e2..4783b8910a4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/builtInsPackageFragmentProvider.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/builtInsPackageFragmentProvider.kt @@ -38,19 +38,21 @@ fun createBuiltInPackageFragmentProvider( } val provider = PackageFragmentProviderImpl(packageFragments) + val notFoundClasses = NotFoundClasses(storageManager, module) val localClassResolver = LocalClassResolverImpl() val components = DeserializationComponents( storageManager, module, DeserializedClassDataFinder(provider), - AnnotationAndConstantLoaderImpl(module, BuiltInSerializerProtocol), + AnnotationAndConstantLoaderImpl(module, notFoundClasses, BuiltInSerializerProtocol), provider, localClassResolver, ErrorReporter.DO_NOTHING, LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.ThrowException, classDescriptorFactory, + notFoundClasses, additionalSupertypes = additionalSupertypes ) diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt index 5f60e70fa20..2e3995246e6 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.KClassValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue +import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.ErrorUtils.UninferredParameterTypeConstructor import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE @@ -374,7 +375,7 @@ internal class DescriptorRendererImpl( append(renderType(annotationType)) if (verbose) { renderAndSortAnnotationArguments(annotation).joinTo(this, ", ", "(", ")") - if (annotationType.isError) { + if (annotationType.isError || annotationType.constructor.declarationDescriptor is NotFoundClasses.MockClassDescriptor) { append(" /* annotation class not found */") } } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationAndConstantLoaderImpl.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationAndConstantLoaderImpl.kt index dbbc9dc9776..a132a26f36f 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationAndConstantLoaderImpl.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationAndConstantLoaderImpl.kt @@ -27,9 +27,10 @@ import org.jetbrains.kotlin.types.KotlinType class AnnotationAndConstantLoaderImpl( module: ModuleDescriptor, + private val notFoundClasses: NotFoundClasses, private val protocol: SerializerExtensionProtocol ) : AnnotationAndConstantLoader, AnnotationWithTarget> { - private val deserializer = AnnotationDeserializer(module) + private val deserializer = AnnotationDeserializer(module, notFoundClasses) override fun loadClassAnnotations( classProto: ProtoBuf.Class, diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationDeserializer.kt index 3c1f6b50bfc..27514f50fd5 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AnnotationDeserializer.kt @@ -36,7 +36,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf -class AnnotationDeserializer(private val module: ModuleDescriptor) { +class AnnotationDeserializer(private val module: ModuleDescriptor, private val notFoundClasses: NotFoundClasses) { private val builtIns: KotlinBuiltIns get() = module.builtIns @@ -164,7 +164,6 @@ class AnnotationDeserializer(private val module: ModuleDescriptor) { } private fun resolveClass(classId: ClassId): ClassDescriptor { - return module.findClassAcrossModuleDependencies(classId) - ?: ErrorUtils.createErrorClass(classId.asSingleFqName().asString()) + return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses) } } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/context.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/context.kt index 26af1a93ffe..6d867dabc6b 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/context.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/context.kt @@ -37,11 +37,11 @@ class DeserializationComponents( val lookupTracker: LookupTracker, val flexibleTypeCapabilitiesDeserializer: FlexibleTypeCapabilitiesDeserializer, val fictitiousClassDescriptorFactory: ClassDescriptorFactory, + val notFoundClasses: NotFoundClasses, val typeCapabilitiesLoader: TypeCapabilitiesLoader = TypeCapabilitiesLoader.NONE, val additionalSupertypes: AdditionalSupertypes = AdditionalSupertypes.None ) { val classDeserializer: ClassDeserializer = ClassDeserializer(this) - val notFoundClasses: NotFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) fun deserializeClass(classId: ClassId): ClassDescriptor? = classDeserializer.deserializeClass(classId) diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/findClassInModule.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/findClassInModule.kt index d8739b14b0e..ef3449573c3 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/findClassInModule.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/findClassInModule.kt @@ -31,3 +31,15 @@ fun ModuleDescriptor.findClassAcrossModuleDependencies(classId: ClassId): ClassD } return result } + +// Returns a mock class descriptor if no existing class is found. +// NB: the returned class has no type parameters and thus cannot be given arguments in types +fun ModuleDescriptor.findNonGenericClassAcrossDependencies(classId: ClassId, notFoundClasses: NotFoundClasses): ClassDescriptor { + val existingClass = findClassAcrossModuleDependencies(classId) + if (existingClass != null) return existingClass + + // Take a list of N zeros, where N is the number of class names in the given ClassId + val typeParametersCount = generateSequence(classId) { if (it.isNestedClass) it.outerClassId else null }.map { 0 }.toList() + + return notFoundClasses.get(classId, typeParametersCount).declarationDescriptor as ClassDescriptor +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDeserializerForDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDeserializerForDecompiler.kt index 705bd81df04..7f229ac470a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDeserializerForDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDeserializerForDecompiler.kt @@ -39,12 +39,19 @@ class KotlinBuiltInDeserializerForDecompiler( ) : DeserializerForDecompilerBase(packageDirectory, packageFqName) { override val targetPlatform: TargetPlatform get() = TargetPlatform.Default - override val deserializationComponents = DeserializationComponents( - storageManager, moduleDescriptor, BuiltInsClassDataFinder(proto, nameResolver), - AnnotationAndConstantLoaderImpl(moduleDescriptor, BuiltInSerializerProtocol), packageFragmentProvider, - ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG), - LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.ThrowException, ClassDescriptorFactory.EMPTY - ) + override val deserializationComponents: DeserializationComponents + + init { + val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) + + deserializationComponents = DeserializationComponents( + storageManager, moduleDescriptor, BuiltInsClassDataFinder(proto, nameResolver), + AnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, BuiltInSerializerProtocol), packageFragmentProvider, + ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG), + LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.ThrowException, ClassDescriptorFactory.EMPTY, + notFoundClasses + ) + } override fun resolveDeclarationsInFacade(facadeFqName: FqName): List { assert(facadeFqName == directoryPackageFqName) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt index 42be78e3623..37f903fc522 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.serialization.ClassDataWithSource import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents +import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil @@ -52,18 +53,21 @@ class DeserializerForClassfileDecompiler( private val classFinder = DirectoryBasedClassFinder(packageDirectory, directoryPackageFqName) - private val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG) + override val deserializationComponents: DeserializationComponents - private val errorReporter = LoggingErrorReporter(LOG) + init { + val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG) + val errorReporter = LoggingErrorReporter(LOG) + val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) + val annotationAndConstantLoader = + BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, storageManager, classFinder, errorReporter) - private val annotationAndConstantLoader = - BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, storageManager, classFinder, errorReporter) - - override val deserializationComponents: DeserializationComponents = DeserializationComponents( - storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, - ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), errorReporter, - LookupTracker.DO_NOTHING, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY - ) + deserializationComponents = DeserializationComponents( + storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, + ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), errorReporter, + LookupTracker.DO_NOTHING, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, notFoundClasses + ) + } override fun resolveDeclarationsInFacade(facadeFqName: FqName): List { val packageFqName = facadeFqName.parent() diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/js/KotlinJavaScriptDeserializerForDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/js/KotlinJavaScriptDeserializerForDecompiler.kt index e735664c361..1b2a52cc338 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/js/KotlinJavaScriptDeserializerForDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/js/KotlinJavaScriptDeserializerForDecompiler.kt @@ -52,13 +52,19 @@ class KotlinJavaScriptDeserializerForDecompiler( packageDirectory.findChild(path.substringAfterLast("/"))?.inputStream } - private val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(moduleDescriptor, JsSerializerProtocol) + override val deserializationComponents: DeserializationComponents - override val deserializationComponents = DeserializationComponents( - storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, - ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG), - LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.Dynamic, ClassDescriptorFactory.EMPTY - ) + init { + val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) + val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, JsSerializerProtocol) + + deserializationComponents = DeserializationComponents( + storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, + ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG), + LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.Dynamic, ClassDescriptorFactory.EMPTY, + notFoundClasses + ) + } override fun resolveDeclarationsInFacade(facadeFqName: FqName): List { val packageFqName = facadeFqName.parent() diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/kotlinJavascriptPackageFragmentProvider.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/kotlinJavascriptPackageFragmentProvider.kt index 2acf77ab3f7..6e8fda24842 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/kotlinJavascriptPackageFragmentProvider.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/kotlinJavascriptPackageFragmentProvider.kt @@ -36,19 +36,21 @@ fun createKotlinJavascriptPackageFragmentProvider( } val provider = PackageFragmentProviderImpl(packageFragments) + val notFoundClasses = NotFoundClasses(storageManager, module) val localClassResolver = LocalClassResolverImpl() val components = DeserializationComponents( storageManager, module, DeserializedClassDataFinder(provider), - AnnotationAndConstantLoaderImpl(module, JsSerializerProtocol), + AnnotationAndConstantLoaderImpl(module, notFoundClasses, JsSerializerProtocol), provider, localClassResolver, ErrorReporter.DO_NOTHING, LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.Dynamic, - ClassDescriptorFactory.EMPTY + ClassDescriptorFactory.EMPTY, + notFoundClasses ) localClassResolver.setDeserializationComponents(components)