javafx: support propertyProperty rename/delete (IDEA-109574)

This commit is contained in:
Anna Kozlova
2013-06-26 15:24:14 +04:00
parent 9adc928cc4
commit d4fc033615
9 changed files with 232 additions and 30 deletions

View File

@@ -17,6 +17,7 @@ package com.intellij.codeInsight.generation;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
@@ -31,6 +32,17 @@ public abstract class GetterSetterPrototypeProvider {
public abstract boolean canGeneratePrototypeFor(PsiField field);
public abstract PsiMethod[] generateGetters(PsiField field);
public abstract PsiMethod[] generateSetters(PsiField field);
public PsiMethod[] findGetters(PsiClass psiClass, String propertyName) {
return null;
}
public String suggestGetterName(String propertyName) {
return null;
}
public boolean isSimpleGetter(PsiMethod method, String oldPropertyName) {
return false;
}
public abstract boolean isReadOnly(PsiField field);
@@ -51,4 +63,27 @@ public abstract class GetterSetterPrototypeProvider {
}
return field.hasModifierProperty(PsiModifier.FINAL);
}
public static PsiMethod[] findGetters(PsiClass aClass, String propertyName, boolean isStatic) {
if (!isStatic) {
for (GetterSetterPrototypeProvider provider : Extensions.getExtensions(EP_NAME)) {
final PsiMethod[] getterSetter = provider.findGetters(aClass, propertyName);
if (getterSetter != null) return getterSetter;
}
}
final PsiMethod propertyGetterSetter = PropertyUtil.findPropertyGetter(aClass, propertyName, isStatic, false);
if (propertyGetterSetter != null) {
return new PsiMethod[] {propertyGetterSetter};
}
return null;
}
public static String suggestNewGetterName(String oldPropertyName, String newPropertyName, PsiMethod method) {
for (GetterSetterPrototypeProvider provider : Extensions.getExtensions(EP_NAME)) {
if (provider.isSimpleGetter(method, oldPropertyName)) {
return provider.suggestGetterName(newPropertyName);
}
}
return null;
}
}

View File

