From 8affb2726f272901c554935ca6b8ea8f0f92902d Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Thu, 3 Nov 2016 12:54:25 +0300 Subject: [PATCH] Pluggable Synthetic Objects --- .../kotlin/backend/common/CodegenUtil.kt | 20 +++ .../common/DataClassMethodGenerator.kt | 38 ++--- .../kotlin/codegen/ClassBodyCodegen.java | 25 ++- .../codegen/CollectionStubMethodGenerator.kt | 2 +- .../DefaultParameterValueSubstitutor.kt | 12 +- .../kotlin/codegen/ExpressionCodegen.java | 2 +- .../kotlin/codegen/FunctionCodegen.java | 19 ++- .../codegen/ImplementationBodyCodegen.java | 82 ++++----- .../codegen/InterfaceImplBodyCodegen.kt | 9 +- .../kotlin/codegen/MemberCodegen.java | 47 ++++-- .../kotlin/codegen/SamWrapperCodegen.java | 2 +- .../jetbrains/kotlin/codegen/StackValue.java | 2 +- .../jetbrains/kotlin/codegen/codegenUtil.kt | 2 +- .../extensions/ExpressionCodegenExtension.kt | 18 +- .../codegen/state/KotlinTypeMapper.java | 9 +- .../cli/jvm/compiler/KotlinCoreEnvironment.kt | 2 + .../resolve/jvm/diagnostics/ErrorsJvm.java | 2 +- .../jvm/diagnostics/JvmDeclarationOrigin.kt | 17 +- .../extensions/ProjectExtensionDescriptor.kt | 6 +- .../src/org/jetbrains/kotlin/psi/KtClass.kt | 2 +- .../jetbrains/kotlin/psi/KtClassOrObject.kt | 32 ++-- .../src/org/jetbrains/kotlin/psi/KtElement.kt | 4 +- .../jetbrains/kotlin/psi/KtElementImpl.java | 6 + .../kotlin/psi/KtElementImplStub.java | 6 + .../src/org/jetbrains/kotlin/psi/KtFile.java | 6 + .../kotlin/psi/KtLambdaExpression.java | 6 + .../kotlin/psi/KtObjectDeclaration.kt | 2 + .../kotlin/psi/KtPureClassOrObject.java | 61 +++++++ .../jetbrains/kotlin/psi/KtPureElement.java | 42 +++++ .../SyntheticClassOrObjectDescriptor.kt | 158 ++++++++++++++++++ .../kotlin/resolve/DelegationResolver.kt | 8 +- .../kotlin/resolve/DescriptorResolver.java | 34 ++-- .../resolve/FunctionDescriptorResolver.kt | 8 +- .../extensions/SyntheticResolveExtension.kt | 73 ++++++++ .../kotlin/resolve/lazy/LazyClassContext.kt | 2 + .../kotlin/resolve/lazy/ResolveSession.java | 11 ++ .../resolve/lazy/data/KtClassLikeInfo.java | 2 +- .../ClassMemberDeclarationProvider.kt | 9 +- .../PsiBasedClassMemberDeclarationProvider.kt | 13 +- .../descriptors/AbstractLazyMemberScope.kt | 13 +- .../lazy/descriptors/LazyClassDescriptor.java | 34 +++- .../lazy/descriptors/LazyClassMemberScope.kt | 39 +++-- .../descriptors/LazyPackageMemberScope.kt | 9 +- .../resolve/source/KotlinSourceElement.kt | 7 +- .../expressions/LocalClassifierAnalyzer.kt | 11 +- .../load/kotlin/methodSignatureMapping.kt | 3 +- .../load/kotlin/typeSignatureMapping.kt | 15 +- .../kotlin/builtins/KotlinBuiltIns.java | 4 +- idea/src/META-INF/extensions/common.xml | 3 + .../AndroidExpressionCodegenExtension.kt | 14 +- 50 files changed, 731 insertions(+), 222 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/psi/KtPureClassOrObject.java create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/psi/KtPureElement.java create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt index 6b1f1e638db..cc2b9563bdd 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt @@ -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) -> 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!!) + } } diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/DataClassMethodGenerator.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/DataClassMethodGenerator.kt index 9d511dde775..94e0ab24497 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/DataClassMethodGenerator.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/DataClassMethodGenerator.kt @@ -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) { - val function = getMemberToGenerate("toString", KotlinBuiltIns::isString, List::isEmpty) ?: return + val function = getMemberToGenerate(classDescriptor, "toString", + KotlinBuiltIns::isString, List::isEmpty) ?: return generateToStringMethod(function, properties) } private fun generateDataClassHashCodeIfNeeded(properties: List) { - val function = getMemberToGenerate("hashCode", KotlinBuiltIns::isInt, List::isEmpty) ?: return + val function = getMemberToGenerate(classDescriptor, "hashCode", + KotlinBuiltIns::isInt, List::isEmpty) ?: return generateHashCodeMethod(function, properties) } private fun generateDataClassEqualsIfNeeded(properties: List) { - 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 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) -> 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!!) - } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBodyCodegen.java index 776376ee568..6bdca2dfe34 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBodyCodegen.java @@ -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 { - protected final KtClassOrObject myClass; - protected final OwnerKind kind; - protected final ClassDescriptor descriptor; +public abstract class ClassBodyCodegen extends MemberCodegen { + 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 { 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 { 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 { @NotNull protected List getPrimaryConstructorParameters() { if (myClass instanceof KtClass) { - return ((KtClass) myClass).getPrimaryConstructorParameters(); + return myClass.getPrimaryConstructorParameters(); } return Collections.emptyList(); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt index 34d1c0bdd7b..fb440ff4f1f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt @@ -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") } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt index 4e5fcaa99ab..c170ef857d3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt @@ -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 diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 189f7313dcf..9309ea57022 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -127,7 +127,7 @@ public class ExpressionCodegen extends KtVisitor 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); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 51d9cf1ab0a..c0e94fd4a77 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -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); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 715db12a6f7..0855a1b9d19 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -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>(); 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 InstructionAdapter v = createOrGetClInitCodegen().v; - markLineNumberForElement(element, v); + markLineNumberForElement(element.getPsiOrParent(), v); v.anew(classAsmType); v.invokespecial(classAsmType.getInternalName(), "", "()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) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt index fe0440b216a..96c35c767d4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/InterfaceImplBodyCodegen.kt @@ -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? { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 42fc4b4d3a6..ea1063d40e5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -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 implements InnerClassConsumer { - protected final GenerationState state; +public abstract class MemberCodegen 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 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", "()V", null, null); } @@ -599,7 +619,8 @@ public abstract class MemberCodegen, state:GenerationState + classDescriptor: ClassDescriptor, classElement: PsiElement, restrictedInheritance: List, state:GenerationState ) { if (!restrictedInheritance.isEmpty()) { val groupBy = restrictedInheritance.groupBy { descriptor -> descriptor.containingDeclaration as ClassDescriptor } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/extensions/ExpressionCodegenExtension.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/extensions/ExpressionCodegenExtension.kt index a79e405db40..984a83f5686 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/extensions/ExpressionCodegenExtension.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/extensions/ExpressionCodegenExtension.kt @@ -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( @@ -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) {} } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index af997d2f1f0..68b253ca40b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -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) { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index 313a632c789..72a5a1caaac 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -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) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index 2d42570eed1..b90ce68d6d6 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -87,7 +87,7 @@ public interface ErrorsJvm { DiagnosticFactory0 WHEN_ENUM_CAN_BE_NULL_IN_JAVA = DiagnosticFactory0.create(WARNING); - DiagnosticFactory3 TARGET6_INTERFACE_INHERITANCE = DiagnosticFactory3.create(ERROR); + DiagnosticFactory3 TARGET6_INTERFACE_INHERITANCE = DiagnosticFactory3.create(ERROR); @SuppressWarnings("UnusedDeclaration") Object _initializer = new Object() { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt index 1978fe35d62..4951c574a52 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt @@ -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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/extensions/ProjectExtensionDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/extensions/ProjectExtensionDescriptor.kt index e9659d320cc..3a671e455fc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/extensions/ProjectExtensionDescriptor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/extensions/ProjectExtensionDescriptor.kt @@ -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(name: String, private val extensionClass: Class) { val extensionPointName: ExtensionPointName = ExtensionPointName.create(name)!! @@ -36,7 +36,7 @@ open class ProjectExtensionDescriptor(name: String, private val extensionClas Extensions.getArea(project).getExtensionPoint(extensionPointName).registerExtension(extension) } - fun getInstances(project: Project): Collection { + fun getInstances(project: Project): List { val projectArea = Extensions.getArea(project) if (!projectArea.hasExtensionPoint(extensionPointName.name!!)) return listOf() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClass.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClass.kt index acba723b2ab..53f39fae056 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClass.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClass.kt @@ -83,7 +83,7 @@ open class KtClass : KtClassOrObject { return StringUtil.join(parts, ".") } - fun getCompanionObjects(): List = getBody()?.allCompanionObjects.orEmpty() + override fun getCompanionObjects(): List = getBody()?.allCompanionObjects.orEmpty() fun getClassOrInterfaceKeyword(): PsiElement? = findChildByType(TokenSet.create(KtTokens.CLASS_KEYWORD, KtTokens.INTERFACE_KEYWORD)) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt index a37893fcc83..aa5103d7c45 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt @@ -29,12 +29,13 @@ import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes abstract class KtClassOrObject : - KtTypeParameterListOwnerStub>, KtDeclarationContainer, KtNamedDeclaration { + KtTypeParameterListOwnerStub>, KtDeclarationContainer, KtNamedDeclaration, KtPureClassOrObject { constructor(node: ASTNode) : super(node) constructor(stub: KotlinClassOrObjectStub, nodeType: IStubElementType<*, *>) : super(stub, nodeType) fun getSuperTypeList(): KtSuperTypeList? = getStubOrPsiChild(KtStubElementTypes.SUPER_TYPE_LIST) - open fun getSuperTypeListEntries(): List = getSuperTypeList()?.entries.orEmpty() + + override fun getSuperTypeListEntries(): List = 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 = 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 = getPrimaryConstructorParameterList()?.parameters.orEmpty() + override fun getPrimaryConstructorModifierList(): KtModifierList? = primaryConstructor?.modifierList - fun hasExplicitPrimaryConstructor(): Boolean = getPrimaryConstructor() != null + fun getPrimaryConstructorParameterList(): KtParameterList? = primaryConstructor?.valueParameterList + + override fun getPrimaryConstructorParameters(): List = 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 = getBody()?.secondaryConstructors.orEmpty() + override fun getSecondaryConstructors(): List = 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() } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElement.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElement.kt index 0032167e9d7..2b8f846d8b1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElement.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElement.kt @@ -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 acceptChildren(visitor: KtVisitor, data: D) fun accept(visitor: KtVisitor, data: D): R diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElementImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElementImpl.java index 9b6e9883431..b4dd410f029 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElementImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElementImpl.java @@ -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; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElementImplStub.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElementImplStub.java index 3733d683fb3..a4890e0b246 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElementImplStub.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtElementImplStub.java @@ -111,4 +111,10 @@ public class KtElementImplStub> extends StubBasedPsiEle ) { return Arrays.asList(getStubOrPsiChildren(elementType, elementType.getArrayFactory())); } + + @NotNull + @Override + public KtElement getPsiOrParent() { + return this; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.java index 6cfdac15b6e..c7c0e6f1e6a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.java @@ -283,4 +283,10 @@ public class KtFile extends PsiFileBase implements KtDeclarationContainer, KtAnn } return result; } + + @NotNull + @Override + public KtElement getPsiOrParent() { + return this; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLambdaExpression.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLambdaExpression.java index 67cf76249e7..7ec9ec4d1ed 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLambdaExpression.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLambdaExpression.java @@ -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; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtObjectDeclaration.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtObjectDeclaration.kt index 0685ba8de85..807e047264c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtObjectDeclaration.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtObjectDeclaration.kt @@ -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 = emptyList() } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPureClassOrObject.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPureClassOrObject.java new file mode 100644 index 00000000000..b0c2dade269 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPureClassOrObject.java @@ -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 getSuperTypeListEntries(); + + @NotNull + @ReadOnly + List getCompanionObjects(); + + boolean hasExplicitPrimaryConstructor(); + + boolean hasPrimaryConstructor(); + + @Nullable + KtPrimaryConstructor getPrimaryConstructor(); + + @Nullable + KtModifierList getPrimaryConstructorModifierList(); + + @NotNull + @ReadOnly + List getPrimaryConstructorParameters(); + + @NotNull + @ReadOnly + List getSecondaryConstructors(); +} + diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPureElement.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPureElement.java new file mode 100644 index 00000000000..04685cdae72 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPureElement.java @@ -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(); +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt new file mode 100644 index 00000000000..6ed1bbb8949 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt @@ -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().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() + override fun getStaticScope() = MemberScope.Empty + override fun getUnsubstitutedMemberScope() = unsubstitutedMemberScope + + override fun getDeclaredCallableMembers(): List = + DescriptorUtils.getAllDescriptors(unsubstitutedMemberScope).filterIsInstance().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 = emptyList() + override fun isFinal(): Boolean = true + override fun isDenotable(): Boolean = true + override fun getDeclarationDescriptor(): ClassifierDescriptor = thisDescriptor + override fun computeSupertypes(): Collection = 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 = emptyList() + override fun getFunctionDeclarations(name: Name): Collection = emptyList() + override fun getPropertyDeclarations(name: Name): Collection = emptyList() + override fun getClassOrObjectDeclarations(name: Name): Collection = emptyList() + override fun getTypeAliasDeclarations(name: Name): Collection = 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 = emptyList() + override fun getSuperTypeListEntries(): List = emptyList() + override fun getCompanionObjects(): List = 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 = emptyList() + override fun getSecondaryConstructors(): List = 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") +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt index 105741e027f..8d069e38b31 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt @@ -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 private constructor( - private val classOrObject: KtClassOrObject, + private val classOrObject: KtPureClassOrObject, private val ownerDescriptor: ClassDescriptor, private val existingMembers: Collection, private val trace: BindingTrace, @@ -68,7 +69,8 @@ class DelegationResolver private constructor( private fun checkClashWithOtherDelegatedMember(candidate: T, delegatedMembers: Collection): 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 private constructor( companion object { fun generateDelegatedMembers( - classOrObject: KtClassOrObject, + classOrObject: KtPureClassOrObject, ownerDescriptor: ClassDescriptor, existingMembers: Collection, trace: BindingTrace, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 9938684c193..cab0b44535e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -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 resolveSupertypes( @NotNull LexicalScope scope, @NotNull ClassDescriptor classDescriptor, - @NotNull KtClassOrObject jetClass, + @Nullable KtPureClassOrObject correspondingClassOrObject, BindingTrace trace ) { List supertypes = Lists.newArrayList(); - List delegationSpecifiers = jetClass.getSuperTypeListEntries(); + List delegationSpecifiers = correspondingClassOrObject == null ? Collections.emptyList() : + correspondingClassOrObject.getSuperTypeListEntries(); Collection 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 result) { + private static boolean containsClass(Collection 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; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt index 7708ac0d853..0cdafdd53d2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt @@ -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, 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, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt new file mode 100644 index 00000000000..de838994a35 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extensions/SyntheticResolveExtension.kt @@ -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( + "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) = + instances.forEach { it.addSyntheticSupertypes(thisDescriptor, supertypes) } + + override fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, name: Name, + fromSupertypes: List, + result: MutableCollection) = + instances.forEach { it.generateSyntheticMethods(thisDescriptor, name, fromSupertypes, result) } + + override fun generateSyntheticProperties(thisDescriptor: ClassDescriptor, name: Name, + fromSupertypes: ArrayList, + result: MutableSet) = + instances.forEach { it.generateSyntheticProperties(thisDescriptor, name, fromSupertypes, result) } + } + } + } + + fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? + + fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList) {} + + fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, + name: Name, + fromSupertypes: List, + result: MutableCollection) {} + + fun generateSyntheticProperties(thisDescriptor: ClassDescriptor, + name: Name, + fromSupertypes: + ArrayList, + result: MutableSet) {} +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyClassContext.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyClassContext.kt index cffded68fda..a780ec5360c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyClassContext.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyClassContext.kt @@ -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 } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java index bf32842c951..d6aeb0687de 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java @@ -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 annotationEntries) { @@ -439,4 +444,10 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { public LanguageVersionSettings getLanguageVersionSettings() { return languageVersionSettings; } + + @NotNull + @Override + public SyntheticResolveExtension getSyntheticResolveExtension() { + return syntheticResolveExtension; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/data/KtClassLikeInfo.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/data/KtClassLikeInfo.java index a43eaf0da29..654c76c5cad 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/data/KtClassLikeInfo.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/data/KtClassLikeInfo.java @@ -41,7 +41,7 @@ public interface KtClassLikeInfo extends KtDeclarationContainer { @NotNull PsiElement getScopeAnchor(); - @Nullable + @Nullable // can be null in KtScript KtClassOrObject getCorrespondingClassOrObject(); @Nullable diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/ClassMemberDeclarationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/ClassMemberDeclarationProvider.kt index b265b4740ef..5d762d6d88c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/ClassMemberDeclarationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/ClassMemberDeclarationProvider.kt @@ -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 get() = ownerInfo?.primaryConstructorParameters ?: emptyList() + val companionObjects: List get() = ownerInfo?.companionObjects ?: emptyList() } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/PsiBasedClassMemberDeclarationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/PsiBasedClassMemberDeclarationProvider.kt index 054beacff30..a1f33bdf3cc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/PsiBasedClassMemberDeclarationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/PsiBasedClassMemberDeclarationProvider.kt @@ -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" } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/AbstractLazyMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/AbstractLazyMemberScope.kt index 2812ee4bb51..183503ba036 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/AbstractLazyMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/AbstractLazyMemberScope.kt @@ -45,20 +45,23 @@ protected constructor( ) : MemberScopeImpl() { protected val storageManager: StorageManager = c.storageManager - private val classDescriptors: MemoizedFunctionToNotNull> = storageManager.createMemoizedFunction { resolveClassDescriptor(it) } + private val classDescriptors: MemoizedFunctionToNotNull> = storageManager.createMemoizedFunction { doGetClasses(it) } private val functionDescriptors: MemoizedFunctionToNotNull> = storageManager.createMemoizedFunction { doGetFunctions(it) } private val propertyDescriptors: MemoizedFunctionToNotNull> = storageManager.createMemoizedFunction { doGetProperties(it) } private val typeAliasDescriptors: MemoizedFunctionToNotNull> = storageManager.createMemoizedFunction { doGetTypeAliases(it) } - private fun resolveClassDescriptor(name: Name): List { - return declarationProvider.getClassOrObjectDeclarations(name).map { + private fun doGetClasses(name: Name): List { + val result = Sets.newLinkedHashSet() + 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) + protected abstract fun getNonDeclaredFunctions(name: Name, result: MutableSet) override fun getContributedVariables(name: Name, location: LookupLocation): Collection { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index 65082acfdfb..4eb961f4da3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -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 companionObjectDescriptor; + private final NullableLazyValue companionObjectDescriptor; private final MemoizedFunctionToNotNull 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() { + this.companionObjectDescriptor = storageManager.createNullableLazyValue(new Function0() { @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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt index 259e5060c83..67c49e3d682 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt @@ -49,9 +49,9 @@ import java.util.* open class LazyClassMemberScope( c: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider, - thisClass: LazyClassDescriptor, + thisClass: ClassDescriptorWithResolutionScopes, trace: BindingTrace -) : AbstractLazyMemberScope(c, declarationProvider, thisClass, trace) { +) : AbstractLazyMemberScope(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) { + generateSyntheticCompanionObject(name, result) + } + override fun getNonDeclaredFunctions(name: Name, result: MutableSet) { 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, 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) { + 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 { // 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) { - 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 generateDelegatingDescriptors(name: Name, extractor: MemberExtractor, existingDescriptors: Collection): Collection { - 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 { - val classOrObject = declarationProvider.getOwnerInfo().correspondingClassOrObject ?: return emptyList() + val classOrObject = declarationProvider.correspondingClassOrObject ?: return emptyList() return classOrObject.getSecondaryConstructors().map { constructor -> val descriptor = c.functionDescriptorResolver.resolveSecondaryConstructorDescriptor( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyPackageMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyPackageMemberScope.kt index 60b949c6139..0ba0765d113 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyPackageMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyPackageMemberScope.kt @@ -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) { + // No extra classes + } + override fun getNonDeclaredFunctions(name: Name, result: MutableSet) { // No extra functions } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/source/KotlinSourceElement.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/source/KotlinSourceElement.kt index 540c8029515..cd3f9571ddc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/source/KotlinSourceElement.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/source/KotlinSourceElement.kt @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt index 2ae61fcb77f..f7e652ccd36 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt @@ -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, diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt index 92ad76a500b..71d16d99aee 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt @@ -153,12 +153,13 @@ private object JvmTypeFactoryImpl : JvmTypeFactory { } -private object TypeMappingConfigurationImpl : TypeMappingConfiguration { +internal object TypeMappingConfigurationImpl : TypeMappingConfiguration { override fun commonSupertype(types: Collection): 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 diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt index 65a83a888ed..03aef0ad3e3 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt @@ -51,6 +51,7 @@ interface TypeMappingConfiguration { 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 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 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 { diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 1528d5a705c..650456d8970 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -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()); } diff --git a/idea/src/META-INF/extensions/common.xml b/idea/src/META-INF/extensions/common.xml index 094a626e586..2bba11e0ebc 100644 --- a/idea/src/META-INF/extensions/common.xml +++ b/idea/src/META-INF/extensions/common.xml @@ -11,6 +11,9 @@ + diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidExpressionCodegenExtension.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidExpressionCodegenExtension.kt index 41f8dd808d4..62b62e7b11f 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidExpressionCodegenExtension.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidExpressionCodegenExtension.kt @@ -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)