mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
javafx: check for acceptable classes to import according to tag placement in .fxml; add checks for hierarchy caused by default property (IDEA-103205)
(cherry picked from commit 968cfb49eb29777863b298beb04b2cfd3cafce15)
This commit is contained in:
+4
@@ -262,6 +262,10 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testUnexpectedNode() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(false, false, getTestName(true) + ".fxml");
|
||||
}
|
||||
|
||||
+7
-1
@@ -33,7 +33,13 @@ public class JavaFXImportTest extends DaemonAnalyzerTestCase {
|
||||
public void testSimpleImport() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testTextField() throws Exception {
|
||||
configureByFiles(null, getTestName(true) + ".fxml", getTestName(false) + ".java");
|
||||
final List<HighlightInfo> infos = doHighlighting();
|
||||
findAndInvokeIntentionAction(infos, "Import Class", getEditor(), getFile());
|
||||
checkResultByFile(getTestName(true) + "_after.fxml");
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
configureByFiles(null, getTestName(true) + ".fxml");
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
package org.jetbrains.plugins.javaFX.fxml;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.xml.XMLLanguage;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
@@ -33,6 +35,8 @@ import com.intellij.util.Processor;
|
||||
import com.intellij.xml.XmlElementDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassBackedElementDescriptor;
|
||||
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyElementDescriptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -430,6 +434,54 @@ public class JavaFxPsiUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String isClassAcceptable(@Nullable XmlTag parentTag, final PsiClass aClass) {
|
||||
if (aClass != null && aClass.isValid()) {
|
||||
if (parentTag == null) {
|
||||
if (!InheritanceUtil.isInheritor(aClass, false, JavaFxCommonClassNames.JAVAFX_SCENE_NODE)) {
|
||||
return unableToCoerceMessage(aClass, JavaFxCommonClassNames.JAVAFX_SCENE_NODE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final XmlElementDescriptor descriptor = parentTag.getDescriptor();
|
||||
if (descriptor instanceof JavaFxPropertyElementDescriptor) {
|
||||
final PsiElement declaration = descriptor.getDeclaration();
|
||||
if (declaration instanceof PsiField) {
|
||||
return canCoerce(aClass, ((PsiField)declaration).getType());
|
||||
}
|
||||
}
|
||||
else if (descriptor instanceof JavaFxClassBackedElementDescriptor) {
|
||||
final PsiElement declaration = descriptor.getDeclaration();
|
||||
if (declaration instanceof PsiClass) {
|
||||
final PsiType type = getDefaultPropertyExpectedType((PsiClass)declaration);
|
||||
if (type != null) {
|
||||
return canCoerce(aClass, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String canCoerce(PsiClass aClass, PsiType type) {
|
||||
final PsiType collectionItemType = GenericsHighlightUtil.getCollectionItemType(type, aClass.getResolveScope());
|
||||
if (collectionItemType != null && PsiPrimitiveType.getUnboxedType(collectionItemType) == null) {
|
||||
final PsiClass baseClass = PsiUtil.resolveClassInType(collectionItemType);
|
||||
if (baseClass != null) {
|
||||
final String qualifiedName = baseClass.getQualifiedName();
|
||||
if (qualifiedName != null && !Comparing.strEqual(qualifiedName, CommonClassNames.JAVA_LANG_STRING)) {
|
||||
if (!InheritanceUtil.isInheritor(aClass, qualifiedName)) {
|
||||
return unableToCoerceMessage(aClass, qualifiedName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String unableToCoerceMessage(PsiClass aClass, String qualifiedName) {
|
||||
return "Unable to coerce " + HighlightUtil.formatClass(aClass)+ " to " + qualifiedName;
|
||||
}
|
||||
|
||||
private static class JavaFxControllerCachedValueProvider implements CachedValueProvider<PsiClass> {
|
||||
private final Project myProject;
|
||||
private final PsiFile myContainingFile;
|
||||
|
||||
+4
-28
@@ -2,7 +2,6 @@ package org.jetbrains.plugins.javaFX.fxml.descriptors;
|
||||
|
||||
import com.intellij.codeInsight.daemon.Validator;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -11,7 +10,6 @@ import com.intellij.psi.impl.source.xml.XmlAttributeImpl;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -280,7 +278,10 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
|
||||
host.addMessage(((XmlAttributeImpl)attribute).getNameElement(), "fx:controller can only be applied to root element", ValidationHost.ErrorType.ERROR); //todo add delete/move to upper tag fix
|
||||
}
|
||||
}
|
||||
validateTagAccordingToFieldType(context, parentTag, host);
|
||||
final String canCoerceError = JavaFxPsiUtil.isClassAcceptable(parentTag, myPsiClass);
|
||||
if (canCoerceError != null) {
|
||||
host.addMessage(context.getNavigationElement(), canCoerceError, ValidationHost.ErrorType.ERROR);
|
||||
}
|
||||
if (myPsiClass != null && myPsiClass.isValid()) {
|
||||
final String message = JavaFxPsiUtil.isAbleToInstantiate(myPsiClass);
|
||||
if (message != null) {
|
||||
@@ -288,29 +289,4 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateTagAccordingToFieldType(XmlTag context, XmlTag parentTag, ValidationHost host) {
|
||||
if (myPsiClass != null && myPsiClass.isValid()) {
|
||||
final XmlElementDescriptor descriptor = parentTag != null ? parentTag.getDescriptor() : null;
|
||||
if (descriptor instanceof JavaFxPropertyElementDescriptor) {
|
||||
final PsiElement declaration = descriptor.getDeclaration();
|
||||
if (declaration instanceof PsiField) {
|
||||
final PsiType type = ((PsiField)declaration).getType();
|
||||
final PsiType collectionItemType = GenericsHighlightUtil.getCollectionItemType(type, myPsiClass.getResolveScope());
|
||||
if (collectionItemType != null && PsiPrimitiveType.getUnboxedType(collectionItemType) == null) {
|
||||
final PsiClass baseClass = PsiUtil.resolveClassInType(collectionItemType);
|
||||
if (baseClass != null) {
|
||||
final String qualifiedName = baseClass.getQualifiedName();
|
||||
if (qualifiedName != null && !Comparing.strEqual(qualifiedName, CommonClassNames.JAVA_LANG_STRING)) {
|
||||
if (!InheritanceUtil.isInheritor(myPsiClass, qualifiedName)) {
|
||||
host.addMessage(context.getNavigationElement(),
|
||||
"Unable to coerce " + HighlightUtil.formatClass(myPsiClass)+ " to " + qualifiedName, ValidationHost.ErrorType.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ abstract class JavaFxImportClassFix extends ImportClassFixBase<XmlTag, JavaFxTag
|
||||
|
||||
@Override
|
||||
protected boolean isAccessible(PsiMember member, XmlTag reference) {
|
||||
return true;
|
||||
return member instanceof PsiClass && JavaFxPsiUtil.isClassAcceptable(reference.getParentTag(), (PsiClass)member) == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import java.lang.Double?>
|
||||
|
||||
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center">
|
||||
<<error descr="Unable to coerce java.lang.Double to javafx.scene.Node">Double</error> />
|
||||
</GridPane>
|
||||
@@ -0,0 +1,2 @@
|
||||
package foo;
|
||||
public class TextField {}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.layout.*?>
|
||||
<GridPane xmlns:fx="http://javafx.com/fxml">
|
||||
<children>
|
||||
<Text<caret>Field/>
|
||||
</children>
|
||||
</GridPane>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<GridPane xmlns:fx="http://javafx.com/fxml">
|
||||
<children>
|
||||
<TextField/>
|
||||
</children>
|
||||
</GridPane>
|
||||
Reference in New Issue
Block a user