From 67fdbbd23096b03fcd49cd89b8915a9ff2a2b3b8 Mon Sep 17 00:00:00 2001 From: svtk Date: Fri, 23 Sep 2011 13:02:11 +0400 Subject: [PATCH 1/3] Added visibility information to descriptors --- .../resolve/java/JavaClassDescriptor.java | 11 +++ .../resolve/java/JavaDescriptorResolver.java | 19 +++- .../jet/lang/descriptors/ClassDescriptor.java | 3 + .../lang/descriptors/ClassDescriptorImpl.java | 6 ++ .../ConstructorDescriptorImpl.java | 8 +- .../descriptors/FunctionDescriptorImpl.java | 14 ++- .../LazySubstitutingClassDescriptor.java | 6 ++ .../lang/descriptors/MemberDescriptor.java | 3 + .../descriptors/MutableClassDescriptor.java | 11 +++ .../PropertyAccessorDescriptor.java | 13 ++- .../lang/descriptors/PropertyDescriptor.java | 13 ++- .../descriptors/PropertyGetterDescriptor.java | 4 +- .../descriptors/PropertySetterDescriptor.java | 4 +- .../VariableAsFunctionDescriptor.java | 2 +- .../jet/lang/descriptors/Visibility.java | 23 +++++ .../lang/resolve/ClassDescriptorResolver.java | 99 ++++++++++++++++--- .../lang/resolve/TypeHierarchyResolver.java | 5 +- .../jetbrains/jet/lang/types/ErrorUtils.java | 7 +- .../jet/lang/types/JetTypeInferrer.java | 2 +- 19 files changed, 216 insertions(+), 37 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/descriptors/Visibility.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java index cad5c8890bb..6419589cff4 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java @@ -23,6 +23,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements private JetType classObjectType; private final WritableFunctionGroup constructors = new WritableFunctionGroup(""); private Modality modality; + private Visibility visibility; private JetType superclassType; private final ClassKind kind; private ClassReceiver implicitReceiver; @@ -41,6 +42,10 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements this.modality = modality; } + public void setVisibility(Visibility visibility) { + this.visibility = visibility; + } + public void setUnsubstitutedMemberScope(JavaClassMembersScope memberScope) { this.unsubstitutedMemberScope = memberScope; } @@ -149,6 +154,12 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements return modality; } + @NotNull + @Override + public Visibility getVisibility() { + return visibility; + } + @Override public R accept(DeclarationDescriptorVisitor visitor, D data) { return visitor.visitClassDescriptor(this, data); 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 5b875998ccb..2e7ab8bf723 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 @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.types.*; import java.util.*; @@ -110,6 +111,7 @@ public class JavaDescriptorResolver { psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(), !psiClass.hasModifierProperty(PsiModifier.FINAL)) ); + classDescriptor.setVisibility(resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), psiClass)); classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor); classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false)); classDescriptor.setClassObjectMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, true)); @@ -135,7 +137,7 @@ public class JavaDescriptorResolver { classDescriptor, Collections.emptyList(), false); - constructorDescriptor.initialize(typeParameters, Collections.emptyList(), Modality.FINAL); + constructorDescriptor.initialize(typeParameters, Collections.emptyList(), Modality.FINAL, classDescriptor.getVisibility()); constructorDescriptor.setReturnType(classDescriptor.getDefaultType()); classDescriptor.addConstructor(constructorDescriptor); semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor); @@ -147,7 +149,8 @@ public class JavaDescriptorResolver { classDescriptor, Collections.emptyList(), // TODO false); - constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()), Modality.FINAL); + constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()), Modality.FINAL, + resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), constructor)); constructorDescriptor.setReturnType(classDescriptor.getDefaultType()); classDescriptor.addConstructor(constructorDescriptor); semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, constructor, constructorDescriptor); @@ -291,6 +294,7 @@ public class JavaDescriptorResolver { containingDeclaration, Collections.emptyList(), Modality.FINAL, + resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), field), !isFinal, null, field.getName(), @@ -359,7 +363,8 @@ public class JavaDescriptorResolver { resolveTypeParameters(functionDescriptorImpl, method.getTypeParameters()), semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters), semanticServices.getTypeTransformer().transformToType(returnType), - Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)) + Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)), + resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), method) ); semanticServices.getTrace().record(BindingContext.FUNCTION, method, functionDescriptorImpl); FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl; @@ -368,4 +373,12 @@ public class JavaDescriptorResolver { } return substitutedFunctionDescriptor; } + + private static Visibility resolveVisibilityFromPsiModifiers(BindingTrace trace, PsiModifierListOwner modifierListOwner) { + //TODO report error + return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibility.PUBLIC : + (modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE) ? Visibility.PRIVATE : + (modifierListOwner.hasModifierProperty(PsiModifier.PROTECTED) ? Visibility.PROTECTED : Visibility.INTERNAL)); + } + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java index 5d0f349f42c..2109517bfee 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java @@ -54,6 +54,9 @@ public interface ClassDescriptor extends ClassifierDescriptor { @NotNull Modality getModality(); + + @NotNull + Visibility getVisibility(); @NotNull ReceiverDescriptor getImplicitReceiver(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java index 77fe77579ac..7c74b53575b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java @@ -155,6 +155,12 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl return Modality.FINAL; } + @NotNull + @Override + public Visibility getVisibility() { + return Visibility.PUBLIC; + } + @NotNull @Override public ReceiverDescriptor getImplicitReceiver() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java index 84353643830..0f00d025056 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java @@ -28,13 +28,13 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements @Override @Deprecated - public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, Modality modality) { + public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, Modality modality, Visibility visibility) { assert receiverType == null; - return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType, modality); + return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType, modality, visibility); } - public ConstructorDescriptorImpl initialize(@NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, Modality modality) { - super.initialize(null, typeParameters, unsubstitutedValueParameters, null, modality); + public ConstructorDescriptorImpl initialize(@NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, Modality modality, Visibility visibility) { + super.initialize(null, typeParameters, unsubstitutedValueParameters, null, modality, visibility); return this; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java index ff2fc69b585..e1692445134 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -28,6 +28,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements private ReceiverDescriptor receiver; private Modality modality; + private Visibility visibility; private final Set overriddenFunctions = Sets.newLinkedHashSet(); private final FunctionDescriptor original; @@ -52,11 +53,13 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, - @Nullable Modality modality) { + @Nullable Modality modality, + @NotNull Visibility visibility) { this.typeParameters = typeParameters; this.unsubstitutedValueParameters = unsubstitutedValueParameters; this.unsubstitutedReturnType = unsubstitutedReturnType; this.modality = modality; + this.visibility = visibility; this.receiver = receiverType == null ? NO_RECEIVER : new ExtensionReceiver(this, receiverType); return this; } @@ -83,6 +86,12 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements return modality; } + @NotNull + @Override + public Visibility getVisibility() { + return visibility; + } + public void addOverriddenFunction(@NotNull FunctionDescriptor overriddenFunction) { overriddenFunctions.add(overriddenFunction); } @@ -144,7 +153,8 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements substitutedTypeParameters, substitutedValueParameters, substitutedReturnType, - modality + modality, + visibility ); for (FunctionDescriptor overriddenFunction : overriddenFunctions) { substitutedDescriptor.addOverriddenFunction(overriddenFunction); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java index 2c1f3e8bca4..be4f47938e3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java @@ -163,6 +163,12 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { return original.getModality(); } + @NotNull + @Override + public Visibility getVisibility() { + return original.getVisibility(); + } + @Override public boolean isClassObjectAValue() { return original.isClassObjectAValue(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MemberDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MemberDescriptor.java index bc9c1ef7716..5327b981133 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MemberDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MemberDescriptor.java @@ -8,4 +8,7 @@ import org.jetbrains.annotations.NotNull; public interface MemberDescriptor { @NotNull Modality getModality(); + + @NotNull + Visibility getVisibility(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index cf2103f43bf..3eb15deeb91 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -29,6 +29,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme private Collection supertypes = Lists.newArrayList(); private Modality modality; + private Visibility visibility; private TypeConstructor typeConstructor; private final WritableScope scopeForMemberResolution; private final WritableScope scopeForMemberLookup; @@ -281,12 +282,22 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme this.modality = modality; } + public void setVisibility(Visibility visibility) { + this.visibility = visibility; + } + @Override @NotNull public Modality getModality() { return modality; } + @NotNull + @Override + public Visibility getVisibility() { + return visibility; + } + @Override public String toString() { return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]"; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java index 7d477fe72b7..d626a45417d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java @@ -15,18 +15,21 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm private final boolean hasBody; private final boolean isDefault; private final Modality modality; + private final Visibility visibility; private final PropertyDescriptor correspondingProperty; - protected PropertyAccessorDescriptor( + public PropertyAccessorDescriptor( @NotNull Modality modality, + @NotNull Visibility visibility, @NotNull PropertyDescriptor correspondingProperty, @NotNull List annotations, @NotNull String name, boolean hasBody, boolean isDefault) { super(correspondingProperty.getContainingDeclaration(), annotations, name); - this.correspondingProperty = correspondingProperty; this.modality = modality; + this.visibility = visibility; + this.correspondingProperty = correspondingProperty; this.hasBody = hasBody; this.isDefault = isDefault; } @@ -63,6 +66,12 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm return modality; } + @NotNull + @Override + public Visibility getVisibility() { + return visibility; + } + @NotNull public PropertyDescriptor getCorrespondingProperty() { return correspondingProperty; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java index b303150e166..50f73f05a23 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java @@ -18,6 +18,7 @@ import java.util.List; public class PropertyDescriptor extends VariableDescriptorImpl implements MemberDescriptor { private final Modality modality; + private final Visibility visibility; private final boolean isVar; private final ReceiverDescriptor receiver; private final List typeParemeters = Lists.newArrayListWithCapacity(0); @@ -30,6 +31,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member @NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, @NotNull Modality modality, + @NotNull Visibility visibility, boolean isVar, @Nullable JetType receiverType, @NotNull String name, @@ -40,6 +42,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member // assert outType != null; this.isVar = isVar; this.modality = modality; + this.visibility = visibility; this.receiver = receiverType == null ? ReceiverDescriptor.NO_RECEIVER : new ExtensionReceiver(this, receiverType); this.original = original == null ? this : original.getOriginal(); } @@ -48,12 +51,13 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member @NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, @NotNull Modality modality, + @NotNull Visibility visibility, boolean isVar, @Nullable JetType receiverType, @NotNull String name, @Nullable JetType inType, @NotNull JetType outType) { - this(null, containingDeclaration, annotations, modality, isVar, receiverType, name, inType, outType); + this(null, containingDeclaration, annotations, modality, visibility, isVar, receiverType, name, inType, outType); } private PropertyDescriptor( @@ -66,6 +70,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member original.getContainingDeclaration(), original.getAnnotations(), // TODO : substitute? original.getModality(), + original.getVisibility(), original.isVar, receiverType, original.getName(), @@ -107,6 +112,12 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member return modality; } + @NotNull + @Override + public Visibility getVisibility() { + return visibility; + } + @Nullable public PropertyGetterDescriptor getGetter() { return getter; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java index 2e54e868dac..677f34481bc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java @@ -18,8 +18,8 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor { private final Set overriddenGetters = Sets.newHashSet(); private JetType returnType; - public PropertyGetterDescriptor(@NotNull Modality modality, @NotNull PropertyDescriptor correspondingProperty, @NotNull List annotations, @Nullable JetType returnType, boolean hasBody, boolean isDefault) { - super(modality, correspondingProperty, annotations, "get-" + correspondingProperty.getName(), hasBody, isDefault); + public PropertyGetterDescriptor(@NotNull Modality modality, @NotNull Visibility visibility, @NotNull PropertyDescriptor correspondingProperty, @NotNull List annotations, @Nullable JetType returnType, boolean hasBody, boolean isDefault) { + super(modality, visibility, correspondingProperty, annotations, "get-" + correspondingProperty.getName(), hasBody, isDefault); this.returnType = returnType == null ? correspondingProperty.getOutType() : returnType; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java index ae28522affb..5381a9e7d85 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java @@ -19,8 +19,8 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor { private MutableValueParameterDescriptor parameter; private final Set overriddenSetters = Sets.newHashSet(); - public PropertySetterDescriptor(@NotNull Modality modality, @NotNull PropertyDescriptor correspondingProperty, @NotNull List annotations, boolean hasBody, boolean isDefault) { - super(modality, correspondingProperty, annotations, "set-" + correspondingProperty.getName(), hasBody, isDefault); + public PropertySetterDescriptor(@NotNull Modality modality, @NotNull Visibility visibility, @NotNull PropertyDescriptor correspondingProperty, @NotNull List annotations, boolean hasBody, boolean isDefault) { + super(modality, visibility, correspondingProperty, annotations, "set-" + correspondingProperty.getName(), hasBody, isDefault); } public void initialize(@NotNull MutableValueParameterDescriptor parameter) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java index dadf04cad21..af1840edf05 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java @@ -16,7 +16,7 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl { assert outType != null; assert JetStandardClasses.isFunctionType(outType); VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor); - result.initialize(JetStandardClasses.getReceiverType(outType), Collections.emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType), Modality.FINAL); + result.initialize(JetStandardClasses.getReceiverType(outType), Collections.emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType), Modality.FINAL, Visibility.LOCAL); return result; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/Visibility.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/Visibility.java new file mode 100644 index 00000000000..e2c5364dfe3 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/Visibility.java @@ -0,0 +1,23 @@ +package org.jetbrains.jet.lang.descriptors; + +/** + * @author svtk + */ +public enum Visibility { + PRIVATE(false), + PROTECTED(true), + INTERNAL(false), + PUBLIC(true), + INTERNAL_PROTECTED(false), + LOCAL(false); + + private final boolean isAPI; + + private Visibility(boolean visibleOutside) { + isAPI = visibleOutside; + } + + public boolean isAPI() { + return isAPI; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 0626401658c..d6e8b151adc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -21,6 +21,8 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lexer.JetKeywordToken; +import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; import java.util.*; @@ -65,7 +67,8 @@ public class ClassDescriptorResolver { } descriptor.setTypeParameterDescriptors(typeParameters); Modality defaultModality = descriptor.getKind() == ClassKind.TRAIT ? Modality.ABSTRACT : Modality.FINAL; - descriptor.setModality(resolveModalityFromModifiers(classElement.getModifierList(), defaultModality)); + descriptor.setModality(resolveModalityFromModifiers(trace, classElement.getModifierList(), defaultModality)); + descriptor.setVisibility(resolveVisibilityFromModifiers(trace, classElement.getModifierList())); trace.record(BindingContext.CLASS, classElement, descriptor); } @@ -195,14 +198,16 @@ public class ClassDescriptorResolver { } else { defaultModality = Modality.FINAL; } - Modality modality = resolveModalityFromModifiers(function.getModifierList(), defaultModality); + Modality modality = resolveModalityFromModifiers(trace, function.getModifierList(), defaultModality); + Visibility visibility = resolveVisibilityFromModifiers(trace, function.getModifierList()); functionDescriptor.initialize( receiverType, typeParameterDescriptors, valueParameterDescriptors, returnType, - modality); + modality, + visibility); trace.record(BindingContext.FUNCTION, function, functionDescriptor); return functionDescriptor; @@ -424,7 +429,8 @@ public class ClassDescriptorResolver { PropertyDescriptor propertyDescriptor = new PropertyDescriptor( containingDeclaration, annotationResolver.createAnnotationStubs(modifierList), - resolveModalityFromModifiers(modifierList), // TODO : default modifiers differ in different contexts + resolveModalityFromModifiers(trace, objectDeclaration.getModifierList()), // TODO : default modifiers differ in different contexts + resolveVisibilityFromModifiers(trace, objectDeclaration.getModifierList()), false, null, JetPsiUtil.safeName(objectDeclaration.getName()), @@ -474,7 +480,8 @@ public class ClassDescriptorResolver { PropertyDescriptor propertyDescriptor = new PropertyDescriptor( containingDeclaration, annotationResolver.resolveAnnotations(scope, modifierList), - resolveModalityFromModifiers(modifierList), // TODO : default modifiers differ in different contexts + resolveModalityFromModifiers(trace, property.getModifierList()), // TODO : default modifiers differ in different contexts + resolveVisibilityFromModifiers(trace, property.getModifierList()), isVar, receiverType, JetPsiUtil.safeName(property.getName()), @@ -523,20 +530,31 @@ public class ClassDescriptorResolver { } @NotNull - private Modality resolveModalityFromModifiers(@Nullable JetModifierList modifierList) { - return resolveModalityFromModifiers(modifierList, Modality.FINAL); + /*package*/ static Modality resolveModalityFromModifiers(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList) { + return resolveModalityFromModifiers(trace, modifierList, Modality.FINAL); } @NotNull - private Modality resolveModalityFromModifiers(@Nullable JetModifierList modifierList, @NotNull Modality defaultModality) { + /*package*/ static Modality resolveModalityFromModifiers(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList, @NotNull Modality defaultModality) { if (modifierList == null) return defaultModality; - if (modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { - return Modality.ABSTRACT; - } + checkCompatibility(trace, modifierList, Lists.newArrayList(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD), + Lists.newArrayList(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD)); + boolean hasAbstractModifier = modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD); + boolean hasOverrideModifier = modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD); + if (modifierList.hasModifier(JetTokens.OPEN_KEYWORD)) { + if (hasAbstractModifier || hasOverrideModifier) { + trace.report(Errors.REDUNDANT_MODIFIER.on(modifierList, JetTokens.OPEN_KEYWORD, hasAbstractModifier ? JetTokens.ABSTRACT_KEYWORD : JetTokens.OVERRIDE_KEYWORD)); + } + if (hasAbstractModifier) { + return Modality.ABSTRACT; + } return Modality.OPEN; } - if (modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD)) { + if (hasAbstractModifier) { + return Modality.ABSTRACT; + } + if (hasOverrideModifier) { return Modality.OPEN; } if (modifierList.hasModifier(JetTokens.FINAL_KEYWORD)) { @@ -545,6 +563,49 @@ public class ClassDescriptorResolver { return defaultModality; } + @NotNull + /*package*/ static Visibility resolveVisibilityFromModifiers(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList) { + return resolveVisibilityFromModifiers(trace, modifierList, Visibility.INTERNAL); + } + + @NotNull + /*package*/ static Visibility resolveVisibilityFromModifiers(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList, @NotNull Visibility defaultVisibility) { + if (modifierList == null) return defaultVisibility; + checkCompatibility(trace, modifierList, Lists.newArrayList(JetTokens.PRIVATE_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PUBLIC_KEYWORD, JetTokens.INTERNAL_KEYWORD), + Lists.newArrayList(JetTokens.PROTECTED_KEYWORD, JetTokens.INTERNAL_KEYWORD)); + if (modifierList.hasModifier(JetTokens.PRIVATE_KEYWORD)) return Visibility.PRIVATE; + if (modifierList.hasModifier(JetTokens.PUBLIC_KEYWORD)) return Visibility.PUBLIC; + if (modifierList.hasModifier(JetTokens.PROTECTED_KEYWORD)) { + if (modifierList.hasModifier(JetTokens.INTERNAL_KEYWORD)) { + return Visibility.INTERNAL_PROTECTED; + } + return Visibility.PROTECTED; + } + return defaultVisibility; + } + + /*package*/ static boolean checkCompatibility(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList, Collection availableModifiers, Collection... availableCombinations) { + if (modifierList == null) return true; + Collection presentModifiers = Sets.newLinkedHashSet(); + for (JetKeywordToken modifier : availableModifiers) { + if (modifierList.hasModifier(modifier)) { + presentModifiers.add(modifier); + } + } + if (presentModifiers.size() == 1) { + return true; + } + for (Collection combination : availableCombinations) { + if (presentModifiers.containsAll(combination) && combination.containsAll(presentModifiers)) { + return true; + } + } + for (JetKeywordToken token : presentModifiers) { + trace.report(Errors.INCOMPATIBLE_MODIFIERS.on(modifierList.getModifierNode(token), presentModifiers)); + } + return false; + } + @Nullable private PropertySetterDescriptor resolvePropertySetterDescriptor(@NotNull JetScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { JetPropertyAccessor setter = property.getSetter(); @@ -554,7 +615,8 @@ public class ClassDescriptorResolver { JetParameter parameter = setter.getParameter(); setterDescriptor = new PropertySetterDescriptor( - resolveModalityFromModifiers(setter.getModifierList()), // TODO : default modifiers differ in different contexts + resolveModalityFromModifiers(trace, setter.getModifierList()), // TODO : default modifiers differ in different contexts + resolveVisibilityFromModifiers(trace, setter.getModifierList(), propertyDescriptor.getVisibility()), propertyDescriptor, annotations, setter.getBodyExpression() != null, false); if (parameter != null) { if (parameter.isRef()) { @@ -596,6 +658,7 @@ public class ClassDescriptorResolver { else if (property.isVar()) { setterDescriptor = new PropertySetterDescriptor( propertyDescriptor.getModality(), + propertyDescriptor.getVisibility(), propertyDescriptor, Collections.emptyList(), false, true); } @@ -627,13 +690,15 @@ public class ClassDescriptorResolver { } getterDescriptor = new PropertyGetterDescriptor( - resolveModalityFromModifiers(getter.getModifierList()), // TODO : default modifiers differ in different contexts + resolveModalityFromModifiers(trace, getter.getModifierList()), // TODO : default modifiers differ in different contexts + resolveVisibilityFromModifiers(trace, getter.getModifierList(), propertyDescriptor.getVisibility()), propertyDescriptor, annotations, returnType, getter.getBodyExpression() != null, false); trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor); } else { getterDescriptor = new PropertyGetterDescriptor( propertyDescriptor.getModality(), + propertyDescriptor.getVisibility(), propertyDescriptor, Collections.emptyList(), propertyDescriptor.getOutType(), false, true); } return getterDescriptor; @@ -664,7 +729,8 @@ public class ClassDescriptorResolver { constructorDescriptor, new WritableScopeImpl(scope, classDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Scope with value parameters of a constructor"), valueParameters), - Modality.FINAL); + Modality.FINAL, + resolveVisibilityFromModifiers(trace, modifierList)); } @Nullable @@ -700,7 +766,8 @@ public class ClassDescriptorResolver { PropertyDescriptor propertyDescriptor = new PropertyDescriptor( classDescriptor, annotationResolver.resolveAnnotations(scope, modifierList), - resolveModalityFromModifiers(modifierList), + resolveModalityFromModifiers(trace, parameter.getModifierList()), + resolveVisibilityFromModifiers(trace, parameter.getModifierList()), isMutable, null, name == null ? "" : name, 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 3bab1a2d111..56b18bbb19e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -96,6 +96,7 @@ public class TypeHierarchyResolver { MutableClassDescriptor classObjectDescriptor = new MutableClassDescriptor(context.getTrace(), mutableClassDescriptor, outerScope, ClassKind.OBJECT); classObjectDescriptor.setName("class-object-for-" + klass.getName()); classObjectDescriptor.setModality(Modality.FINAL); + classObjectDescriptor.setVisibility(ClassDescriptorResolver.resolveVisibilityFromModifiers(context.getTrace(), klass.getModifierList())); classObjectDescriptor.createTypeConstructor(); createPrimaryConstructor(classObjectDescriptor); mutableClassDescriptor.setClassObjectDescriptor(classObjectDescriptor); @@ -151,7 +152,7 @@ public class TypeHierarchyResolver { private void createPrimaryConstructor(MutableClassDescriptor mutableClassDescriptor) { ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(mutableClassDescriptor, Collections.emptyList(), true); constructorDescriptor.initialize(Collections.emptyList(), Collections.emptyList(), - Modality.FINAL); + Modality.FINAL, Visibility.INTERNAL);//TODO check set mutableClassDescriptor.getVisibility() // TODO : make the constructor private? mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor); } @@ -265,8 +266,10 @@ public class TypeHierarchyResolver { descriptor.createTypeConstructor(); } for (Map.Entry entry : context.getObjects().entrySet()) { + JetObjectDeclaration objectDeclaration = entry.getKey(); MutableClassDescriptor descriptor = entry.getValue(); descriptor.setModality(Modality.FINAL); + descriptor.setVisibility(ClassDescriptorResolver.resolveVisibilityFromModifiers(context.getTrace(), objectDeclaration.getModifierList())); descriptor.createTypeConstructor(); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java index ebcff036fb7..afa7a1dba62 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -118,6 +118,7 @@ public class ErrorUtils { ERROR_CLASS, Collections.emptyList(), Modality.OPEN, + Visibility.INTERNAL, true, null, "", @@ -130,7 +131,8 @@ public class ErrorUtils { typeParameters, getValueParameters(functionDescriptor, positionedValueArgumentTypes), createErrorType(""), - Modality.OPEN + Modality.OPEN, + Visibility.INTERNAL ); } @@ -140,7 +142,8 @@ public class ErrorUtils { Collections.emptyList(), // TODO Collections.emptyList(), // TODO createErrorType(""), - Modality.OPEN + Modality.OPEN, + Visibility.INTERNAL ); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 08280937ae4..b0d8058f0d7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -975,7 +975,7 @@ public class JetTypeInferrer { else { effectiveReceiverType = receiverType; } - functionDescriptor.initialize(effectiveReceiverType, Collections.emptyList(), valueParameterDescriptors, null, Modality.FINAL); + functionDescriptor.initialize(effectiveReceiverType, Collections.emptyList(), valueParameterDescriptors, null, Modality.FINAL, Visibility.LOCAL); context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor); JetType returnType = NO_EXPECTED_TYPE; From 4ac2a46fb44b1429d51012d43418b150e1dbe570 Mon Sep 17 00:00:00 2001 From: svtk Date: Fri, 23 Sep 2011 13:03:14 +0400 Subject: [PATCH 2/3] Added 'incompatible modifiers' error; 'remove redundant modifier' fix --- .../jet/lang/diagnostics/Errors.java | 23 ++++++++ .../jet/plugin/annotations/JetPsiChecker.java | 2 +- .../jet/plugin/quickfix/QuickFixes.java | 8 ++- .../plugin/quickfix/RemoveModifierFix.java | 47 +++++++++------- .../quickfix/RemoveRedundantModifierFix.java | 53 +++++++++++++++++++ .../afterRemoveRedundantModifier1.kt | 8 +++ .../afterRemoveRedundantModifier2.kt | 8 +++ .../afterRemoveRedundantModifier3.kt | 8 +++ .../beforeRemoveRedundantModifier1.kt | 8 +++ .../beforeRemoveRedundantModifier2.kt | 8 +++ .../beforeRemoveRedundantModifier3.kt | 8 +++ .../jet/plugin/quickfix/ModifiersTest.java | 26 +++++++++ 12 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRedundantModifierFix.java create mode 100644 idea/testData/quickfix/modifiers/afterRemoveRedundantModifier1.kt create mode 100644 idea/testData/quickfix/modifiers/afterRemoveRedundantModifier2.kt create mode 100644 idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt create mode 100644 idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier1.kt create mode 100644 idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier2.kt create mode 100644 idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier3.kt create mode 100644 idea/tests/org/jetbrains/jet/plugin/quickfix/ModifiersTest.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 73cd701c5f7..0042d1c3c74 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.lang.diagnostics; +import com.google.common.collect.Lists; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; @@ -7,6 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.resolve.DescriptorRenderer; import java.lang.reflect.Field; @@ -25,6 +27,27 @@ public interface Errors { UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.INSTANCE; RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.INSTANCE; PsiElementOnlyDiagnosticFactory2 TYPE_MISMATCH = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected"); + ParameterizedDiagnosticFactory1> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1>(ERROR, "Incompatible modifiers: {0}") { + @Override + protected String makeMessageFor(Collection argument) { + StringBuilder sb = new StringBuilder(); + for (Iterator iterator = argument.iterator(); iterator.hasNext(); ) { + JetKeywordToken modifier = iterator.next(); + sb.append(modifier.getValue()); + if (iterator.hasNext()) { + sb.append(" "); + } + } + return sb.toString(); + } + }; + PsiElementOnlyDiagnosticFactory2 REDUNDANT_MODIFIER = new PsiElementOnlyDiagnosticFactory2(Severity.WARNING, "Modifier {0} is redundant because {1} is present") { + @NotNull + @Override + public Diagnostic on(@NotNull JetModifierList element, @NotNull ASTNode node, @NotNull JetKeywordToken redundantModifier, @NotNull JetKeywordToken presentModifier) { + return new DiagnosticWithAdditionalInfo(this, severity, makeMessage(redundantModifier, presentModifier), element, node.getTextRange(), redundantModifier); + } + }; SimpleDiagnosticFactory SAFE_CALLS_ARE_NOT_ALLOWED_ON_NAMESPACES = SimpleDiagnosticFactory.create(ERROR, "Safe calls are not allowed on namespaces"); SimpleDiagnosticFactory TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = SimpleDiagnosticFactory.create(ERROR, "Type checking has run into a recursive problem"); // TODO: message diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java index 8350ecd9543..54e7aceec3e 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java @@ -90,7 +90,7 @@ public class JetPsiChecker implements Annotator { DiagnosticWithPsiElement diagnosticWithPsiElement = (DiagnosticWithPsiElement) diagnostic; if (diagnostic.getFactory() instanceof PsiElementOnlyDiagnosticFactory) { PsiElementOnlyDiagnosticFactory factory = (PsiElementOnlyDiagnosticFactory) diagnostic.getFactory(); - Set intentionActionFactories = QuickFixes.get(factory); + Collection intentionActionFactories = QuickFixes.get(factory); for (IntentionActionFactory intentionActionFactory : intentionActionFactories) { IntentionAction action = null; if (intentionActionFactory != null) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index 4d5dfa51b46..79b4184183b 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.plugin.quickfix; import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import com.intellij.psi.PsiElement; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.diagnostics.PsiElementOnlyDiagnosticFactory; @@ -11,15 +12,16 @@ import org.jetbrains.jet.lang.psi.JetPropertyAccessor; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; +import java.util.Collection; import java.util.Set; /** * @author svtk */ public class QuickFixes { - private static HashMultimap actionMap = HashMultimap.create(); + private static final Multimap actionMap = HashMultimap.create(); - public static Set get(PsiElementOnlyDiagnosticFactory diagnosticFactory) { + public static Collection get(PsiElementOnlyDiagnosticFactory diagnosticFactory) { return actionMap.get(diagnosticFactory); } @@ -83,6 +85,8 @@ public class QuickFixes { add(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory()); add(Errors.UNNECESSARY_SAFE_CALL, ReplaceSafeCallToDotCall.createFactory()); + + add(Errors.REDUNDANT_MODIFIER, RemoveRedundantModifierFix.createFactory()); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java index c1e9edfb1e5..99fd068f5d3 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.plugin.quickfix; +import com.intellij.extapi.psi.ASTDelegatePsiElement; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -47,32 +48,42 @@ public class RemoveModifierFix extends ModifierFix { @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - element.replace(removeModifier(element, modifier)); + JetModifierListOwner newElement = (JetModifierListOwner) element.copy(); + element.replace(removeModifier(newElement, modifier)); } @NotNull /*package*/ static T removeModifier(T element, JetToken modifier) { - T newElement = (T) (element.copy()); - assert newElement.hasModifier(modifier); - JetModifierList modifierList = newElement.getModifierList(); - ASTNode modifierNode = modifierList.getModifierNode(modifier); - PsiElement whiteSpace = modifierNode.getPsi().getNextSibling(); - ((JetElement)newElement).deleteChildInternal(modifierNode); - if (modifierList.getChildren().length == 0) { - whiteSpace = modifierList.getNextSibling(); - ((JetElement) newElement).deleteChildInternal(modifierList.getNode()); - removeWhiteSpace(newElement, whiteSpace); + JetModifierList modifierList = element.getModifierList(); + assert modifierList != null; + removeModifierFromList(modifierList, modifier); + if (modifierList.getFirstChild() == null) { + PsiElement whiteSpace = modifierList.getNextSibling(); + assert element instanceof JetElement; + ((JetElement) element).deleteChildInternal(modifierList.getNode()); + removeWhiteSpace((JetElement) element, whiteSpace); } - else { - removeWhiteSpace(newElement, whiteSpace); - } - return newElement; + return element; } - private static void removeWhiteSpace(PsiElement element, PsiElement subElement) { - if (subElement instanceof PsiWhiteSpace) { - ((JetElement) element).deleteChildInternal(subElement.getNode()); + /*package*/ static JetModifierList removeModifierFromList(@NotNull JetModifierList modifierList, JetToken modifier) { + assert modifierList.hasModifier(modifier); + ASTNode modifierNode = modifierList.getModifierNode(modifier); + PsiElement whiteSpace = modifierNode.getPsi().getNextSibling(); + boolean wsRemoved = removeWhiteSpace(modifierList, whiteSpace); + modifierList.deleteChildInternal(modifierNode); + if (!wsRemoved) { + removeWhiteSpace(modifierList, modifierList.getLastChild()); } + return modifierList; + } + + private static boolean removeWhiteSpace(ASTDelegatePsiElement element, PsiElement subElement) { + if (subElement instanceof PsiWhiteSpace) { + element.deleteChildInternal(subElement.getNode()); + return true; + } + return false; } public static IntentionActionFactory createFactory(final JetKeywordToken modifier) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRedundantModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRedundantModifierFix.java new file mode 100644 index 00000000000..348c0a7886a --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRedundantModifierFix.java @@ -0,0 +1,53 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithAdditionalInfo; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.psi.JetModifierList; +import org.jetbrains.jet.lexer.JetKeywordToken; + +/** + * @author svtk + */ +public class RemoveRedundantModifierFix extends IntentionActionForPsiElement { + private JetKeywordToken redundantModifier; + public RemoveRedundantModifierFix(@NotNull JetModifierList element, @NotNull JetKeywordToken redundantModifier) { + super(element); + this.redundantModifier = redundantModifier; + } + + @NotNull + @Override + public String getText() { + return "Remove redundant '" + redundantModifier + "' modifier"; + } + + @NotNull + @Override + public String getFamilyName() { + return "Remove redundant modifier"; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetModifierList newElement = (JetModifierList) element.copy(); + element.replace(RemoveModifierFix.removeModifierFromList(newElement, redundantModifier)); + } + + public static IntentionActionFactory createFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetModifierList; + assert diagnostic instanceof DiagnosticWithAdditionalInfo; + Object info = ((DiagnosticWithAdditionalInfo) diagnostic).getInfo(); + assert info instanceof JetKeywordToken; + return new RemoveRedundantModifierFix((JetModifierList) diagnostic.getPsiElement(), (JetKeywordToken) info); + } + }; + } +} diff --git a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier1.kt b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier1.kt new file mode 100644 index 00000000000..38c63050707 --- /dev/null +++ b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier1.kt @@ -0,0 +1,8 @@ +// "Remove redundant 'open' modifier" "true" +abstract class B() { + abstract fun foo() +} + +abstract class A() : B() { + abstract override fun foo() +} diff --git a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier2.kt b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier2.kt new file mode 100644 index 00000000000..38c63050707 --- /dev/null +++ b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier2.kt @@ -0,0 +1,8 @@ +// "Remove redundant 'open' modifier" "true" +abstract class B() { + abstract fun foo() +} + +abstract class A() : B() { + abstract override fun foo() +} diff --git a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt new file mode 100644 index 00000000000..38c63050707 --- /dev/null +++ b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt @@ -0,0 +1,8 @@ +// "Remove redundant 'open' modifier" "true" +abstract class B() { + abstract fun foo() +} + +abstract class A() : B() { + abstract override fun foo() +} diff --git a/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier1.kt b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier1.kt new file mode 100644 index 00000000000..acec3eb7ca5 --- /dev/null +++ b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier1.kt @@ -0,0 +1,8 @@ +// "Remove redundant 'open' modifier" "true" +abstract class B() { + abstract fun foo() +} + +abstract class A() : B() { + open abstract override fun foo() +} diff --git a/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier2.kt b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier2.kt new file mode 100644 index 00000000000..4d4d6440fb0 --- /dev/null +++ b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier2.kt @@ -0,0 +1,8 @@ +// "Remove redundant 'open' modifier" "true" +abstract class B() { + abstract fun foo() +} + +abstract class A() : B() { + abstract open override fun foo() +} diff --git a/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier3.kt b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier3.kt new file mode 100644 index 00000000000..53a92e31819 --- /dev/null +++ b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier3.kt @@ -0,0 +1,8 @@ +// "Remove redundant 'open' modifier" "true" +abstract class B() { + abstract fun foo() +} + +abstract class A() : B() { + abstract override open fun foo() +} diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/ModifiersTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/ModifiersTest.java new file mode 100644 index 00000000000..e1199ce2a37 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/ModifiersTest.java @@ -0,0 +1,26 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import org.jetbrains.jet.JetTestCaseBase; + +/** + * @author svtk + */ +public class ModifiersTest extends LightQuickFixTestCase { + + public void test() throws Exception { + doAllTests(); + } + + @Override + protected String getBasePath() { + return "/quickfix/modifiers"; + } + + @Override + protected String getTestDataPath() { + return JetTestCaseBase.getTestDataPathBase(); + } +} + + From 9b55aafe55297df61e8ed4b09aa4113c81eb1210 Mon Sep 17 00:00:00 2001 From: svtk Date: Fri, 23 Sep 2011 13:37:45 +0400 Subject: [PATCH 3/3] Bug with '{0}' in Errors fixed (need ''{0}'') --- .../org/jetbrains/jet/lang/diagnostics/Errors.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 0042d1c3c74..2065ee465e6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -27,7 +27,7 @@ public interface Errors { UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.INSTANCE; RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.INSTANCE; PsiElementOnlyDiagnosticFactory2 TYPE_MISMATCH = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected"); - ParameterizedDiagnosticFactory1> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1>(ERROR, "Incompatible modifiers: {0}") { + ParameterizedDiagnosticFactory1> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1>(ERROR, "Incompatible modifiers: ''{0}''") { @Override protected String makeMessageFor(Collection argument) { StringBuilder sb = new StringBuilder(); @@ -121,10 +121,10 @@ public interface Errors { return e.getClass().getSimpleName() + ": " + e.getMessage(); } }; - PsiElementOnlyDiagnosticFactory3 VIRTUAL_METHOD_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "Function '{0}' hides '{1}' in class {2} and needs 'override' modifier"); + PsiElementOnlyDiagnosticFactory3 VIRTUAL_METHOD_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "Function ''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier"); SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code"); - ParameterizedDiagnosticFactory1 UNREACHABLE_BECAUSE_OF_NOTHING = ParameterizedDiagnosticFactory1.create(ERROR, "This code is unreachable, because '{0}' never terminates normally"); + ParameterizedDiagnosticFactory1 UNREACHABLE_BECAUSE_OF_NOTHING = ParameterizedDiagnosticFactory1.create(ERROR, "This code is unreachable, because ''{0}'' never terminates normally"); SimpleDiagnosticFactory MANY_CLASS_OBJECTS = SimpleDiagnosticFactory.create(ERROR, "Only one class object is allowed per class"); SimpleDiagnosticFactory CLASS_OBJECT_NOT_ALLOWED = SimpleDiagnosticFactory.create(ERROR, "A class object is not allowed here"); @@ -211,7 +211,7 @@ public interface Errors { SimpleDiagnosticFactory REF_PARAMETER_WITH_VAL_OR_VAR = SimpleDiagnosticFactory.create(ERROR, "'val' and 'var' are not allowed on ref-parameters"); SimpleDiagnosticFactory VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION = SimpleDiagnosticFactory.create(ERROR, "A type annotation is required on a value parameter"); SimpleDiagnosticFactory BREAK_OR_CONTINUE_OUTSIDE_A_LOOP = SimpleDiagnosticFactory.create(ERROR, "'break' and 'continue' are only allowed inside a loop"); - ParameterizedDiagnosticFactory1 NOT_A_LOOP_LABEL = ParameterizedDiagnosticFactory1.create(ERROR, "The label '{0}' does not denote a loop"); + ParameterizedDiagnosticFactory1 NOT_A_LOOP_LABEL = ParameterizedDiagnosticFactory1.create(ERROR, "The label ''{0}'' does not denote a loop"); SimpleDiagnosticFactory ANONYMOUS_INITIALIZER_WITHOUT_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "Anonymous initializers are only allowed in the presence of a primary constructor"); SimpleDiagnosticFactory NULLABLE_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "A supertype cannot be nullable"); @@ -285,7 +285,7 @@ public interface Errors { return descriptor.getName(); } }; - ParameterizedDiagnosticFactory3 ABSTRACT_METHOD_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory3(ERROR, "Class '{0}' must be declared abstract or implement abstract method '{1}' declared in {2}") { + ParameterizedDiagnosticFactory3 ABSTRACT_METHOD_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory3(ERROR, "Class ''{0}'' must be declared abstract or implement abstract method ''{1}'' declared in {2}") { @Override protected String makeMessageForA(@NotNull JetClassOrObject jetClassOrObject) { return jetClassOrObject.getName(); @@ -303,7 +303,7 @@ public interface Errors { }; ParameterizedDiagnosticFactory3 RESULT_TYPE_MISMATCH = ParameterizedDiagnosticFactory3.create(ERROR, "{0} must return {1} but returns {2}"); - ParameterizedDiagnosticFactory3 UNSAFE_INFIX_CALL = ParameterizedDiagnosticFactory3.create(ERROR, "Infix call corresponds to a dot-qualified call '{0}.{1}({2})' which is not allowed on a nullable receiver '{0}'. Use '?.'-qualified call instead"); + ParameterizedDiagnosticFactory3 UNSAFE_INFIX_CALL = ParameterizedDiagnosticFactory3.create(ERROR, "Infix call corresponds to a dot-qualified call ''{0}.{1}({2})' which is not allowed on a nullable receiver ''{0}''. Use '?.'-qualified call instead"); ParameterizedDiagnosticFactory1> OVERLOAD_RESOLUTION_AMBIGUITY = new AmbiguousDescriptorDiagnosticFactory("Overload resolution ambiguity: {0}"); ParameterizedDiagnosticFactory1> NONE_APPLICABLE = new AmbiguousDescriptorDiagnosticFactory("None of the following functions can be called with the arguments supplied: {0}");