From 06c8b177bc2d3cec7375f703aa2341974569e582 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Wed, 27 Apr 2016 13:40:43 +0300 Subject: [PATCH] Javafx: Rename static FXML property and corresponding static Java method simultaneously. Add index of FXML imports. Add searcher for Java methods referenced in FXML. Move reusable code to base class. Tests added. (IDEA-105038, IDEA-105231) --- .../plugins/javaFX/fxml/JavaFXRenameTest.java | 5 ++ .../JavaFxComponentIdReferenceProvider.java | 2 +- .../refs/JavaFxFieldIdReferenceProvider.java | 2 +- .../fxml/refs/JavaFxMethodSearcher.java | 11 ++- .../fxml/refs/JavaFxPropertyReference.java | 7 +- .../refs/JavaFxStaticPropertyReference.java | 40 +++++++-- .../javaFX/indexing/JavaFxImportsIndex.java | 1 - .../refactoring/JavaFxPropertyElement.java | 15 ++-- .../JavaFxPropertyRenameHandler.java | 90 ++++++------------- .../JavaFxStaticPropertyElement.java | 44 --------- .../rename/StaticPropertyFromLibrary.java | 1 + .../rename/staticPropertyFromLibrary.fxml | 5 ++ 12 files changed, 96 insertions(+), 127 deletions(-) delete mode 100644 plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxStaticPropertyElement.java create mode 100644 plugins/javaFX/testData/rename/StaticPropertyFromLibrary.java create mode 100644 plugins/javaFX/testData/rename/staticPropertyFromLibrary.fxml diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java index 74bcd0036326..c76fb32297d9 100644 --- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java +++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java @@ -170,6 +170,11 @@ public class JavaFXRenameTest extends DaemonAnalyzerTestCase { assertMethodExists(psiClass, newName); } + public void testStaticPropertyFromLibrary() throws Exception { + doTestErrorHint("Foo", "Cannot perform refactoring.\n" + + "Selected method is not located inside the project"); + } + public void testControllerMethod() throws Exception { final PsiClass psiClass = doTestHandler("newName", null); assertMethodExists(psiClass, "getNewName"); diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java index dd774550864e..fe8d81f915ed 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java @@ -283,7 +283,7 @@ public class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider { @NotNull @Override - protected String getPropertyName() { + public String getPropertyName() { return myFieldName; } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java index d6ecbb160549..29ddef78527d 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java @@ -150,7 +150,7 @@ public class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferen @Nullable @Override - protected String getPropertyName() { + public String getPropertyName() { return PropertyUtil.getPropertyName(myFieldOrMethod); } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxMethodSearcher.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxMethodSearcher.java index 3ab43f9bec3a..357ee1eb8576 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxMethodSearcher.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxMethodSearcher.java @@ -30,7 +30,7 @@ import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.javaFX.indexing.JavaFxImportsIndex; -import org.jetbrains.plugins.javaFX.refactoring.JavaFxStaticPropertyElement; +import org.jetbrains.plugins.javaFX.refactoring.JavaFxPropertyElement; import java.util.List; @@ -45,8 +45,13 @@ public class JavaFxMethodSearcher implements QueryExecutor extends PsiR return JavaFxPsiUtil.findObservablePropertyGetter(myPsiClass, getPropertyName()); } + @Nullable + public PsiMethod getStaticSetter() { + return null; + } + @Nullable public PsiType getType() { return JavaFxPsiUtil.getReadablePropertyType(resolve()); } @Nullable - protected abstract String getPropertyName(); + public abstract String getPropertyName(); } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxStaticPropertyReference.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxStaticPropertyReference.java index 13d772e04195..0b84f3708756 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxStaticPropertyReference.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxStaticPropertyReference.java @@ -11,14 +11,14 @@ import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil; /** * @author Pavel.Dolgov */ -public class JavaFxStaticPropertyReference extends PsiReferenceBase { +public class JavaFxStaticPropertyReference extends JavaFxPropertyReference { private String myPropertyName; private PsiMethod myStaticMethod; public JavaFxStaticPropertyReference(@NotNull XmlAttribute xmlAttribute, @Nullable PsiClass psiClass, @NotNull String propertyName) { - super(xmlAttribute); + super(xmlAttribute, psiClass); myPropertyName = propertyName; myStaticMethod = JavaFxPsiUtil.findStaticPropertySetter(propertyName, psiClass); } @@ -29,6 +29,37 @@ public class JavaFxStaticPropertyReference extends PsiReferenceBase elementsToRename = getElementsToRename(propertyReference, "a"); + final boolean cannotRename = !elementsToRename.isEmpty() && + elementsToRename.keySet().stream() + .anyMatch(element -> !PsiElementRenameHandler.canRename(project, editor, element)); + if (cannotRename) { + return; + } if (ApplicationManager.getApplication().isUnitTestMode()) { final String newName = PsiElementRenameHandler.DEFAULT_NAME.getData(dataContext); assert newName != null : "Rename property"; doRename(propertyReference, newName, false, false); return; } - final Map elementsToRename = getElementsToRename(propertyReference, "a"); - for (PsiElement element : elementsToRename.values()) { - if (!PsiElementRenameHandler.canRename(project, editor, element)) return; - } final PsiElement psiElement = JavaFxPropertyElement.fromReference(propertyReference); if (psiElement != null) { new PropertyRenameDialog(propertyReference, psiElement, project, editor).show(); } } - if (reference instanceof JavaFxStaticPropertyReference) { - final JavaFxStaticPropertyReference propertyReference = (JavaFxStaticPropertyReference)reference; - if (ApplicationManager.getApplication().isUnitTestMode()) { - final String newName = PsiElementRenameHandler.DEFAULT_NAME.getData(dataContext); - assert newName != null : "Rename property"; - doRenameStatic(propertyReference, newName, false, false); - return; - } - final Map elementsToRename = getStaticElementsToRename(propertyReference, "a"); - for (PsiElement element : elementsToRename.values()) { - if (!PsiElementRenameHandler.canRename(project, editor, element)) return; - } - final PsiElement psiElement = JavaFxStaticPropertyElement.fromReference(propertyReference); - if (psiElement != null) { - new PropertyRenameDialog(reference, psiElement, project, editor).show(); - } - } } private static void doRename(JavaFxPropertyReference reference, String newName, final boolean searchInComments, boolean isPreview) { @@ -104,28 +91,11 @@ public class JavaFxPropertyRenameHandler implements RenameHandler { final RenameRefactoring rename = new JavaRenameRefactoringImpl(psiElement.getProject(), psiElement, newName, searchInComments, false); rename.setPreviewUsages(isPreview); - final Map elementsToRename = getElementsToRename(reference, newName); - for (Map.Entry entry : elementsToRename.entrySet()) { - rename.addElement(entry.getValue(), entry.getKey()); - } + final Map elementsToRename = getElementsToRename(reference, newName); + elementsToRename.forEach(rename::addElement); rename.run(); } - private static void doRenameStatic(JavaFxStaticPropertyReference reference, - String newName, - final boolean searchInComments, - boolean isPreview) { - final PsiElement psiElement = JavaFxStaticPropertyElement.fromReference(reference); - if (psiElement == null) return; - final RenameRefactoring rename = new JavaRenameRefactoringImpl(psiElement.getProject(), psiElement, newName, searchInComments, false); - rename.setPreviewUsages(isPreview); - - final Map elementsToRename = getStaticElementsToRename(reference, newName); - for (Map.Entry entry : elementsToRename.entrySet()) { - rename.addElement(entry.getValue(), entry.getKey()); - } - rename.run(); - } @Nullable private static PsiReference getReference(DataContext dataContext) { @@ -159,7 +129,6 @@ public class JavaFxPropertyRenameHandler implements RenameHandler { private static boolean isKnown(PsiReference reference) { if (reference instanceof JavaFxPropertyReference) return true; - if (reference instanceof JavaFxStaticPropertyReference) return ((JavaFxStaticPropertyReference)reference).getStaticMethod() != null; if (reference instanceof JavaFxComponentIdReferenceProvider.JavaFxIdReferenceBase) { return ((JavaFxComponentIdReferenceProvider.JavaFxIdReferenceBase)reference).isBuiltIn(); } @@ -167,28 +136,26 @@ public class JavaFxPropertyRenameHandler implements RenameHandler { } @NotNull - private static Map getElementsToRename(@NotNull JavaFxPropertyReference reference, @NotNull String newPropertyName) { - final Map rename = new THashMap<>(); - ContainerUtil.putIfNotNull(newPropertyName, reference.getField(), rename); - ContainerUtil.putIfNotNull(PropertyUtil.suggestGetterName(newPropertyName, reference.getType()), reference.getGetter(), rename); - ContainerUtil.putIfNotNull(PropertyUtil.suggestSetterName(newPropertyName), reference.getSetter(), rename); - ContainerUtil.putIfNotNull(newPropertyName + JavaFxCommonNames.PROPERTY_METHOD_SUFFIX, reference.getObservableGetter(), rename); + private static Map getElementsToRename(@NotNull JavaFxPropertyReference reference, @NotNull String newPropertyName) { + final Map rename = new THashMap<>(); + putIfKeyNotNull(rename, reference.getGetter(), () -> PropertyUtil.suggestGetterName(newPropertyName, reference.getType())); + putIfKeyNotNull(rename, reference.getField(), () -> newPropertyName); + putIfKeyNotNull(rename, reference.getSetter(), () -> PropertyUtil.suggestSetterName(newPropertyName)); + putIfKeyNotNull(rename, reference.getObservableGetter(), () -> newPropertyName + JavaFxCommonNames.PROPERTY_METHOD_SUFFIX); + putIfKeyNotNull(rename, reference.getStaticSetter(), () -> PropertyUtil.suggestSetterName(newPropertyName)); //TODO add "name" parameter of the observable property constructor (like new SimpleObjectProperty(this, "name", null); return rename; } - private static Map getStaticElementsToRename(@NotNull JavaFxStaticPropertyReference reference, - @NotNull String newPropertyName) { - final PsiMethod method = reference.getStaticMethod(); - if (method == null) return Collections.emptyMap(); - return Collections.singletonMap(PropertyUtil.suggestSetterName(newPropertyName), method); + private static void putIfKeyNotNull(Map map, K key, NotNullProducer valueProducer) { + if (key != null) map.put(key, valueProducer.produce()); } private static class PropertyRenameDialog extends RenameDialog { - private final PsiReference myPropertyReference; + private final JavaFxPropertyReference myPropertyReference; - protected PropertyRenameDialog(@NotNull PsiReference propertyReference, + protected PropertyRenameDialog(@NotNull JavaFxPropertyReference propertyReference, @NotNull PsiElement psiElement, @NotNull Project project, Editor editor) { @@ -199,12 +166,7 @@ public class JavaFxPropertyRenameHandler implements RenameHandler { protected void doAction() { final String newName = getNewName(); final boolean searchInComments = isSearchInComments(); - if (myPropertyReference instanceof JavaFxPropertyReference) { - doRename((JavaFxPropertyReference)myPropertyReference, newName, searchInComments, isPreviewUsages()); - } - else if (myPropertyReference instanceof JavaFxStaticPropertyReference) { - doRenameStatic((JavaFxStaticPropertyReference)myPropertyReference, newName, searchInComments, isPreviewUsages()); - } + doRename(myPropertyReference, newName, searchInComments, isPreviewUsages()); close(DialogWrapper.OK_EXIT_CODE); } } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxStaticPropertyElement.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxStaticPropertyElement.java deleted file mode 100644 index ddfa1dcc489e..000000000000 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxStaticPropertyElement.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.jetbrains.plugins.javaFX.refactoring; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiType; -import com.intellij.psi.impl.beanProperties.BeanPropertyElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxStaticPropertyReference; - -/** - * @author Pavel.Dolgov - */ -public class JavaFxStaticPropertyElement extends BeanPropertyElement { - private final JavaFxStaticPropertyReference myPropertyReference; - - private JavaFxStaticPropertyElement(JavaFxStaticPropertyReference propertyReference, String propertyName, PsiMethod method) { - super(method, propertyName); - myPropertyReference = propertyReference; - } - - @Nullable - @Override - public PsiType getPropertyType() { - return myPropertyReference.getType(); - } - - @Override - public String getTypeName() { - return "property"; - } - - @Nullable - static PsiElement fromReference(@NotNull final JavaFxStaticPropertyReference propertyReference) { - final PsiMethod method = propertyReference.getStaticMethod(); - if (method != null) { - final String propertyName = propertyReference.getPropertyName(); - if (propertyName != null) { - return new JavaFxStaticPropertyElement(propertyReference, propertyName, method); - } - } - return null; - } -} diff --git a/plugins/javaFX/testData/rename/StaticPropertyFromLibrary.java b/plugins/javaFX/testData/rename/StaticPropertyFromLibrary.java new file mode 100644 index 000000000000..8ca65ac0c6a9 --- /dev/null +++ b/plugins/javaFX/testData/rename/StaticPropertyFromLibrary.java @@ -0,0 +1 @@ +class StaticPropertyFromLibrary {} \ No newline at end of file diff --git a/plugins/javaFX/testData/rename/staticPropertyFromLibrary.fxml b/plugins/javaFX/testData/rename/staticPropertyFromLibrary.fxml new file mode 100644 index 000000000000..b160797ffba7 --- /dev/null +++ b/plugins/javaFX/testData/rename/staticPropertyFromLibrary.fxml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file