diff --git a/compiler/backend-common/src/org/jetbrains/jet/backend/common/CodegenUtil.java b/compiler/backend-common/src/org/jetbrains/jet/backend/common/CodegenUtil.java index 8eab7c45810..5d4a64fd1f3 100644 --- a/compiler/backend-common/src/org/jetbrains/jet/backend/common/CodegenUtil.java +++ b/compiler/backend-common/src/org/jetbrains/jet/backend/common/CodegenUtil.java @@ -143,19 +143,32 @@ public class CodegenUtil { // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here // with traitMember's modality - CallableMemberDescriptor copy = - inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC, - CallableMemberDescriptor.Kind.DECLARATION, true); + result.putAll(copyFunctions(inheritedMember, traitMember, inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC, + CallableMemberDescriptor.Kind.DECLARATION, true)); + } + return result; + } - if (traitMember instanceof SimpleFunctionDescriptor) { - result.put((FunctionDescriptor) traitMember, (FunctionDescriptor) copy); - } - else if (traitMember instanceof PropertyDescriptor) { - for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) { - for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) { - if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind - result.put(traitAccessor, inheritedAccessor); - } + @NotNull + public static Map copyFunctions( + @NotNull CallableMemberDescriptor inheritedMember, + @NotNull CallableMemberDescriptor traitMember, + DeclarationDescriptor newOwner, + Modality modality, + Visibility visibility, + CallableMemberDescriptor.Kind kind, + boolean copyOverrides + ) { + CallableMemberDescriptor copy = inheritedMember.copy(newOwner, modality, visibility, kind, copyOverrides); + Map result = new LinkedHashMap(0); + if (traitMember instanceof SimpleFunctionDescriptor) { + result.put((FunctionDescriptor) traitMember, (FunctionDescriptor) copy); + } + else if (traitMember instanceof PropertyDescriptor) { + for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) { + for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) { + if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind + result.put(traitAccessor, inheritedAccessor); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java index 0bab49faf80..c38eb54b0e4 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java @@ -173,7 +173,7 @@ public class AsmUtil { public static boolean isStaticMethod(OwnerKind kind, CallableMemberDescriptor functionDescriptor) { return isStaticKind(kind) || JetTypeMapper.isAccessor(functionDescriptor) || - AnnotationsPackage.isPlatformStaticInObject(functionDescriptor); + AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor); } public static boolean isStaticKind(OwnerKind kind) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 2245a4a4f59..5e8d4dfa0d6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2419,7 +2419,7 @@ public class ExpressionCodegen extends JetVisitor implem if (isSingleton) { if (context.hasThisDescriptor() && context.getThisDescriptor().equals(calleeContainingClass) && - !AnnotationsPackage.isPlatformStaticInObject(context.getContextDescriptor())) { + !AnnotationsPackage.isPlatformStaticInObjectOrClass(context.getContextDescriptor())) { return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); } else { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PlatformStaticGenerator.kt b/compiler/backend/src/org/jetbrains/jet/codegen/PlatformStaticGenerator.kt index 825a23c2129..3b615f60a2e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PlatformStaticGenerator.kt +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PlatformStaticGenerator.kt @@ -17,12 +17,18 @@ package org.jetbrains.jet.codegen import org.jetbrains.jet.lang.descriptors.FunctionDescriptor -import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.jet.codegen.state.GenerationState import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.jet.lang.descriptors.ClassDescriptor import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin import org.jetbrains.jet.lang.resolve.java.diagnostics.Synthetic +import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor +import org.jetbrains.org.objectweb.asm.MethodVisitor +import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature +import org.jetbrains.jet.codegen.context.MethodContext +import org.jetbrains.jet.lang.psi.JetElement +import org.jetbrains.jet.backend.common.CodegenUtil +import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor class PlatformStaticGenerator( val descriptor: FunctionDescriptor, @@ -31,39 +37,54 @@ class PlatformStaticGenerator( ) : Function2 { override fun invoke(codegen: ImplementationBodyCodegen, classBuilder: ClassBuilder) { - val typeMapper = state.getTypeMapper() - val asmMethod = typeMapper.mapSignature(descriptor).getAsmMethod() - val flags = Opcodes.ACC_STATIC or AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION) - val methodVisitor = classBuilder.newMethod( - Synthetic(declarationOrigin.element, descriptor), - flags, - asmMethod.getName()!!, - asmMethod.getDescriptor()!!, - typeMapper.mapSignature(descriptor).getGenericsSignature(), - FunctionCodegen.getThrownExceptions(descriptor, typeMapper)) + val memberDescriptor = if (descriptor is PropertyAccessorDescriptor) descriptor.getCorrespondingProperty() else descriptor + val copies = CodegenUtil.copyFunctions( + memberDescriptor, + memberDescriptor, + declarationOrigin.descriptor?.getContainingDeclaration()?.getContainingDeclaration(), + descriptor.getModality(), + descriptor.getVisibility(), + CallableMemberDescriptor.Kind.SYNTHESIZED, + false + ) + val staticFunctionDescriptor = copies[descriptor]!! - AnnotationCodegen.forMethod(methodVisitor, typeMapper)!!.genAnnotations(descriptor, asmMethod.getReturnType()) + val jvmMethodSignature = state.getTypeMapper().mapSignature(staticFunctionDescriptor) - if (state.getClassBuilderMode() == ClassBuilderMode.FULL && flags and Opcodes.ACC_NATIVE == 0) { - methodVisitor.visitCode(); - val iv = InstructionAdapter(methodVisitor) - val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor - val singletonValue = StackValue.singleton(classDescriptor, typeMapper)!! - singletonValue.put(singletonValue.type, iv); - var index = 0; - for (paramType in asmMethod.getArgumentTypes()) { - iv.load(index, paramType); - index += paramType.getSize(); - } + codegen.functionCodegen.generateMethod( + Synthetic(declarationOrigin.element, staticFunctionDescriptor), + jvmMethodSignature, + staticFunctionDescriptor, + object: FunctionGenerationStrategy() { + override fun generateBody( + mv: MethodVisitor, + frameMap: FrameMap, + signature: JvmMethodSignature, + context: MethodContext, + parentCodegen: MemberCodegen + ) { + val typeMapper = parentCodegen.typeMapper - val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod( - codegen.getContext().accessibleFunctionDescriptor(descriptor), - false, - codegen.getContext() - ) - syntheticOrOriginalMethod.invokeWithoutAssertions(iv) - iv.areturn(asmMethod.getReturnType()); - methodVisitor.visitEnd(); - } + val iv = InstructionAdapter(mv) + val classDescriptor = descriptor.getContainingDeclaration() as ClassDescriptor + val singletonValue = StackValue.singleton(classDescriptor, typeMapper) + singletonValue.put(singletonValue.type, iv); + var index = 0; + val asmMethod = signature.getAsmMethod() + for (paramType in asmMethod.getArgumentTypes()) { + iv.load(index, paramType); + index += paramType.getSize(); + } + + val syntheticOrOriginalMethod = typeMapper.mapToCallableMethod( + codegen.getContext().accessibleFunctionDescriptor(descriptor), + false, + codegen.getContext() + ) + syntheticOrOriginalMethod.invokeWithoutAssertions(iv) + iv.areturn(asmMethod.getReturnType()); + } + } + ) } } \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 5e36caf6b3d..49561b43c4a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -480,7 +480,7 @@ public abstract class StackValue { } private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) { - if (AnnotationsPackage.isPlatformStaticInObject(descriptor)) { + if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) { if (resultReceiver.canHaveSideEffects()) { return coercion(resultReceiver, Type.VOID_TYPE); } @@ -1414,7 +1414,7 @@ public abstract class StackValue { return callableMethod != null ? callableMethod.getReceiverClass() : typeMapper.mapType(extensionReceiver.getType()); } else if (dispatchReceiver != null) { - if (AnnotationsPackage.isPlatformStaticInObject(descriptor)) { + if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) { return Type.VOID_TYPE; } else { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 5234eb351e2..900f13c7398 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -488,7 +488,7 @@ public class JetTypeMapper { else { if (isStaticDeclaration(functionDescriptor) || isAccessor(functionDescriptor) || - AnnotationsPackage.isPlatformStaticInObject(functionDescriptor)) { + AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) { invokeOpcode = INVOKESTATIC; } else if (isInterface) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtil.kt index e68b844baf0..a8162e393d5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtil.kt @@ -17,7 +17,6 @@ package org.jetbrains.jet.lang.resolve.annotations import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.lang.descriptors.CallableDescriptor import org.jetbrains.jet.lang.resolve.DescriptorUtils @@ -36,18 +35,18 @@ public fun DeclarationDescriptor.hasIntrinsicAnnotation(): Boolean { return getAnnotations().findAnnotation(FqName("kotlin.jvm.internal.Intrinsic")) != null } -public fun CallableDescriptor.isPlatformStaticInObject(): Boolean = - isPlatformStaticIn(ClassKind.OBJECT) +public fun CallableDescriptor.isPlatformStaticInObjectOrClass(): Boolean = + isPlatformStaticIn(ClassKind.OBJECT, ClassKind.CLASS) public fun CallableDescriptor.isPlatformStaticInClassObject(): Boolean = isPlatformStaticIn(ClassKind.CLASS_OBJECT) -private fun CallableDescriptor.isPlatformStaticIn(kind: ClassKind): Boolean = +private fun CallableDescriptor.isPlatformStaticIn(vararg kinds: ClassKind): Boolean = when (this) { is PropertyAccessorDescriptor -> { val propertyDescriptor = getCorrespondingProperty() - DescriptorUtils.isKindOf(propertyDescriptor.getContainingDeclaration(), kind) && + kinds.any { DescriptorUtils.isKindOf(propertyDescriptor.getContainingDeclaration(), it) } && (hasPlatformStaticAnnotation() || propertyDescriptor.hasPlatformStaticAnnotation()) } - else -> DescriptorUtils.isKindOf(getContainingDeclaration(), kind) && hasPlatformStaticAnnotation() + else -> kinds.any { DescriptorUtils.isKindOf(getContainingDeclaration(), it) } && hasPlatformStaticAnnotation() } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/SourceElement.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/SourceElement.java index d6ee47c2801..a345e059b01 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/SourceElement.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/SourceElement.java @@ -17,5 +17,10 @@ package org.jetbrains.jet.lang.descriptors; public interface SourceElement { - SourceElement NO_SOURCE = new SourceElement() { }; + SourceElement NO_SOURCE = new SourceElement() { + @Override + public String toString() { + return "NO_SOURCE"; + } + }; } \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/SimpleFunctionDescriptorImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/SimpleFunctionDescriptorImpl.java index a2fe5ffc80d..173d704469e 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/SimpleFunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/SimpleFunctionDescriptorImpl.java @@ -92,7 +92,7 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme getAnnotations(), getName(), kind, - SourceElement.NO_SOURCE + getSource() ); }