Do not produce error classes for not found annotations

This commit is contained in:
Alexander Udalov
2016-03-21 18:54:29 +03:00
parent e915e1548c
commit 8d64ed7f3f
24 changed files with 147 additions and 61 deletions
@@ -48,7 +48,7 @@ class MethodBinding(val method: Method, val argumentDescriptors: List<ValueDescr
fun computeArguments(argumentDescriptors: List<ValueDescriptor>): List<Any> = argumentDescriptors.map { it.getValue() } fun computeArguments(argumentDescriptors: List<ValueDescriptor>): List<Any> = argumentDescriptors.map { it.getValue() }
fun Class<*>.bindToConstructor(context: ValueResolveContext): ConstructorBinding { fun Class<*>.bindToConstructor(context: ValueResolveContext): ConstructorBinding {
val constructorInfo = getInfo().constructorInfo!! val constructorInfo = getInfo().constructorInfo ?: error("No constructor for $this: ${getInfo()}")
val candidate = constructorInfo.constructor val candidate = constructorInfo.constructor
return ConstructorBinding(candidate, candidate.bindArguments(constructorInfo.parameters, context)) return ConstructorBinding(candidate, candidate.bindArguments(constructorInfo.parameters, context))
} }
@@ -0,0 +1,7 @@
package test;
public interface A {
@interface Anno {
String value();
}
}
@@ -0,0 +1,7 @@
package test;
@A.Anno("B")
public interface B {
@A.Anno("foo")
<T> T foo(T t);
}
@@ -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("")
}
@@ -0,0 +1,6 @@
package a
interface A {
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER)
annotation class Anno(val value: String)
}
@@ -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
}
@@ -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("")
}
@@ -52,6 +52,7 @@ import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.ClassVisitor; import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.ClassWriter; import org.jetbrains.org.objectweb.asm.ClassWriter;
import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Opcodes;
import org.junit.Assert;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
@@ -83,7 +84,8 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
@NotNull @NotNull
private File compileLibrary(@NotNull String sourcePath, @NotNull File... extraClassPath) { private File compileLibrary(@NotNull String sourcePath, @NotNull File... extraClassPath) {
File result = new File(tmpdir, sourcePath + ".jar"); File result = new File(tmpdir, sourcePath + ".jar");
compileKotlin(sourcePath, result, extraClassPath); Pair<String, ExitCode> output = compileKotlin(sourcePath, result, extraClassPath);
Assert.assertEquals(normalizeOutput(new Pair<String, ExitCode>("", ExitCode.OK)), normalizeOutput(output));
return result; return result;
} }
@@ -298,6 +300,10 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir {
doTestBrokenKotlinLibrary("library", "a/A.class"); doTestBrokenKotlinLibrary("library", "a/A.class");
} }
public void testMissingDependencyNestedAnnotation() throws Exception {
doTestBrokenKotlinLibrary("library", "a/A$Anno.class");
}
public void testMissingDependencyConflictingLibraries() throws Exception { public void testMissingDependencyConflictingLibraries() throws Exception {
File library1 = copyJarFileWithoutEntry(compileLibrary("library1"), File library1 = copyJarFileWithoutEntry(compileLibrary("library1"),
"a/A.class", "a/A$Inner.class", "a/AA.class", "a/AA$Inner.class"); "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)); 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*/ /*test source mapping generation when source info is absent*/
public void testInlineFunWithoutDebugInfo() throws Exception { public void testInlineFunWithoutDebugInfo() throws Exception {
compileKotlin("sourceInline.kt", tmpdir); compileKotlin("sourceInline.kt", tmpdir);
@@ -16,10 +16,9 @@
package org.jetbrains.kotlin.load.java.lazy.descriptors 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.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.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils 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.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap 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.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass 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.types.*
import org.jetbrains.kotlin.utils.keysToMapExceptNulls import org.jetbrains.kotlin.utils.keysToMapExceptNulls
@@ -51,7 +51,8 @@ class LazyJavaAnnotationDescriptor(
val fqName = fqName() ?: return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation") val fqName = fqName() ?: return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation")
val annotationClass = JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(fqName) val annotationClass = JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(fqName)
?: javaAnnotation.resolve()?.let { javaClass -> c.components.moduleClassResolver.resolveClass(javaClass) } ?: 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) private val source = c.components.sourceElementFactory.source(javaAnnotation)
@@ -151,13 +152,8 @@ class LazyJavaAnnotationDescriptor(
} }
private fun createTypeForMissingDependencies(fqName: FqName) = private fun createTypeForMissingDependencies(fqName: FqName) =
ErrorUtils.createErrorTypeWithCustomConstructor( c.module.findNonGenericClassAcrossDependencies(
"[Missing annotation class: $fqName]", ClassId.topLevel(fqName),
ClassDescriptorImpl( c.components.deserializedDescriptorResolver.components.notFoundClasses
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
) )
} }
@@ -30,23 +30,20 @@ import org.jetbrains.kotlin.resolve.constants.AnnotationValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer import org.jetbrains.kotlin.serialization.deserialization.*
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.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.ErrorUtils
import java.util.* import java.util.*
class BinaryClassAnnotationAndConstantLoaderImpl( class BinaryClassAnnotationAndConstantLoaderImpl(
private val module: ModuleDescriptor, private val module: ModuleDescriptor,
private val notFoundClasses: NotFoundClasses,
storageManager: StorageManager, storageManager: StorageManager,
kotlinClassFinder: KotlinClassFinder, kotlinClassFinder: KotlinClassFinder,
errorReporter: ErrorReporter errorReporter: ErrorReporter
) : AbstractBinaryClassAnnotationAndConstantLoader<AnnotationDescriptor, ConstantValue<*>, AnnotationWithTarget>( ) : AbstractBinaryClassAnnotationAndConstantLoader<AnnotationDescriptor, ConstantValue<*>, AnnotationWithTarget>(
storageManager, kotlinClassFinder, errorReporter storageManager, kotlinClassFinder, errorReporter
) { ) {
private val annotationDeserializer = AnnotationDeserializer(module) private val annotationDeserializer = AnnotationDeserializer(module, notFoundClasses)
private val factory = ConstantValueFactory(module.builtIns) private val factory = ConstantValueFactory(module.builtIns)
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor = override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor =
@@ -167,7 +164,6 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
} }
private fun resolveClass(classId: ClassId): ClassDescriptor { private fun resolveClass(classId: ClassId): ClassDescriptor {
return module.findClassAcrossModuleDependencies(classId) return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses)
?: ErrorUtils.createErrorClass(classId.asSingleFqName().asString())
} }
} }
@@ -19,10 +19,7 @@ package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory import org.jetbrains.kotlin.serialization.deserialization.*
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.storage.StorageManager 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. // 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, classDataFinder: JavaClassDataFinder,
annotationAndConstantLoader: BinaryClassAnnotationAndConstantLoaderImpl, annotationAndConstantLoader: BinaryClassAnnotationAndConstantLoaderImpl,
packageFragmentProvider: LazyJavaPackageFragmentProvider, packageFragmentProvider: LazyJavaPackageFragmentProvider,
notFoundClasses: NotFoundClasses,
errorReporter: ErrorReporter, errorReporter: ErrorReporter,
lookupTracker: LookupTracker lookupTracker: LookupTracker
) { ) {
@@ -42,7 +40,8 @@ class DeserializationComponentsForJava(
val localClassResolver = LocalClassResolverImpl() val localClassResolver = LocalClassResolverImpl()
components = DeserializationComponents( components = DeserializationComponents(
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, localClassResolver, storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, localClassResolver,
errorReporter, lookupTracker, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, JavaTypeCapabilitiesLoader, errorReporter, lookupTracker, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY,
notFoundClasses, JavaTypeCapabilitiesLoader,
additionalSupertypes = BuiltInClassesAreSerializableOnJvm(moduleDescriptor) additionalSupertypes = BuiltInClassesAreSerializableOnJvm(moduleDescriptor)
) )
localClassResolver.setDeserializationComponents(components) localClassResolver.setDeserializationComponents(components)
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.platform.JvmBuiltIns
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
import org.jetbrains.kotlin.serialization.deserialization.LocalClassResolver import org.jetbrains.kotlin.serialization.deserialization.LocalClassResolver
import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
class RuntimeModuleData private constructor(val deserialization: DeserializationComponents, val packageFacadeProvider: RuntimePackagePartProvider) { 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)) LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module))
val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider) val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider)
val javaClassDataFinder = JavaClassDataFinder(reflectKotlinClassFinder, deserializedDescriptorResolver) 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( val deserializationComponentsForJava = DeserializationComponentsForJava(
storageManager, module, javaClassDataFinder, binaryClassAnnotationAndConstantLoader, storageManager, module, javaClassDataFinder, binaryClassAnnotationAndConstantLoader,
lazyJavaPackageFragmentProvider, RuntimeErrorReporter, LookupTracker.DO_NOTHING lazyJavaPackageFragmentProvider, notFoundClasses, RuntimeErrorReporter, LookupTracker.DO_NOTHING
) )
singleModuleClassResolver.resolver = javaDescriptorResolver singleModuleClassResolver.resolver = javaDescriptorResolver
deserializedDescriptorResolver.setComponents(deserializationComponentsForJava) deserializedDescriptorResolver.setComponents(deserializationComponentsForJava)
@@ -38,19 +38,21 @@ fun createBuiltInPackageFragmentProvider(
} }
val provider = PackageFragmentProviderImpl(packageFragments) val provider = PackageFragmentProviderImpl(packageFragments)
val notFoundClasses = NotFoundClasses(storageManager, module)
val localClassResolver = LocalClassResolverImpl() val localClassResolver = LocalClassResolverImpl()
val components = DeserializationComponents( val components = DeserializationComponents(
storageManager, storageManager,
module, module,
DeserializedClassDataFinder(provider), DeserializedClassDataFinder(provider),
AnnotationAndConstantLoaderImpl(module, BuiltInSerializerProtocol), AnnotationAndConstantLoaderImpl(module, notFoundClasses, BuiltInSerializerProtocol),
provider, provider,
localClassResolver, localClassResolver,
ErrorReporter.DO_NOTHING, ErrorReporter.DO_NOTHING,
LookupTracker.DO_NOTHING, LookupTracker.DO_NOTHING,
FlexibleTypeCapabilitiesDeserializer.ThrowException, FlexibleTypeCapabilitiesDeserializer.ThrowException,
classDescriptorFactory, classDescriptorFactory,
notFoundClasses,
additionalSupertypes = additionalSupertypes additionalSupertypes = additionalSupertypes
) )
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.KClassValue import org.jetbrains.kotlin.resolve.constants.KClassValue
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.ErrorUtils.UninferredParameterTypeConstructor import org.jetbrains.kotlin.types.ErrorUtils.UninferredParameterTypeConstructor
import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE
@@ -374,7 +375,7 @@ internal class DescriptorRendererImpl(
append(renderType(annotationType)) append(renderType(annotationType))
if (verbose) { if (verbose) {
renderAndSortAnnotationArguments(annotation).joinTo(this, ", ", "(", ")") renderAndSortAnnotationArguments(annotation).joinTo(this, ", ", "(", ")")
if (annotationType.isError) { if (annotationType.isError || annotationType.constructor.declarationDescriptor is NotFoundClasses.MockClassDescriptor) {
append(" /* annotation class not found */") append(" /* annotation class not found */")
} }
} }
@@ -27,9 +27,10 @@ import org.jetbrains.kotlin.types.KotlinType
class AnnotationAndConstantLoaderImpl( class AnnotationAndConstantLoaderImpl(
module: ModuleDescriptor, module: ModuleDescriptor,
private val notFoundClasses: NotFoundClasses,
private val protocol: SerializerExtensionProtocol private val protocol: SerializerExtensionProtocol
) : AnnotationAndConstantLoader<AnnotationDescriptor, ConstantValue<*>, AnnotationWithTarget> { ) : AnnotationAndConstantLoader<AnnotationDescriptor, ConstantValue<*>, AnnotationWithTarget> {
private val deserializer = AnnotationDeserializer(module) private val deserializer = AnnotationDeserializer(module, notFoundClasses)
override fun loadClassAnnotations( override fun loadClassAnnotations(
classProto: ProtoBuf.Class, classProto: ProtoBuf.Class,
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf 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 private val builtIns: KotlinBuiltIns
get() = module.builtIns get() = module.builtIns
@@ -164,7 +164,6 @@ class AnnotationDeserializer(private val module: ModuleDescriptor) {
} }
private fun resolveClass(classId: ClassId): ClassDescriptor { private fun resolveClass(classId: ClassId): ClassDescriptor {
return module.findClassAcrossModuleDependencies(classId) return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses)
?: ErrorUtils.createErrorClass(classId.asSingleFqName().asString())
} }
} }
@@ -37,11 +37,11 @@ class DeserializationComponents(
val lookupTracker: LookupTracker, val lookupTracker: LookupTracker,
val flexibleTypeCapabilitiesDeserializer: FlexibleTypeCapabilitiesDeserializer, val flexibleTypeCapabilitiesDeserializer: FlexibleTypeCapabilitiesDeserializer,
val fictitiousClassDescriptorFactory: ClassDescriptorFactory, val fictitiousClassDescriptorFactory: ClassDescriptorFactory,
val notFoundClasses: NotFoundClasses,
val typeCapabilitiesLoader: TypeCapabilitiesLoader = TypeCapabilitiesLoader.NONE, val typeCapabilitiesLoader: TypeCapabilitiesLoader = TypeCapabilitiesLoader.NONE,
val additionalSupertypes: AdditionalSupertypes = AdditionalSupertypes.None val additionalSupertypes: AdditionalSupertypes = AdditionalSupertypes.None
) { ) {
val classDeserializer: ClassDeserializer = ClassDeserializer(this) val classDeserializer: ClassDeserializer = ClassDeserializer(this)
val notFoundClasses: NotFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
fun deserializeClass(classId: ClassId): ClassDescriptor? = classDeserializer.deserializeClass(classId) fun deserializeClass(classId: ClassId): ClassDescriptor? = classDeserializer.deserializeClass(classId)
@@ -31,3 +31,15 @@ fun ModuleDescriptor.findClassAcrossModuleDependencies(classId: ClassId): ClassD
} }
return result 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
}
@@ -39,12 +39,19 @@ class KotlinBuiltInDeserializerForDecompiler(
) : DeserializerForDecompilerBase(packageDirectory, packageFqName) { ) : DeserializerForDecompilerBase(packageDirectory, packageFqName) {
override val targetPlatform: TargetPlatform get() = TargetPlatform.Default override val targetPlatform: TargetPlatform get() = TargetPlatform.Default
override val deserializationComponents = DeserializationComponents( override val deserializationComponents: DeserializationComponents
storageManager, moduleDescriptor, BuiltInsClassDataFinder(proto, nameResolver),
AnnotationAndConstantLoaderImpl(moduleDescriptor, BuiltInSerializerProtocol), packageFragmentProvider, init {
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG), val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.ThrowException, ClassDescriptorFactory.EMPTY
) 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<DeclarationDescriptor> { override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
assert(facadeFqName == directoryPackageFqName) { assert(facadeFqName == directoryPackageFqName) {
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.serialization.ClassDataWithSource
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents 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.deserialization.descriptors.DeserializedPackageMemberScope
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
@@ -52,18 +53,21 @@ class DeserializerForClassfileDecompiler(
private val classFinder = DirectoryBasedClassFinder(packageDirectory, directoryPackageFqName) 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 = deserializationComponents = DeserializationComponents(
BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, storageManager, classFinder, errorReporter) storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider,
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), errorReporter,
override val deserializationComponents: DeserializationComponents = DeserializationComponents( LookupTracker.DO_NOTHING, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, notFoundClasses
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, )
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), errorReporter, }
LookupTracker.DO_NOTHING, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY
)
override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> { override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
val packageFqName = facadeFqName.parent() val packageFqName = facadeFqName.parent()
@@ -52,13 +52,19 @@ class KotlinJavaScriptDeserializerForDecompiler(
packageDirectory.findChild(path.substringAfterLast("/"))?.inputStream packageDirectory.findChild(path.substringAfterLast("/"))?.inputStream
} }
private val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(moduleDescriptor, JsSerializerProtocol) override val deserializationComponents: DeserializationComponents
override val deserializationComponents = DeserializationComponents( init {
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG), val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, JsSerializerProtocol)
LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.Dynamic, ClassDescriptorFactory.EMPTY
) 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<DeclarationDescriptor> { override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
val packageFqName = facadeFqName.parent() val packageFqName = facadeFqName.parent()
@@ -36,19 +36,21 @@ fun createKotlinJavascriptPackageFragmentProvider(
} }
val provider = PackageFragmentProviderImpl(packageFragments) val provider = PackageFragmentProviderImpl(packageFragments)
val notFoundClasses = NotFoundClasses(storageManager, module)
val localClassResolver = LocalClassResolverImpl() val localClassResolver = LocalClassResolverImpl()
val components = DeserializationComponents( val components = DeserializationComponents(
storageManager, storageManager,
module, module,
DeserializedClassDataFinder(provider), DeserializedClassDataFinder(provider),
AnnotationAndConstantLoaderImpl(module, JsSerializerProtocol), AnnotationAndConstantLoaderImpl(module, notFoundClasses, JsSerializerProtocol),
provider, provider,
localClassResolver, localClassResolver,
ErrorReporter.DO_NOTHING, ErrorReporter.DO_NOTHING,
LookupTracker.DO_NOTHING, LookupTracker.DO_NOTHING,
FlexibleTypeCapabilitiesDeserializer.Dynamic, FlexibleTypeCapabilitiesDeserializer.Dynamic,
ClassDescriptorFactory.EMPTY ClassDescriptorFactory.EMPTY,
notFoundClasses
) )
localClassResolver.setDeserializationComponents(components) localClassResolver.setDeserializationComponents(components)