diff --git a/.idea/runConfigurations/All_Jvm_Backend_Tests.xml b/.idea/runConfigurations/All_Jvm_Backend_Tests.xml new file mode 100644 index 00000000000..4270bdf9050 --- /dev/null +++ b/.idea/runConfigurations/All_Jvm_Backend_Tests.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 0c64361d3fc..167a0fe6d11 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -16,7 +16,6 @@ package org.jetbrains.jet.codegen; -import org.jetbrains.asm4.FieldVisitor; import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.Opcodes; import org.jetbrains.asm4.Type; @@ -25,14 +24,12 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static org.jetbrains.asm4.Opcodes.ACC_ABSTRACT; -import static org.jetbrains.asm4.Opcodes.ACC_PRIVATE; import static org.jetbrains.asm4.Opcodes.ACC_PUBLIC; /** @@ -100,26 +97,10 @@ public abstract class ClassBodyCodegen { PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); if (propertyDescriptor != null) { if (!isAnnotation) { - int accessModifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); - if((accessModifiers & ACC_PRIVATE) == 0) { - propertyCodegen.generateDefaultGetter(propertyDescriptor, accessModifiers, p); - if (propertyDescriptor.isVar()) { - propertyCodegen.generateDefaultSetter(propertyDescriptor, accessModifiers, origin); - } - } - - //noinspection ConstantConditions - if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { - int modifiers = accessModifiers; - if (!propertyDescriptor.isVar()) { - modifiers |= Opcodes.ACC_FINAL; - } - if (JetStandardLibrary.isVolatile(propertyDescriptor)) { - modifiers |= Opcodes.ACC_VOLATILE; - } - Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE); - FieldVisitor fieldVisitor = v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, null); - AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor); + propertyCodegen.generateBackingField(p, propertyDescriptor); + propertyCodegen.generateDefaultGetter(propertyDescriptor, JetTypeMapper.getAccessModifiers(propertyDescriptor,0), p); + if (propertyDescriptor.isVar()) { + propertyCodegen.generateDefaultSetter(propertyDescriptor, JetTypeMapper.getAccessModifiers(propertyDescriptor,0), p); } } else { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 36e3b05e7d6..38fb54ae2f6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -1027,18 +1027,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } } - - for (JetParameter p : toClass.getPrimaryConstructorParameters()) { - if (p.getValOrVarNode() != null) { - PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); - if (propertyDescriptor != null) { - propertyCodegen.generateDefaultGetter(propertyDescriptor, ACC_PUBLIC, p); - if (propertyDescriptor.isVar()) { - propertyCodegen.generateDefaultSetter(propertyDescriptor, ACC_PUBLIC, p); - } - } - } - } } @Nullable diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 957c3bcbd6d..2e801326afe 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -1002,7 +1002,7 @@ public class JetTypeMapper { return defaultFlags; } if (p.getContainingDeclaration() instanceof NamespaceDescriptor) { - return ACC_PROTECTED; + return 0; } return ACC_PRIVATE; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 84a2f4c6307..2b43bb9085f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -41,6 +41,7 @@ import java.util.BitSet; /** * @author max + * @author alex.tkachman */ public class PropertyCodegen { private final GenerationState state; @@ -75,14 +76,14 @@ public class PropertyCodegen { } } - private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) { + public void generateBackingField(PsiElement p, PropertyDescriptor propertyDescriptor) { if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); if (CodegenUtil.isInterface(containingDeclaration)) return; Object value = null; - final JetExpression initializer = p.getInitializer(); + final JetExpression initializer = p instanceof JetProperty ? ((JetProperty)p).getInitializer() : null; if (initializer != null) { if (initializer instanceof JetConstantExpression) { CompileTimeConstant compileTimeValue = state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer); @@ -91,11 +92,10 @@ public class PropertyCodegen { } int modifiers; if (kind == OwnerKind.NAMESPACE) { - int access = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); - modifiers = access | Opcodes.ACC_STATIC; + modifiers = Opcodes.ACC_STATIC; } else { - modifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); + modifiers = Opcodes.ACC_PRIVATE; } if (!propertyDescriptor.isVar()) { modifiers |= Opcodes.ACC_FINAL; @@ -104,7 +104,7 @@ public class PropertyCodegen { modifiers |= Opcodes.ACC_VOLATILE; } Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE); - FieldVisitor fieldVisitor = v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, value); + FieldVisitor fieldVisitor = v.newField(p, modifiers, propertyDescriptor.getName().getName(), type.getDescriptor(), null, value); AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor); } } @@ -150,7 +150,8 @@ public class PropertyCodegen { private void generateDefaultGetter(JetProperty p) { final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p); - int flags = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0) | (propertyDescriptor.getModality() == Modality.ABSTRACT ? Opcodes.ACC_ABSTRACT : 0); + assert propertyDescriptor != null; + int flags = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0) | (propertyDescriptor.getModality() == Modality.ABSTRACT ? Opcodes.ACC_ABSTRACT : (propertyDescriptor.getModality() == Modality.FINAL ? Opcodes.ACC_FINAL : 0)); generateDefaultGetter(propertyDescriptor, flags, p); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ScriptDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ScriptDescriptor.java index c65634add26..9bcc56b5514 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ScriptDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ScriptDescriptor.java @@ -21,7 +21,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -34,11 +33,9 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver; import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.lang.JetStandardClasses; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -106,17 +103,8 @@ public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl { if(jetDeclaration instanceof JetProperty) { VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, jetDeclaration); assert descriptor != null; - propertyDescriptor = new PropertyDescriptor(classDescriptor, - Collections.emptyList(), - Modality.FINAL, - propertyDescriptor.getVisibility(), - false, - false, - descriptor.getName(), - CallableMemberDescriptor.Kind.DECLARATION); - propertyDescriptor.setType(returnType, Collections.emptyList(), classReceiver, ReceiverDescriptor.NO_RECEIVER); - propertyDescriptor.initialize(null, null); - classScope.addPropertyDescriptor(propertyDescriptor); + initializeWithDefaultGetterSetter((PropertyDescriptor) descriptor); + classScope.addPropertyDescriptor(descriptor); } else if(jetDeclaration instanceof JetNamedFunction) { SimpleFunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, jetDeclaration); @@ -128,6 +116,21 @@ public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl { } } + public static void initializeWithDefaultGetterSetter(PropertyDescriptor propertyDescriptor) { + PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); + if(getter == null) { + getter = propertyDescriptor.getVisibility() != Visibilities.PRIVATE ? DescriptorResolver.createDefaultGetter(propertyDescriptor) : null; + if(getter != null) + getter.initialize(propertyDescriptor.getType()); + } + + PropertySetterDescriptor setter = propertyDescriptor.getSetter(); + if(setter == null) { + setter = propertyDescriptor.isVar() ? DescriptorResolver.createDefaultSetter(propertyDescriptor) : null; + } + propertyDescriptor.initialize(getter, setter); + } + public int getPriority() { return priority; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 4f3e312880c..737da823250 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -372,7 +372,7 @@ public class DescriptorResolver { return constructorDescriptor; } - final class UpperBoundCheckerTask { + static final class UpperBoundCheckerTask { JetTypeReference upperBound; JetType upperBoundType; boolean isClassObjectConstraint; @@ -834,7 +834,7 @@ public class DescriptorResolver { return setterDescriptor; } - private PropertySetterDescriptor createDefaultSetter(PropertyDescriptor propertyDescriptor) { + public static PropertySetterDescriptor createDefaultSetter(PropertyDescriptor propertyDescriptor) { PropertySetterDescriptor setterDescriptor; setterDescriptor = new PropertySetterDescriptor( propertyDescriptor, Collections.emptyList(), propertyDescriptor.getModality(), diff --git a/compiler/testData/codegen/regressions/kt2589.kt b/compiler/testData/codegen/regressions/kt2589.kt new file mode 100644 index 00000000000..b65ee0c7297 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2589.kt @@ -0,0 +1 @@ +open class Foo(var foo: String?, open protected val bar: String?) \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java index ff9fa95edef..3ec12e348eb 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PropertyGenTest.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.codegen; +import org.jetbrains.asm4.Opcodes; import org.jetbrains.jet.ConfigurationKind; import java.lang.reflect.Constructor; @@ -81,7 +82,7 @@ public class PropertyGenTest extends CodegenTestCase { final Field field = fields[0]; field.setAccessible(true); assertEquals("x", field.getName()); - assertEquals(Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL, field.getModifiers()); + assertEquals(Modifier.STATIC | Modifier.FINAL, field.getModifiers()); assertEquals(239, field.get(null)); } @@ -279,4 +280,32 @@ public class PropertyGenTest extends CodegenTestCase { blackBoxFile("regressions/kt2509.kt"); } + public void testKt2589() throws Exception { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + loadFile("regressions/kt2589.kt"); + final Class aClass = loadImplementationClass(generateClassesInFile(), "Foo"); + assertTrue((aClass.getModifiers() & Opcodes.ACC_FINAL) == 0); + + try { + Field foo = aClass.getDeclaredField("foo"); + assertTrue((foo.getModifiers() & Opcodes.ACC_PRIVATE) != 0); + assertTrue((foo.getModifiers() & Opcodes.ACC_FINAL) == 0); + + Field bar = aClass.getDeclaredField("bar"); + assertTrue((bar.getModifiers() & Opcodes.ACC_PRIVATE) != 0); + assertTrue((bar.getModifiers() & Opcodes.ACC_FINAL) != 0); + + Method getFoo = aClass.getDeclaredMethod("getFoo"); + assertTrue((getFoo.getModifiers() & Opcodes.ACC_PUBLIC) != 0); + assertTrue((getFoo.getModifiers() & Opcodes.ACC_FINAL) != 0); + + Method getBar = aClass.getDeclaredMethod("getBar"); + assertTrue((getBar.getModifiers() & Opcodes.ACC_PROTECTED) != 0); + assertTrue((getBar.getModifiers() & Opcodes.ACC_FINAL) == 0); + } + catch (Throwable e) { + System.out.println(generateToText()); + throw new RuntimeException(e); + } + } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java index d1950cf12f7..7ca4920fc7a 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.codegen; import com.intellij.openapi.components.ServiceManager; +import org.jetbrains.asm4.Opcodes; import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.lang.parsing.JetParserDefinition; import org.jetbrains.jet.lang.parsing.JetScriptDefinition; @@ -106,7 +107,8 @@ public class ScriptGenTest extends CodegenTestCase { final Class aClass = loadClass("Fib", generateClassesInFile()); try { Constructor constructor = aClass.getConstructor(int.class); - Field result = aClass.getField("result"); + Field result = aClass.getDeclaredField("result"); + result.setAccessible(true); Object script = constructor.newInstance(5); assertEquals(8,result.get(script)); } @@ -121,7 +123,8 @@ public class ScriptGenTest extends CodegenTestCase { final Class aClass = loadClass("test.Fibwp", generateClassesInFile()); try { Constructor constructor = aClass.getConstructor(int.class); - Field result = aClass.getField("result"); + Field result = aClass.getDeclaredField("result"); + result.setAccessible(true); Object script = constructor.newInstance(5); assertEquals(8,result.get(script)); } @@ -136,11 +139,17 @@ public class ScriptGenTest extends CodegenTestCase { final Class aClass = loadClass("Fibwprunner", generateClassesInFile()); try { Constructor constructor = aClass.getConstructor(); - Field result = aClass.getField("result"); + Field result = aClass.getDeclaredField("result"); + result.setAccessible(true); + Method resultMethod = aClass.getDeclaredMethod("getResult"); + assertTrue((resultMethod.getModifiers() & Opcodes.ACC_FINAL) != 0); + assertTrue((resultMethod.getModifiers() & Opcodes.ACC_PUBLIC) != 0); Field rv = aClass.getField("rv"); + assertTrue((result.getModifiers() & Opcodes.ACC_PRIVATE) != 0); Object script = constructor.newInstance(); assertEquals(12,rv.get(script)); assertEquals(8,result.get(script)); + assertEquals(8,resultMethod.invoke(script)); } catch (Exception e) { throw new RuntimeException(e);