mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
javafx: Don't highlight as error the built-in "$controller" field and its properties visible in FXML (IDEA-150446)
This commit is contained in:
+7
-3
@@ -24,6 +24,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
|
||||
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
|
||||
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
|
||||
|
||||
@@ -53,10 +54,13 @@ public class JavaFxGetterSetterPrototypeProvider extends GetterSetterPrototypePr
|
||||
|
||||
final PsiCodeBlock getterBody = getter.getBody();
|
||||
LOG.assertTrue(getterBody != null);
|
||||
getterBody.getStatements()[0].replace(factory.createStatementFromText("return " + field.getName() + ".get();", field));
|
||||
final String fieldName = field.getName();
|
||||
getterBody.getStatements()[0].replace(factory.createStatementFromText("return " + fieldName + ".get();", field));
|
||||
|
||||
final PsiMethod propertyGetter = PropertyUtil.generateGetterPrototype(field);
|
||||
propertyGetter.setName(JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD) + "Property");
|
||||
if (propertyGetter != null && fieldName != null) {
|
||||
propertyGetter.setName(JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(fieldName, VariableKind.FIELD) + FxmlConstants.PROPERTY_FIELD_SUFFIX);
|
||||
}
|
||||
return new PsiMethod[] {getter, GenerateMembersUtil.annotateOnOverrideImplement(field.getContainingClass(), propertyGetter)};
|
||||
}
|
||||
|
||||
@@ -96,7 +100,7 @@ public class JavaFxGetterSetterPrototypeProvider extends GetterSetterPrototypePr
|
||||
|
||||
@Override
|
||||
public String suggestGetterName(String propertyName) {
|
||||
return propertyName + "Property";
|
||||
return propertyName + FxmlConstants.PROPERTY_FIELD_SUFFIX;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,6 +40,7 @@ public class FxmlConstants {
|
||||
@NonNls public static final String TYPE = "type";
|
||||
@NonNls public static final String RESOURCES = "resources";
|
||||
@NonNls public static final String CHARSET = "charset";
|
||||
@NonNls public static final String CONTROLLER = "controller";
|
||||
|
||||
@NonNls public static final String STYLE_CLASS = "styleClass";
|
||||
@NonNls public static final String STYLESHEETS = "stylesheets";
|
||||
@@ -50,6 +51,9 @@ public class FxmlConstants {
|
||||
public static final String FX_ELEMENT_SOURCE = "source";
|
||||
|
||||
public static final Map<String, List<String>> FX_ELEMENT_ATTRIBUTES = new HashMap<String, List<String>>();
|
||||
|
||||
public static final String PROPERTY_FIELD_SUFFIX = "Property";
|
||||
|
||||
static {
|
||||
FX_ELEMENT_ATTRIBUTES.put(FX_INCLUDE, Arrays.asList(FX_ELEMENT_SOURCE, FX_ID, RESOURCES, CHARSET));
|
||||
FX_ELEMENT_ATTRIBUTES.put(FX_REFERENCE, Collections.singletonList(FX_ELEMENT_SOURCE));
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.xml.*;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.xml.XmlAttributeDescriptor;
|
||||
import com.intellij.xml.XmlElementDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -373,7 +374,7 @@ public class JavaFxPsiUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getPropertyType(final PsiType type, final Project project) {
|
||||
public static PsiType getWritablePropertyType(final PsiType type, final Project project) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type);
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
if (psiClass != null) {
|
||||
@@ -505,7 +506,7 @@ public class JavaFxPsiUtil {
|
||||
private static String canCoerce(PsiClass aClass, PsiType type) {
|
||||
PsiType collectionItemType = JavaGenericsUtil.getCollectionItemType(type, aClass.getResolveScope());
|
||||
if (collectionItemType == null && InheritanceUtil.isInheritor(type, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY)) {
|
||||
collectionItemType = getPropertyType(type, aClass.getProject());
|
||||
collectionItemType = getWritablePropertyType(type, aClass.getProject());
|
||||
}
|
||||
if (collectionItemType != null && PsiPrimitiveType.getUnboxedType(collectionItemType) == null) {
|
||||
final PsiClass baseClass = PsiUtil.resolveClassInType(collectionItemType);
|
||||
@@ -570,6 +571,99 @@ public class JavaFxPsiUtil {
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getWritablePropertyType(PsiElement declaration) {
|
||||
if (declaration instanceof PsiField) {
|
||||
return getWrappedPropertyType((PsiField)declaration, declaration.getProject(), JavaFxCommonClassNames.ourWritableMap);
|
||||
}
|
||||
if (declaration instanceof PsiMethod) {
|
||||
final PsiParameter[] parameters = ((PsiMethod)declaration).getParameterList().getParameters();
|
||||
final boolean isStatic = ((PsiMethod)declaration).hasModifierProperty(PsiModifier.STATIC);
|
||||
if (isStatic && parameters.length == 2 || !isStatic && parameters.length == 1) {
|
||||
return parameters[parameters.length - 1].getType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static PsiType getReadablePropertyType(PsiElement declaration) {
|
||||
if (declaration instanceof PsiField) {
|
||||
return getWrappedPropertyType((PsiField)declaration, declaration.getProject(), JavaFxCommonClassNames.ourReadOnlyMap);
|
||||
}
|
||||
if (declaration instanceof PsiMethod) {
|
||||
PsiMethod psiMethod = (PsiMethod)declaration;
|
||||
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
|
||||
final boolean isStatic = psiMethod.hasModifierProperty(PsiModifier.STATIC);
|
||||
if (!isStatic && parameters.length == 0) {
|
||||
return psiMethod.getReturnType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<String, XmlAttributeValue> collectFileIds(final XmlTag currentTag) {
|
||||
final Map<String, XmlAttributeValue> fileIds = new HashMap<String, XmlAttributeValue>();
|
||||
currentTag.getContainingFile().accept(new XmlRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitXmlTag(XmlTag tag) {
|
||||
super.visitXmlTag(tag);
|
||||
if (currentTag != tag) {
|
||||
final XmlAttribute attribute = tag.getAttribute(FxmlConstants.FX_ID);
|
||||
if (attribute != null) {
|
||||
fileIds.put(attribute.getValue(), attribute.getValueElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
final PsiFile containingFile = currentTag.getContainingFile();
|
||||
if (containingFile instanceof XmlFile) {
|
||||
final XmlTag rootTag = ((XmlFile)containingFile).getRootTag();
|
||||
if (rootTag != null) {
|
||||
final XmlAttribute attribute = rootTag.getAttribute(FxmlConstants.FX_CONTROLLER);
|
||||
if (attribute != null) {
|
||||
fileIds.put(FxmlConstants.CONTROLLER, attribute.getValueElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileIds;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClass getTagClassById(String id, PsiElement context, XmlAttributeValue xmlAttributeValue) {
|
||||
return FxmlConstants.CONTROLLER.equals(id) ? getControllerClass(context.getContainingFile()) : getTagClass(xmlAttributeValue);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClass getPropertyClass(XmlAttributeValue xmlAttributeValue) {
|
||||
final PsiElement declaration = getPropertyDeclaration(xmlAttributeValue);
|
||||
return getPropertyClass(getWritablePropertyType(declaration), xmlAttributeValue);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClass getPropertyClass(PsiType propertyType, XmlAttributeValue context) {
|
||||
if (propertyType instanceof PsiPrimitiveType) {
|
||||
PsiClassType boxedType = ((PsiPrimitiveType)propertyType).getBoxedType(context);
|
||||
return boxedType != null ? boxedType.resolve() : null;
|
||||
}
|
||||
return PsiUtil.resolveClassInType(propertyType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getPropertyDeclaration(XmlAttributeValue xmlAttributeValue) {
|
||||
PsiClass tagClass = getTagClass(xmlAttributeValue);
|
||||
if (tagClass != null) {
|
||||
XmlAttribute xmlAttribute = (XmlAttribute)xmlAttributeValue.getParent();
|
||||
final XmlAttributeDescriptor attributeDescriptor = xmlAttribute.getDescriptor();
|
||||
if (attributeDescriptor != null) {
|
||||
return attributeDescriptor.getDeclaration();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class JavaFxControllerCachedValueProvider implements CachedValueProvider<PsiClass> {
|
||||
private final Project myProject;
|
||||
private final PsiFile myContainingFile;
|
||||
|
||||
+46
-11
@@ -1,9 +1,13 @@
|
||||
package org.jetbrains.plugins.javaFX.fxml.descriptors;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.xml.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.xml.XmlAttributeDescriptor;
|
||||
@@ -19,6 +23,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
@@ -148,6 +153,45 @@ public class JavaFxPropertyAttributeDescriptor extends BasicXmlAttributeDescript
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value.startsWith("$")) {
|
||||
final String referencesId = value.substring(1);
|
||||
final XmlTag currentTag = PsiTreeUtil.getParentOfType(xmlAttributeValue, XmlTag.class);
|
||||
final Map<String, XmlAttributeValue> fileIds = JavaFxPsiUtil.collectFileIds(currentTag);
|
||||
final PsiClass targetPropertyClass = JavaFxPsiUtil.getPropertyClass(xmlAttributeValue);
|
||||
if (targetPropertyClass == null ||
|
||||
Comparing.strEqual(targetPropertyClass.getQualifiedName(), CommonClassNames.JAVA_LANG_STRING) ||
|
||||
JavaFxPsiUtil.findValueOfMethod(targetPropertyClass) != null) {
|
||||
return null;
|
||||
}
|
||||
final PsiClass valueClass;
|
||||
if (JavaFxPsiUtil.isExpressionBinding(value)) {
|
||||
final String expressionText = referencesId.substring(1, referencesId.length() - 1);
|
||||
final String newId = StringUtil.getPackageName(expressionText);
|
||||
final PsiClass tagClass = JavaFxPsiUtil.getTagClassById(newId, xmlAttributeValue, fileIds.get(newId));
|
||||
if (tagClass == null) return null;
|
||||
|
||||
final String fieldRef = StringUtil.getShortName(expressionText);
|
||||
final String fieldName = JavaCodeStyleManager.getInstance(tagClass.getProject()).propertyNameToVariableName(fieldRef, VariableKind.FIELD);
|
||||
PsiField psiField = tagClass.findFieldByName(fieldName, true);
|
||||
|
||||
final PsiMember propertyDeclaration;
|
||||
if (psiField != null && psiField.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
propertyDeclaration = psiField;
|
||||
}
|
||||
else {
|
||||
propertyDeclaration = JavaFxPsiUtil.findPropertyGetter(fieldRef, tagClass);
|
||||
}
|
||||
if (propertyDeclaration == null) return null;
|
||||
valueClass = JavaFxPsiUtil.getPropertyClass(JavaFxPsiUtil.getReadablePropertyType(propertyDeclaration), xmlAttributeValue);
|
||||
}
|
||||
else {
|
||||
valueClass = JavaFxPsiUtil.getTagClassById(referencesId, xmlAttributeValue, fileIds.get(referencesId));
|
||||
}
|
||||
if (valueClass == null || InheritanceUtil.isInheritorOrSelf(valueClass, targetPropertyClass, true)) {
|
||||
return null;
|
||||
}
|
||||
return "Invalid value: unable to coerce to " + targetPropertyClass.getQualifiedName();
|
||||
}
|
||||
else {
|
||||
final XmlAttributeDescriptor attributeDescriptor = ((XmlAttribute)parent).getDescriptor();
|
||||
if (attributeDescriptor != null) {
|
||||
@@ -199,16 +243,7 @@ public class JavaFxPropertyAttributeDescriptor extends BasicXmlAttributeDescript
|
||||
|
||||
@Nullable
|
||||
private static String getBoxedPropertyType(PsiElement declaration) {
|
||||
PsiType attrType = null;
|
||||
if (declaration instanceof PsiField) {
|
||||
attrType = JavaFxPsiUtil.getWrappedPropertyType((PsiField)declaration, declaration.getProject(), JavaFxCommonClassNames.ourWritableMap);
|
||||
} else if (declaration instanceof PsiMethod) {
|
||||
final PsiParameter[] parameters = ((PsiMethod)declaration).getParameterList().getParameters();
|
||||
final boolean isStatic = ((PsiMethod)declaration).hasModifierProperty(PsiModifier.STATIC);
|
||||
if (isStatic && parameters.length == 2 || !isStatic && parameters.length == 1) {
|
||||
attrType = parameters[parameters.length - 1].getType();
|
||||
}
|
||||
}
|
||||
PsiType attrType = JavaFxPsiUtil.getWritablePropertyType(declaration);
|
||||
|
||||
String boxedQName = null;
|
||||
if (attrType instanceof PsiPrimitiveType) {
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ public class JavaFxPropertyElementDescriptor implements XmlElementDescriptor {
|
||||
descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass));
|
||||
}
|
||||
} else if (InheritanceUtil.isInheritor(psiType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY)) {
|
||||
final PsiType propertyType = JavaFxPsiUtil.getPropertyType(psiType, project);
|
||||
final PsiType propertyType = JavaFxPsiUtil.getWritablePropertyType(psiType, project);
|
||||
final PsiClass aClass = PsiUtil.resolveClassInType(propertyType);
|
||||
if (aClass != null) {
|
||||
descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass));
|
||||
|
||||
+72
-27
@@ -15,9 +15,12 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.javaFX.fxml.refs;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
@@ -32,6 +35,7 @@ import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
|
||||
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
@@ -46,42 +50,21 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
|
||||
final String value = xmlAttributeValue.getValue();
|
||||
final boolean startsWithDollar = value.startsWith("$");
|
||||
final String referencesId = startsWithDollar ? value.substring(1) : value;
|
||||
final Map<String, XmlAttributeValue> fileIds = new HashMap<String, XmlAttributeValue>();
|
||||
xmlAttributeValue.getContainingFile().accept(new XmlRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitXmlTag(XmlTag tag) {
|
||||
super.visitXmlTag(tag);
|
||||
if (currentTag != tag) {
|
||||
final XmlAttribute attribute = tag.getAttribute(FxmlConstants.FX_ID);
|
||||
if (attribute != null) {
|
||||
fileIds.put(attribute.getValue(), attribute.getValueElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
final Map<String, XmlAttributeValue> fileIds = JavaFxPsiUtil.collectFileIds(currentTag);
|
||||
|
||||
if (JavaFxPsiUtil.isExpressionBinding(value)) {
|
||||
final String expressionText = referencesId.substring(1, referencesId.length() - 1);
|
||||
final String newId = StringUtil.getPackageName(expressionText);
|
||||
final String fieldRef = StringUtil.getShortName(expressionText);
|
||||
|
||||
final PsiReferenceBase idReferenceBase;
|
||||
|
||||
final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(element.getContainingFile());
|
||||
final PsiField controllerField = controllerClass != null ? controllerClass.findFieldByName(newId, false) : null;
|
||||
if (controllerField == null) {
|
||||
idReferenceBase = new JavaFxIdReferenceBase(xmlAttributeValue, fileIds, newId);
|
||||
} else {
|
||||
idReferenceBase = new JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef(xmlAttributeValue, controllerField, controllerClass);
|
||||
}
|
||||
|
||||
final PsiReferenceBase idReferenceBase = getIdReferenceBase(xmlAttributeValue, newId, fileIds, Collections.emptyMap(), controllerClass);
|
||||
final TextRange range = idReferenceBase.getRangeInElement();
|
||||
final int startOffset = range.getStartOffset() + 2;
|
||||
final int endOffset = startOffset + newId.length();
|
||||
idReferenceBase.setRangeInElement(new TextRange(startOffset, endOffset));
|
||||
if (fileIds.containsKey(newId)) {
|
||||
final XmlAttributeValue attributeValue = fileIds.get(newId);
|
||||
final PsiClass tagClass = JavaFxPsiUtil.getTagClass(attributeValue);
|
||||
final PsiClass tagClass = FxmlConstants.CONTROLLER.equals(newId) ? controllerClass : JavaFxPsiUtil.getTagClass(fileIds.get(newId));
|
||||
if (tagClass != null) {
|
||||
final JavaFxExpressionReferenceBase referenceBase = new JavaFxExpressionReferenceBase(xmlAttributeValue, tagClass, fieldRef);
|
||||
final TextRange textRange = referenceBase.getRangeInElement();
|
||||
@@ -92,7 +75,20 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
|
||||
return new PsiReference[] {idReferenceBase};
|
||||
}
|
||||
if (startsWithDollar) {
|
||||
final JavaFxIdReferenceBase idReferenceBase = new JavaFxIdReferenceBase(xmlAttributeValue, fileIds, referencesId);
|
||||
final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(element.getContainingFile());
|
||||
|
||||
final PsiClass targetPropertyClass = JavaFxPsiUtil.getPropertyClass(xmlAttributeValue);
|
||||
final boolean isConvertible = targetPropertyClass != null &&
|
||||
(Comparing.strEqual(targetPropertyClass.getQualifiedName(), CommonClassNames.JAVA_LANG_STRING)
|
||||
|| JavaFxPsiUtil.findValueOfMethod(targetPropertyClass) != null);
|
||||
|
||||
final Map<String, TypeMatch> typeMatches = fileIds.entrySet().stream().collect(
|
||||
Collectors.toMap(Map.Entry::getKey, e -> {
|
||||
final PsiClass valueClass = JavaFxPsiUtil.getTagClassById(e.getKey(), xmlAttributeValue, e.getValue());
|
||||
return TypeMatch.getMatch(valueClass, targetPropertyClass, isConvertible);
|
||||
}));
|
||||
|
||||
final PsiReferenceBase idReferenceBase = getIdReferenceBase(xmlAttributeValue, referencesId, fileIds, typeMatches, controllerClass);
|
||||
final TextRange rangeInElement = idReferenceBase.getRangeInElement();
|
||||
idReferenceBase.setRangeInElement(new TextRange(rangeInElement.getStartOffset() + 1, rangeInElement.getEndOffset()));
|
||||
return new PsiReference[]{idReferenceBase};
|
||||
@@ -112,9 +108,50 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiReferenceBase getIdReferenceBase(XmlAttributeValue xmlAttributeValue,
|
||||
String referencesId,
|
||||
Map<String, XmlAttributeValue> fileIds,
|
||||
Map<String, TypeMatch> typeMatches,
|
||||
PsiClass controllerClass) {
|
||||
if (controllerClass != null && !FxmlConstants.CONTROLLER.equals(referencesId)) {
|
||||
final PsiField controllerField = controllerClass.findFieldByName(referencesId, false);
|
||||
if (controllerField != null) {
|
||||
return new JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef(xmlAttributeValue, controllerField, controllerClass);
|
||||
}
|
||||
}
|
||||
return new JavaFxIdReferenceBase(xmlAttributeValue, fileIds, typeMatches, referencesId);
|
||||
}
|
||||
|
||||
private enum TypeMatch {
|
||||
ASSIGNABLE(3.0),
|
||||
CONVERTIBLE(2.0),
|
||||
UNDEFINED(1.0),
|
||||
INCOMPATIBLE(0.0);
|
||||
|
||||
private final double myPriority;
|
||||
|
||||
TypeMatch(double priority) {
|
||||
myPriority = priority;
|
||||
}
|
||||
|
||||
public static double getPriority(TypeMatch match) {
|
||||
return match != null ? match.myPriority : 0.0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TypeMatch getMatch(PsiClass valueClass, PsiClass targetPropertyClass, boolean isConvertible) {
|
||||
if (valueClass == null || targetPropertyClass == null) return UNDEFINED;
|
||||
if (InheritanceUtil.isInheritorOrSelf(valueClass, targetPropertyClass, true)) return ASSIGNABLE;
|
||||
if (isConvertible) return CONVERTIBLE;
|
||||
return INCOMPATIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
private static class JavaFxIdReferenceBase extends PsiReferenceBase<XmlAttributeValue> {
|
||||
private final Map<String, XmlAttributeValue> myFileIds;
|
||||
private final Set<String> myAcceptableIds;
|
||||
private final Map<String, TypeMatch> myTypeMatches;
|
||||
private final String myReferencesId;
|
||||
|
||||
private JavaFxIdReferenceBase(XmlAttributeValue element,
|
||||
@@ -125,13 +162,16 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
|
||||
myFileIds = fileIds;
|
||||
myAcceptableIds = acceptableIds;
|
||||
myReferencesId = referencesId;
|
||||
myTypeMatches = Collections.emptyMap();
|
||||
}
|
||||
|
||||
public JavaFxIdReferenceBase(XmlAttributeValue xmlAttributeValue,
|
||||
Map<String, XmlAttributeValue> fileIds,
|
||||
Map<String, TypeMatch> typeMatches,
|
||||
String referencesId) {
|
||||
super(xmlAttributeValue);
|
||||
myFileIds = fileIds;
|
||||
myTypeMatches = typeMatches;
|
||||
myReferencesId = referencesId;
|
||||
myAcceptableIds = myFileIds.keySet();
|
||||
}
|
||||
@@ -145,7 +185,12 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] getVariants() {
|
||||
return ArrayUtil.toStringArray(myAcceptableIds);
|
||||
return myAcceptableIds.stream().map(
|
||||
id -> {
|
||||
LookupItem<String> item = new LookupItem<String>(id, id);
|
||||
item.setPriority(TypeMatch.getPriority(myTypeMatches.get(id)));
|
||||
return item;
|
||||
}).toArray(LookupItem[]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +228,7 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
|
||||
|
||||
private Object[] collectProperties(@NotNull PsiField psiField) {
|
||||
final PsiType type = psiField.getType();
|
||||
final PsiType propertyType = JavaFxPsiUtil.getPropertyType(type, psiField.getProject());
|
||||
final PsiType propertyType = JavaFxPsiUtil.getWritablePropertyType(type, psiField.getProject());
|
||||
final List<PsiField> objs = new ArrayList<PsiField>();
|
||||
for (PsiField field : myTagClass.getAllFields()) {
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC)) continue;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.fxml.FXML;
|
||||
|
||||
public class ControllerInExpression {
|
||||
@FXML
|
||||
private ControllerInExpressionWrapper wrapper;
|
||||
@FXML
|
||||
private ControllerInExpressionWrapper wrapper2;
|
||||
|
||||
private StringProperty strProp = new SimpleStringProperty("Text");
|
||||
public StringProperty strPropProperty() {
|
||||
return strProp;
|
||||
}
|
||||
public String getStrProp() {
|
||||
return strProp.get();
|
||||
}
|
||||
public void setStrProp(StringProperty strProp) {
|
||||
this.strProp = strProp;
|
||||
}
|
||||
|
||||
private IntegerProperty intProp = new SimpleIntegerProperty(123);
|
||||
public IntegerProperty intPropProperty() {
|
||||
return intProp;
|
||||
}
|
||||
public int getIntProp() {
|
||||
return intProp.get();
|
||||
}
|
||||
public void setIntProp(int intProp) {
|
||||
this.intProp.set(intProp);
|
||||
}
|
||||
|
||||
private DoubleProperty doubleProp = new SimpleDoubleProperty(123.45);
|
||||
public DoubleProperty doublePropProperty() {
|
||||
return doubleProp;
|
||||
}
|
||||
public double getDoubleProp() {
|
||||
return doubleProp.get();
|
||||
}
|
||||
public void setDoubleProp(double doubleProp) {
|
||||
this.doubleProp.set(doubleProp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "222.2";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
|
||||
public class ControllerInExpressionWrapper {
|
||||
private ObjectProperty<ControllerInExpression> controller = new SimpleObjectProperty<>(this, "controller");
|
||||
|
||||
public ObjectProperty<ControllerInExpression> controllerProperty() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
public ControllerInExpression getController() {
|
||||
return controller.get();
|
||||
}
|
||||
|
||||
public void setController(ControllerInExpression controller) {
|
||||
this.controller.set(controller);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.control.Tooltip?>
|
||||
<?import ControllerInExpressionWrapper?>
|
||||
<?import ControllerInExpression?>
|
||||
<VBox fx:controller="ControllerInExpression" xmlns:fx="http://javafx.com/fxml">
|
||||
<fx:define>
|
||||
<Tooltip text="tooltip" fx:id="tooltip"/>
|
||||
</fx:define>
|
||||
<fx:define>
|
||||
<ControllerInExpressionWrapper fx:id="wrapper" controller="$controller"/>
|
||||
</fx:define>
|
||||
<fx:define>
|
||||
<ControllerInExpressionWrapper fx:id="wrapper2" controller=<error descr="Invalid value: unable to coerce to ControllerInExpression">"$tooltip"</error>/>
|
||||
</fx:define>
|
||||
<Label text="$controller"/>
|
||||
<Label text="${controller.strProp}"
|
||||
maxWidth="$controller"
|
||||
minHeight="${controller.intProp}"
|
||||
maxHeight="${controller.doubleProp}"
|
||||
tooltip=<error descr="Invalid value: unable to coerce to javafx.scene.control.Tooltip">"${controller.strProp}"</error>
|
||||
/>
|
||||
<Label text="${controller.<error descr="Cannot resolve symbol 'unknownProp'">unknownProp</error>}"/>
|
||||
</VBox>
|
||||
Reference in New Issue
Block a user