Load annotations of const properties from multifile classes
Rework backing field generation logic in PropertyCodegen to switch the
ClassBuilder instance for a multifile part to that of the corresponding facade
class. This became needed because multifile parts, and their metadata, are
generated _before_ the multifile facade class and otherwise we would never
record that there's a synthetic '$annotations' method for a const val and would
not write that to the protobuf message for the property.
See also bad83200
#KT-10892 Fixed
This commit is contained in:
@@ -73,7 +73,7 @@ class MultifileClassCodegen(
|
||||
private fun getDeserializedCallables(compiledPackageFragment: PackageFragmentDescriptor) =
|
||||
compiledPackageFragment.getMemberScope().getContributedDescriptors(DescriptorKindFilter.CALLABLES, MemberScope.ALL_NAME_FILTER).filterIsInstance<DeserializedCallableMemberDescriptor>()
|
||||
|
||||
private val classBuilder = ClassBuilderOnDemand {
|
||||
val classBuilder = ClassBuilderOnDemand {
|
||||
val originFile = files.firstOrNull()
|
||||
val actualPackageFragment = packageFragment ?:
|
||||
compiledPackageFragment ?:
|
||||
@@ -163,7 +163,7 @@ class MultifileClassCodegen(
|
||||
var generatePart = false
|
||||
val partClassInfo = state.fileClassesProvider.getFileClassInfo(file)
|
||||
val partType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(partClassInfo.fileClassFqName)
|
||||
val partContext = state.rootContext.intoMultifileClassPart(packageFragment, facadeClassType, partType, file)
|
||||
val partContext = state.rootContext.intoMultifileClassPart(this, packageFragment, facadeClassType, partType, file)
|
||||
|
||||
for (declaration in file.declarations) {
|
||||
when (declaration) {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -69,9 +68,6 @@ import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJ
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class PropertyCodegen {
|
||||
|
||||
private static Logger LOG = Logger.getInstance(PropertyCodegen.class);
|
||||
|
||||
private final GenerationState state;
|
||||
private final ClassBuilder v;
|
||||
private final FunctionCodegen functionCodegen;
|
||||
@@ -123,7 +119,7 @@ public class PropertyCodegen {
|
||||
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DEFAULT_IMPLS
|
||||
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
|
||||
|
||||
if (isBackingFieldOwner(descriptor)) {
|
||||
if (CodegenContextUtil.isImplClassOwner(context)) {
|
||||
assert declaration != null : "Declaration is null for different context: " + context;
|
||||
|
||||
genBackingFieldAndAnnotations(declaration, descriptor, false);
|
||||
@@ -137,14 +133,10 @@ public class PropertyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBackingFieldOwner(@NotNull PropertyDescriptor descriptor) {
|
||||
if (descriptor.isConst()) {
|
||||
return !(context instanceof MultifileClassPartContext);
|
||||
}
|
||||
return CodegenContextUtil.isImplClassOwner(context);
|
||||
}
|
||||
|
||||
private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) {
|
||||
ClassBuilder builder = getCorrectClassBuilder(descriptor);
|
||||
if (builder == null) return;
|
||||
|
||||
boolean hasBackingField = hasBackingField(declaration, descriptor);
|
||||
boolean hasDelegate = declaration instanceof KtProperty && ((KtProperty) declaration).hasDelegate();
|
||||
|
||||
@@ -157,8 +149,17 @@ public class PropertyCodegen {
|
||||
Annotations delegateAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD);
|
||||
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
|
||||
|
||||
generateBackingField(declaration, descriptor, fieldAnnotations, delegateAnnotations);
|
||||
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
|
||||
generateBackingField(builder, declaration, descriptor, fieldAnnotations, delegateAnnotations);
|
||||
generateSyntheticMethodIfNeeded(builder, descriptor, propertyAnnotations);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassBuilder getCorrectClassBuilder(@NotNull PropertyDescriptor descriptor) {
|
||||
if (descriptor.isConst() && context instanceof MultifileClassPartContext) {
|
||||
return ((MultifileClassPartContext) context).getMultifileClassCodegen().getClassBuilder();
|
||||
}
|
||||
|
||||
return this.v;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,6 +245,7 @@ public class PropertyCodegen {
|
||||
}
|
||||
|
||||
private boolean generateBackingField(
|
||||
@NotNull ClassBuilder builder,
|
||||
@NotNull KtNamedDeclaration p,
|
||||
@NotNull PropertyDescriptor descriptor,
|
||||
@NotNull Annotations backingFieldAnnotations,
|
||||
@@ -254,10 +256,10 @@ public class PropertyCodegen {
|
||||
}
|
||||
|
||||
if (p instanceof KtProperty && ((KtProperty) p).hasDelegate()) {
|
||||
generatePropertyDelegateAccess((KtProperty) p, descriptor, delegateAnnotations);
|
||||
generatePropertyDelegateAccess(builder, (KtProperty) p, descriptor, delegateAnnotations);
|
||||
}
|
||||
else if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
|
||||
generateBackingFieldAccess(p, descriptor, backingFieldAnnotations);
|
||||
generateBackingFieldAccess(builder, p, descriptor, backingFieldAnnotations);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
@@ -267,16 +269,19 @@ public class PropertyCodegen {
|
||||
|
||||
// Annotations on properties are stored in bytecode on an empty synthetic method. This way they're still
|
||||
// accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally
|
||||
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, Annotations annotations) {
|
||||
private void generateSyntheticMethodIfNeeded(
|
||||
@NotNull ClassBuilder builder,
|
||||
@NotNull PropertyDescriptor descriptor,
|
||||
@NotNull Annotations annotations
|
||||
) {
|
||||
if (annotations.getAllAnnotations().isEmpty()) return;
|
||||
|
||||
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
|
||||
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
|
||||
String desc = receiver == null ? "()V" : "(" + typeMapper.mapType(receiver.getType()) + ")V";
|
||||
Method syntheticMethod = getSyntheticMethodSignature(descriptor);
|
||||
|
||||
if (!isInterface(context.getContextDescriptor()) || kind == OwnerKind.DEFAULT_IMPLS) {
|
||||
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
|
||||
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), flags, name, desc, null, null);
|
||||
MethodVisitor mv = builder.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), flags, syntheticMethod.getName(),
|
||||
syntheticMethod.getDescriptor(), null, null);
|
||||
AnnotationCodegen.forMethod(mv, typeMapper)
|
||||
.genAnnotations(new AnnotatedSimple(annotations), Type.VOID_TYPE, AnnotationUseSiteTarget.PROPERTY);
|
||||
mv.visitCode();
|
||||
@@ -285,15 +290,24 @@ public class PropertyCodegen {
|
||||
}
|
||||
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS) {
|
||||
v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, new Method(name, desc));
|
||||
v.getSerializationBindings().put(SYNTHETIC_METHOD_FOR_PROPERTY, descriptor, syntheticMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Method getSyntheticMethodSignature(@NotNull PropertyDescriptor descriptor) {
|
||||
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
|
||||
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
|
||||
String desc = receiver == null ? "()V" : "(" + typeMapper.mapType(receiver.getType()) + ")V";
|
||||
return new Method(name, desc);
|
||||
}
|
||||
|
||||
private void generateBackingField(
|
||||
ClassBuilder builder,
|
||||
KtNamedDeclaration element,
|
||||
PropertyDescriptor propertyDescriptor,
|
||||
boolean isDelegate,
|
||||
KotlinType jetType,
|
||||
KotlinType kotlinType,
|
||||
Object defaultValue,
|
||||
Annotations annotations
|
||||
) {
|
||||
@@ -317,9 +331,7 @@ public class PropertyCodegen {
|
||||
modifiers |= ACC_SYNTHETIC;
|
||||
}
|
||||
|
||||
Type type = typeMapper.mapType(jetType);
|
||||
|
||||
ClassBuilder builder = v;
|
||||
Type type = typeMapper.mapType(kotlinType);
|
||||
|
||||
FieldOwnerContext backingFieldContext = context;
|
||||
if (AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor) ) {
|
||||
@@ -342,15 +354,22 @@ public class PropertyCodegen {
|
||||
|
||||
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name));
|
||||
|
||||
FieldVisitor fv = builder.newField(JvmDeclarationOriginKt.OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||
typeMapper.mapFieldSignature(jetType, propertyDescriptor), defaultValue);
|
||||
FieldVisitor fv = builder.newField(
|
||||
JvmDeclarationOriginKt.OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||
typeMapper.mapFieldSignature(kotlinType, propertyDescriptor), defaultValue
|
||||
);
|
||||
|
||||
Annotated fieldAnnotated = new AnnotatedWithFakeAnnotations(propertyDescriptor, annotations);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(
|
||||
fieldAnnotated, type, isDelegate ? AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD : AnnotationUseSiteTarget.FIELD);
|
||||
}
|
||||
|
||||
private void generatePropertyDelegateAccess(KtProperty p, PropertyDescriptor propertyDescriptor, Annotations annotations) {
|
||||
private void generatePropertyDelegateAccess(
|
||||
@NotNull ClassBuilder builder,
|
||||
@NotNull KtProperty p,
|
||||
@NotNull PropertyDescriptor propertyDescriptor,
|
||||
@NotNull Annotations annotations
|
||||
) {
|
||||
KtExpression delegateExpression = p.getDelegateExpression();
|
||||
KotlinType delegateType = delegateExpression != null ? bindingContext.getType(p.getDelegateExpression()) : null;
|
||||
if (delegateType == null) {
|
||||
@@ -358,10 +377,15 @@ public class PropertyCodegen {
|
||||
delegateType = ErrorUtils.createErrorType("Delegate type");
|
||||
}
|
||||
|
||||
generateBackingField(p, propertyDescriptor, true, delegateType, null, annotations);
|
||||
generateBackingField(builder, p, propertyDescriptor, true, delegateType, null, annotations);
|
||||
}
|
||||
|
||||
private void generateBackingFieldAccess(KtNamedDeclaration p, PropertyDescriptor propertyDescriptor, Annotations annotations) {
|
||||
private void generateBackingFieldAccess(
|
||||
@NotNull ClassBuilder builder,
|
||||
@NotNull KtNamedDeclaration p,
|
||||
@NotNull PropertyDescriptor propertyDescriptor,
|
||||
@NotNull Annotations annotations
|
||||
) {
|
||||
Object value = null;
|
||||
|
||||
if (shouldWriteFieldInitializer(propertyDescriptor)) {
|
||||
@@ -371,7 +395,7 @@ public class PropertyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value, annotations);
|
||||
generateBackingField(builder, p, propertyDescriptor, false, propertyDescriptor.getType(), value, annotations);
|
||||
}
|
||||
|
||||
private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) {
|
||||
|
||||
@@ -251,12 +251,13 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
|
||||
@NotNull
|
||||
public FieldOwnerContext<PackageFragmentDescriptor> intoMultifileClassPart(
|
||||
@NotNull MultifileClassCodegen codegen,
|
||||
@NotNull PackageFragmentDescriptor descriptor,
|
||||
@NotNull Type multifileClassType,
|
||||
@NotNull Type filePartType,
|
||||
@NotNull KtFile sourceFile
|
||||
) {
|
||||
return new MultifileClassPartContext(descriptor, this, multifileClassType, filePartType, sourceFile);
|
||||
return new MultifileClassPartContext(codegen, descriptor, this, multifileClassType, filePartType, sourceFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+9
@@ -18,14 +18,17 @@ package org.jetbrains.kotlin.codegen.context;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.MultifileClassCodegen;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class MultifileClassPartContext extends MultifileClassContextBase implements DelegatingToPartContext, FacadePartWithSourceFile {
|
||||
private final KtFile sourceFile;
|
||||
private final MultifileClassCodegen codegen;
|
||||
|
||||
public MultifileClassPartContext(
|
||||
@NotNull MultifileClassCodegen codegen,
|
||||
PackageFragmentDescriptor descriptor,
|
||||
CodegenContext parent,
|
||||
Type multifileClassType,
|
||||
@@ -34,6 +37,7 @@ public class MultifileClassPartContext extends MultifileClassContextBase impleme
|
||||
) {
|
||||
super(descriptor, parent, multifileClassType, filePartType);
|
||||
this.sourceFile = sourceFile;
|
||||
this.codegen = codegen;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -47,4 +51,9 @@ public class MultifileClassPartContext extends MultifileClassContextBase impleme
|
||||
public KtFile getSourceFile() {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MultifileClassCodegen getMultifileClassCodegen() {
|
||||
return codegen;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -115,7 +115,7 @@ class IncrementalPackageFragmentProvider(
|
||||
|
||||
val scopes = actualPackagePartFiles.mapNotNull { internalName ->
|
||||
incrementalCache.getPackagePartData(internalName)?.let { internalName to it }
|
||||
}.map { createPackageScope(it.first, it.second) }
|
||||
}.map { createPackageScope(it.first, it.second, null) }
|
||||
|
||||
if (scopes.isEmpty()) {
|
||||
MemberScope.Empty
|
||||
@@ -147,7 +147,7 @@ class IncrementalPackageFragmentProvider(
|
||||
else {
|
||||
ChainedMemberScope(
|
||||
"Member scope for incremental compilation: union of multifile class parts data for $multifileClassFqName",
|
||||
partsData.map { createPackageScope(it.first, it.second) }
|
||||
partsData.map { createPackageScope(it.first, it.second, multifileClassFqName.asString()) }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -155,11 +155,14 @@ class IncrementalPackageFragmentProvider(
|
||||
override fun getMemberScope(): MemberScope = memberScope()
|
||||
}
|
||||
|
||||
fun createPackageScope(internalName: String, part: JvmPackagePartProto): DeserializedPackageMemberScope {
|
||||
fun createPackageScope(internalName: String, part: JvmPackagePartProto, facadeFqName: String?): DeserializedPackageMemberScope {
|
||||
val packageData = JvmProtoBufUtil.readPackageDataFrom(part.data, part.strings)
|
||||
return DeserializedPackageMemberScope(
|
||||
this, packageData.packageProto, packageData.nameResolver,
|
||||
JvmPackagePartSource(JvmClassName.byInternalName(internalName)),
|
||||
JvmPackagePartSource(
|
||||
JvmClassName.byInternalName(internalName),
|
||||
facadeFqName?.let(JvmClassName::byFqNameWithoutInnerClasses)
|
||||
),
|
||||
deserializationComponents, { listOf() }
|
||||
)
|
||||
}
|
||||
|
||||
+5
-7
@@ -1,4 +1,4 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_REFLECT
|
||||
// FILE: 1.kt
|
||||
|
||||
import a.OK
|
||||
@@ -6,12 +6,10 @@ import a.OK
|
||||
fun box(): String {
|
||||
val okRef = ::OK
|
||||
|
||||
// TODO: see KT-10892
|
||||
// val annotations = okRef.annotations
|
||||
// val numAnnotations = annotations.size
|
||||
// if (numAnnotations != 1) {
|
||||
// return "Failed, annotations: $annotations"
|
||||
// }
|
||||
val annotations = okRef.annotations
|
||||
if (annotations.size != 1) {
|
||||
return "Failed, annotations: $annotations"
|
||||
}
|
||||
|
||||
return okRef.get()
|
||||
}
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("Test")
|
||||
package test
|
||||
|
||||
annotation class Anno(val value: String)
|
||||
|
||||
@Anno(constant)
|
||||
const val constant = "OK"
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
@test.Anno(value = "OK") public const val constant: kotlin.String = "OK"
|
||||
public fun <get-constant>(): kotlin.String
|
||||
|
||||
public final annotation class Anno : kotlin.Annotation {
|
||||
/*primary*/ public constructor Anno(/*0*/ value: kotlin.String)
|
||||
public final val value: kotlin.String
|
||||
public final fun <get-value>(): kotlin.String
|
||||
}
|
||||
@@ -4880,6 +4880,21 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlinWithStdlib"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Annotations extends AbstractLoadJavaTest {
|
||||
public void testAllFilesPresentInAnnotations() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("ConstValInMultifileClass.kt")
|
||||
public void testConstValInMultifileClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/ConstValInMultifileClass.kt");
|
||||
doTestCompiledKotlinWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/compiledKotlinWithStdlib/mutability")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+24
-9
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.Flags
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||
import org.jetbrains.kotlin.serialization.jvm.ClassMapperLite
|
||||
@@ -96,12 +97,14 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any,
|
||||
val syntheticFunctionSignature = getPropertySignature(proto, container.nameResolver, container.typeTable, synthetic = true)
|
||||
val fieldSignature = getPropertySignature(proto, container.nameResolver, container.typeTable, field = true)
|
||||
|
||||
val isConst = Flags.IS_CONST.get(proto.flags)
|
||||
|
||||
val propertyAnnotations = syntheticFunctionSignature?.let { sig ->
|
||||
findClassAndLoadMemberAnnotations(container, sig, property = true)
|
||||
findClassAndLoadMemberAnnotations(container, sig, property = true, isConst = isConst)
|
||||
}.orEmpty()
|
||||
|
||||
val fieldAnnotations = fieldSignature?.let { sig ->
|
||||
findClassAndLoadMemberAnnotations(container, sig, property = true, field = true)
|
||||
findClassAndLoadMemberAnnotations(container, sig, property = true, field = true, isConst = isConst)
|
||||
}.orEmpty()
|
||||
|
||||
// TODO: check delegate presence in some other way
|
||||
@@ -132,9 +135,10 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any,
|
||||
protected abstract fun transformAnnotations(annotations: List<A>): List<T>
|
||||
|
||||
private fun findClassAndLoadMemberAnnotations(
|
||||
container: ProtoContainer, signature: MemberSignature, property: Boolean = false, field: Boolean = false
|
||||
container: ProtoContainer, signature: MemberSignature,
|
||||
property: Boolean = false, field: Boolean = false, isConst: Boolean? = null
|
||||
): List<A> {
|
||||
val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(container, property), field)
|
||||
val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(container, property, isConst), field)
|
||||
?: return listOf()
|
||||
|
||||
return storage(kotlinClass).memberAnnotations[signature] ?: listOf()
|
||||
@@ -196,8 +200,8 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any,
|
||||
val signature = getCallableSignature(proto, container.nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY)
|
||||
?: return null
|
||||
|
||||
val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(container, property = true), field = true)
|
||||
?: return null
|
||||
val implClassName = getImplClassName(container, property = true, isConst = Flags.IS_CONST.get(proto.flags))
|
||||
val kotlinClass = findClassWithAnnotationsAndInitializers(container, implClassName, field = true) ?: return null
|
||||
|
||||
return storage(kotlinClass).propertyConstants[signature]
|
||||
}
|
||||
@@ -222,9 +226,20 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any,
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getImplClassName(container: ProtoContainer, property: Boolean): ClassId? {
|
||||
if (property && container is ProtoContainer.Class && container.kind == ProtoBuf.Class.Kind.INTERFACE) {
|
||||
return container.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
|
||||
private fun getImplClassName(container: ProtoContainer, property: Boolean, isConst: Boolean?): ClassId? {
|
||||
if (property) {
|
||||
checkNotNull(isConst) { "isConst should not be null for property (container=$container)" }
|
||||
if (container is ProtoContainer.Class && container.kind == ProtoBuf.Class.Kind.INTERFACE) {
|
||||
return container.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
|
||||
}
|
||||
if (isConst!! && container is ProtoContainer.Package) {
|
||||
// Const properties in multifile classes are generated into the facade class
|
||||
val facadeClassName = (container.packagePartSource as? JvmPackagePartSource)?.facadeClassName
|
||||
if (facadeClassName != null) {
|
||||
// Converting '/' to '.' is fine here because the facade class has a top level ClassId
|
||||
return ClassId.topLevel(FqName(facadeClassName.internalName.replace('/', '.')))
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((container as? ProtoContainer.Package)?.packagePartSource as? JvmPackagePartSource)?.classId
|
||||
}
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ class DeserializedDescriptorResolver(private val errorReporter: ErrorReporter) {
|
||||
val (nameResolver, packageProto) = parseProto(kotlinClass) {
|
||||
JvmProtoBufUtil.readPackageDataFrom(data, strings)
|
||||
}
|
||||
val source = JvmPackagePartSource(kotlinClass.classId)
|
||||
val source = JvmPackagePartSource(kotlinClass)
|
||||
return DeserializedPackageMemberScope(descriptor, packageProto, nameResolver, source, components) {
|
||||
// All classes are included into Java scope
|
||||
emptyList()
|
||||
|
||||
+7
-2
@@ -21,8 +21,13 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.PackagePartSource
|
||||
|
||||
class JvmPackagePartSource(val className: JvmClassName) : PackagePartSource {
|
||||
constructor(classId: ClassId) : this(JvmClassName.byClassId(classId))
|
||||
class JvmPackagePartSource(val className: JvmClassName, val facadeClassName: JvmClassName?) : PackagePartSource {
|
||||
constructor(kotlinClass: KotlinJvmBinaryClass) : this(
|
||||
JvmClassName.byClassId(kotlinClass.classId),
|
||||
kotlinClass.classHeader.multifileClassName?.let {
|
||||
if (it.isNotEmpty()) JvmClassName.byInternalName(it) else null
|
||||
}
|
||||
)
|
||||
|
||||
val simpleName: Name get() = Name.identifier(className.internalName.substringAfterLast('/'))
|
||||
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ class DeserializerForClassfileDecompiler(
|
||||
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings)
|
||||
val membersScope = DeserializedPackageMemberScope(
|
||||
createDummyPackageFragment(packageFqName), packageProto, nameResolver,
|
||||
JvmPackagePartSource(binaryClassForPackageClass!!.classId), deserializationComponents
|
||||
JvmPackagePartSource(binaryClassForPackageClass!!), deserializationComponents
|
||||
) { emptyList() }
|
||||
return membersScope.getContributedDescriptors().toList()
|
||||
}
|
||||
|
||||
+3
-2
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.Flags
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
|
||||
@@ -68,7 +69,7 @@ fun createFileFacadeStub(
|
||||
val fileStub = KotlinFileStubForIde.forFileFacadeStub(facadeFqName, packageFqName.isRoot)
|
||||
setupFileStub(fileStub, packageFqName)
|
||||
val container = ProtoContainer.Package(
|
||||
packageFqName, c.nameResolver, c.typeTable, JvmPackagePartSource(ClassId.topLevel(facadeFqName))
|
||||
packageFqName, c.nameResolver, c.typeTable, JvmPackagePartSource(JvmClassName.byClassId(ClassId.topLevel(facadeFqName)), null)
|
||||
)
|
||||
createCallableStubs(fileStub, c, container, packageProto.functionList, packageProto.propertyList)
|
||||
return fileStub
|
||||
@@ -89,7 +90,7 @@ fun createMultifileClassStub(
|
||||
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(partHeader.data!!, partHeader.strings!!)
|
||||
val partContext = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
|
||||
val container = ProtoContainer.Package(packageFqName, partContext.nameResolver, partContext.typeTable,
|
||||
JvmPackagePartSource(partFile.classId))
|
||||
JvmPackagePartSource(partFile))
|
||||
createCallableStubs(fileStub, partContext, container, packageProto.functionList, packageProto.propertyList)
|
||||
}
|
||||
return fileStub
|
||||
|
||||
Reference in New Issue
Block a user