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)

This commit is contained in:
Pavel Dolgov
2016-04-27 18:50:53 +03:00
parent 3f508d40d6
commit 455d2b1c31
6 changed files with 66 additions and 99 deletions
@@ -234,7 +234,8 @@ public class JavaFxPsiUtil {
return null;
}
public static PsiMethod findPropertyGetter(@NotNull PsiClass psiClass, @NotNull String propertyName) {
public static PsiMethod findPropertyGetter(@NotNull PsiClass psiClass, @Nullable String propertyName) {
if (StringUtil.isEmpty(propertyName)) return null;
PsiMethod getter = findPropertyGetter(psiClass, propertyName, null);
if (getter != null) {
return getter;
@@ -255,7 +256,8 @@ public class JavaFxPsiUtil {
return null;
}
public static PsiMethod findObservablePropertyGetter(@NotNull PsiClass psiClass, @NotNull String propertyName) {
public static PsiMethod findObservablePropertyGetter(@NotNull PsiClass psiClass, @Nullable String propertyName) {
if (StringUtil.isEmpty(propertyName)) return null;
final PsiMethod[] getters = psiClass.findMethodsByName(propertyName + JavaFxCommonNames.PROPERTY_METHOD_SUFFIX, true);
for (PsiMethod getter : getters) {
if (getter.hasModifierProperty(PsiModifier.PUBLIC) &&
@@ -959,7 +961,8 @@ public class JavaFxPsiUtil {
}
@Nullable
public static PsiMethod findInstancePropertySetter(@NotNull PsiClass psiClass, @NotNull String propertyName) {
public static PsiMethod findInstancePropertySetter(@NotNull PsiClass psiClass, @Nullable String propertyName) {
if (StringUtil.isEmpty(propertyName)) return null;
final String suggestedSetterName = PropertyUtil.suggestSetterName(propertyName);
final PsiMethod[] setters = psiClass.findMethodsByName(suggestedSetterName, true);
for (PsiMethod setter : setters) {
@@ -43,7 +43,7 @@ import java.util.stream.Collectors;
/**
* User: anna
*/
class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
public class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
@NotNull
@Override
@@ -190,7 +190,7 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
}
}
private static class JavaFxIdReferenceBase extends PsiReferenceBase<XmlAttributeValue> implements JavaFxIdAttributeReference {
public static class JavaFxIdReferenceBase extends PsiReferenceBase<XmlAttributeValue> {
private final Map<String, XmlAttributeValue> myFileIds;
private final Set<String> myAcceptableIds;
private final Map<String, TypeMatch> myTypeMatches;
@@ -232,26 +232,23 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
.toArray(LookupElement[]::new);
}
@Override
public boolean isBuiltIn() {
return FxmlConstants.CONTROLLER.equals(myReferencesId) || myReferencesId.endsWith(FxmlConstants.CONTROLLER_SUFFIX);
}
}
private static class JavaFxExpressionReferenceBase extends PsiReferenceBase<XmlAttributeValue> implements JavaFxPropertyReference {
private final PsiClass myTagClass;
private static class JavaFxExpressionReferenceBase extends JavaFxPropertyReference<XmlAttributeValue> {
private final String myFieldName;
public JavaFxExpressionReferenceBase(XmlAttributeValue xmlAttributeValue, PsiClass tagClass, String fieldName) {
super(xmlAttributeValue);
myTagClass = tagClass;
public JavaFxExpressionReferenceBase(@NotNull XmlAttributeValue xmlAttributeValue, PsiClass tagClass, @NotNull String fieldName) {
super(xmlAttributeValue, tagClass);
myFieldName = fieldName;
}
@Nullable
@Override
public PsiElement resolve() {
return JavaFxPsiUtil.collectReadableProperties(myTagClass).get(myFieldName);
return JavaFxPsiUtil.collectReadableProperties(myPsiClass).get(myFieldName);
}
@NotNull
@@ -259,7 +256,7 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
public Object[] getVariants() {
final XmlAttributeValue xmlAttributeValue = getElement();
final PsiElement declaration = JavaFxPsiUtil.getAttributeDeclaration(xmlAttributeValue);
final PsiType propertyType = JavaFxPsiUtil.getWritablePropertyType(myTagClass, declaration);
final PsiType propertyType = JavaFxPsiUtil.getWritablePropertyType(myPsiClass, declaration);
if (propertyType != null) {
return collectProperties(propertyType, xmlAttributeValue.getProject());
}
@@ -269,7 +266,7 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
private Object[] collectProperties(@NotNull PsiType propertyType, @NotNull Project project) {
final PsiType resolvedType = JavaFxPsiUtil.getWritablePropertyType(propertyType, project);
final List<LookupElement> objs = new ArrayList<>();
final Collection<PsiMember> readableProperties = JavaFxPsiUtil.collectReadableProperties(myTagClass).values();
final Collection<PsiMember> readableProperties = JavaFxPsiUtil.collectReadableProperties(myPsiClass).values();
for (PsiMember readableMember : readableProperties) {
final PsiType readableType = JavaFxPsiUtil.getReadablePropertyType(readableMember);
if (readableType == null) continue;
@@ -284,34 +281,10 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
return ArrayUtil.toObjectArray(objs);
}
@Nullable
@NotNull
@Override
public PsiMethod getGetter() {
return JavaFxPropertyReference.getGetter(myTagClass, myFieldName);
}
@Nullable
@Override
public PsiMethod getSetter() {
return JavaFxPropertyReference.getSetter(myTagClass, myFieldName);
}
@Nullable
@Override
public PsiField getField() {
return JavaFxPropertyReference.getField(myTagClass, myFieldName);
}
@Nullable
@Override
public PsiMethod getObservableGetter() {
return JavaFxPropertyReference.getObservableGetter(myTagClass, myFieldName);
}
@Nullable
@Override
public PsiType getType() {
return JavaFxPsiUtil.getReadablePropertyType(resolve());
protected String getPropertyName() {
return myFieldName;
}
@Override
@@ -55,13 +55,13 @@ public class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferen
return new PsiReference[]{new JavaFxControllerFieldRef(xmlAttributeValue, fieldOrGetterMethod, aClass)};
}
public static class JavaFxControllerFieldRef extends PsiReferenceBase<XmlAttributeValue> implements JavaFxPropertyReference {
public static class JavaFxControllerFieldRef extends JavaFxPropertyReference<XmlAttributeValue> {
private final XmlAttributeValue myXmlAttributeValue;
private final PsiMember myFieldOrMethod;
private final PsiClass myAClass;
public JavaFxControllerFieldRef(XmlAttributeValue xmlAttributeValue, PsiMember fieldOrMethod, PsiClass aClass) {
super(xmlAttributeValue, true);
super(xmlAttributeValue, aClass, true);
myXmlAttributeValue = xmlAttributeValue;
myFieldOrMethod = fieldOrMethod;
myAClass = aClass;
@@ -127,7 +127,7 @@ public class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferen
if (myFieldOrMethod instanceof PsiMethod && PropertyUtil.isSimplePropertyGetter((PsiMethod)myFieldOrMethod)) {
return (PsiMethod)myFieldOrMethod;
}
return JavaFxPropertyReference.getGetter(myAClass, PropertyUtil.getPropertyName(myFieldOrMethod));
return super.getGetter();
}
@Nullable
@@ -136,7 +136,7 @@ public class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferen
if (myFieldOrMethod instanceof PsiMethod && PropertyUtil.isSimplePropertySetter((PsiMethod)myFieldOrMethod)) {
return (PsiMethod)myFieldOrMethod;
}
return JavaFxPropertyReference.getSetter(myAClass, PropertyUtil.getPropertyName(myFieldOrMethod));
return super.getSetter();
}
@Nullable
@@ -145,19 +145,13 @@ public class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferen
if (myFieldOrMethod instanceof PsiField) {
return (PsiField)myFieldOrMethod;
}
return JavaFxPropertyReference.getField(myAClass, PropertyUtil.getPropertyName(myFieldOrMethod));
return super.getField();
}
@Nullable
@Override
public PsiMethod getObservableGetter() {
return JavaFxPropertyReference.getObservableGetter(myAClass, PropertyUtil.getPropertyName(myFieldOrMethod));
}
@Nullable
@Override
public PsiType getType() {
return JavaFxPsiUtil.getReadablePropertyType(myFieldOrMethod);
protected String getPropertyName() {
return PropertyUtil.getPropertyName(myFieldOrMethod);
}
@Override
@@ -1,10 +0,0 @@
package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.psi.PsiReference;
/**
* @author Pavel.Dolgov
*/
public interface JavaFxIdAttributeReference extends PsiReference {
boolean isBuiltIn();
}
@@ -1,51 +1,55 @@
package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.psi.*;
import com.intellij.psi.util.PropertyUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
import java.util.Map;
/**
* @author Pavel.Dolgov
*/
public interface JavaFxPropertyReference extends PsiReference {
@Nullable
PsiMethod getGetter();
public abstract class JavaFxPropertyReference<T extends PsiElement> extends PsiReferenceBase<T> {
protected final PsiClass myPsiClass;
@Nullable
PsiMethod getSetter();
@Nullable
PsiField getField();
@Nullable
PsiMethod getObservableGetter();
@Nullable
PsiType getType();
static PsiMethod getGetter(PsiClass psiClass, String propertyName) {
if (psiClass == null || propertyName == null) return null;
return JavaFxPsiUtil.findPropertyGetter(psiClass, propertyName);
public JavaFxPropertyReference(@NotNull T element, PsiClass aClass, boolean soft) {
super(element, soft);
myPsiClass = aClass;
}
static PsiMethod getSetter(PsiClass psiClass, String propertyName) {
if (psiClass == null || propertyName == null) return null;
return JavaFxPsiUtil.findInstancePropertySetter(psiClass, propertyName);
public JavaFxPropertyReference(@NotNull T element, PsiClass aClass) {
super(element);
myPsiClass = aClass;
}
static PsiField getField(PsiClass psiClass, String propertyName) {
if (psiClass == null || propertyName == null) return null;
return psiClass.findFieldByName(propertyName, true);
@Nullable
public PsiMethod getGetter() {
if (myPsiClass == null) return null;
return JavaFxPsiUtil.findPropertyGetter(myPsiClass, getPropertyName());
}
static PsiMethod getObservableGetter(PsiClass psiClass, String propertyName) {
if (psiClass == null || propertyName == null) return null;
return JavaFxPsiUtil.findObservablePropertyGetter(psiClass, propertyName);
@Nullable
public PsiMethod getSetter() {
if (myPsiClass == null) return null;
return JavaFxPsiUtil.findInstancePropertySetter(myPsiClass, getPropertyName());
}
@Nullable
public PsiField getField() {
if (myPsiClass == null) return null;
return myPsiClass.findFieldByName(getPropertyName(), true);
}
@Nullable
public PsiMethod getObservableGetter() {
if (myPsiClass == null) return null;
return JavaFxPsiUtil.findObservablePropertyGetter(myPsiClass, getPropertyName());
}
@Nullable
public PsiType getType() {
return JavaFxPsiUtil.getReadablePropertyType(resolve());
}
@Nullable
protected abstract String getPropertyName();
}
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxIdAttributeReference;
import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxComponentIdReferenceProvider;
import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxPropertyReference;
import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxStaticPropertyReference;
@@ -57,7 +57,8 @@ public class JavaFxPropertyRenameHandler implements RenameHandler {
private static void performInvoke(@NotNull Project project, @Nullable Editor editor, DataContext dataContext) {
PsiReference reference = getReference(dataContext);
if (reference == null) return;
if (reference instanceof JavaFxIdAttributeReference && ((JavaFxIdAttributeReference)reference).isBuiltIn()) {
if (reference instanceof JavaFxComponentIdReferenceProvider.JavaFxIdReferenceBase &&
((JavaFxComponentIdReferenceProvider.JavaFxIdReferenceBase)reference).isBuiltIn()) {
CommonRefactoringUtil.showErrorHint(project, editor, "Cannot rename built-in property", null, null);
return;
}
@@ -159,7 +160,9 @@ 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 JavaFxIdAttributeReference) return ((JavaFxIdAttributeReference)reference).isBuiltIn();
if (reference instanceof JavaFxComponentIdReferenceProvider.JavaFxIdReferenceBase) {
return ((JavaFxComponentIdReferenceProvider.JavaFxIdReferenceBase)reference).isBuiltIn();
}
return false;
}