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 00ab88ec6225..592432817f71 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
@@ -190,6 +190,19 @@ public class JavaFXRenameTest extends AbstractJavaFXRenameTest {
assertMethodExists(psiClass, "getNewName");
}
+ public void testNestedControllerIdFromFxml() throws Exception {
+ doTestHandler("newName", getTestName(false) + "Internal");
+ myFixture.checkResultByFile(getTestName(false) + ".java", getTestName(false) + "_after.java", false);
+ }
+
+ public void testNestedControllerIdFromJava() throws Exception {
+ myFixture.configureByFiles(getTestName(false) + ".java", getTestName(false) + "Internal.java", getTestName(true) + ".fxml");
+ final PsiElement elementAtCaret = myFixture.getElementAtCaret();
+ new RenameProcessor(getProject(), elementAtCaret, "newName", false, false).run();
+ myFixture.checkResultByFile(getTestName(true) + ".fxml", getTestName(true) + "_after.fxml", false);
+ myFixture.checkResultByFile(getTestName(false) + ".java", getTestName(false) + "_after.java", false);
+ }
+
public void testControllerStringProperty() throws Exception {
doTestProperty("newName", false);
}
diff --git a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
index 73735cf560b4..5f88e12bf2e5 100644
--- a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
+++ b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
@@ -15,6 +15,7 @@
+
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxPropertyRenameHandler.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxPropertyRenameHandler.java
index ff39fd2e385e..ade73e296eab 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxPropertyRenameHandler.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxPropertyRenameHandler.java
@@ -6,14 +6,14 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiReference;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference;
import com.intellij.psi.util.PropertyUtil;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
import com.intellij.refactoring.RenameRefactoring;
import com.intellij.refactoring.openapi.impl.JavaRenameRefactoringImpl;
import com.intellij.refactoring.rename.PsiElementRenameHandler;
@@ -25,8 +25,10 @@ import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxComponentIdReferenceProvider;
import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxFieldIdReferenceProvider;
import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxPropertyReference;
@@ -87,23 +89,26 @@ public class JavaFxPropertyRenameHandler implements RenameHandler {
}
}
if (reference instanceof JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef) {
+ final XmlAttributeValue fxIdValueElement =
+ ((JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef)reference).getXmlAttributeValue();
final Set elementsToRename = new THashSet<>();
JavaFxRenameAttributeProcessor.visitReferencedElements(references, psiElement -> {
if (psiElement != null) {
elementsToRename.add(psiElement);
}
});
+ ContainerUtil.addIfNotNull(elementsToRename, getNestedControllerField(fxIdValueElement));
+
if (!canRename(project, editor, elementsToRename)) {
return;
}
- final XmlAttributeValue fxIdElement = ((JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef)reference).getXmlAttributeValue();
if (ApplicationManager.getApplication().isUnitTestMode()) {
final String newName = PsiElementRenameHandler.DEFAULT_NAME.getData(dataContext);
assert newName != null : "Rename property";
- new RenameDialog(project, fxIdElement, null, editor).performRename(newName);
+ doRenameFxId(fxIdValueElement, newName, false, false);
}
else {
- new RenameDialog(project, fxIdElement, null, editor).show();
+ new RenameFxIdDialog(fxIdValueElement, editor).show();
}
}
}
@@ -180,6 +185,33 @@ public class JavaFxPropertyRenameHandler implements RenameHandler {
if (key != null) map.put(key, value);
}
+ public static void doRenameFxId(XmlAttributeValue fxIdValueElement, String newName, boolean searchInComments, boolean previewUsages) {
+ final RenameRefactoring rename =
+ new JavaRenameRefactoringImpl(fxIdValueElement.getProject(), fxIdValueElement, newName, searchInComments, false);
+ rename.setPreviewUsages(previewUsages);
+
+ final PsiField nestedControllerField = getNestedControllerField(fxIdValueElement);
+ if (nestedControllerField != null) {
+ rename.addElement(nestedControllerField, newName + FxmlConstants.CONTROLLER_SUFFIX);
+ }
+ rename.run();
+ }
+
+ @Nullable
+ private static PsiField getNestedControllerField(@NotNull XmlAttributeValue fxIdValueElement) {
+ final String fxId = fxIdValueElement.getValue();
+ if (!StringUtil.isEmpty(fxId)) {
+ final XmlTag tag = PsiTreeUtil.getParentOfType(fxIdValueElement, XmlTag.class);
+ if (tag != null && FxmlConstants.FX_INCLUDE.equals(tag.getName())) {
+ final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(tag.getContainingFile());
+ if (controllerClass != null) {
+ return controllerClass.findFieldByName(fxId + FxmlConstants.CONTROLLER_SUFFIX, true);
+ }
+ }
+ }
+ return null;
+ }
+
private static class PropertyRenameDialog extends RenameDialog {
private final JavaFxPropertyReference myPropertyReference;
@@ -199,4 +231,19 @@ public class JavaFxPropertyRenameHandler implements RenameHandler {
close(DialogWrapper.OK_EXIT_CODE);
}
}
+
+ private static class RenameFxIdDialog extends RenameDialog {
+ public RenameFxIdDialog(@NotNull XmlAttributeValue fxIdValueElement, Editor editor) {
+ super(fxIdValueElement.getProject(), fxIdValueElement, null, editor);
+ }
+
+ @Override
+ protected void doAction() {
+ final String newName = getNewName();
+ final PsiElement element = getPsiElement();
+ assert element instanceof XmlAttributeValue;
+ doRenameFxId(((XmlAttributeValue)element), newName, isSearchInComments(), isPreviewUsages());
+ close(DialogWrapper.OK_EXIT_CODE);
+ }
+ }
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxRenameFxIdFieldProcessor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxRenameFxIdFieldProcessor.java
new file mode 100644
index 000000000000..562ec99b2d2c
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/refactoring/JavaFxRenameFxIdFieldProcessor.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2000-2013 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.refactoring;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.refactoring.rename.RenamePsiElementProcessor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
+import org.jetbrains.plugins.javaFX.indexing.JavaFxControllerClassIndex;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * @author Pavel.Dolgov
+ */
+public class JavaFxRenameFxIdFieldProcessor extends RenamePsiElementProcessor {
+ @Override
+ public boolean canProcessElement(@NotNull PsiElement element) {
+ final NestedControllerCandidate nestedControllerCandidate = findNestedControllerCandidate(element);
+ final Collection fxmls = findFxmlWithController(nestedControllerCandidate);
+ return !fxmls.isEmpty();
+ }
+
+ @Override
+ public boolean isInplaceRenameSupported() {
+ return false;
+ }
+
+ @Override
+ public void prepareRenaming(PsiElement element, String newName, Map allRenames, SearchScope scope) {
+ final NestedControllerCandidate nestedControllerCandidate = findNestedControllerCandidate(element);
+ if (nestedControllerCandidate != null) {
+ final Collection fxmls = findFxmlWithController(nestedControllerCandidate);
+ for (PsiFile fxml : fxmls) {
+ final Ref found = new Ref<>(false);
+ fxml.accept(new XmlRecursiveElementVisitor() {
+ @Override
+ public void visitXmlTag(XmlTag tag) {
+ super.visitXmlTag(tag);
+ if (found.get()) return;
+ if (FxmlConstants.FX_INCLUDE.equals(tag.getName())) {
+ final String value = tag.getAttributeValue(FxmlConstants.FX_ID);
+ if (StringUtil.equals(nestedControllerCandidate.fxId, value)) {
+ found.set(true);
+ }
+ }
+ }
+ });
+ if (found.get()) {
+ allRenames.put(nestedControllerCandidate.nestedControllerField, newName + FxmlConstants.CONTROLLER_SUFFIX);
+ return;
+ }
+ }
+ }
+ }
+
+ @Nullable
+ private static NestedControllerCandidate findNestedControllerCandidate(@NotNull PsiElement element) {
+ if (element instanceof PsiField) {
+ final PsiField field = (PsiField)element;
+ final String fxId = field.getName();
+ if (!StringUtil.isEmpty(fxId)) {
+ final PsiClass containingClass = field.getContainingClass();
+ if (containingClass != null) {
+ final PsiField nestedControllerField = containingClass.findFieldByName(fxId + FxmlConstants.CONTROLLER_SUFFIX, true);
+ if (nestedControllerField != null) {
+ final PsiType psiType = nestedControllerField.getType();
+ if (!(psiType instanceof PsiPrimitiveType) && !(psiType instanceof PsiArrayType)) { // optimization
+ return new NestedControllerCandidate(fxId, nestedControllerField, containingClass);
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ private static Collection findFxmlWithController(@Nullable NestedControllerCandidate nestedControllerCandidate) {
+ if (nestedControllerCandidate != null) {
+ final String qualifiedName = nestedControllerCandidate.controllerClass.getQualifiedName();
+ if (qualifiedName != null) {
+ final Project project = nestedControllerCandidate.controllerClass.getProject();
+ return JavaFxControllerClassIndex.findFxmlWithController(project, qualifiedName);
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private static class NestedControllerCandidate {
+ private final String fxId;
+ private final PsiField nestedControllerField;
+ private final PsiClass controllerClass;
+
+ private NestedControllerCandidate(@NotNull String fxId, @NotNull PsiField nestedControllerField, @NotNull PsiClass controllerClass) {
+ this.fxId = fxId;
+ this.nestedControllerField = nestedControllerField;
+ this.controllerClass = controllerClass;
+ }
+ }
+}
diff --git a/plugins/javaFX/testData/rename/NestedControllerIdFromFxml.java b/plugins/javaFX/testData/rename/NestedControllerIdFromFxml.java
new file mode 100644
index 000000000000..893cfafc4878
--- /dev/null
+++ b/plugins/javaFX/testData/rename/NestedControllerIdFromFxml.java
@@ -0,0 +1,5 @@
+import javafx.fxml.FXML;
+
+class NestedControllerIdFromFxml {
+ @FXML NestedControllerIdFromFxmlInternal internalController;
+}
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/NestedControllerIdFromFxmlInternal.java b/plugins/javaFX/testData/rename/NestedControllerIdFromFxmlInternal.java
new file mode 100644
index 000000000000..272e78809e45
--- /dev/null
+++ b/plugins/javaFX/testData/rename/NestedControllerIdFromFxmlInternal.java
@@ -0,0 +1,2 @@
+class NestedControllerIdFromFxmlInternal {
+}
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/NestedControllerIdFromFxml_after.java b/plugins/javaFX/testData/rename/NestedControllerIdFromFxml_after.java
new file mode 100644
index 000000000000..150b4cf39dba
--- /dev/null
+++ b/plugins/javaFX/testData/rename/NestedControllerIdFromFxml_after.java
@@ -0,0 +1,5 @@
+import javafx.fxml.FXML;
+
+class NestedControllerIdFromFxml {
+ @FXML NestedControllerIdFromFxmlInternal newNameController;
+}
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/NestedControllerIdFromJava.java b/plugins/javaFX/testData/rename/NestedControllerIdFromJava.java
new file mode 100644
index 000000000000..ae21b99732b4
--- /dev/null
+++ b/plugins/javaFX/testData/rename/NestedControllerIdFromJava.java
@@ -0,0 +1,8 @@
+import javafx.fxml.FXML;
+import javafx.scene.layout.VBox;
+
+class NestedControllerIdFromJava {
+ @FXML
+ private VBox internal;
+ @FXML NestedControllerIdFromJavaInternal internalController;
+}
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/NestedControllerIdFromJavaInternal.java b/plugins/javaFX/testData/rename/NestedControllerIdFromJavaInternal.java
new file mode 100644
index 000000000000..327fb485706a
--- /dev/null
+++ b/plugins/javaFX/testData/rename/NestedControllerIdFromJavaInternal.java
@@ -0,0 +1,2 @@
+class NestedControllerIdFromJavaInternal {
+}
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/NestedControllerIdFromJava_after.java b/plugins/javaFX/testData/rename/NestedControllerIdFromJava_after.java
new file mode 100644
index 000000000000..796133317dc2
--- /dev/null
+++ b/plugins/javaFX/testData/rename/NestedControllerIdFromJava_after.java
@@ -0,0 +1,8 @@
+import javafx.fxml.FXML;
+import javafx.scene.layout.VBox;
+
+class NestedControllerIdFromJava {
+ @FXML
+ private VBox newName;
+ @FXML NestedControllerIdFromJavaInternal newNameController;
+}
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/nestedControllerIdFromFxml.fxml b/plugins/javaFX/testData/rename/nestedControllerIdFromFxml.fxml
new file mode 100644
index 000000000000..fa1b7ad93447
--- /dev/null
+++ b/plugins/javaFX/testData/rename/nestedControllerIdFromFxml.fxml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/nestedControllerIdFromFxmlInternal.fxml b/plugins/javaFX/testData/rename/nestedControllerIdFromFxmlInternal.fxml
new file mode 100644
index 000000000000..cf287a6a296a
--- /dev/null
+++ b/plugins/javaFX/testData/rename/nestedControllerIdFromFxmlInternal.fxml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/nestedControllerIdFromFxml_after.fxml b/plugins/javaFX/testData/rename/nestedControllerIdFromFxml_after.fxml
new file mode 100644
index 000000000000..cd9566594679
--- /dev/null
+++ b/plugins/javaFX/testData/rename/nestedControllerIdFromFxml_after.fxml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/nestedControllerIdFromJava.fxml b/plugins/javaFX/testData/rename/nestedControllerIdFromJava.fxml
new file mode 100644
index 000000000000..a097a0bbf9e0
--- /dev/null
+++ b/plugins/javaFX/testData/rename/nestedControllerIdFromJava.fxml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/nestedControllerIdFromJavaInternal.fxml b/plugins/javaFX/testData/rename/nestedControllerIdFromJavaInternal.fxml
new file mode 100644
index 000000000000..e4b5a3c7300e
--- /dev/null
+++ b/plugins/javaFX/testData/rename/nestedControllerIdFromJavaInternal.fxml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/nestedControllerIdFromJava_after.fxml b/plugins/javaFX/testData/rename/nestedControllerIdFromJava_after.fxml
new file mode 100644
index 000000000000..3cb346c53230
--- /dev/null
+++ b/plugins/javaFX/testData/rename/nestedControllerIdFromJava_after.fxml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file