J2K backend-common classes: convert

Also merge CodegenUtilKt into CodegenUtil
This commit is contained in:
Alexander Udalov
2016-04-13 14:53:47 +03:00
parent 27ed0dd25f
commit c1c2651988
7 changed files with 234 additions and 331 deletions
@@ -14,183 +14,200 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.common;
package org.jetbrains.kotlin.backend.common
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.bridges.findTraitImplementation
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.MemberComparator
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
import java.util.*;
object CodegenUtil {
// class Foo : Bar by baz
// descriptor = Foo
// toInterface = Bar
// delegateExpressionType = typeof(baz)
// return Map<member of Foo, corresponding member of typeOf(baz)>
@JvmStatic
fun getDelegates(
descriptor: ClassDescriptor,
toInterface: ClassDescriptor,
delegateExpressionType: KotlinType? = null
): Map<CallableMemberDescriptor, CallableDescriptor> {
if (delegateExpressionType?.isDynamic() ?: false) return emptyMap()
public class CodegenUtil {
return descriptor.defaultType.memberScope.getContributedDescriptors().asSequence()
.filterIsInstance<CallableMemberDescriptor>()
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
.asIterable()
.sortedWith(MemberComparator.INSTANCE)
.keysToMapExceptNulls { delegatingMember ->
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
.mapNotNull { overriddenDescriptor ->
if (overriddenDescriptor.containingDeclaration == toInterface) {
val scope = (delegateExpressionType ?: toInterface.defaultType).memberScope
val name = overriddenDescriptor.name
private CodegenUtil() {
}
// this is the actual member of delegateExpressionType that we are delegating to
(scope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) +
scope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND))
.firstOrNull {
(listOf(it) + DescriptorUtils.getAllOverriddenDescriptors(it))
.map(CallableMemberDescriptor::getOriginal)
.contains(overriddenDescriptor.original)
}
}
else null
}
@Nullable
public static FunctionDescriptor getDeclaredFunctionByRawSignature(
@NotNull ClassDescriptor owner,
@NotNull Name name,
@NotNull ClassifierDescriptor returnedClassifier,
@NotNull ClassifierDescriptor... valueParameterClassifiers
) {
Collection<SimpleFunctionDescriptor> functions = owner.getDefaultType().getMemberScope().getContributedFunctions(name, NoLookupLocation.FROM_BACKEND);
for (FunctionDescriptor function : functions) {
if (!CallResolverUtilKt.isOrOverridesSynthesized(function)
&& function.getTypeParameters().isEmpty()
&& valueParameterClassesMatch(function.getValueParameters(), Arrays.asList(valueParameterClassifiers))
&& rawTypeMatches(function.getReturnType(), returnedClassifier)) {
return function;
}
}
return null;
}
assert(actualDelegates.size <= 1) { "Many delegates found for $delegatingMember: $actualDelegates" }
@Nullable
public static PropertyDescriptor getDelegatePropertyIfAny(KtExpression expression, ClassDescriptor classDescriptor, BindingContext bindingContext) {
PropertyDescriptor propertyDescriptor = null;
if (expression instanceof KtSimpleNameExpression) {
ResolvedCall<?> call = CallUtilKt.getResolvedCall(expression, bindingContext);
if (call != null) {
CallableDescriptor callResultingDescriptor = call.getResultingDescriptor();
if (callResultingDescriptor instanceof ValueParameterDescriptor) {
ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) callResultingDescriptor;
// constructor parameter
if (valueParameterDescriptor.getContainingDeclaration() instanceof ConstructorDescriptor) {
// constructor of my class
if (valueParameterDescriptor.getContainingDeclaration().getContainingDeclaration() == classDescriptor) {
propertyDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameterDescriptor);
}
}
actualDelegates.firstOrNull()
}
}
// todo: when and if frontend will allow properties defined not as constructor parameters to be used in delegation specifier
@JvmStatic
fun getDeclaredFunctionByRawSignature(
owner: ClassDescriptor,
name: Name,
returnedClassifier: ClassifierDescriptor,
vararg valueParameterClassifiers: ClassifierDescriptor
): FunctionDescriptor? {
return owner.defaultType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).firstOrNull { function ->
!isOrOverridesSynthesized(function) &&
function.typeParameters.isEmpty() &&
valueParameterClassesMatch(function.valueParameters, valueParameterClassifiers.toList()) &&
rawTypeMatches(function.returnType!!, returnedClassifier)
}
}
@JvmStatic
fun getDelegatePropertyIfAny(
expression: KtExpression, classDescriptor: ClassDescriptor, bindingContext: BindingContext
): PropertyDescriptor? {
val call = (expression as? KtSimpleNameExpression)?.getResolvedCall(bindingContext) ?: return null
val callResultingDescriptor = call.resultingDescriptor as? ValueParameterDescriptor ?: return null
// constructor parameter
if (callResultingDescriptor.containingDeclaration is ConstructorDescriptor) {
// constructor of my class
if (callResultingDescriptor.containingDeclaration.containingDeclaration === classDescriptor) {
return bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, callResultingDescriptor)
}
}
return propertyDescriptor;
return null
}
public static boolean isFinalPropertyWithBackingField(PropertyDescriptor propertyDescriptor, BindingContext bindingContext) {
@JvmStatic
fun isFinalPropertyWithBackingField(propertyDescriptor: PropertyDescriptor?, bindingContext: BindingContext): Boolean {
return propertyDescriptor != null &&
!propertyDescriptor.isVar() &&
Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor));
!propertyDescriptor.isVar &&
(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor) ?: false)
}
@NotNull
public static Map<FunctionDescriptor, FunctionDescriptor> getNonPrivateTraitMethods(ClassDescriptor descriptor) {
Map<FunctionDescriptor, FunctionDescriptor> result = new LinkedHashMap<FunctionDescriptor, FunctionDescriptor>();
for (DeclarationDescriptor declaration : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
if (!(declaration instanceof CallableMemberDescriptor)) continue;
@JvmStatic
fun getNonPrivateTraitMethods(descriptor: ClassDescriptor): Map<FunctionDescriptor, FunctionDescriptor> {
val result = linkedMapOf<FunctionDescriptor, FunctionDescriptor>()
for (declaration in DescriptorUtils.getAllDescriptors(descriptor.defaultType.memberScope)) {
if (declaration !is CallableMemberDescriptor) continue
CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration;
CallableMemberDescriptor traitMember = ImplKt.findTraitImplementation(inheritedMember);
if (traitMember == null || Visibilities.isPrivate(traitMember.getVisibility())) continue;
val traitMember = findTraitImplementation(declaration)
if (traitMember == null || Visibilities.isPrivate(traitMember.visibility)) continue
assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember;
assert(traitMember.modality !== Modality.ABSTRACT) { "Cannot delegate to abstract trait method: $declaration" }
// inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here
// with traitMember's modality
result.putAll(copyFunctions(inheritedMember, traitMember, inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC,
CallableMemberDescriptor.Kind.DECLARATION, true));
result.putAll(copyFunctions(declaration, traitMember, declaration.containingDeclaration, traitMember.modality,
Visibilities.PUBLIC, CallableMemberDescriptor.Kind.DECLARATION, true))
}
return result;
return result
}
@NotNull
public static Map<FunctionDescriptor, FunctionDescriptor> copyFunctions(
@NotNull CallableMemberDescriptor inheritedMember,
@NotNull CallableMemberDescriptor traitMember,
DeclarationDescriptor newOwner,
Modality modality,
Visibility visibility,
CallableMemberDescriptor.Kind kind,
boolean copyOverrides
) {
CallableMemberDescriptor copy = inheritedMember.copy(newOwner, modality, visibility, kind, copyOverrides);
Map<FunctionDescriptor, FunctionDescriptor> result = new LinkedHashMap<FunctionDescriptor, FunctionDescriptor>(0);
if (traitMember instanceof SimpleFunctionDescriptor) {
result.put((FunctionDescriptor) traitMember, (FunctionDescriptor) copy);
fun copyFunctions(
inheritedMember: CallableMemberDescriptor,
traitMember: CallableMemberDescriptor,
newOwner: DeclarationDescriptor,
modality: Modality,
visibility: Visibility,
kind: CallableMemberDescriptor.Kind,
copyOverrides: Boolean
): Map<FunctionDescriptor, FunctionDescriptor> {
val copy = inheritedMember.copy(newOwner, modality, visibility, kind, copyOverrides)
val result = linkedMapOf<FunctionDescriptor, FunctionDescriptor>()
if (traitMember is SimpleFunctionDescriptor) {
result[traitMember] = copy as FunctionDescriptor
}
else if (traitMember instanceof PropertyDescriptor) {
for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) {
for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) {
if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind
result.put(traitAccessor, inheritedAccessor);
else if (traitMember is PropertyDescriptor) {
for (traitAccessor in traitMember.accessors) {
for (inheritedAccessor in (copy as PropertyDescriptor).accessors) {
if (inheritedAccessor.javaClass == traitAccessor.javaClass) { // same accessor kind
result.put(traitAccessor, inheritedAccessor)
}
}
}
}
return result;
return result
}
@NotNull
public static ClassDescriptor getSuperClassBySuperTypeListEntry(@NotNull KtSuperTypeListEntry specifier, @NotNull BindingContext bindingContext) {
KotlinType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null : "superType should not be null: " + specifier.getText();
@JvmStatic
fun getSuperClassBySuperTypeListEntry(specifier: KtSuperTypeListEntry, bindingContext: BindingContext): ClassDescriptor {
val superType = bindingContext.get(BindingContext.TYPE, specifier.typeReference!!)
?: error("superType should not be null: ${specifier.text}")
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
assert superClassDescriptor != null : "superClassDescriptor should not be null: " + specifier.getText();
return superClassDescriptor;
return superType.constructor.declarationDescriptor as? ClassDescriptor
?: error("ClassDescriptor of superType should not be null: ${specifier.text}")
}
private static boolean valueParameterClassesMatch(
@NotNull List<ValueParameterDescriptor> parameters,
@NotNull List<ClassifierDescriptor> classifiers
) {
if (parameters.size() != classifiers.size()) return false;
for (int i = 0; i < parameters.size(); i++) {
ValueParameterDescriptor parameterDescriptor = parameters.get(i);
ClassifierDescriptor classDescriptor = classifiers.get(i);
if (!rawTypeMatches(parameterDescriptor.getType(), classDescriptor)) {
return false;
private fun valueParameterClassesMatch(
parameters: List<ValueParameterDescriptor>,
classifiers: List<ClassifierDescriptor>
): Boolean {
if (parameters.size != classifiers.size) return false
for ((parameterDescriptor, classDescriptor) in parameters.zip(classifiers)) {
if (!rawTypeMatches(parameterDescriptor.type, classDescriptor)) {
return false
}
}
return true;
return true
}
private static boolean rawTypeMatches(KotlinType type, ClassifierDescriptor classifier) {
return type.getConstructor().equals(classifier.getTypeConstructor());
private fun rawTypeMatches(type: KotlinType, classifier: ClassifierDescriptor): Boolean =
type.constructor == classifier.typeConstructor
@JvmStatic
fun isEnumValueOfMethod(functionDescriptor: FunctionDescriptor): Boolean {
val methodTypeParameters = functionDescriptor.valueParameters
val nullableString = TypeUtils.makeNullable(functionDescriptor.builtIns.stringType)
return DescriptorUtils.ENUM_VALUE_OF == functionDescriptor.name
&& methodTypeParameters.size == 1
&& KotlinTypeChecker.DEFAULT.isSubtypeOf(methodTypeParameters[0].type, nullableString)
}
public static boolean isEnumValueOfMethod(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
KotlinType nullableString = TypeUtils.makeNullable(DescriptorUtilsKt.getBuiltIns(functionDescriptor).getStringType());
return DescriptorUtils.ENUM_VALUE_OF.equals(functionDescriptor.getName())
&& methodTypeParameters.size() == 1
&& KotlinTypeChecker.DEFAULT.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString);
}
@Nullable
public static Integer getLineNumberForElement(@NotNull PsiElement statement, boolean markEndOffset) {
PsiFile file = statement.getContainingFile();
if (file instanceof KtFile) {
if (KtPsiFactoryKt.getDoNotAnalyze((KtFile) file) != null) {
return null;
}
@JvmStatic
fun getLineNumberForElement(statement: PsiElement, markEndOffset: Boolean): Int? {
val file = statement.containingFile
if (file is KtFile && file.doNotAnalyze != null) {
return null
}
if (statement instanceof KtConstructorDelegationReferenceExpression && statement.getTextLength() == 0) {
if (statement is KtConstructorDelegationReferenceExpression && statement.textLength == 0) {
// PsiElement for constructor delegation reference is always generated, so we shouldn't mark it's line number if it's empty
return null;
return null
}
Document document = file.getViewProvider().getDocument();
return document != null ? document.getLineNumber(markEndOffset ? statement.getTextRange().getEndOffset() : statement.getTextOffset()) + 1 : null;
val document = file.viewProvider.document
return document?.getLineNumber(if (markEndOffset) statement.textRange.endOffset else statement.textOffset)?.plus(1)
}
}
@@ -1,74 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.MemberComparator
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
import java.util.Comparator
object CodegenUtilKt {
// class Foo : Bar by baz
// descriptor = Foo
// toInterface = Bar
// delegateExpressionType = typeof(baz)
// return Map<member of Foo, corresponding member of typeOf(baz)>
@JvmStatic fun getDelegates(
descriptor: ClassDescriptor,
toInterface: ClassDescriptor,
delegateExpressionType: KotlinType? = null
): Map<CallableMemberDescriptor, CallableDescriptor> {
if (delegateExpressionType?.isDynamic() ?: false) return mapOf()
return descriptor.defaultType.memberScope.getContributedDescriptors().asSequence()
.filterIsInstance<CallableMemberDescriptor>()
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
.asIterable()
.sortedWith(MemberComparator.INSTANCE)
.keysToMapExceptNulls {
delegatingMember ->
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
.mapNotNull {
overriddenDescriptor ->
if (overriddenDescriptor.containingDeclaration == toInterface) {
val scope = (delegateExpressionType ?: toInterface.defaultType).memberScope
val name = overriddenDescriptor.name
// this is the actual member of delegateExpressionType that we are delegating to
(scope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) + scope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND))
.firstOrNull {
(listOf(it) + DescriptorUtils.getAllOverriddenDescriptors(it))
.map { it.original }
.contains(overriddenDescriptor.original)
}
}
else null
}
assert(actualDelegates.size <= 1) { "Many delegates found for $delegatingMember: $actualDelegates" }
actualDelegates.firstOrNull()
}
}
}
@@ -14,158 +14,115 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.common;
package org.jetbrains.kotlin.backend.common
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.KtClass;
import org.jetbrains.kotlin.psi.KtClassOrObject;
import org.jetbrains.kotlin.psi.KtParameter;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
import org.jetbrains.kotlin.resolve.OverrideResolver;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import java.util.Collections;
import java.util.List;
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.OverrideResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
/**
* A platform-independent logic for generating data class synthetic methods.
* TODO: data class with zero components gets no toString/equals/hashCode methods. This is inconsistent and should be
* changed here with the platform backends adopted.
* changed here with the platform backends adopted.
*/
public abstract class DataClassMethodGenerator {
private final KtClassOrObject declaration;
private final BindingContext bindingContext;
private final ClassDescriptor classDescriptor;
private final KotlinBuiltIns builtIns;
abstract class DataClassMethodGenerator(private val declaration: KtClassOrObject, private val bindingContext: BindingContext) {
protected val classDescriptor: ClassDescriptor = BindingContextUtils.getNotNull(bindingContext, BindingContext.CLASS, declaration)
public DataClassMethodGenerator(KtClassOrObject declaration, BindingContext bindingContext) {
this.declaration = declaration;
this.bindingContext = bindingContext;
this.classDescriptor = BindingContextUtils.getNotNull(bindingContext, BindingContext.CLASS, declaration);
this.builtIns = DescriptorUtilsKt.getBuiltIns(classDescriptor);
}
private val builtIns = classDescriptor.builtIns
public void generate() {
generateComponentFunctionsForDataClasses();
fun generate() {
generateComponentFunctionsForDataClasses()
generateCopyFunctionForDataClasses(getPrimaryConstructorParameters());
generateCopyFunctionForDataClasses(primaryConstructorParameters)
List<PropertyDescriptor> properties = getDataProperties();
if (!properties.isEmpty()) {
generateDataClassToStringIfNeeded(properties);
generateDataClassHashCodeIfNeeded(properties);
generateDataClassEqualsIfNeeded(properties);
val properties = dataProperties
if (properties.isNotEmpty()) {
generateDataClassToStringIfNeeded(properties)
generateDataClassHashCodeIfNeeded(properties)
generateDataClassEqualsIfNeeded(properties)
}
}
protected abstract void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull ValueParameterDescriptor parameter);
protected abstract fun generateComponentFunction(function: FunctionDescriptor, parameter: ValueParameterDescriptor)
protected abstract void generateCopyFunction(@NotNull FunctionDescriptor function, @NotNull List<KtParameter> constructorParameters);
protected abstract fun generateCopyFunction(function: FunctionDescriptor, constructorParameters: List<KtParameter>)
protected abstract void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties);
protected abstract fun generateToStringMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>)
protected abstract void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties);
protected abstract fun generateHashCodeMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>)
protected abstract void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties);
protected abstract fun generateEqualsMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>)
@NotNull
protected ClassDescriptor getClassDescriptor() {
return classDescriptor;
}
private void generateComponentFunctionsForDataClasses() {
ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
private fun generateComponentFunctionsForDataClasses() {
// primary constructor should exist for data classes
// but when generating light-classes still need to check we have one
if (constructor == null) return;
val constructor = classDescriptor.unsubstitutedPrimaryConstructor ?: return
for (ValueParameterDescriptor parameter : constructor.getValueParameters()) {
FunctionDescriptor function = bindingContext.get(BindingContext.DATA_CLASS_COMPONENT_FUNCTION, parameter);
for (parameter in constructor.valueParameters) {
val function = bindingContext.get(BindingContext.DATA_CLASS_COMPONENT_FUNCTION, parameter)
if (function != null) {
generateComponentFunction(function, parameter);
generateComponentFunction(function, parameter)
}
}
}
private void generateCopyFunctionForDataClasses(List<KtParameter> constructorParameters) {
FunctionDescriptor copyFunction = bindingContext.get(BindingContext.DATA_CLASS_COPY_FUNCTION, classDescriptor);
if (copyFunction != null) {
generateCopyFunction(copyFunction, constructorParameters);
}
private fun generateCopyFunctionForDataClasses(constructorParameters: List<KtParameter>) {
val copyFunction = bindingContext.get(BindingContext.DATA_CLASS_COPY_FUNCTION, classDescriptor) ?: return
generateCopyFunction(copyFunction, constructorParameters)
}
private void generateDataClassToStringIfNeeded(@NotNull List<PropertyDescriptor> properties) {
FunctionDescriptor function = getDeclaredMember("toString", builtIns.getString());
private fun generateDataClassToStringIfNeeded(properties: List<PropertyDescriptor>) {
val function = getDeclaredMember("toString", builtIns.string)
if (function != null && isTrivial(function)) {
generateToStringMethod(function, properties);
generateToStringMethod(function, properties)
}
}
private void generateDataClassHashCodeIfNeeded(@NotNull List<PropertyDescriptor> properties) {
FunctionDescriptor function = getDeclaredMember("hashCode", builtIns.getInt());
private fun generateDataClassHashCodeIfNeeded(properties: List<PropertyDescriptor>) {
val function = getDeclaredMember("hashCode", builtIns.int)
if (function != null && isTrivial(function)) {
generateHashCodeMethod(function, properties);
generateHashCodeMethod(function, properties)
}
}
private void generateDataClassEqualsIfNeeded(@NotNull List<PropertyDescriptor> properties) {
FunctionDescriptor function = getDeclaredMember("equals", builtIns.getBoolean(), builtIns.getAny());
private fun generateDataClassEqualsIfNeeded(properties: List<PropertyDescriptor>) {
val function = getDeclaredMember("equals", builtIns.boolean, builtIns.any)
if (function != null && isTrivial(function)) {
generateEqualsMethod(function, properties);
generateEqualsMethod(function, properties)
}
}
private List<PropertyDescriptor> getDataProperties() {
List<PropertyDescriptor> result = Lists.newArrayList();
for (KtParameter parameter : getPrimaryConstructorParameters()) {
if (parameter.hasValOrVar()) {
result.add(bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter));
}
}
return result;
}
private val dataProperties: List<PropertyDescriptor>
get() = primaryConstructorParameters
.filter { it.hasValOrVar() }
.map { bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it)!! }
@NotNull
private List<KtParameter> getPrimaryConstructorParameters() {
if (declaration instanceof KtClass) {
return declaration.getPrimaryConstructorParameters();
}
return Collections.emptyList();
}
private val primaryConstructorParameters: List<KtParameter>
get() = (declaration as? KtClass)?.getPrimaryConstructorParameters().orEmpty()
@Nullable
private FunctionDescriptor getDeclaredMember(
@NotNull String name,
@NotNull ClassDescriptor returnedClassifier,
@NotNull ClassDescriptor... valueParameterClassifiers
) {
return CodegenUtil.getDeclaredFunctionByRawSignature(
classDescriptor, Name.identifier(name), returnedClassifier, valueParameterClassifiers
);
}
private fun getDeclaredMember(
name: String,
returnedClassifier: ClassDescriptor,
vararg valueParameterClassifiers: ClassDescriptor
): FunctionDescriptor? = CodegenUtil.getDeclaredFunctionByRawSignature(
classDescriptor, Name.identifier(name), returnedClassifier, *valueParameterClassifiers
)
/**
* @return true if the member is an inherited implementation of a method from Any
*/
private boolean isTrivial(@NotNull FunctionDescriptor function) {
if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
return false;
}
for (CallableDescriptor overridden : OverrideResolver.getOverriddenDeclarations(function)) {
if (overridden instanceof CallableMemberDescriptor
&& ((CallableMemberDescriptor) overridden).getKind() == CallableMemberDescriptor.Kind.DECLARATION
&& !overridden.getContainingDeclaration().equals(builtIns.getAny())) {
return false;
}
}
return true;
private fun isTrivial(function: FunctionDescriptor): Boolean {
return function.kind != CallableMemberDescriptor.Kind.DECLARATION &&
OverrideResolver.getOverriddenDeclarations(function).none { overridden ->
overridden is CallableMemberDescriptor &&
overridden.kind == CallableMemberDescriptor.Kind.DECLARATION &&
overridden.containingDeclaration != builtIns.any
}
}
}
@@ -27,7 +27,6 @@ import kotlin.jvm.functions.Function2;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.backend.common.CodegenUtilKt;
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
@@ -496,7 +495,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
@Override
public void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties) {
public void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> properties) {
MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -553,7 +552,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
@Override
public void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties) {
public void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> properties) {
MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "hashCode", "()I", null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -602,7 +601,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
@Override
public void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> properties) {
public void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> properties) {
MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -692,7 +691,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
@Override
public void generateCopyFunction(@NotNull final FunctionDescriptor function, @NotNull List<KtParameter> constructorParameters) {
public void generateCopyFunction(
@NotNull final FunctionDescriptor function,
@NotNull List<? extends KtParameter> constructorParameters
) {
final Type thisDescriptorType = typeMapper.mapType(descriptor);
functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(myClass, function), function, new FunctionGenerationStrategy() {
@@ -1640,8 +1642,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
fieldInfo.name, fieldInfo.type.getDescriptor(), /*TODO*/null, null);
}
protected void generateDelegates(ClassDescriptor toTrait, KotlinType delegateExpressionType, DelegationFieldsInfo.Field field) {
for (Map.Entry<CallableMemberDescriptor, CallableDescriptor> entry : CodegenUtilKt.getDelegates(descriptor, toTrait, delegateExpressionType).entrySet()) {
private void generateDelegates(ClassDescriptor toTrait, KotlinType delegateExpressionType, DelegationFieldsInfo.Field field) {
for (Map.Entry<CallableMemberDescriptor, CallableDescriptor> entry :
CodegenUtil.getDelegates(descriptor, toTrait, delegateExpressionType).entrySet()) {
CallableMemberDescriptor callableMemberDescriptor = entry.getKey();
CallableDescriptor delegateTo = entry.getValue();
if (callableMemberDescriptor instanceof PropertyDescriptor) {
@@ -82,12 +82,13 @@ class JvmStaticGenerator(
}
companion object {
@JvmStatic fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
@JvmStatic
fun createStaticFunctionDescriptor(descriptor: FunctionDescriptor): FunctionDescriptor {
val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.correspondingProperty else descriptor
val copies = CodegenUtil.copyFunctions(
memberDescriptor,
memberDescriptor,
descriptor.containingDeclaration.containingDeclaration,
descriptor.containingDeclaration.containingDeclaration!!,
descriptor.modality,
descriptor.visibility,
CallableMemberDescriptor.Kind.SYNTHESIZED,
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.translate.declaration
import com.google.dart.compiler.backend.js.ast.*
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.backend.common.CodegenUtilKt
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext
@@ -32,8 +31,8 @@ import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunc
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateFunctionAsEcma5PropertyDescriptor
import org.jetbrains.kotlin.js.translate.utils.generateDelegateCall
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
import org.jetbrains.kotlin.resolve.DescriptorUtils
class DelegationTranslator(
@@ -90,7 +89,7 @@ class DelegationTranslator(
CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext())
private fun generateDelegates(toClass: ClassDescriptor, field: Field, properties: MutableList<JsPropertyInitializer>) {
for ((descriptor, overriddenDescriptor) in CodegenUtilKt.getDelegates(classDescriptor, toClass)) {
for ((descriptor, overriddenDescriptor) in CodegenUtil.getDelegates(classDescriptor, toClass)) {
when (descriptor) {
is PropertyDescriptor ->
generateDelegateCallForPropertyMember(descriptor, field.name, properties)
@@ -61,7 +61,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
}
@Override
public void generateCopyFunction(@NotNull FunctionDescriptor function, @NotNull List<KtParameter> constructorParameters) {
public void generateCopyFunction(@NotNull FunctionDescriptor function, @NotNull List<? extends KtParameter> constructorParameters) {
JsFunction functionObj = generateJsMethod(function);
assert function.getValueParameters().size() == constructorParameters.size();
@@ -110,7 +110,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
}
@Override
public void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> classProperties) {
public void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
// TODO: relax this limitation, with the data generation logic fixed.
assert !classProperties.isEmpty();
JsFunction functionObj = generateJsMethod(function);
@@ -136,7 +136,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
}
@Override
public void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> classProperties) {
public void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
JsFunction functionObj = generateJsMethod(function);
JsProgram jsProgram = context.program();
@@ -161,7 +161,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
}
@Override
public void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<PropertyDescriptor> classProperties) {
public void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> classProperties) {
assert !classProperties.isEmpty();
JsFunction functionObj = generateJsMethod(function);
JsFunctionScope funScope = functionObj.getScope();