Pluggable Synthetic Objects

This commit is contained in:
Roman Elizarov
2016-11-03 12:54:25 +03:00
parent 7a4b6a1462
commit 8affb2726f
50 changed files with 731 additions and 222 deletions
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation
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
@@ -162,4 +163,23 @@ object CodegenUtil {
val document = file.viewProvider.document
return document?.getLineNumber(if (markEndOffset) statement.textRange.endOffset else statement.textOffset)?.plus(1)
}
// Returns the descriptor for a function (whose parameters match the given predicate) which should be generated in the class.
// Note that we always generate equals/hashCode/toString in data classes, unless that would lead to a JVM signature clash with
// another method, which can only happen if the method is declared in the data class (manually or via delegation).
// Also there are no hard asserts or assumptions because such methods are generated for erroneous code as well (in light classes mode).
fun getMemberToGenerate(
classDescriptor: ClassDescriptor,
name: String,
isReturnTypeOk: (KotlinType) -> Boolean,
areParametersOk: (List<ValueParameterDescriptor>) -> Boolean
): FunctionDescriptor? =
classDescriptor.unsubstitutedMemberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
.singleOrNull { function ->
function.kind.let { kind -> kind == CallableMemberDescriptor.Kind.SYNTHESIZED || kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } &&
function.modality != Modality.FINAL &&
areParametersOk(function.valueParameters) &&
function.returnType != null &&
isReturnTypeOk(function.returnType!!)
}
}
@@ -16,18 +16,17 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.backend.common.CodegenUtil.getMemberToGenerate
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
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.types.KotlinType
/**
* A platform-independent logic for generating data class synthetic methods.
@@ -79,17 +78,20 @@ abstract class DataClassMethodGenerator(private val declaration: KtClassOrObject
}
private fun generateDataClassToStringIfNeeded(properties: List<PropertyDescriptor>) {
val function = getMemberToGenerate("toString", KotlinBuiltIns::isString, List<ValueParameterDescriptor>::isEmpty) ?: return
val function = getMemberToGenerate(classDescriptor, "toString",
KotlinBuiltIns::isString, List<ValueParameterDescriptor>::isEmpty) ?: return
generateToStringMethod(function, properties)
}
private fun generateDataClassHashCodeIfNeeded(properties: List<PropertyDescriptor>) {
val function = getMemberToGenerate("hashCode", KotlinBuiltIns::isInt, List<ValueParameterDescriptor>::isEmpty) ?: return
val function = getMemberToGenerate(classDescriptor, "hashCode",
KotlinBuiltIns::isInt, List<ValueParameterDescriptor>::isEmpty) ?: return
generateHashCodeMethod(function, properties)
}
private fun generateDataClassEqualsIfNeeded(properties: List<PropertyDescriptor>) {
val function = getMemberToGenerate("equals", KotlinBuiltIns::isBoolean) { parameters ->
val function = getMemberToGenerate(classDescriptor, "equals",
KotlinBuiltIns::isBoolean) { parameters ->
parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type)
} ?: return
generateEqualsMethod(function, properties)
@@ -102,22 +104,4 @@ abstract class DataClassMethodGenerator(private val declaration: KtClassOrObject
private val primaryConstructorParameters: List<KtParameter>
get() = (declaration as? KtClass)?.getPrimaryConstructorParameters().orEmpty()
// Returns the descriptor for a function (whose parameters match the given predicate) which should be generated in the data class.
// Note that we always generate equals/hashCode/toString in data classes, unless that would lead to a JVM signature clash with
// another method, which can only happen if the method is declared in the data class (manually or via delegation).
// Also there are no hard asserts or assumptions because such methods are generated for erroneous code as well (in light classes mode).
private fun getMemberToGenerate(
name: String,
isReturnTypeOk: (KotlinType) -> Boolean,
areParametersOk: (List<ValueParameterDescriptor>) -> Boolean
): FunctionDescriptor? =
classDescriptor.unsubstitutedMemberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
.singleOrNull { function ->
function.kind.let { kind -> kind == SYNTHESIZED || kind == FAKE_OVERRIDE } &&
function.modality != Modality.FINAL &&
areParametersOk(function.valueParameters) &&
function.returnType != null &&
isReturnTypeOk(function.returnType!!)
}
}
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.codegen.context.ClassContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*;
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;
@@ -32,13 +34,13 @@ import java.util.List;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
protected final KtClassOrObject myClass;
protected final OwnerKind kind;
protected final ClassDescriptor descriptor;
public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject> {
public final KtPureClassOrObject myClass;
public final OwnerKind kind;
public final ClassDescriptor descriptor;
protected ClassBodyCodegen(
@NotNull KtClassOrObject myClass,
@NotNull KtPureClassOrObject myClass,
@NotNull ClassContext context,
@NotNull ClassBuilder v,
@NotNull GenerationState state,
@@ -47,7 +49,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
super(state, parentCodegen, context, myClass, v);
this.myClass = myClass;
this.kind = context.getContextKind();
this.descriptor = bindingContext.get(BindingContext.CLASS, myClass);
this.descriptor = SyntheticClassOrObjectDescriptorKt.findClassDescriptor(myClass, bindingContext);
}
@Override
@@ -79,8 +81,15 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
generateConstructors();
generateDefaultImplsIfNeeded();
// Generate _declared_ companions
for (KtObjectDeclaration companion : companions) {
generateDeclaration(companion);
genClassOrObject(companion);
}
// Generate synthetic (non-declared) companion if needed
ClassDescriptor companionObjectDescriptor = descriptor.getCompanionObjectDescriptor();
if (companionObjectDescriptor instanceof SyntheticClassOrObjectDescriptor) {
genSyntheticClassOrObject((SyntheticClassOrObjectDescriptor) companionObjectDescriptor);
}
if (!DescriptorUtils.isInterface(descriptor)) {
@@ -152,7 +161,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
@NotNull
protected List<KtParameter> getPrimaryConstructorParameters() {
if (myClass instanceof KtClass) {
return ((KtClass) myClass).getPrimaryConstructorParameters();
return myClass.getPrimaryConstructorParameters();
}
return Collections.emptyList();
}
@@ -342,7 +342,7 @@ class CollectionStubMethodGenerator(
InstructionAdapter(mv),
"java/lang/UnsupportedOperationException",
"Operation is not supported for read-only collection")
FunctionCodegen.endVisit(mv, "built-in stub for $signature", null)
FunctionCodegen.endVisit(mv, "built-in stub for $signature")
}
}
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.psi.KtPureElement
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
@@ -52,7 +52,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
classBuilder: ClassBuilder,
memberCodegen: MemberCodegen<*>,
contextKind: OwnerKind,
classOrObject: KtClassOrObject
classOrObject: KtPureClassOrObject
) {
val methodElement = classOrObject.getPrimaryConstructor() ?: classOrObject
@@ -83,7 +83,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
* @return true if the overloads annotation was found on the element, false otherwise
*/
fun generateOverloadsIfNeeded(
methodElement: KtElement?,
methodElement: KtPureElement?,
functionDescriptor: FunctionDescriptor,
delegateFunctionDescriptor: FunctionDescriptor,
contextKind: OwnerKind,
@@ -122,7 +122,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
delegateFunctionDescriptor: FunctionDescriptor,
classBuilder: ClassBuilder,
memberCodegen: MemberCodegen<*>,
methodElement: KtElement?,
methodElement: KtPureElement?,
contextKind: OwnerKind,
substituteCount: Int
) {
@@ -248,7 +248,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
return functionDescriptor.valueParameters.filter { !it.declaresDefaultValue() || --remainingCount >= 0 }
}
private fun isEmptyConstructorNeeded(constructorDescriptor: ConstructorDescriptor, classOrObject: KtClassOrObject): Boolean {
private fun isEmptyConstructorNeeded(constructorDescriptor: ConstructorDescriptor, classOrObject: KtPureClassOrObject): Boolean {
val classDescriptor = constructorDescriptor.constructedClass
if (classDescriptor.kind != ClassKind.CLASS) return false
@@ -127,7 +127,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public final InstructionAdapter v;
public final FrameMap myFrameMap;
private final MethodContext context;
public final MethodContext context;
private final Type returnType;
private final CodegenStatementVisitor statementVisitor = new CodegenStatementVisitor(this);
@@ -44,10 +44,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.psi.KtFunction;
import org.jetbrains.kotlin.psi.KtNamedFunction;
import org.jetbrains.kotlin.psi.KtParameter;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
@@ -484,7 +481,7 @@ public class FunctionCodegen {
if (indexOfLambdaOrdinal > 0) {
int lambdaOrdinal = Integer.parseInt(name.substring(indexOfLambdaOrdinal + 1));
KtElement functionArgument = parentCodegen.element;
KtPureElement functionArgument = parentCodegen.element;
String functionName = "unknown";
if (functionArgument instanceof KtFunction) {
ValueParameterDescriptor inlineArgumentDescriptor =
@@ -674,6 +671,18 @@ public class FunctionCodegen {
kind == JvmMethodParameterKind.SUPER_CALL_PARAM;
}
public static void endVisit(MethodVisitor mv, @Nullable String description) {
endVisit(mv, description, (PsiElement)null);
}
public static void endVisit(MethodVisitor mv, @Nullable String description, @Nullable KtPureElement method) {
endVisit(mv, description, (PsiElement)(method == null ? null : method.getPsiOrParent()));
}
public static void endVisit(MethodVisitor mv, @Nullable String description, @NotNull KtElement method) {
endVisit(mv, description, (PsiElement)method);
}
public static void endVisit(MethodVisitor mv, @Nullable String description, @Nullable PsiElement method) {
try {
mv.visitMaxs(-1, -1);
@@ -37,9 +37,6 @@ import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.lexer.KtTokens;
@@ -105,7 +102,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
new ArrayList<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>>();
public ImplementationBodyCodegen(
@NotNull KtClassOrObject aClass,
@NotNull KtPureClassOrObject aClass,
@NotNull ClassContext context,
@NotNull ClassBuilder v,
@NotNull GenerationState state,
@@ -212,7 +209,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
v.defineClass(
myClass,
myClass.getPsiOrParent(),
state.getClassFileVersion(),
access,
signature.getName(),
@@ -221,7 +218,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ArrayUtil.toStringArray(signature.getInterfaces())
);
v.visitSource(myClass.getContainingFile().getName(), null);
v.visitSource(myClass.getContainingKtFile().getName(), null);
InlineCodegenUtil.initDefaultSourceMappingIfNeeded(context, this, state);
@@ -237,7 +234,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (isInterface(descriptor) && !isLocal && (!isJvm8Interface(descriptor, state) || state.getGenerateDefaultImplsForJvm8())) {
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
ClassBuilder defaultImplsBuilder =
state.getFactory().newVisitor(JvmDeclarationOriginKt.DefaultImpls(myClass, descriptor), defaultImplsType, myClass.getContainingFile());
state.getFactory().newVisitor(JvmDeclarationOriginKt.DefaultImpls(myClass.getPsiOrParent(), descriptor), defaultImplsType, myClass.getContainingKtFile());
CodegenContext parentContext = context.getParentContext();
assert parentContext != null : "Parent context of interface declaration should not be null";
@@ -371,10 +368,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateToArray();
genClosureFields(context.closure, v, typeMapper);
if (context.closure != null)
genClosureFields(context.closure, v, typeMapper);
for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
extension.generateClassSyntheticParts(v, state, myClass, descriptor);
extension.generateClassSyntheticParts(this);
}
}
@@ -481,10 +479,33 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
public Type genPropertyOnStack(
InstructionAdapter iv,
MethodContext context,
@NotNull PropertyDescriptor propertyDescriptor,
Type classAsmType,
int index
) {
iv.load(index, classAsmType);
if (couldUseDirectAccessToProperty(propertyDescriptor, /* forGetter = */ true,
/* isDelegated = */ false, context, state.getShouldInlineConstVals())) {
Type type = typeMapper.mapType(propertyDescriptor.getType());
String fieldName = ((FieldOwnerContext) context.getParentContext()).getFieldName(propertyDescriptor, false);
iv.getfield(classAsmType.getInternalName(), fieldName, type.getDescriptor());
return type;
}
else {
//noinspection ConstantConditions
Method method = typeMapper.mapAsmMethod(propertyDescriptor.getGetter());
iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor(), false);
return method.getReturnType();
}
}
private void generateFunctionsForDataClasses() {
if (!descriptor.isData()) return;
new DataClassMethodGeneratorImpl(myClass, bindingContext).generate();
if (!(myClass instanceof KtClassOrObject)) return;
new DataClassMethodGeneratorImpl((KtClassOrObject)myClass, bindingContext).generate();
}
private class DataClassMethodGeneratorImpl extends DataClassMethodGenerator {
@@ -520,10 +541,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (PropertyDescriptor propertyDescriptor : properties) {
Type asmType = typeMapper.mapType(propertyDescriptor);
Type thisPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, 0);
Type thisPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 0);
StackValue.coerce(thisPropertyType, asmType, iv);
Type otherPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, 2);
Type otherPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 2);
StackValue.coerce(otherPropertyType, asmType, iv);
if (asmType.getSort() == Type.FLOAT) {
@@ -566,7 +587,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.mul(Type.INT_TYPE);
}
Type propertyType = genPropertyOnStack(iv, context, propertyDescriptor, 0);
Type propertyType = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 0);
Type asmType = typeMapper.mapType(propertyDescriptor);
StackValue.coerce(propertyType, asmType, iv);
@@ -621,7 +642,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
Type type = genPropertyOnStack(iv, context, propertyDescriptor, 0);
Type type = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 0);
if (type.getSort() == Type.ARRAY) {
Type elementType = correctElementType(type);
@@ -648,23 +669,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
FunctionCodegen.endVisit(mv, "toString", myClass);
}
private Type genPropertyOnStack(InstructionAdapter iv, MethodContext context, @NotNull PropertyDescriptor propertyDescriptor, int index) {
iv.load(index, classAsmType);
if (couldUseDirectAccessToProperty(propertyDescriptor, /* forGetter = */ true,
/* isDelegated = */ false, context, state.getShouldInlineConstVals())) {
Type type = typeMapper.mapType(propertyDescriptor.getType());
String fieldName = ((FieldOwnerContext) context.getParentContext()).getFieldName(propertyDescriptor, false);
iv.getfield(classAsmType.getInternalName(), fieldName, type.getDescriptor());
return type;
}
else {
//noinspection ConstantConditions
Method method = typeMapper.mapAsmMethod(propertyDescriptor.getGetter());
iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor(), false);
return method.getReturnType();
}
}
@Override
public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) {
PsiElement originalElement = DescriptorToSourceUtils.descriptorToDeclaration(parameter);
@@ -684,7 +688,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, descriptorToDeclaration(parameter));
assert property != null : "Property descriptor is not found for primary constructor parameter: " + parameter;
Type propertyType = genPropertyOnStack(iv, context, property, 0);
Type propertyType = genPropertyOnStack(iv, context, property, ImplementationBodyCodegen.this.classAsmType, 0);
StackValue.coerce(propertyType, componentType, iv);
}
iv.areturn(componentType);
@@ -848,7 +852,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (!state.getClassBuilderMode().generateBodies) return;
// Invoke the object constructor but ignore the result because INSTANCE will be initialized in the first line of <init>
InstructionAdapter v = createOrGetClInitCodegen().v;
markLineNumberForElement(element, v);
markLineNumberForElement(element.getPsiOrParent(), v);
v.anew(classAsmType);
v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false);
@@ -860,11 +864,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return;
}
KtObjectDeclaration companionObject = CollectionsKt.firstOrNull(((KtClass) myClass).getCompanionObjects());
assert companionObject != null : "Companion object not found: " + myClass.getText();
@Nullable KtObjectDeclaration companionObject = CollectionsKt.firstOrNull(myClass.getCompanionObjects());
StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper);
v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject),
ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
}
private void generateCompanionObjectBackingFieldCopies() {
@@ -935,7 +939,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final KtPrimaryConstructor primaryConstructor = myClass.getPrimaryConstructor();
JvmDeclarationOrigin origin = JvmDeclarationOriginKt
.OtherOrigin(primaryConstructor != null ? primaryConstructor : myClass, constructorDescriptor);
.OtherOrigin(primaryConstructor != null ? primaryConstructor : myClass.getPsiOrParent(), constructorDescriptor);
functionCodegen.generateMethod(origin, constructorDescriptor, constructorContext,
new FunctionGenerationStrategy.CodegenBased(state) {
@Override
@@ -1332,7 +1336,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
CodegenUtilKt.reportTarget6InheritanceErrorIfNeeded(descriptor, myClass, restrictedInheritance, state);
CodegenUtilKt.reportTarget6InheritanceErrorIfNeeded(descriptor, myClass.getPsiOrParent(), restrictedInheritance, state);
}
private void generateDelegationToDefaultImpl(@NotNull final FunctionDescriptor traitFun, @NotNull final FunctionDescriptor inheritedFun) {
@@ -26,20 +26,19 @@ import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.diagnostics.DelegationToDefaultImpls
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes.*
import java.util.*
class InterfaceImplBodyCodegen(
aClass: KtClassOrObject,
aClass: KtPureClassOrObject,
context: ClassContext,
v: ClassBuilder,
state: GenerationState,
@@ -50,11 +49,11 @@ class InterfaceImplBodyCodegen(
override fun generateDeclaration() {
v.defineClass(
myClass, state.classFileVersion, ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
myClass.psiOrParent, state.classFileVersion, ACC_PUBLIC or ACC_FINAL or ACC_SUPER,
typeMapper.mapDefaultImpls(descriptor).internalName,
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
)
v.visitSource(myClass.containingFile.name, null)
v.visitSource(myClass.containingKtFile.name, null)
}
override fun classForInnerClassRecord(): ClassDescriptor? {
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.SpecialNames;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
@@ -73,15 +74,18 @@ import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclarationContainer*/> implements InnerClassConsumer {
protected final GenerationState state;
public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarationContainer*/> implements InnerClassConsumer {
public final GenerationState state;
protected final T element;
protected final FieldOwnerContext context;
protected final ClassBuilder v;
protected final FunctionCodegen functionCodegen;
protected final PropertyCodegen propertyCodegen;
protected final KotlinTypeMapper typeMapper;
protected final BindingContext bindingContext;
public final ClassBuilder v;
public final FunctionCodegen functionCodegen;
public final PropertyCodegen propertyCodegen;
public final KotlinTypeMapper typeMapper;
public final BindingContext bindingContext;
protected final JvmFileClassesProvider fileClassesProvider;
private final MemberCodegen<?> parentCodegen;
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
@@ -260,9 +264,21 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
if (descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) {
badDescriptor(descriptor, state.getClassBuilderMode());
}
genClassOrObject(parentContext, aClass, state, parentCodegen, descriptor);
}
private static void genClassOrObject(
@NotNull CodegenContext parentContext,
@NotNull KtPureClassOrObject aClass,
@NotNull GenerationState state,
@Nullable MemberCodegen<?> parentCodegen,
@NotNull ClassDescriptor descriptor
) {
Type classType = state.getTypeMapper().mapClass(descriptor);
ClassBuilder classBuilder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(aClass, descriptor), classType, aClass.getContainingFile());
ClassBuilder classBuilder = state.getFactory().newVisitor(
JvmDeclarationOriginKt.OtherOrigin(aClass, descriptor),
classType, aClass.getContainingKtFile());
ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen, false).generate();
}
@@ -277,6 +293,10 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
genClassOrObject(context, aClass, state, this);
}
public void genSyntheticClassOrObject(SyntheticClassOrObjectDescriptor descriptor) {
genClassOrObject(context, descriptor.getSyntheticDeclaration(), state, this, descriptor);
}
private void writeInnerClasses() {
// JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
// for each enclosing class and for each immediate member
@@ -389,7 +409,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
}
@NotNull
protected final ExpressionCodegen createOrGetClInitCodegen() {
public final ExpressionCodegen createOrGetClInitCodegen() {
if (clInit == null) {
DeclarationDescriptor contextDescriptor = context.getContextDescriptor();
SimpleFunctionDescriptorImpl clInitDescriptor = createClInitFunctionDescriptor(contextDescriptor);
@@ -400,7 +420,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
}
@NotNull
protected MethodVisitor createClInitMethodVisitor(@NotNull DeclarationDescriptor contextDescriptor) {
public MethodVisitor createClInitMethodVisitor(@NotNull DeclarationDescriptor contextDescriptor) {
return v.newMethod(JvmDeclarationOriginKt.OtherOrigin(contextDescriptor), ACC_STATIC, "<clinit>", "()V", null, null);
}
@@ -599,7 +619,8 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
@NotNull
public DefaultSourceMapper getOrCreateSourceMapper() {
if (sourceMapper == null) {
sourceMapper = new DefaultSourceMapper(SourceInfo.Companion.createInfo(element, getClassName()));
// note: this is used for in InlineCodegen and the element is always physical (KtElement) there
sourceMapper = new DefaultSourceMapper(SourceInfo.Companion.createInfo((KtElement)element, getClassName()));
}
return sourceMapper;
}
@@ -634,7 +655,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
new FunctionGenerationStrategy.CodegenBased(state) {
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
markLineNumberForElement(element, codegen.v);
markLineNumberForElement(element.getPsiOrParent(), codegen.v);
generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), codegen.v);
@@ -669,7 +690,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
InstructionAdapter iv = codegen.v;
markLineNumberForElement(element, iv);
markLineNumberForElement(element.getPsiOrParent(), iv);
Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
for (int i = 0, reg = 0; i < argTypes.length; i++) {
@@ -145,7 +145,7 @@ public class SamWrapperCodegen {
iv.putfield(ownerType.getInternalName(), FUNCTION_FIELD_NAME, functionType.getDescriptor());
iv.visitInsn(RETURN);
FunctionCodegen.endVisit(iv, "constructor of SAM wrapper", null);
FunctionCodegen.endVisit(iv, "constructor of SAM wrapper");
}
}
@@ -1159,7 +1159,7 @@ public abstract class StackValue {
}
}
static class Property extends StackValueWithSimpleReceiver {
public static class Property extends StackValueWithSimpleReceiver {
private final CallableMethod getter;
private final CallableMethod setter;
private final Type backingFieldOwner;
@@ -223,7 +223,7 @@ fun ClassBuilder.generateMethod(
fun reportTarget6InheritanceErrorIfNeeded(
classDescriptor: ClassDescriptor, classElement: KtClassOrObject, restrictedInheritance: List<FunctionDescriptor>, state:GenerationState
classDescriptor: ClassDescriptor, classElement: PsiElement, restrictedInheritance: List<FunctionDescriptor>, state:GenerationState
) {
if (!restrictedInheritance.isEmpty()) {
val groupBy = restrictedInheritance.groupBy { descriptor -> descriptor.containingDeclaration as ClassDescriptor }
@@ -16,15 +16,12 @@
package org.jetbrains.kotlin.codegen.extensions
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
interface ExpressionCodegenExtension {
companion object : ProjectExtensionDescriptor<ExpressionCodegenExtension>(
@@ -47,10 +44,5 @@ interface ExpressionCodegenExtension {
*/
fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
fun generateClassSyntheticParts(
classBuilder: ClassBuilder,
state: GenerationState,
classOrObject: KtClassOrObject,
descriptor: ClassDescriptor
) {}
fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {}
}
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory;
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
@@ -82,7 +81,6 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod;
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
@@ -136,6 +134,13 @@ public class KotlinTypeMapper {
return bindingContext.get(ASM_TYPE, classDescriptor);
}
@Nullable
@Override
public String getPredefinedInternalNameForClass(@NotNull ClassDescriptor classDescriptor) {
Type type = getPredefinedTypeForClass(classDescriptor);
return type == null ? null : type.getInternalName();
}
@Override
public void processErrorType(@NotNull KotlinType kotlinType, @NotNull ClassDescriptor descriptor) {
if (classBuilderMode.generateBodies) {
@@ -94,6 +94,7 @@ import org.jetbrains.kotlin.name.isValidJavaFqName
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
@@ -167,6 +168,7 @@ class KotlinCoreEnvironment private constructor(
project.registerService(JvmVirtualFileFinderFactory::class.java, finderFactory)
ExpressionCodegenExtension.registerExtensionPoint(project)
SyntheticResolveExtension.registerExtensionPoint(project)
ClassBuilderInterceptorExtension.registerExtensionPoint(project)
AnalysisHandlerExtension.registerExtensionPoint(project)
PackageFragmentProviderExtension.registerExtensionPoint(project)
@@ -87,7 +87,7 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtExpression> WHEN_ENUM_CAN_BE_NULL_IN_JAVA = DiagnosticFactory0.create(WARNING);
DiagnosticFactory3<KtExpression, DeclarationDescriptor, DeclarationDescriptor, String> TARGET6_INTERFACE_INHERITANCE = DiagnosticFactory3.create(ERROR);
DiagnosticFactory3<PsiElement, DeclarationDescriptor, DeclarationDescriptor, String> TARGET6_INTERFACE_INHERITANCE = DiagnosticFactory3.create(ERROR);
@SuppressWarnings("UnusedDeclaration")
Object _initializer = new Object() {
@@ -18,8 +18,9 @@ package org.jetbrains.kotlin.resolve.jvm.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPureElement
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
@@ -55,9 +56,19 @@ fun OtherOrigin(element: PsiElement?, descriptor: DeclarationDescriptor?): JvmDe
JvmDeclarationOrigin.NO_ORIGIN
else JvmDeclarationOrigin(OTHER, element, descriptor)
fun OtherOrigin(element: KtPureElement?, descriptor: DeclarationDescriptor?): JvmDeclarationOrigin =
OtherOrigin(element?.psiOrParent as PsiElement, descriptor)
fun OtherOrigin(element: KtElement, descriptor: DeclarationDescriptor?): JvmDeclarationOrigin =
OtherOrigin(element as PsiElement, descriptor)
fun OtherOrigin(element: PsiElement): JvmDeclarationOrigin = OtherOrigin(element, null)
fun OtherOrigin(descriptor: DeclarationDescriptor): JvmDeclarationOrigin = OtherOrigin(null, descriptor)
fun OtherOrigin(element: KtPureElement): JvmDeclarationOrigin = OtherOrigin(element, null)
fun OtherOrigin(element: KtElement): JvmDeclarationOrigin = OtherOrigin(element, null)
fun OtherOrigin(descriptor: DeclarationDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(OTHER, null, descriptor)
fun Bridge(descriptor: DeclarationDescriptor, element: PsiElement? = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)): JvmDeclarationOrigin =
JvmDeclarationOrigin(BRIDGE, element, descriptor)
@@ -72,7 +83,7 @@ fun MultifileClass(representativeFile: KtFile?, descriptor: PackageFragmentDescr
fun MultifileClassPart(file: KtFile, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(MULTIFILE_CLASS_PART, file, descriptor)
fun DefaultImpls(element: KtClassOrObject, descriptor: ClassDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(INTERFACE_DEFAULT_IMPL, element, descriptor)
fun DefaultImpls(element: PsiElement?, descriptor: ClassDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(INTERFACE_DEFAULT_IMPL, element, descriptor)
fun DelegationToDefaultImpls(element: PsiElement?, descriptor: FunctionDescriptor): JvmDeclarationOrigin =
JvmDeclarationOrigin(DELEGATION_TO_DEFAULT_IMPLS, element, descriptor)
@@ -16,10 +16,10 @@
package org.jetbrains.kotlin.extensions
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.openapi.extensions.ExtensionPoint
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.project.Project
open class ProjectExtensionDescriptor<T>(name: String, private val extensionClass: Class<T>) {
val extensionPointName: ExtensionPointName<T> = ExtensionPointName.create(name)!!
@@ -36,7 +36,7 @@ open class ProjectExtensionDescriptor<T>(name: String, private val extensionClas
Extensions.getArea(project).getExtensionPoint(extensionPointName).registerExtension(extension)
}
fun getInstances(project: Project): Collection<T> {
fun getInstances(project: Project): List<T> {
val projectArea = Extensions.getArea(project)
if (!projectArea.hasExtensionPoint(extensionPointName.name!!)) return listOf()
@@ -83,7 +83,7 @@ open class KtClass : KtClassOrObject {
return StringUtil.join(parts, ".")
}
fun getCompanionObjects(): List<KtObjectDeclaration> = getBody()?.allCompanionObjects.orEmpty()
override fun getCompanionObjects(): List<KtObjectDeclaration> = getBody()?.allCompanionObjects.orEmpty()
fun getClassOrInterfaceKeyword(): PsiElement? = findChildByType(TokenSet.create(KtTokens.CLASS_KEYWORD, KtTokens.INTERFACE_KEYWORD))
}
@@ -29,12 +29,13 @@ import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
abstract class KtClassOrObject :
KtTypeParameterListOwnerStub<KotlinClassOrObjectStub<out KtClassOrObject>>, KtDeclarationContainer, KtNamedDeclaration {
KtTypeParameterListOwnerStub<KotlinClassOrObjectStub<out KtClassOrObject>>, KtDeclarationContainer, KtNamedDeclaration, KtPureClassOrObject {
constructor(node: ASTNode) : super(node)
constructor(stub: KotlinClassOrObjectStub<out KtClassOrObject>, nodeType: IStubElementType<*, *>) : super(stub, nodeType)
fun getSuperTypeList(): KtSuperTypeList? = getStubOrPsiChild(KtStubElementTypes.SUPER_TYPE_LIST)
open fun getSuperTypeListEntries(): List<KtSuperTypeListEntry> = getSuperTypeList()?.entries.orEmpty()
override fun getSuperTypeListEntries(): List<KtSuperTypeListEntry> = getSuperTypeList()?.entries.orEmpty()
fun addSuperTypeListEntry(superTypeListEntry: KtSuperTypeListEntry): KtSuperTypeListEntry {
getSuperTypeList()?.let {
@@ -42,7 +43,7 @@ abstract class KtClassOrObject :
if (single != null && single.typeReference?.typeElement == null) {
return single.replace(superTypeListEntry) as KtSuperTypeListEntry
}
return EditCommaSeparatedListHelper.addItem(it, getSuperTypeListEntries(), superTypeListEntry)
return EditCommaSeparatedListHelper.addItem(it, superTypeListEntries, superTypeListEntry)
}
val psiFactory = KtPsiFactory(this)
@@ -85,31 +86,34 @@ abstract class KtClassOrObject :
fun isTopLevel(): Boolean = stub?.isTopLevel() ?: (parent == null || parent is KtFile)
fun isLocal(): Boolean = stub?.isLocal() ?: KtPsiUtil.isLocal(this)
override fun getDeclarations() = getBody()?.declarations.orEmpty()
override fun isLocal(): Boolean = stub?.isLocal() ?: KtPsiUtil.isLocal(this)
override fun getDeclarations(): List<KtDeclaration> = getBody()?.declarations.orEmpty()
override fun getPresentation(): ItemPresentation? = ItemPresentationProviders.getItemPresentation(this)
fun getPrimaryConstructor(): KtPrimaryConstructor? = getStubOrPsiChild(KtStubElementTypes.PRIMARY_CONSTRUCTOR)
override fun getPrimaryConstructor(): KtPrimaryConstructor? = getStubOrPsiChild(KtStubElementTypes.PRIMARY_CONSTRUCTOR)
fun getPrimaryConstructorModifierList(): KtModifierList? = getPrimaryConstructor()?.modifierList
fun getPrimaryConstructorParameterList(): KtParameterList? = getPrimaryConstructor()?.valueParameterList
fun getPrimaryConstructorParameters(): List<KtParameter> = getPrimaryConstructorParameterList()?.parameters.orEmpty()
override fun getPrimaryConstructorModifierList(): KtModifierList? = primaryConstructor?.modifierList
fun hasExplicitPrimaryConstructor(): Boolean = getPrimaryConstructor() != null
fun getPrimaryConstructorParameterList(): KtParameterList? = primaryConstructor?.valueParameterList
override fun getPrimaryConstructorParameters(): List<KtParameter> = getPrimaryConstructorParameterList()?.parameters.orEmpty()
override fun hasExplicitPrimaryConstructor(): Boolean = primaryConstructor != null
override fun hasPrimaryConstructor(): Boolean = hasExplicitPrimaryConstructor() || !hasSecondaryConstructors()
fun hasPrimaryConstructor(): Boolean = hasExplicitPrimaryConstructor() || !hasSecondaryConstructors()
private fun hasSecondaryConstructors(): Boolean = !getSecondaryConstructors().isEmpty()
fun getSecondaryConstructors(): List<KtSecondaryConstructor> = getBody()?.secondaryConstructors.orEmpty()
override fun getSecondaryConstructors(): List<KtSecondaryConstructor> = getBody()?.secondaryConstructors.orEmpty()
fun isAnnotation(): Boolean = hasModifier(KtTokens.ANNOTATION_KEYWORD)
override fun delete() {
CheckUtil.checkWritable(this)
val file = getContainingKtFile()
val file = containingKtFile
if (!isTopLevel() || file.declarations.size > 1) {
super.delete()
}
@@ -19,9 +19,7 @@ package org.jetbrains.kotlin.psi
import com.intellij.psi.NavigatablePsiElement
import com.intellij.psi.PsiReference
interface KtElement : NavigatablePsiElement {
fun getContainingKtFile(): KtFile
interface KtElement : NavigatablePsiElement, KtPureElement {
fun <D> acceptChildren(visitor: KtVisitor<Void, D>, data: D)
fun <R, D> accept(visitor: KtVisitor<R, D>, data: D): R
@@ -90,4 +90,10 @@ public class KtElementImpl extends ASTWrapperPsiElement implements KtElement {
public PsiReference[] getReferences() {
return ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiReferenceService.Hints.NO_HINTS);
}
@NotNull
@Override
public KtElement getPsiOrParent() {
return this;
}
}
@@ -111,4 +111,10 @@ public class KtElementImplStub<T extends StubElement<?>> extends StubBasedPsiEle
) {
return Arrays.asList(getStubOrPsiChildren(elementType, elementType.getArrayFactory()));
}
@NotNull
@Override
public KtElement getPsiOrParent() {
return this;
}
}
@@ -283,4 +283,10 @@ public class KtFile extends PsiFileBase implements KtDeclarationContainer, KtAnn
}
return result;
}
@NotNull
@Override
public KtElement getPsiOrParent() {
return this;
}
}
@@ -98,4 +98,10 @@ public class KtLambdaExpression extends LazyParseablePsiElement implements KtExp
public String toString() {
return getNode().getElementType().toString();
}
@NotNull
@Override
public KtElement getPsiOrParent() {
return this;
}
}
@@ -67,4 +67,6 @@ class KtObjectDeclaration : KtClassOrObject {
fun isObjectLiteral(): Boolean = _stub?.isObjectLiteral() ?: (parent is KtObjectLiteralExpression)
fun getObjectKeyword(): PsiElement? = findChildByType(KtTokens.OBJECT_KEYWORD)
override fun getCompanionObjects(): List<KtObjectDeclaration> = emptyList()
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2016 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.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
import java.util.List;
/**
* A minimal interface that {@link KtClassOrObject} implements for the purpose of code-generation that does not need the full power of PSI.
* This interface can be easily implemented by synthetic elements to generate code for them.
*/
public interface KtPureClassOrObject extends KtPureElement, KtDeclarationContainer {
@Nullable
String getName();
boolean isLocal();
@NotNull
@ReadOnly
List<KtSuperTypeListEntry> getSuperTypeListEntries();
@NotNull
@ReadOnly
List<KtObjectDeclaration> getCompanionObjects();
boolean hasExplicitPrimaryConstructor();
boolean hasPrimaryConstructor();
@Nullable
KtPrimaryConstructor getPrimaryConstructor();
@Nullable
KtModifierList getPrimaryConstructorModifierList();
@NotNull
@ReadOnly
List<KtParameter> getPrimaryConstructorParameters();
@NotNull
@ReadOnly
List<KtSecondaryConstructor> getSecondaryConstructors();
}
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2016 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.psi;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
/**
* A minimal interface that {@link KtElement} implements for the purpose of code-generation that does not need the full power of PSI.
* This interface can be easily implemented by synthetic elements to generate code for them.
*/
public interface KtPureElement {
/**
* Returns this or parent source element (for synthetic element declarations).
* Use it only for the purposes of source attribution.
*/
@NotNull
KtElement getPsiOrParent();
/**
* Returns parent source element.
*/
@NotNull
PsiElement getParent();
@NotNull
KtFile getContainingKtFile();
}
@@ -0,0 +1,158 @@
/*
* Copyright 2010-2016 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.psi.synthetics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.lazy.descriptors.ClassResolutionScopesSupport
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassMemberScope
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.AbstractClassTypeConstructor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructor
/*
* This class introduces all attributes that are needed for synthetic classes/object so far.
* This list may grow in the future, adding more constructor parameters.
* This class has its own synthetic declaration inside.
*/
class SyntheticClassOrObjectDescriptor(
c: LazyClassContext,
parentClassOrObject: KtPureClassOrObject,
containingDeclaration: DeclarationDescriptor,
name: Name,
source: SourceElement,
outerScope: LexicalScope,
private val modality: Modality,
private val visibility: Visibility,
private val kind: ClassKind,
private val isCompanionObject: Boolean
) : ClassDescriptorBase(c.storageManager, containingDeclaration, name, source, false), ClassDescriptorWithResolutionScopes {
val syntheticDeclaration: KtPureClassOrObject = SyntheticDeclaration(parentClassOrObject, name.asString())
private val thisDescriptor: SyntheticClassOrObjectDescriptor get() = this // code readability
private val typeConstructor = SyntheticTypeConstructor(c.storageManager)
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()
override val annotations: Annotations get() = Annotations.EMPTY
override fun getModality() = modality
override fun getVisibility() = visibility
override fun getKind() = kind
override fun isCompanionObject() = isCompanionObject
override fun isInner() = false
override fun isData() = false
override fun isPlatform() = false
override fun isImpl() = false
override fun getCompanionObjectDescriptor() = null
override fun getTypeConstructor(): TypeConstructor = typeConstructor
override fun getUnsubstitutedPrimaryConstructor() = unsubstitutedPrimaryConstructor
override fun getConstructors() = listOf(unsubstitutedPrimaryConstructor)
override fun getDeclaredTypeParameters() = emptyList<TypeParameterDescriptor>()
override fun getStaticScope() = MemberScope.Empty
override fun getUnsubstitutedMemberScope() = unsubstitutedMemberScope
override fun getDeclaredCallableMembers(): List<CallableMemberDescriptor> =
DescriptorUtils.getAllDescriptors(unsubstitutedMemberScope).filterIsInstance<CallableMemberDescriptor>().filter {
it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE
}
override fun getScopeForClassHeaderResolution(): LexicalScope = resolutionScopesSupport.scopeForClassHeaderResolution()
override fun getScopeForConstructorHeaderResolution(): LexicalScope = resolutionScopesSupport.scopeForConstructorHeaderResolution()
override fun getScopeForCompanionObjectHeaderResolution(): LexicalScope = resolutionScopesSupport.scopeForCompanionObjectHeaderResolution()
override fun getScopeForMemberDeclarationResolution(): LexicalScope = resolutionScopesSupport.scopeForMemberDeclarationResolution()
override fun getScopeForStaticMemberDeclarationResolution(): LexicalScope = resolutionScopesSupport.scopeForStaticMemberDeclarationResolution()
override fun getScopeForInitializerResolution(): LexicalScope = throw UnsupportedOperationException("Not supported for synthetic class or object")
override fun toString(): String = "synthetic class " + name.toString() + " in " + containingDeclaration
private fun createUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor {
val constructor = DescriptorFactory.createPrimaryConstructorForObject(thisDescriptor, source)
constructor.returnType = getDefaultType()
return constructor
}
private inner class SyntheticTypeConstructor(storageManager: StorageManager) : AbstractClassTypeConstructor(storageManager) {
override fun getParameters(): List<TypeParameterDescriptor> = emptyList()
override fun isFinal(): Boolean = true
override fun isDenotable(): Boolean = true
override fun getDeclarationDescriptor(): ClassifierDescriptor = thisDescriptor
override fun computeSupertypes(): Collection<KotlinType> = syntheticSupertypes
override val supertypeLoopChecker: SupertypeLoopChecker = SupertypeLoopChecker.EMPTY
}
private class SyntheticClassMemberDeclarationProvider(
override val correspondingClassOrObject: KtPureClassOrObject
) : ClassMemberDeclarationProvider {
override val ownerInfo: KtClassLikeInfo? = null
override fun getDeclarations(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List<KtDeclaration> = emptyList()
override fun getFunctionDeclarations(name: Name): Collection<KtNamedFunction> = emptyList()
override fun getPropertyDeclarations(name: Name): Collection<KtProperty> = emptyList()
override fun getClassOrObjectDeclarations(name: Name): Collection<KtClassLikeInfo> = emptyList()
override fun getTypeAliasDeclarations(name: Name): Collection<KtTypeAlias> = emptyList()
}
internal inner class SyntheticDeclaration(
private val _parent: KtPureElement,
private val _name: String
) : KtPureClassOrObject {
fun descriptor() = thisDescriptor
override fun getName(): String? = _name
override fun isLocal(): Boolean = false
override fun getDeclarations(): List<KtDeclaration> = emptyList()
override fun getSuperTypeListEntries(): List<KtSuperTypeListEntry> = emptyList()
override fun getCompanionObjects(): List<KtObjectDeclaration> = emptyList()
override fun hasExplicitPrimaryConstructor(): Boolean = false
override fun hasPrimaryConstructor(): Boolean = false
override fun getPrimaryConstructor(): KtPrimaryConstructor? = null
override fun getPrimaryConstructorModifierList(): KtModifierList? = null
override fun getPrimaryConstructorParameters(): List<KtParameter> = emptyList()
override fun getSecondaryConstructors(): List<KtSecondaryConstructor> = emptyList()
override fun getPsiOrParent() = _parent.psiOrParent
override fun getParent() = _parent.psiOrParent
override fun getContainingKtFile() = _parent.containingKtFile
}
}
fun KtPureElement.findClassDescriptor(bindingContext: BindingContext): ClassDescriptor = when (this) {
is PsiElement -> BindingContextUtils.getNotNull(bindingContext, BindingContext.CLASS, this)
is SyntheticClassOrObjectDescriptor.SyntheticDeclaration -> descriptor()
else -> throw IllegalArgumentException("$this shall be PsiElement or SyntheticClassOrObjectDescriptor.SyntheticDeclaration")
}
@@ -21,13 +21,14 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
class DelegationResolver<T : CallableMemberDescriptor> private constructor(
private val classOrObject: KtClassOrObject,
private val classOrObject: KtPureClassOrObject,
private val ownerDescriptor: ClassDescriptor,
private val existingMembers: Collection<CallableDescriptor>,
private val trace: BindingTrace,
@@ -68,7 +69,8 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
private fun checkClashWithOtherDelegatedMember(candidate: T, delegatedMembers: Collection<T>): Boolean {
val alreadyDelegated = delegatedMembers.firstOrNull { isOverridableBy(it, candidate) }
if (alreadyDelegated != null) {
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(classOrObject, classOrObject, alreadyDelegated))
if (classOrObject is KtClassOrObject) // report errors only for physical (non-synthetic) classes or objects
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(classOrObject, classOrObject, alreadyDelegated))
return true
}
return false
@@ -98,7 +100,7 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
companion object {
fun <T : CallableMemberDescriptor> generateDelegatedMembers(
classOrObject: KtClassOrObject,
classOrObject: KtPureClassOrObject,
ownerDescriptor: ClassDescriptor,
existingMembers: Collection<CallableDescriptor>,
trace: BindingTrace,
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import kotlin.Pair;
import kotlin.collections.CollectionsKt;
@@ -47,6 +48,7 @@ import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor;
import org.jetbrains.kotlin.resolve.scopes.*;
@@ -82,6 +84,7 @@ public class DescriptorResolver {
private final FunctionsTypingVisitor functionsTypingVisitor;
private final DestructuringDeclarationResolver destructuringDeclarationResolver;
private final ModifiersChecker modifiersChecker;
private final SyntheticResolveExtension syntheticResolveExtension;
public DescriptorResolver(
@NotNull AnnotationResolver annotationResolver,
@@ -95,7 +98,8 @@ public class DescriptorResolver {
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull FunctionsTypingVisitor functionsTypingVisitor,
@NotNull DestructuringDeclarationResolver destructuringDeclarationResolver,
@NotNull ModifiersChecker modifiersChecker
@NotNull ModifiersChecker modifiersChecker,
@NotNull Project project
) {
this.annotationResolver = annotationResolver;
this.builtIns = builtIns;
@@ -109,16 +113,18 @@ public class DescriptorResolver {
this.functionsTypingVisitor = functionsTypingVisitor;
this.destructuringDeclarationResolver = destructuringDeclarationResolver;
this.modifiersChecker = modifiersChecker;
this.syntheticResolveExtension = SyntheticResolveExtension.Companion.getInstance(project);
}
public List<KotlinType> resolveSupertypes(
@NotNull LexicalScope scope,
@NotNull ClassDescriptor classDescriptor,
@NotNull KtClassOrObject jetClass,
@Nullable KtPureClassOrObject correspondingClassOrObject,
BindingTrace trace
) {
List<KotlinType> supertypes = Lists.newArrayList();
List<KtSuperTypeListEntry> delegationSpecifiers = jetClass.getSuperTypeListEntries();
List<KtSuperTypeListEntry> delegationSpecifiers = correspondingClassOrObject == null ? Collections.<KtSuperTypeListEntry>emptyList() :
correspondingClassOrObject.getSuperTypeListEntries();
Collection<KotlinType> declaredSupertypes = resolveSuperTypeListEntries(
scope,
delegationSpecifiers,
@@ -132,8 +138,11 @@ public class DescriptorResolver {
supertypes.add(0, builtIns.getEnumType(classDescriptor.getDefaultType()));
}
syntheticResolveExtension.addSyntheticSupertypes(classDescriptor, supertypes);
if (supertypes.isEmpty()) {
KotlinType defaultSupertype = getDefaultSupertype(jetClass, trace, classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS);
KotlinType defaultSupertype = correspondingClassOrObject == null ? builtIns.getAnyType() :
getDefaultSupertype(correspondingClassOrObject, trace, classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS);
addValidSupertype(supertypes, defaultSupertype);
}
@@ -146,7 +155,7 @@ public class DescriptorResolver {
}
}
private boolean containsClass(Collection<KotlinType> result) {
private static boolean containsClass(Collection<KotlinType> result) {
for (KotlinType type : result) {
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.INTERFACE) {
@@ -156,16 +165,17 @@ public class DescriptorResolver {
return false;
}
private KotlinType getDefaultSupertype(KtClassOrObject jetClass, BindingTrace trace, boolean isAnnotation) {
private KotlinType getDefaultSupertype(KtPureClassOrObject ktClass, BindingTrace trace, boolean isAnnotation) {
// TODO : beautify
if (jetClass instanceof KtEnumEntry) {
KtClassOrObject parent = KtStubbedPsiUtil.getContainingDeclaration(jetClass, KtClassOrObject.class);
if (ktClass instanceof KtEnumEntry) {
KtEnumEntry enumEntry = (KtEnumEntry) ktClass;
KtClassOrObject parent = KtStubbedPsiUtil.getContainingDeclaration(enumEntry, KtClassOrObject.class);
ClassDescriptor parentDescriptor = trace.getBindingContext().get(BindingContext.CLASS, parent);
if (parentDescriptor.getTypeConstructor().getParameters().isEmpty()) {
return parentDescriptor.getDefaultType();
}
else {
trace.report(NO_GENERICS_IN_SUPERTYPE_SPECIFIER.on(jetClass.getNameIdentifier()));
trace.report(NO_GENERICS_IN_SUPERTYPE_SPECIFIER.on(enumEntry.getNameIdentifier()));
return ErrorUtils.createErrorType("Supertype not specified");
}
}
@@ -449,15 +459,15 @@ public class DescriptorResolver {
@NotNull
public static ClassConstructorDescriptorImpl createAndRecordPrimaryConstructorForObject(
@Nullable KtClassOrObject object,
@Nullable KtPureClassOrObject object,
@NotNull ClassDescriptor classDescriptor,
@NotNull BindingTrace trace
) {
ClassConstructorDescriptorImpl constructorDescriptor =
DescriptorFactory.createPrimaryConstructorForObject(classDescriptor, KotlinSourceElementKt.toSourceElement(object));
if (object != null) {
if (object instanceof PsiElement) {
KtPrimaryConstructor primaryConstructor = object.getPrimaryConstructor();
trace.record(CONSTRUCTOR, primaryConstructor != null ? primaryConstructor : object, constructorDescriptor);
trace.record(CONSTRUCTOR, primaryConstructor != null ? primaryConstructor : (PsiElement)object, constructorDescriptor);
}
return constructorDescriptor;
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
@@ -251,7 +252,7 @@ class FunctionDescriptorResolver(
fun resolvePrimaryConstructorDescriptor(
scope: LexicalScope,
classDescriptor: ClassDescriptor,
classElement: KtClassOrObject,
classElement: KtPureClassOrObject,
trace: BindingTrace
): ClassConstructorDescriptorImpl? {
if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY || !classElement.hasPrimaryConstructor()) return null
@@ -288,7 +289,7 @@ class FunctionDescriptorResolver(
classDescriptor: ClassDescriptor,
isPrimary: Boolean,
modifierList: KtModifierList?,
declarationToTrace: KtDeclaration,
declarationToTrace: KtPureElement,
valueParameters: List<KtParameter>,
trace: BindingTrace
): ClassConstructorDescriptorImpl {
@@ -304,7 +305,8 @@ class FunctionDescriptorResolver(
if (classDescriptor.isImpl) {
constructorDescriptor.isImpl = true
}
trace.record(BindingContext.CONSTRUCTOR, declarationToTrace, constructorDescriptor)
if (declarationToTrace is PsiElement)
trace.record(BindingContext.CONSTRUCTOR, declarationToTrace, constructorDescriptor)
val parameterScope = LexicalWritableScope(
scope,
constructorDescriptor,
@@ -0,0 +1,73 @@
/*
* Copyright 2010-2016 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.resolve.extensions
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.descriptors.ClassDescriptor
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.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import java.util.*
//----------------------------------------------------------------
// extension interface
interface SyntheticResolveExtension {
companion object : ProjectExtensionDescriptor<SyntheticResolveExtension>(
"org.jetbrains.kotlin.syntheticResolveExtension", SyntheticResolveExtension::class.java) {
fun getInstance(project: Project): SyntheticResolveExtension {
val instances = getInstances(project)
if (instances.size == 1) return instances.single()
// return list combiner here
return object : SyntheticResolveExtension {
override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? =
instances.firstNotNullResult { it.getSyntheticCompanionObjectNameIfNeeded(thisDescriptor) }
override fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) =
instances.forEach { it.addSyntheticSupertypes(thisDescriptor, supertypes) }
override fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, name: Name,
fromSupertypes: List<SimpleFunctionDescriptor>,
result: MutableCollection<SimpleFunctionDescriptor>) =
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) }
}
}
}
fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name?
fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {}
fun generateSyntheticMethods(thisDescriptor: ClassDescriptor,
name: Name,
fromSupertypes: List<SimpleFunctionDescriptor>,
result: MutableCollection<SimpleFunctionDescriptor>) {}
fun generateSyntheticProperties(thisDescriptor: ClassDescriptor,
name: Name,
fromSupertypes:
ArrayList<PropertyDescriptor>,
result: MutableSet<PropertyDescriptor>) {}
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.storage.StorageManager
@@ -38,4 +39,5 @@ interface LazyClassContext {
val lookupTracker: LookupTracker
val supertypeLoopChecker: SupertypeLoopChecker
val languageVersionSettings: LanguageVersionSettings
val syntheticResolveExtension: SyntheticResolveExtension
}
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension;
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo;
import org.jetbrains.kotlin.resolve.lazy.data.KtClassOrObjectInfo;
import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo;
@@ -81,6 +82,8 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
private SupertypeLoopChecker supertypeLoopsResolver;
private LanguageVersionSettings languageVersionSettings;
private final SyntheticResolveExtension syntheticResolveExtension;
@Inject
public void setJetImportFactory(KtImportsFactory jetImportFactory) {
this.jetImportFactory = jetImportFactory;
@@ -192,6 +195,8 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
return createAnnotations(file, file.getDanglingAnnotations());
}
});
syntheticResolveExtension = SyntheticResolveExtension.Companion.getInstance(project);
}
private LazyAnnotations createAnnotations(KtFile file, List<KtAnnotationEntry> annotationEntries) {
@@ -439,4 +444,10 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
public LanguageVersionSettings getLanguageVersionSettings() {
return languageVersionSettings;
}
@NotNull
@Override
public SyntheticResolveExtension getSyntheticResolveExtension() {
return syntheticResolveExtension;
}
}
@@ -41,7 +41,7 @@ public interface KtClassLikeInfo extends KtDeclarationContainer {
@NotNull
PsiElement getScopeAnchor();
@Nullable
@Nullable // can be null in KtScript
KtClassOrObject getCorrespondingClassOrObject();
@Nullable
@@ -16,8 +16,15 @@
package org.jetbrains.kotlin.resolve.lazy.declarations
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
interface ClassMemberDeclarationProvider : DeclarationProvider {
fun getOwnerInfo(): KtClassLikeInfo
val ownerInfo: KtClassLikeInfo? // is null for synthetic classes/object that don't present in the source code
val correspondingClassOrObject: KtPureClassOrObject? get() = ownerInfo?.correspondingClassOrObject
val primaryConstructorParameters: List<KtParameter> get() = ownerInfo?.primaryConstructorParameters ?: emptyList()
val companionObjects: List<KtObjectDeclaration> get() = ownerInfo?.companionObjects ?: emptyList()
}
@@ -16,28 +16,25 @@
package org.jetbrains.kotlin.resolve.lazy.declarations
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
import org.jetbrains.kotlin.storage.StorageManager
class PsiBasedClassMemberDeclarationProvider(
storageManager: StorageManager,
private val classInfo: KtClassLikeInfo)
override val ownerInfo: KtClassLikeInfo)
: AbstractPsiBasedDeclarationProvider(storageManager), ClassMemberDeclarationProvider {
override fun getOwnerInfo() = classInfo
override fun doCreateIndex(index: AbstractPsiBasedDeclarationProvider.Index) {
for (declaration in classInfo.declarations) {
for (declaration in ownerInfo.declarations) {
index.putToIndex(declaration)
}
for (parameter in classInfo.primaryConstructorParameters) {
for (parameter in ownerInfo.primaryConstructorParameters) {
if (parameter.hasValOrVar()) {
index.putToIndex(parameter)
}
}
}
override fun toString() = "Declarations for $classInfo"
override fun toString() = "Declarations for $ownerInfo"
}
@@ -45,20 +45,23 @@ protected constructor(
) : MemberScopeImpl() {
protected val storageManager: StorageManager = c.storageManager
private val classDescriptors: MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> = storageManager.createMemoizedFunction { resolveClassDescriptor(it) }
private val classDescriptors: MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> = storageManager.createMemoizedFunction { doGetClasses(it) }
private val functionDescriptors: MemoizedFunctionToNotNull<Name, Collection<SimpleFunctionDescriptor>> = storageManager.createMemoizedFunction { doGetFunctions(it) }
private val propertyDescriptors: MemoizedFunctionToNotNull<Name, Collection<PropertyDescriptor>> = storageManager.createMemoizedFunction { doGetProperties(it) }
private val typeAliasDescriptors: MemoizedFunctionToNotNull<Name, Collection<TypeAliasDescriptor>> = storageManager.createMemoizedFunction { doGetTypeAliases(it) }
private fun resolveClassDescriptor(name: Name): List<ClassDescriptor> {
return declarationProvider.getClassOrObjectDeclarations(name).map {
private fun doGetClasses(name: Name): List<ClassDescriptor> {
val result = Sets.newLinkedHashSet<ClassDescriptor>()
declarationProvider.getClassOrObjectDeclarations(name).mapTo(result) {
if (it is KtScriptInfo)
LazyScriptDescriptor(c as ResolveSession, thisDescriptor, name, it)
else {
val isExternal = it.modifierList?.hasModifier(KtTokens.EXTERNAL_KEYWORD) ?: false
LazyClassDescriptor(c, thisDescriptor, name, it, isExternal)
}
}.toReadOnlyList()
}
getNonDeclaredClasses(name, result)
return result.toReadOnlyList()
}
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
@@ -95,6 +98,8 @@ protected constructor(
protected abstract fun getScopeForMemberDeclarationResolution(declaration: KtDeclaration): LexicalScope
protected abstract fun getNonDeclaredClasses(name: Name, result: MutableSet<ClassDescriptor>)
protected abstract fun getNonDeclaredFunctions(name: Name, result: MutableSet<SimpleFunctionDescriptor>)
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
@@ -65,6 +66,7 @@ import java.util.Collections;
import java.util.List;
import static kotlin.collections.CollectionsKt.firstOrNull;
import static org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC;
import static org.jetbrains.kotlin.diagnostics.Errors.CYCLIC_INHERITANCE_HIERARCHY;
import static org.jetbrains.kotlin.diagnostics.Errors.TYPE_PARAMETERS_IN_ENUM;
import static org.jetbrains.kotlin.resolve.BindingContext.TYPE;
@@ -80,6 +82,9 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
};
private final LazyClassContext c;
@Nullable // can be null in KtScript
private final KtClassOrObject classOrObject;
private final ClassMemberDeclarationProvider declarationProvider;
private final LazyClassTypeConstructor typeConstructor;
@@ -93,7 +98,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
private final Annotations annotations;
private final Annotations danglingAnnotations;
private final NullableLazyValue<LazyClassDescriptor> companionObjectDescriptor;
private final NullableLazyValue<ClassDescriptorWithResolutionScopes> companionObjectDescriptor;
private final MemoizedFunctionToNotNull<KtObjectDeclaration, ClassDescriptor> extraCompanionObjectDescriptors;
private final LazyClassMemberScope unsubstitutedMemberScope;
@@ -120,7 +125,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
);
this.c = c;
final KtClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
classOrObject = classLikeInfo.getCorrespondingClassOrObject();
if (classOrObject != null) {
this.c.getTrace().record(BindingContext.CLASS, classOrObject, this);
}
@@ -225,9 +230,9 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
);
}
this.companionObjectDescriptor = storageManager.createNullableLazyValue(new Function0<LazyClassDescriptor>() {
this.companionObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptorWithResolutionScopes>() {
@Override
public LazyClassDescriptor invoke() {
public ClassDescriptorWithResolutionScopes invoke() {
return computeCompanionObjectDescriptor(getCompanionObjectIfAllowed());
}
});
@@ -411,7 +416,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
}
@Override
public LazyClassDescriptor getCompanionObjectDescriptor() {
public ClassDescriptorWithResolutionScopes getCompanionObjectDescriptor() {
return companionObjectDescriptor.invoke();
}
@@ -440,7 +445,9 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
}
@Nullable
private LazyClassDescriptor computeCompanionObjectDescriptor(@Nullable KtObjectDeclaration companionObject) {
private ClassDescriptorWithResolutionScopes computeCompanionObjectDescriptor(@Nullable KtObjectDeclaration companionObject) {
if (companionObject == null)
return createSyntheticCompanionObjectDescriptor();
KtClassLikeInfo companionObjectInfo = getCompanionObjectInfo(companionObject);
if (!(companionObjectInfo instanceof KtClassOrObjectInfo)) {
return null;
@@ -449,15 +456,26 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
assert name != null;
getUnsubstitutedMemberScope().getContributedClassifier(name, NoLookupLocation.WHEN_GET_COMPANION_OBJECT);
ClassDescriptor companionObjectDescriptor = c.getTrace().get(BindingContext.CLASS, companionObject);
if (companionObjectDescriptor instanceof LazyClassDescriptor) {
if (companionObjectDescriptor instanceof ClassDescriptorWithResolutionScopes) {
assert DescriptorUtils.isCompanionObject(companionObjectDescriptor) : "Not a companion object: " + companionObjectDescriptor;
return (LazyClassDescriptor) companionObjectDescriptor;
return (ClassDescriptorWithResolutionScopes)companionObjectDescriptor;
}
else {
return null;
}
}
private ClassDescriptorWithResolutionScopes createSyntheticCompanionObjectDescriptor() {
Name syntheticCompanionName = c.getSyntheticResolveExtension().getSyntheticCompanionObjectNameIfNeeded(this);
if (syntheticCompanionName == null)
return null;
return new SyntheticClassOrObjectDescriptor(c,
/* parentClassOrObject= */ classOrObject,
this, syntheticCompanionName, getSource(),
/* outerScope= */ getOuterScope(),
Modality.FINAL, PUBLIC, ClassKind.OBJECT, true);
}
@Nullable
private static KtClassLikeInfo getCompanionObjectInfo(@Nullable KtObjectDeclaration companionObject) {
if (companionObject != null) {
@@ -49,9 +49,9 @@ import java.util.*
open class LazyClassMemberScope(
c: LazyClassContext,
declarationProvider: ClassMemberDeclarationProvider,
thisClass: LazyClassDescriptor,
thisClass: ClassDescriptorWithResolutionScopes,
trace: BindingTrace
) : AbstractLazyMemberScope<LazyClassDescriptor, ClassMemberDeclarationProvider>(c, declarationProvider, thisClass, trace) {
) : AbstractLazyMemberScope<ClassDescriptorWithResolutionScopes, ClassMemberDeclarationProvider>(c, declarationProvider, thisClass, trace) {
private val descriptorsFromDeclaredElements = storageManager.createLazyValue {
computeDescriptorsFromDeclaredElements(DescriptorKindFilter.ALL, MemberScope.ALL_NAME_FILTER, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
@@ -82,6 +82,7 @@ open class LazyClassMemberScope(
}
addDataClassMethods(result, location)
addSyntheticCompanionObject(result, location)
result.trimToSize()
return result
@@ -129,6 +130,10 @@ open class LazyClassMemberScope(
return functions
}
override fun getNonDeclaredClasses(name: Name, result: MutableSet<ClassDescriptor>) {
generateSyntheticCompanionObject(name, result)
}
override fun getNonDeclaredFunctions(name: Name, result: MutableSet<SimpleFunctionDescriptor>) {
val location = NoLookupLocation.FOR_ALREADY_TRACKED
@@ -138,6 +143,7 @@ open class LazyClassMemberScope(
}
result.addAll(generateDelegatingDescriptors(name, EXTRACT_FUNCTIONS, result))
generateDataClassMethods(result, name, location, fromSupertypes)
c.syntheticResolveExtension.generateSyntheticMethods(thisDescriptor, name, fromSupertypes, result)
generateFakeOverrides(name, fromSupertypes, result, SimpleFunctionDescriptor::class.java)
}
@@ -150,8 +156,8 @@ open class LazyClassMemberScope(
if (!thisDescriptor.isData) return
val constructor = getPrimaryConstructor() ?: return
val primaryConstructorParameters = declarationProvider.primaryConstructorParameters
val primaryConstructorParameters = declarationProvider.getOwnerInfo().primaryConstructorParameters
assert(constructor.valueParameters.size == primaryConstructorParameters.size) { "From descriptor: " + constructor.valueParameters.size + " but from PSI: " + primaryConstructorParameters.size }
if (DataClassDescriptorResolver.isComponentLike(name)) {
@@ -210,6 +216,21 @@ open class LazyClassMemberScope(
}
}
private fun addSyntheticCompanionObject(result: MutableCollection<DeclarationDescriptor>, location: LookupLocation) {
val syntheticCompanionName = c.syntheticResolveExtension.getSyntheticCompanionObjectNameIfNeeded(thisDescriptor) ?: return
val descriptor = getContributedClassifier(syntheticCompanionName, location) ?: return
result.add(descriptor)
}
private fun generateSyntheticCompanionObject(name: Name, result: MutableSet<ClassDescriptor>) {
val syntheticCompanionName = c.syntheticResolveExtension.getSyntheticCompanionObjectNameIfNeeded(thisDescriptor) ?: return
if (name == syntheticCompanionName && result.none { it.isCompanionObject }) {
// forces creation of companion object if needed
val companionObjectDescriptor = thisDescriptor.companionObjectDescriptor ?: return
result.add(companionObjectDescriptor)
}
}
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
// TODO: this should be handled by lazy property descriptors
val properties = super.getContributedVariables(name, location)
@@ -235,17 +256,17 @@ open class LazyClassMemberScope(
fromSupertypes.addAll(supertype.memberScope.getContributedVariables(name, NoLookupLocation.FOR_ALREADY_TRACKED))
}
result.addAll(generateDelegatingDescriptors(name, EXTRACT_PROPERTIES, result))
c.syntheticResolveExtension.generateSyntheticProperties(thisDescriptor, name, fromSupertypes, result)
generateFakeOverrides(name, fromSupertypes, result, PropertyDescriptor::class.java)
}
protected open fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet<PropertyDescriptor>) {
val classInfo = declarationProvider.getOwnerInfo()
// From primary constructor parameters
val primaryConstructor = getPrimaryConstructor() ?: return
val valueParameterDescriptors = primaryConstructor.valueParameters
val primaryConstructorParameters = classInfo.primaryConstructorParameters
val primaryConstructorParameters = declarationProvider.primaryConstructorParameters
assert(valueParameterDescriptors.size == primaryConstructorParameters.size) {
"From descriptor: ${valueParameterDescriptors.size} but from PSI: ${primaryConstructorParameters.size}"
}
@@ -264,8 +285,7 @@ open class LazyClassMemberScope(
}
private fun <T : CallableMemberDescriptor> generateDelegatingDescriptors(name: Name, extractor: MemberExtractor<T>, existingDescriptors: Collection<CallableDescriptor>): Collection<T> {
val classOrObject = declarationProvider.getOwnerInfo().correspondingClassOrObject
?: return setOf()
val classOrObject = declarationProvider.correspondingClassOrObject ?: return setOf()
val lazyTypeResolver = object : DelegationResolver.TypeResolver {
override fun resolve(reference: KtTypeReference): KotlinType? =
@@ -309,8 +329,7 @@ open class LazyClassMemberScope(
fun getPrimaryConstructor(): ClassConstructorDescriptor? = primaryConstructor()
protected open fun resolvePrimaryConstructor(): ClassConstructorDescriptor? {
val ownerInfo = declarationProvider.getOwnerInfo()
val classOrObject = ownerInfo.correspondingClassOrObject ?: return null
val classOrObject = declarationProvider.correspondingClassOrObject ?: return null
val hasPrimaryConstructor = classOrObject.hasExplicitPrimaryConstructor()
if (DescriptorUtils.isInterface(thisDescriptor) && !hasPrimaryConstructor) return null
@@ -330,7 +349,7 @@ open class LazyClassMemberScope(
}
private fun resolveSecondaryConstructors(): Collection<ClassConstructorDescriptor> {
val classOrObject = declarationProvider.getOwnerInfo().correspondingClassOrObject ?: return emptyList()
val classOrObject = declarationProvider.correspondingClassOrObject ?: return emptyList()
return classOrObject.getSecondaryConstructors().map { constructor ->
val descriptor = c.functionDescriptorResolver.resolveSecondaryConstructorDescriptor(
@@ -16,10 +16,7 @@
package org.jetbrains.kotlin.resolve.lazy.descriptors
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.incremental.record
@@ -42,6 +39,10 @@ class LazyPackageMemberScope(
override fun getScopeForMemberDeclarationResolution(declaration: KtDeclaration)
= resolveSession.fileScopeProvider.getFileResolutionScope(declaration.getContainingKtFile())
override fun getNonDeclaredClasses(name: Name, result: MutableSet<ClassDescriptor>) {
// No extra classes
}
override fun getNonDeclaredFunctions(name: Name, result: MutableSet<SimpleFunctionDescriptor>) {
// No extra functions
}
@@ -16,12 +16,13 @@
package org.jetbrains.kotlin.resolve.source
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.descriptors.SourceElement
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtPureElement
class KotlinSourceElement(override val psi: KtElement) : PsiSourceElement
fun KtElement?.toSourceElement(): SourceElement = if (this == null) SourceElement.NO_SOURCE else KotlinSourceElement(this)
fun KtPureElement?.toSourceElement(): SourceElement = if (this == null) SourceElement.NO_SOURCE else KotlinSourceElement(psiOrParent)
fun SourceElement.getPsi(): PsiElement? = (this as? PsiSourceElement)?.psi
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.data.KtClassInfoUtil
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
@@ -68,7 +69,8 @@ class LocalClassifierAnalyzer(
classOrObject: KtClassOrObject
) {
val module = DescriptorUtils.getContainingModule(containingDeclaration)
val moduleContext = globalContext.withProject(classOrObject.getProject()).withModule(module)
val project = classOrObject.getProject()
val moduleContext = globalContext.withProject(project).withModule(module)
val container = createContainerForLazyLocalClassifierAnalyzer(
moduleContext,
context.trace,
@@ -88,7 +90,8 @@ class LocalClassifierAnalyzer(
typeResolver,
annotationResolver,
supertypeLoopChecker,
languageVersionSettings
languageVersionSettings,
SyntheticResolveExtension.getInstance(project)
)
)
@@ -112,7 +115,8 @@ class LocalClassDescriptorHolder(
val typeResolver: TypeResolver,
val annotationResolver: AnnotationResolver,
val supertypeLoopChecker: SupertypeLoopChecker,
val languageVersionSettings: LanguageVersionSettings
val languageVersionSettings: LanguageVersionSettings,
val syntheticResolveExtension: SyntheticResolveExtension
) {
// We do not need to synchronize here, because this code is used strictly from one thread
private var classDescriptor: ClassDescriptor? = null
@@ -149,6 +153,7 @@ class LocalClassDescriptorHolder(
override val lookupTracker: LookupTracker = LookupTracker.DO_NOTHING
override val supertypeLoopChecker = this@LocalClassDescriptorHolder.supertypeLoopChecker
override val languageVersionSettings = this@LocalClassDescriptorHolder.languageVersionSettings
override val syntheticResolveExtension = this@LocalClassDescriptorHolder.syntheticResolveExtension
}
,
containingDeclaration,
@@ -153,12 +153,13 @@ private object JvmTypeFactoryImpl : JvmTypeFactory<JvmType> {
}
private object TypeMappingConfigurationImpl : TypeMappingConfiguration<JvmType> {
internal object TypeMappingConfigurationImpl : TypeMappingConfiguration<JvmType> {
override fun commonSupertype(types: Collection<KotlinType>): KotlinType {
throw AssertionError("There should be no intersection type in existing descriptors, but found: " + types.joinToString())
}
override fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor) = null
override fun getPredefinedInternalNameForClass(classDescriptor: ClassDescriptor): String? = null
override fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) {
// DO nothing
@@ -51,6 +51,7 @@ interface TypeMappingConfiguration<out T : Any> {
fun commonSupertype(types: Collection<@JvmSuppressWildcards KotlinType>): KotlinType
fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor): T?
fun getPredefinedInternalNameForClass(classDescriptor: ClassDescriptor): String?
fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor)
}
@@ -133,7 +134,7 @@ fun <T : Any> mapType(
factory.javaLangClassType
else
typeMappingConfiguration.getPredefinedTypeForClass(descriptor.original)
?: factory.createObjectType(computeInternalName(descriptor.original, typeMappingConfiguration.innerClassNameFactory))
?: factory.createObjectType(computeInternalName(descriptor.original, typeMappingConfiguration))
writeGenericType(kotlinType, jvmType, mode)
@@ -189,7 +190,7 @@ private fun <T : Any> mapBuiltInType(
internal fun computeInternalName(
klass: ClassDescriptor,
innerClassNameFactory: (outer: String, inner: String) -> String = TypeMappingConfiguration.DEFAULT_INNER_CLASS_NAME_FACTORY
typeMappingConfiguration: TypeMappingConfiguration<*> = TypeMappingConfigurationImpl
): String {
val container = klass.containingDeclaration
@@ -199,10 +200,14 @@ internal fun computeInternalName(
return if (fqName.isRoot) name else fqName.asString().replace('.', '/') + '/' + name
}
assert(container is ClassDescriptor) { "Unexpected container: $container for $klass" }
val containerClass = container as? ClassDescriptor ?:
throw IllegalArgumentException("Unexpected container: $container for $klass")
val containerInternalName = computeInternalName(container as ClassDescriptor, innerClassNameFactory)
return if (klass.kind == ClassKind.ENUM_ENTRY) containerInternalName else innerClassNameFactory(containerInternalName, name)
val containerInternalName =
typeMappingConfiguration.getPredefinedInternalNameForClass(containerClass) ?:
computeInternalName(containerClass, typeMappingConfiguration)
return if (klass.kind == ClassKind.ENUM_ENTRY) containerInternalName
else typeMappingConfiguration.innerClassNameFactory(containerInternalName, name)
}
private fun getRepresentativeUpperBound(descriptor: TypeParameterDescriptor): KotlinType {
@@ -868,12 +868,12 @@ public abstract class KotlinBuiltIns {
return getPrimitiveTypeByFqName(getFqName(descriptor)) != null;
}
private static boolean isConstructedFromGivenClass(@NotNull KotlinType type, @NotNull FqNameUnsafe fqName) {
public static boolean isConstructedFromGivenClass(@NotNull KotlinType type, @NotNull FqNameUnsafe fqName) {
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
return descriptor instanceof ClassDescriptor && classFqNameEquals(descriptor, fqName);
}
private static boolean isConstructedFromGivenClass(@NotNull KotlinType type, @NotNull FqName fqName) {
public static boolean isConstructedFromGivenClass(@NotNull KotlinType type, @NotNull FqName fqName) {
return isConstructedFromGivenClass(type, fqName.toUnsafe());
}
+3
View File
@@ -11,6 +11,9 @@
<extensionPoint name="expressionCodegenExtension"
interface="org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension"
area="IDEA_PROJECT"/>
<extensionPoint name="syntheticResolveExtension"
interface="org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension"
area="IDEA_PROJECT"/>
<extensionPoint name="findUsagesHandlerDecorator"
interface="org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator"
area="IDEA_PROJECT"/>
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFunction
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.FunctionCodegen
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.codegen.state.GenerationState
@@ -245,13 +246,14 @@ class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
return (extensionReceiver as ReceiverValue).type.constructor.declarationDescriptor
}
override fun generateClassSyntheticParts(
classBuilder: ClassBuilder,
state: GenerationState,
classOrObject: KtClassOrObject,
descriptor: ClassDescriptor
) {
override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {
val classBuilder = codegen.v
val state = codegen.state
val classOrObject = codegen.myClass
val descriptor = codegen.descriptor
if (descriptor.kind != ClassKind.CLASS || descriptor.isInner || DescriptorUtils.isLocal(descriptor)) return
if (classOrObject !is KtClassOrObject) return // works only only on physical classes, not synthetic ones
// Do not generate anything if class is not supported
val androidClassType = AndroidClassType.getClassType(descriptor)