@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.rename;
import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -43,10 +44,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.RenameJavaVariableProcessor");
@@ -150,7 +148,9 @@ public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor {
String newPropertyName = manager.variableNameToPropertyName(newName, VariableKind.FIELD);
boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
PsiMethod getter = PropertyUtil.findPropertyGetter(aClass, propertyName, isStatic, false);
PsiMethod[] getters = GetterSetterPrototypeProvider.findGetters(aClass, propertyName, isStatic);
PsiMethod setter = PropertyUtil.findPropertySetter(aClass, propertyName, isStatic, false);
boolean shouldRenameSetterParameter = false;
@@ -161,22 +161,31 @@ public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor {
shouldRenameSetterParameter = parameterName.equals(setterParameter.getName());
}
String newGetterName = "";
if (getter != null) {
String getterId = getter.getName();
newGetterName = PropertyUtil.suggestGetterName(newPropertyName, field.getType(), getterId);
if (newGetterName.equals(getterId)) {
getter = null;
newGetterName = null;
} else {
for (PsiMethod method : getter.findDeepestSuperMethods()) {
if (method instanceof PsiCompiledElement) {
getter = null;
break;
}
if (getters != null) {
List<PsiMethod> validGetters = new ArrayList<PsiMethod>();
for (PsiMethod getter : getters) {
String newGetterName = GetterSetterPrototypeProvider.suggestNewGetterName(propertyName, newPropertyName, getter);
String getterId = null;
if (newGetterName == null) {
getterId = getter.getName();
newGetterName = PropertyUtil.suggestGetterName(newPropertyName, field.getType(), getterId);
}
if (newGetterName.equals(getterId)) {
continue;
}
else {
boolean valid = true;
for (PsiMethod method : getter.findDeepestSuperMethods()) {
if (method instanceof PsiCompiledElement) {
valid = false;
break;
}
}
if (!valid) continue;
}
validGetters.add(getter);
}
getters = validGetters.isEmpty() ? null : validGetters.toArray(new PsiMethod[validGetters.size()]);
}
String newSetterName = "";
@@ -201,14 +210,20 @@ public class RenameJavaVariableProcessor extends RenameJavaMemberProcessor {
}
}
if ((getter != null || setter != null) && askToRenameAccesors(getter, setter, newName, project)) {
getter = null;
if ((getters != null || setter != null) && askToRenameAccesors(getters != null ? getters[0] : null, setter, newName, project)) {
getters = null;
setter = null;
shouldRenameSetterParameter = false;
}
if (getter != null) {
addOverriddenAndImplemented(getter, newGetterName, allRenames);
if (getters != null) {
for (PsiMethod getter : getters) {
String newGetterName = GetterSetterPrototypeProvider.suggestNewGetterName(propertyName, newPropertyName, getter);
if (newGetterName == null) {
newGetterName = PropertyUtil.suggestGetterName(newPropertyName, field.getType(), getter.getName());
}
addOverriddenAndImplemented(getter, newGetterName, allRenames);
}
}
if (setter != null) {

View File

@@ -16,6 +16,7 @@
package com.intellij.refactoring.safeDelete;
import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableUtil;
import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider;
import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter;
import com.intellij.ide.util.SuperMethodWarningUtil;
import com.intellij.openapi.application.ApplicationManager;
@@ -187,21 +188,30 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
PsiClass aClass = field.getContainingClass();
if (aClass != null) {
boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
PsiMethod getter = PropertyUtil.findPropertyGetter(aClass, propertyName, isStatic, false);
if (allElementsToDelete.contains(getter) || getter != null && !getter.isPhysical()) getter = null;
PsiMethod[] getters = GetterSetterPrototypeProvider.findGetters(aClass, propertyName, isStatic);
if (getters != null) {
final List<PsiMethod> validGetters = new ArrayList<PsiMethod>(1);
for (PsiMethod getter : getters) {
if (!allElementsToDelete.contains(getter) && (getter != null && getter.isPhysical())) {
validGetters.add(getter);
}
}
getters = validGetters.isEmpty() ? null : validGetters.toArray(new PsiMethod[validGetters.size()]);
}
PsiMethod setter = PropertyUtil.findPropertySetter(aClass, propertyName, isStatic, false);
if (allElementsToDelete.contains(setter) || setter != null && !setter.isPhysical()) setter = null;
if (askUser && (getter != null || setter != null)) {
if (askUser && (getters != null || setter != null)) {
final String message =
RefactoringMessageUtil.getGetterSetterMessage(field.getName(), RefactoringBundle.message("delete.title"), getter, setter);
if (Messages.showYesNoDialog(project, message, RefactoringBundle.message("safe.delete.title"), Messages.getQuestionIcon()) != 0) {
getter = null;
RefactoringMessageUtil.getGetterSetterMessage(field.getName(), RefactoringBundle.message("delete.title"), getters != null ? getters[0] : null, setter);
if (!ApplicationManager.getApplication().isUnitTestMode() && Messages.showYesNoDialog(project, message, RefactoringBundle.message("safe.delete.title"), Messages.getQuestionIcon()) != 0) {
getters = null;
setter = null;
}
}
List<PsiElement> elements = new ArrayList<PsiElement>();
if (setter != null) elements.add(setter);
if (getter != null) elements.add(getter);
if (getters != null) Collections.addAll(elements, getters);
return elements;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2000-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.plugins.javaFX;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.rename.RenameProcessor;
import com.intellij.refactoring.safeDelete.SafeDeleteHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.fxml.AbstractJavaFXTestCase;
public class RefactoringFieldTest extends AbstractJavaFXTestCase {
public void testPropertyRename() throws Exception {
myFixture.configureByFile(getTestName(false) + ".java");
performRename("newName");
myFixture.checkResultByFile(getTestName(false) + "_after.java");
}
public void testPropertyDelete() throws Exception {
myFixture.configureByFile(getTestName(false) + ".java");
performDelete();
myFixture.checkResultByFile(getTestName(false) + "_after.java");
}
protected void performRename(String newName) {
PsiElement element = TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase
.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
new RenameProcessor(getProject(), element, newName, false, false).run();
}
private void performDelete() {
final PsiElement psiElement = TargetElementUtilBase
.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
assertNotNull("No element found in text:\n" + myFixture.getFile().getText(), psiElement);
SafeDeleteHandler.invoke(getProject(), new PsiElement[]{psiElement}, true);
}
@NotNull
@Override
protected String getTestDataPath() {
return PluginPathManager.getPluginHomePath("javaFX") + "/testData/fieldRefactoring/";
}
}

View File

@@ -81,6 +81,28 @@ public class JavaFxGetterSetterPrototypeProvider extends GetterSetterPrototypePr
return new PsiMethod[] {setter};
}
@Override
public PsiMethod[] findGetters(PsiClass psiClass, String propertyName) {
final String getterName = suggestGetterName(propertyName);
final PsiMethod specificGetter = psiClass
.findMethodBySignature(JavaPsiFacade.getElementFactory(psiClass.getProject()).createMethod(getterName, PsiType.VOID), false);
if (specificGetter != null) {
final PsiMethod getter = PropertyUtil.findPropertyGetter(psiClass, propertyName, false, false);
return getter == null ? new PsiMethod[] {specificGetter} : new PsiMethod[] {getter, specificGetter};
}
return super.findGetters(psiClass, propertyName);
}
@Override
public String suggestGetterName(String propertyName) {
return propertyName + "Property";
}
@Override
public boolean isSimpleGetter(PsiMethod method, String oldPropertyName) {
return method.getName().equals(suggestGetterName(oldPropertyName));
}
@Override
public boolean isReadOnly(PsiField field) {
return !InheritanceUtil.isInheritor(field.getType(), JavaFxCommonClassNames.JAVAFX_BEANS_VALUE_WRITABLE_VALUE);

View File

@@ -0,0 +1,18 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
class Test {
private IntegerProperty c<caret>ount = new SimpleIntegerProperty(this, "count");
public int getCount() {
return count.get();
}
public IntegerProperty countProperty() {
return count;
}
public void setCount(int count) {
this.count.set(count);
}
}

View File

@@ -0,0 +1,6 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
class Test {
}

View File

@@ -0,0 +1,18 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
class Test {
private IntegerProperty c<caret>ount = new SimpleIntegerProperty(this, "count");
public int getCount() {
return count.get();
}
public IntegerProperty countProperty() {
return count;
}
public void setCount(int count) {
this.count.set(count);
}
}

View File

@@ -0,0 +1,18 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
class Test {
private IntegerProperty newName = new SimpleIntegerProperty(this, "count");
public int getNewName() {
return newName.get();
}
public IntegerProperty newNameProperty() {
return newName;
}
public void setNewName(int newName) {
this.newName.set(newName);
}
}