diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 7a9fc0d0441e..66923d9db269 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -845,6 +845,11 @@ public class GenericsHighlightUtil { public static PsiType getCollectionItemType(@NotNull PsiExpression expression) { final PsiType type = expression.getType(); if (type == null) return null; + return getCollectionItemType(type, expression.getResolveScope()); + } + + @Nullable + public static PsiType getCollectionItemType(final PsiType type, final GlobalSearchScope scope) { if (type instanceof PsiArrayType) { return ((PsiArrayType)type).getComponentType(); } @@ -857,7 +862,7 @@ public class GenericsHighlightUtil { PsiSubstitutor substitutor = resolveResult.getSubstitutor(); JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject()); if (qName != null) { - PsiClass myClass = facade.findClass(qName, expression.getResolveScope()); + PsiClass myClass = facade.findClass(qName, scope); if (myClass != null && myClass != aClass) { //different JDKs PsiTypeParameter thisTypeParameter = getIterableTypeParameter(facade, myClass); diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxClassBackedElementDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxClassBackedElementDescriptor.java index 697944fc7e53..383685464cb7 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxClassBackedElementDescriptor.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxClassBackedElementDescriptor.java @@ -1,11 +1,15 @@ package org.jetbrains.plugins.javaFX.fxml; 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; import com.intellij.psi.*; import com.intellij.psi.impl.source.xml.XmlAttributeImpl; +import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; @@ -168,11 +172,38 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor, @Override public void validate(@NotNull XmlTag context, @NotNull ValidationHost host) { - if (context.getParentTag() != null) { + final XmlTag parentTag = context.getParentTag(); + if (parentTag != null) { final XmlAttribute attribute = context.getAttribute(FxmlConstants.FX_CONTROLLER); if (attribute != null) { 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); + } + } + + private void validateTagAccordingToFieldType(XmlTag context, XmlTag parentTag, ValidationHost host) { + if (myPsiClass != null && myPsiClass.isValid()) { + final XmlElementDescriptor descriptor = parentTag.getDescriptor(); + if (descriptor instanceof JavaFxListPropertyElementDescriptor) { + 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); + } + } + } + } + } + } } } } diff --git a/plugins/javaFX/testData/highlighting/CoercedTypes.fxml b/plugins/javaFX/testData/highlighting/CoercedTypes.fxml new file mode 100644 index 000000000000..4f870619b884 --- /dev/null +++ b/plugins/javaFX/testData/highlighting/CoercedTypes.fxml @@ -0,0 +1,12 @@ + + + + + + + <ArrayList/> + + + + + diff --git a/plugins/javaFX/testData/jfxrt.jar b/plugins/javaFX/testData/jfxrt.jar index fbaec4cc796e..48109d611026 100644 Binary files a/plugins/javaFX/testData/jfxrt.jar and b/plugins/javaFX/testData/jfxrt.jar differ diff --git a/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java b/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java index 2abe6ed57d6d..0dda34ffc421 100644 --- a/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java +++ b/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java @@ -28,6 +28,10 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase { doTest(); } + public void testCoercedTypes() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false, false, getTestName(true) + ".fxml"); }