Changes required for serialization plugin to work:

* Support for generation of synthetic nested classes (for implementations
of user-defined serial annotations):

    1. Compiler extenstion points for contributing names and descriptoprs
of nested classes

    2. Control on synthetic class primary constructor visibility

* Public functions for generating initializing expressions for optional
properties
This commit is contained in:
Leonid Startsev
2017-07-21 15:27:20 +03:00
committed by Roman Elizarov
parent 9e6b706a03
commit 527ccaff16
6 changed files with 60 additions and 18 deletions
@@ -27,8 +27,11 @@ import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptorKt;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -101,6 +104,16 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) companionObjectDescriptor);
}
// Generate synthetic nested classes
Collection<DeclarationDescriptor> classifiers = descriptor
.getUnsubstitutedMemberScope()
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.Companion.getALL_NAME_FILTER());
for (DeclarationDescriptor memberDescriptor : classifiers) {
if (memberDescriptor instanceof SyntheticClassOrObjectDescriptor) {
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) memberDescriptor);
}
}
if (generateNonClassMembers) {
generateBridges();
}
@@ -182,7 +195,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
}
@NotNull
protected List<KtParameter> getPrimaryConstructorParameters() {
public List<KtParameter> getPrimaryConstructorParameters() {
if (myClass instanceof KtClass) {
return myClass.getPrimaryConstructorParameters();
}
@@ -516,7 +516,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
public void beforeMethodBody(@NotNull MethodVisitor mv) {
}
private void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull KtProperty property) {
// Requires public access, because it is used by serialization plugin to generate initializer in synthetic constructor
public void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull KtProperty property) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
assert propertyDescriptor != null;
@@ -541,7 +542,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
propValue.store(delegateValue, codegen.v);
}
protected boolean shouldInitializeProperty(@NotNull KtProperty property) {
// Public accessible for serialization plugin to check whether call to initializeProperty(..) is legal.
public boolean shouldInitializeProperty(@NotNull KtProperty property) {
if (!property.hasDelegateExpressionOrInitializer()) return false;
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
@@ -53,6 +53,7 @@ class SyntheticClassOrObjectDescriptor(
outerScope: LexicalScope,
private val modality: Modality,
private val visibility: Visibility,
constructorVisibility: Visibility,
private val kind: ClassKind,
private val isCompanionObject: Boolean
) : ClassDescriptorBase(c.storageManager, containingDeclaration, name, source, false), ClassDescriptorWithResolutionScopes {
@@ -63,7 +64,7 @@ class SyntheticClassOrObjectDescriptor(
private val resolutionScopesSupport = ClassResolutionScopesSupport(thisDescriptor, c.storageManager, { outerScope })
private val syntheticSupertypes = mutableListOf<KotlinType>().apply { c.syntheticResolveExtension.addSyntheticSupertypes(thisDescriptor, this) }
private val unsubstitutedMemberScope = LazyClassMemberScope(c, SyntheticClassMemberDeclarationProvider(syntheticDeclaration), this, c.trace)
private val unsubstitutedPrimaryConstructor = createUnsubstitutedPrimaryConstructor()
private val unsubstitutedPrimaryConstructor = createUnsubstitutedPrimaryConstructor(constructorVisibility)
override val annotations: Annotations get() = Annotations.EMPTY
@@ -104,8 +105,9 @@ class SyntheticClassOrObjectDescriptor(
override fun toString(): String = "synthetic class " + name.toString() + " in " + containingDeclaration
private fun createUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor {
private fun createUnsubstitutedPrimaryConstructor(constructorVisibility: Visibility): ClassConstructorDescriptor {
val constructor = DescriptorFactory.createPrimaryConstructorForObject(thisDescriptor, source)
constructor.visibility = constructorVisibility
constructor.returnType = getDefaultType()
return constructor
}
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import java.util.*
@@ -37,38 +39,56 @@ interface SyntheticResolveExtension {
if (instances.size == 1) return instances.single()
// return list combiner here
return object : SyntheticResolveExtension {
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> =
instances.flatMap { it.getSyntheticNestedClassNames(thisDescriptor) }
override fun generateSyntheticClasses(thisDescriptor: ClassDescriptor, name: Name,
ctx: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider,
result: MutableSet<ClassDescriptor>) =
instances.forEach { it.generateSyntheticClasses(thisDescriptor, name, ctx, declarationProvider, result) }
override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? =
instances.firstNotNullResult { it.getSyntheticCompanionObjectNameIfNeeded(thisDescriptor) }
instances.firstNotNullResult { it.getSyntheticCompanionObjectNameIfNeeded(thisDescriptor) }
override fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) =
instances.forEach { it.addSyntheticSupertypes(thisDescriptor, supertypes) }
instances.forEach { it.addSyntheticSupertypes(thisDescriptor, supertypes) }
// todo revert
override fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, name: Name,
fromSupertypes: List<SimpleFunctionDescriptor>,
result: MutableCollection<SimpleFunctionDescriptor>) =
instances.forEach { it.generateSyntheticMethods(thisDescriptor, name, fromSupertypes, result) }
instances.forEach { it.generateSyntheticMethods(thisDescriptor, name, fromSupertypes, result) }
override fun generateSyntheticProperties(thisDescriptor: ClassDescriptor, name: Name,
fromSupertypes: ArrayList<PropertyDescriptor>,
result: MutableSet<PropertyDescriptor>) =
instances.forEach { it.generateSyntheticProperties(thisDescriptor, name, fromSupertypes, result) }
result: MutableSet<PropertyDescriptor>) =
instances.forEach { it.generateSyntheticProperties(thisDescriptor, name, fromSupertypes, result) }
}
}
}
fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name?
fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? = null
fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> = emptyList()
fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {}
fun generateSyntheticClasses(thisDescriptor: ClassDescriptor,
name: Name,
ctx: LazyClassContext,
declarationProvider: ClassMemberDeclarationProvider,
result: MutableSet<ClassDescriptor>) {
}
fun generateSyntheticMethods(thisDescriptor: ClassDescriptor,
name: Name,
fromSupertypes: List<SimpleFunctionDescriptor>,
result: MutableCollection<SimpleFunctionDescriptor>) {}
result: MutableCollection<SimpleFunctionDescriptor>) {
}
fun generateSyntheticProperties(thisDescriptor: ClassDescriptor,
name: Name,
fromSupertypes:
ArrayList<PropertyDescriptor>,
result: MutableSet<PropertyDescriptor>) {}
fromSupertypes: ArrayList<PropertyDescriptor>,
result: MutableSet<PropertyDescriptor>) {
}
}
@@ -60,6 +60,7 @@ import java.util.Collections;
import java.util.List;
import static kotlin.collections.CollectionsKt.firstOrNull;
import static org.jetbrains.kotlin.descriptors.Visibilities.PRIVATE;
import static org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.resolve.BindingContext.TYPE;
@@ -424,7 +425,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
/* parentClassOrObject= */ classOrObject,
this, syntheticCompanionName, getSource(),
/* outerScope= */ getOuterScope(),
Modality.FINAL, PUBLIC, ClassKind.OBJECT, true);
Modality.FINAL, PUBLIC, PRIVATE, ClassKind.OBJECT, true);
}
@Nullable
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.incremental.record
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
@@ -42,7 +41,6 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.NotNullLazyValue
import org.jetbrains.kotlin.storage.NullableLazyValue
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
@@ -83,6 +81,7 @@ open class LazyClassMemberScope(
addDataClassMethods(result, location)
addSyntheticCompanionObject(result, location)
addSyntheticNestedClasses(result, location)
result.trimToSize()
return result
@@ -131,6 +130,7 @@ open class LazyClassMemberScope(
override fun getNonDeclaredClasses(name: Name, result: MutableSet<ClassDescriptor>) {
generateSyntheticCompanionObject(name, result)
c.syntheticResolveExtension.generateSyntheticClasses(thisDescriptor, name, c, declarationProvider, result)
}
override fun getNonDeclaredFunctions(name: Name, result: MutableSet<SimpleFunctionDescriptor>) {
@@ -220,6 +220,10 @@ open class LazyClassMemberScope(
result.add(descriptor)
}
private fun addSyntheticNestedClasses(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {
result.addAll(c.syntheticResolveExtension.getSyntheticNestedClassNames(thisDescriptor).mapNotNull { getContributedClassifier(it, location) }.toList())
}
private fun generateSyntheticCompanionObject(name: Name, result: MutableSet<ClassDescriptor>) {
val syntheticCompanionName = c.syntheticResolveExtension.getSyntheticCompanionObjectNameIfNeeded(thisDescriptor) ?: return
if (name == syntheticCompanionName && result.none { it.isCompanionObject }) {