Added 'change visibility modifier' quick fix

This commit is contained in:
Svetlana Isakova
2012-04-04 14:22:10 +04:00
parent fbffbc541a
commit 0f20d4a6e2
10 changed files with 264 additions and 59 deletions
@@ -49,3 +49,4 @@ macro.iterable.variable=kotlinIterableVariable()
macro.suggest.variable.name=kotlinSuggestVariableName()
macro.fun.parameters=functionParameters()
macro.fun.anonymousSuper=anonymousSuper()
change.visibility.modifier=Change visibility modifier
@@ -85,11 +85,11 @@ public class AddModifierFix extends JetIntentionAction<JetModifierListOwner> {
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
element.replace(addModifier(element, modifier, modifiersThanCanBeReplaced, project));
element.replace(addModifier(element, modifier, modifiersThanCanBeReplaced, project, false));
}
@NotNull
private static JetModifierListOwner addModifier(@NotNull PsiElement element, @NotNull JetKeywordToken modifier, @Nullable JetToken[] modifiersThanCanBeReplaced, @NotNull Project project) {
/*package*/ static JetModifierListOwner addModifier(@NotNull PsiElement element, @NotNull JetKeywordToken modifier, @Nullable JetToken[] modifiersThatCanBeReplaced, @NotNull Project project, boolean toBeginning) {
JetModifierListOwner newElement = (JetModifierListOwner) (element.copy());
JetModifierList modifierList = newElement.getModifierList();
@@ -102,20 +102,39 @@ public class AddModifierFix extends JetIntentionAction<JetModifierListOwner> {
}
else {
boolean replaced = false;
if (modifiersThanCanBeReplaced != null) {
for (JetToken modifierThanCanBeReplaced : modifiersThanCanBeReplaced) {
if (modifierList.hasModifier(modifierThanCanBeReplaced)) {
PsiElement openModifierPsi = modifierList.getModifierNode(modifierThanCanBeReplaced).getPsi();
assert openModifierPsi != null;
openModifierPsi.replace(listWithModifier.getFirstChild());
replaced = true;
if (modifiersThatCanBeReplaced != null) {
PsiElement toBeReplaced = null;
PsiElement toReplace = null;
for (JetToken modifierThatCanBeReplaced : modifiersThatCanBeReplaced) {
if (modifierList.hasModifier(modifierThatCanBeReplaced)) {
PsiElement modifierElement = modifierList.getModifierNode(modifierThatCanBeReplaced).getPsi();
assert modifierElement != null;
if (!replaced) {
toBeReplaced = modifierElement;
toReplace = listWithModifier.getFirstChild();
//modifierElement.replace(listWithModifier.getFirstChild());
replaced = true;
}
else {
modifierList.deleteChildInternal(modifierElement.getNode());
}
}
}
if (toBeReplaced != null && toReplace != null) {
toBeReplaced.replace(toReplace);
}
}
if (!replaced) {
PsiElement lastChild = modifierList.getLastChild();
modifierList.addAfter(listWithModifier.getFirstChild(), lastChild);
modifierList.addAfter(whiteSpace, lastChild);
if (toBeginning) {
PsiElement firstChild = modifierList.getFirstChild();
modifierList.addBefore(listWithModifier.getFirstChild(), firstChild);
modifierList.addBefore(whiteSpace, firstChild);
}
else {
PsiElement lastChild = modifierList.getLastChild();
modifierList.addAfter(listWithModifier.getFirstChild(), lastChild);
modifierList.addAfter(whiteSpace, lastChild);
}
}
}
return newElement;
@@ -0,0 +1,131 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetModifierListOwner;
import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetBundle;
/**
* @author svtk
*/
public class ChangeVisibilityModifierFix extends JetIntentionAction<JetModifierListOwner> {
public ChangeVisibilityModifierFix(@NotNull JetModifierListOwner element) {
super(element);
}
@NotNull
@Override
public String getText() {
return JetBundle.message("change.visibility.modifier");
}
@NotNull
@Override
public String getFamilyName() {
return JetBundle.message("change.visibility.modifier");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!(file instanceof JetFile)) return false;
return super.isAvailable(project, editor, file) && (findVisibilityChangeTo((JetFile)file) != null);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!(file instanceof JetFile)) return;
JetKeywordToken modifier = findVisibilityChangeTo((JetFile)file);
JetToken[] modifiersThanCanBeReplaced = new JetKeywordToken[] { JetTokens.PUBLIC_KEYWORD, JetTokens.PRIVATE_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.INTERNAL_KEYWORD };
element.replace(AddModifierFix.addModifier(element, modifier, modifiersThanCanBeReplaced, project, true));
}
private JetKeywordToken findVisibilityChangeTo(JetFile file) {
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER).getBindingContext();
DeclarationDescriptor descriptor;
if (element instanceof JetParameter) {
descriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, element);
}
else {
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
}
if (!(descriptor instanceof CallableMemberDescriptor)) return null;
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor)descriptor;
Visibility maxVisibility = null;
for (CallableMemberDescriptor overriddenDescriptor : memberDescriptor.getOverriddenDescriptors()) {
Visibility overriddenDescriptorVisibility = overriddenDescriptor.getVisibility();
if (maxVisibility == null) {
maxVisibility = overriddenDescriptorVisibility;
continue;
}
Integer compare = Visibilities.compare(maxVisibility, overriddenDescriptorVisibility);
if (compare == null) {
maxVisibility = Visibilities.PUBLIC;
}
else if (compare < 0) {
maxVisibility = overriddenDescriptorVisibility;
}
}
if (maxVisibility == memberDescriptor.getVisibility()) {
return null;
}
JetKeywordToken modifier = null;
if (maxVisibility == Visibilities.PUBLIC) {
modifier = JetTokens.PUBLIC_KEYWORD;
}
else if (maxVisibility == Visibilities.PROTECTED) {
modifier = JetTokens.PROTECTED_KEYWORD;
}
else if (maxVisibility == Visibilities.INTERNAL) {
modifier = JetTokens.INTERNAL_KEYWORD;
}
else if (maxVisibility == Visibilities.INTERNAL_PROTECTED) {
//todo should be internal and protected keywords
modifier = JetTokens.INTERNAL_KEYWORD;
}
return modifier;
}
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetModifierListOwner> createAction(Diagnostic diagnostic) {
PsiElement element = diagnostic.getPsiElement();
if (!(element instanceof JetModifierListOwner)) return null;
return new ChangeVisibilityModifierFix((JetModifierListOwner)element);
}
};
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler;
import java.util.Collection;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lexer.JetTokens.*;
/**
@@ -50,88 +51,91 @@ public class QuickFixes {
JetIntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ABSTRACT_KEYWORD);
JetIntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(ABSTRACT_KEYWORD);
factories.put(Errors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_NOT_IN_CLASS, removeAbstractModifierFactory);
factories.put(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory);
factories.put(ABSTRACT_PROPERTY_NOT_IN_CLASS, removeAbstractModifierFactory);
JetIntentionActionFactory removePartsFromPropertyFactory = RemovePartsFromPropertyFix.createFactory();
factories.put(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removePartsFromPropertyFactory);
factories.put(ABSTRACT_PROPERTY_WITH_INITIALIZER, removeAbstractModifierFactory);
factories.put(ABSTRACT_PROPERTY_WITH_INITIALIZER, removePartsFromPropertyFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removePartsFromPropertyFactory);
factories.put(ABSTRACT_PROPERTY_WITH_GETTER, removeAbstractModifierFactory);
factories.put(ABSTRACT_PROPERTY_WITH_GETTER, removePartsFromPropertyFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removePartsFromPropertyFactory);
factories.put(ABSTRACT_PROPERTY_WITH_SETTER, removeAbstractModifierFactory);
factories.put(ABSTRACT_PROPERTY_WITH_SETTER, removePartsFromPropertyFactory);
factories.put(Errors.PROPERTY_INITIALIZER_IN_TRAIT, removePartsFromPropertyFactory);
factories.put(PROPERTY_INITIALIZER_IN_TRAIT, removePartsFromPropertyFactory);
factories.put(Errors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, addAbstractModifierFactory);
factories.put(MUST_BE_INITIALIZED_OR_BE_ABSTRACT, addAbstractModifierFactory);
JetIntentionActionFactory addAbstractToClassFactory = AddModifierFix.createFactory(ABSTRACT_KEYWORD, JetClass.class);
factories.put(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
factories.put(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
factories.put(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
JetIntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory();
factories.put(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
factories.put(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
factories.put(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
factories.put(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory);
factories.put(ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory);
factories.put(ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory);
JetIntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory();
factories.put(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory);
factories.put(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory);
factories.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory);
factories.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory);
factories.put(Errors.NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory);
factories.put(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory);
factories.put(NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory);
factories.put(NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory);
factories.put(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OVERRIDE_KEYWORD));
factories.put(Errors.VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(OVERRIDE_KEYWORD));
factories.put(NOTHING_TO_OVERRIDE, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OVERRIDE_KEYWORD));
factories.put(VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(OVERRIDE_KEYWORD));
factories.put(Errors.USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory());
factories.put(Errors.USELESS_CAST, RemoveRightPartOfBinaryExpressionFix.createRemoveCastFactory());
factories.put(USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory());
factories.put(USELESS_CAST, RemoveRightPartOfBinaryExpressionFix.createRemoveCastFactory());
JetIntentionActionFactory changeAccessorTypeFactory = ChangeAccessorTypeFix.createFactory();
factories.put(Errors.WRONG_SETTER_PARAMETER_TYPE, changeAccessorTypeFactory);
factories.put(Errors.WRONG_GETTER_RETURN_TYPE, changeAccessorTypeFactory);
factories.put(WRONG_SETTER_PARAMETER_TYPE, changeAccessorTypeFactory);
factories.put(WRONG_GETTER_RETURN_TYPE, changeAccessorTypeFactory);
factories.put(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory());
factories.put(USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory());
JetIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true);
factories.put(Errors.REDUNDANT_MODIFIER, removeRedundantModifierFactory);
factories.put(Errors.ABSTRACT_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ABSTRACT_KEYWORD, true));
factories.put(Errors.OPEN_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD, true));
factories.put(Errors.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(FINAL_KEYWORD));
factories.put(REDUNDANT_MODIFIER, removeRedundantModifierFactory);
factories.put(ABSTRACT_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ABSTRACT_KEYWORD, true));
factories.put(OPEN_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD, true));
factories.put(TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(FINAL_KEYWORD));
JetIntentionActionFactory removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD);
factories.put(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, AddModifierFix.createFactory(OPEN_KEYWORD, JetClass.class));
factories.put(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, removeOpenModifierFactory);
factories.put(NON_FINAL_MEMBER_IN_FINAL_CLASS, AddModifierFix.createFactory(OPEN_KEYWORD, JetClass.class));
factories.put(NON_FINAL_MEMBER_IN_FINAL_CLASS, removeOpenModifierFactory);
JetIntentionActionFactory removeModifierFactory = RemoveModifierFix.createRemoveModifierFactory();
factories.put(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory);
factories.put(Errors.REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory);
factories.put(Errors.ILLEGAL_MODIFIER, removeModifierFactory);
factories.put(GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory);
factories.put(REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory);
factories.put(ILLEGAL_MODIFIER, removeModifierFactory);
factories.put(Errors.PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory());
factories.put(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory());
JetIntentionActionFactory changeToBackingFieldFactory = ChangeToBackingFieldFix.createFactory();
factories.put(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory);
factories.put(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory);
factories.put(INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory);
factories.put(INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory);
JetIntentionActionFactory unresolvedReferenceFactory = ImportClassAndFunFix.createFactory();
factories.put(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory);
factories.put(UNRESOLVED_REFERENCE, unresolvedReferenceFactory);
factories.put(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory());
factories.put(SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory());
factories.put(CANNOT_CHANGE_ACCESS_PRIVILEGE, ChangeVisibilityModifierFix.createFactory());
factories.put(CANNOT_WEAKEN_ACCESS_PRIVILEGE, ChangeVisibilityModifierFix.createFactory());
ImplementMethodsHandler implementMethodsHandler = new ImplementMethodsHandler();
actions.put(Errors.ABSTRACT_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
actions.put(Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
actions.put(ABSTRACT_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
actions.put(MANY_IMPL_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
ChangeVariableMutabilityFix changeVariableMutabilityFix = new ChangeVariableMutabilityFix();
actions.put(Errors.VAL_WITH_SETTER, changeVariableMutabilityFix);
actions.put(Errors.VAL_REASSIGNMENT, changeVariableMutabilityFix);
actions.put(VAL_WITH_SETTER, changeVariableMutabilityFix);
actions.put(VAL_REASSIGNMENT, changeVariableMutabilityFix);
actions.put(Errors.UNNECESSARY_SAFE_CALL, new ReplaceCallFix(false));
actions.put(Errors.UNSAFE_CALL, new ReplaceCallFix(true));
actions.put(UNNECESSARY_SAFE_CALL, new ReplaceCallFix(false));
actions.put(UNSAFE_CALL, new ReplaceCallFix(true));
}
}
@@ -0,0 +1,8 @@
// "Change visibility modifier" "true"
open class A {
protected open fun run() {}
}
class B : A() {
<caret>protected override fun run() {}
}
@@ -0,0 +1,8 @@
// "Change visibility modifier" "true"
open class A {
protected open fun run() {}
}
class B : A() {
<caret>protected override fun run() {}
}
@@ -0,0 +1,9 @@
// "Change visibility modifier" "true"
trait ParseResult<out T> {
public val success : Boolean
public val value : T
}
class Success<T>(<caret>public override val value : T) : ParseResult<T> {
public override val success : Boolean = true
}
@@ -0,0 +1,8 @@
// "Change visibility modifier" "true"
open class A {
protected open fun run() {}
}
class B : A() {
<caret>private override fun run() {}
}
@@ -0,0 +1,8 @@
// "Change visibility modifier" "true"
open class A {
protected open fun run() {}
}
class B : A() {
<caret>override fun run() {}
}
@@ -0,0 +1,9 @@
// "Change visibility modifier" "true"
trait ParseResult<out T> {
public val success : Boolean
public val value : T
}
class Success<T>(<caret>override val value : T) : ParseResult<T> {
public override val success : Boolean = true
}