From 00a12bd013844de31dc7a708cdbeb1707a8d2fe4 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Tue, 28 Aug 2012 16:56:23 +0400 Subject: [PATCH] Constructors for enum entries and class objects have private visibility in frontend. Introduce DescriptorUtils#getDefaultConstructorVisibility. DescriptorResolver: remove exception wrapping. Hardcode package-private visibility for enum entries in JetTypeMapper. Refactoring: DescriptorResolver: rename createPrimaryConstructorForObject -> createAndRecordPrimaryConstructorForObject, createPrimaryConstructorForObject now a separate method. JavaDescriptorResolver: extract containingDeclaration variable. JetTypeMapper: rename variable declaration -> containingDeclaration. --- .../jetbrains/jet/codegen/JetTypeMapper.java | 13 ++++-- .../resolve/java/JavaDescriptorResolver.java | 29 ++++++------- .../jet/lang/resolve/DescriptorResolver.java | 42 +++++++++---------- .../jet/lang/resolve/DescriptorUtils.java | 23 ++++++++++ .../lang/resolve/TypeHierarchyResolver.java | 2 +- .../resolve/lazy/LazyClassMemberScope.java | 2 +- 6 files changed, 67 insertions(+), 44 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index eeef19d5bcf..4a735a53131 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -44,6 +44,8 @@ import java.util.List; import java.util.Map; import static org.jetbrains.asm4.Opcodes.*; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumEntry; import static org.jetbrains.jet.codegen.context.CodegenBinding.*; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; @@ -980,8 +982,8 @@ public class JetTypeMapper { public static int getAccessModifiers(@NotNull MemberDescriptor p, int defaultFlags) { - DeclarationDescriptor declaration = p.getContainingDeclaration(); - if (CodegenUtil.isInterface(declaration)) { + DeclarationDescriptor containingDeclaration = p.getContainingDeclaration(); + if (CodegenUtil.isInterface(containingDeclaration)) { return ACC_PUBLIC; } if (p.getVisibility() == Visibilities.PUBLIC) { @@ -991,10 +993,13 @@ public class JetTypeMapper { return ACC_PROTECTED; } else if (p.getVisibility() == Visibilities.PRIVATE) { - if (DescriptorUtils.isClassObject(declaration)) { + if (isClassObject(containingDeclaration)) { return defaultFlags; } - if (p.getContainingDeclaration() instanceof NamespaceDescriptor) { + if (p instanceof ConstructorDescriptor && isEnumEntry(containingDeclaration)) { + return 0; + } + if (containingDeclaration instanceof NamespaceDescriptor) { return 0; } return ACC_PRIVATE; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index d7e1a634a70..d565819dc5f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -56,8 +56,7 @@ import org.jetbrains.jet.utils.ExceptionUtils; import javax.inject.Inject; import java.util.*; -import static org.jetbrains.jet.lang.resolve.DescriptorResolver.createEnumClassObjectValueOfMethod; -import static org.jetbrains.jet.lang.resolve.DescriptorResolver.createEnumClassObjectValuesMethod; +import static org.jetbrains.jet.lang.resolve.DescriptorResolver.*; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName; /** @@ -445,22 +444,17 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes PsiClass psiClass = classData.psiClass; + ClassDescriptorFromJvmBytecode containingClass = classData.classDescriptor; TypeVariableResolver resolverForTypeParameters = TypeVariableResolvers.classTypeVariableResolver( - classData.classDescriptor, "class " + psiClass.getQualifiedName()); + containingClass, "class " + psiClass.getQualifiedName()); - List typeParameters = classData.classDescriptor.getTypeConstructor().getParameters(); + List typeParameters = containingClass.getTypeConstructor().getParameters(); PsiMethod[] psiConstructors = psiClass.getConstructors(); boolean isStatic = psiClass.hasModifierProperty(PsiModifier.STATIC); - if (classData.classDescriptor.getKind() == ClassKind.OBJECT || classData.classDescriptor.getKind() == ClassKind.CLASS_OBJECT) { - // TODO: wrong: class objects do not need visible constructors - ConstructorDescriptorImpl constructor = new ConstructorDescriptorImpl(classData.classDescriptor, new ArrayList(0), true); - Visibility visibility = psiConstructors.length != 0 - ? resolveVisibility(psiConstructors[0], new PsiMethodWrapper(psiConstructors[0]).getJetConstructor()) - : Visibilities.PUBLIC; - constructor.initialize(new ArrayList(0), new ArrayList(0), visibility); - constructors.add(constructor); + if (containingClass.getKind() == ClassKind.OBJECT || containingClass.getKind() == ClassKind.CLASS_OBJECT) { + constructors.add(createPrimaryConstructorForObject(containingClass)); } else if (psiConstructors.length == 0) { // We need to create default constructors for classes and abstract classes. @@ -469,17 +463,18 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes // abstract public class Java {} if (!psiClass.isInterface()) { ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl( - classData.classDescriptor, + containingClass, Collections.emptyList(), false); - constructorDescriptor.initialize(typeParameters, Collections.emptyList(), classData.classDescriptor.getVisibility(), isStatic); + constructorDescriptor.initialize(typeParameters, Collections.emptyList(), containingClass + .getVisibility(), isStatic); constructors.add(constructorDescriptor); trace.record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor); } if (psiClass.isAnnotationType()) { // A constructor for an annotation type takes all the "methods" in the @interface as parameters ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl( - classData.classDescriptor, + containingClass, Collections.emptyList(), false); @@ -512,7 +507,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes } } - constructorDescriptor.initialize(typeParameters, valueParameters, classData.classDescriptor.getVisibility(), isStatic); + constructorDescriptor.initialize(typeParameters, valueParameters, containingClass.getVisibility(), isStatic); constructors.add(constructorDescriptor); trace.record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor); } @@ -527,7 +522,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes } for (ConstructorDescriptor constructor : constructors) { - ((ConstructorDescriptorImpl) constructor).setReturnType(classData.classDescriptor.getDefaultType()); + ((ConstructorDescriptorImpl) constructor).setReturnType(containingClass.getDefaultType()); } return constructors; 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 db4a8788e58..f282de85c1c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -25,7 +25,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.name.Name; @@ -49,6 +48,8 @@ import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.CONSTRUCTOR; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getDefaultConstructorVisibility; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getExpectedThisObjectIfNeeded; import static org.jetbrains.jet.lexer.JetTokens.OVERRIDE_KEYWORD; /** @@ -282,7 +283,7 @@ public class DescriptorResolver { boolean isInline = (modifierList != null) && modifierList.hasModifier(JetTokens.INLINE_KEYWORD); functionDescriptor.initialize( receiverType, - DescriptorUtils.getExpectedThisObjectIfNeeded(containingDescriptor), + getExpectedThisObjectIfNeeded(containingDescriptor), typeParameterDescriptors, valueParameterDescriptors, returnType, @@ -429,30 +430,29 @@ public class DescriptorResolver { return typeParameterDescriptor; } - public static ConstructorDescriptorImpl createPrimaryConstructorForObject( + @NotNull + public static ConstructorDescriptorImpl createAndRecordPrimaryConstructorForObject( @Nullable PsiElement object, @NotNull ClassDescriptor classDescriptor, @NotNull BindingTrace trace ) { - ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(classDescriptor, Collections - .emptyList(), true); - - // TODO : make the constructor private? - // TODO check set classDescriptor.getVisibility() - constructorDescriptor.initialize(Collections.emptyList(), - Collections.emptyList(), Visibilities.INTERNAL); - + ConstructorDescriptorImpl constructorDescriptor = createPrimaryConstructorForObject(classDescriptor); if (object != null) { - try { - trace.record(CONSTRUCTOR, object, constructorDescriptor); - } - catch (RuntimeException e) { - throw new RuntimeException(e.getMessage() + " at " + DiagnosticUtils.atLocation(object), e); - } + trace.record(CONSTRUCTOR, object, constructorDescriptor); } return constructorDescriptor; } + @NotNull + public static ConstructorDescriptorImpl createPrimaryConstructorForObject(@NotNull ClassDescriptor containingClass) { + ConstructorDescriptorImpl constructorDescriptor = + new ConstructorDescriptorImpl(containingClass, Collections.emptyList(), true); + constructorDescriptor.initialize(Collections.emptyList(), + Collections.emptyList(), + getDefaultConstructorVisibility(containingClass)); + return constructorDescriptor; + } + static final class UpperBoundCheckerTask { JetTypeReference upperBound; JetType upperBoundType; @@ -702,7 +702,7 @@ public class DescriptorResolver { CallableMemberDescriptor.Kind.DECLARATION ); propertyDescriptor.setType(classDescriptor.getDefaultType(), Collections.emptyList(), - DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), ReceiverDescriptor.NO_RECEIVER); + getExpectedThisObjectIfNeeded(containingDeclaration), ReceiverDescriptor.NO_RECEIVER); propertyDescriptor.initialize(createDefaultGetter(propertyDescriptor), null); trace.record(BindingContext.OBJECT_DECLARATION_CLASS, propertyDescriptor, classDescriptor); JetObjectDeclarationName nameAsDeclaration = objectDeclaration.getNameAsDeclaration(); @@ -809,7 +809,7 @@ public class DescriptorResolver { JetType type = getVariableType(propertyScope, property, DataFlowInfo.EMPTY, true, trace); - propertyDescriptor.setType(type, typeParameterDescriptors, DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), + propertyDescriptor.setType(type, typeParameterDescriptors, getExpectedThisObjectIfNeeded(containingDeclaration), receiverDescriptor); PropertyGetterDescriptor getter = resolvePropertyGetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor, trace); @@ -1022,7 +1022,7 @@ public class DescriptorResolver { constructorDescriptor, parameterScope, valueParameters, trace), - ModifiersChecker.resolveVisibilityFromModifiers(modifierList, Visibilities.PUBLIC)); + ModifiersChecker.resolveVisibilityFromModifiers(modifierList, getDefaultConstructorVisibility(classDescriptor))); } @Nullable @@ -1071,7 +1071,7 @@ public class DescriptorResolver { CallableMemberDescriptor.Kind.DECLARATION ); propertyDescriptor.setType(type, Collections.emptyList(), - DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), ReceiverDescriptor.NO_RECEIVER); + getExpectedThisObjectIfNeeded(classDescriptor), ReceiverDescriptor.NO_RECEIVER); PropertyGetterDescriptor getter = createDefaultGetter(propertyDescriptor); PropertySetterDescriptor setter = propertyDescriptor.isVar() ? createDefaultSetter(propertyDescriptor) : null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index cf4b4b98cd8..c8bdf1cab47 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -283,6 +283,11 @@ public class DescriptorUtils { && ((ClassDescriptor) descriptor).getKind() == ClassKind.CLASS_OBJECT; } + public static boolean isEnumEntry(@NotNull DeclarationDescriptor descriptor) { + return descriptor instanceof ClassDescriptor + && ((ClassDescriptor) descriptor).getKind() == ClassKind.ENUM_ENTRY; + } + @NotNull public static List getSuperclassDescriptors(@NotNull ClassDescriptor classDescriptor) { Collection superclassTypes = classDescriptor.getTypeConstructor().getSupertypes(); @@ -358,4 +363,22 @@ public class DescriptorUtils { return ((containingDeclaration instanceof ClassDescriptor) && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.ENUM_CLASS); } + + @NotNull + public static Visibility getDefaultConstructorVisibility(@NotNull ClassDescriptor classDescriptor) { + ClassKind classKind = classDescriptor.getKind(); + if (classKind == ClassKind.ENUM_CLASS) { + //TODO: should be PRIVATE + // see http://youtrack.jetbrains.com/issue/KT-2680 + return Visibilities.PROTECTED; + } + if (classKind == ClassKind.ENUM_ENTRY || classKind == ClassKind.CLASS_OBJECT) { + return Visibilities.PRIVATE; + } + if (classKind == ClassKind.OBJECT) { + return Visibilities.INTERNAL; + } + assert classKind == ClassKind.CLASS || classKind == ClassKind.TRAIT || classKind == ClassKind.ANNOTATION_CLASS; + return Visibilities.PUBLIC; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 1cde4f00066..6ebc1032b5b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -350,7 +350,7 @@ public class TypeHierarchyResolver { MutableClassDescriptor mutableClassDescriptor ) { ConstructorDescriptorImpl constructorDescriptor = DescriptorResolver - .createPrimaryConstructorForObject(object, mutableClassDescriptor, trace); + .createAndRecordPrimaryConstructorForObject(object, mutableClassDescriptor, trace); mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor, trace); return constructorDescriptor; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassMemberScope.java index e9ec962634b..2377bd45919 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassMemberScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassMemberScope.java @@ -299,7 +299,7 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope