javafx: check controller not specified (IDEA-100225)

This commit is contained in:
Anna Kozlova
2013-01-31 20:29:38 +04:00
parent d48bfe6243
commit 32ef183f96
6 changed files with 81 additions and 20 deletions
@@ -21,10 +21,12 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.xml.*;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -184,4 +186,38 @@ public class JavaFxPsiUtil {
}
return null;
}
public static PsiClass getControllerClass(PsiFile containingFile) {
if (containingFile instanceof XmlFile) {
final XmlTag rootTag = ((XmlFile)containingFile).getRootTag();
if (rootTag != null) {
final XmlAttribute attribute = rootTag.getAttribute(FxmlConstants.FX_CONTROLLER);
if (attribute != null) {
final String attributeValue = attribute.getValue();
if (!StringUtil.isEmptyOrSpaces(attributeValue)) {
return JavaPsiFacade.getInstance(containingFile.getProject()).findClass(attributeValue, containingFile.getResolveScope());
}
}
}
}
return null;
}
public static boolean checkIfAttributeHandler(XmlAttribute attribute) {
final String attributeName = attribute.getName();
final XmlTag xmlTag = attribute.getParent();
final XmlElementDescriptor descriptor = xmlTag.getDescriptor();
if (descriptor == null) return false;
final PsiElement currentTagClass = descriptor.getDeclaration();
if (!(currentTagClass instanceof PsiClass)) return false;
final PsiField handlerField = ((PsiClass)currentTagClass).findFieldByName(attributeName, true);
if (handlerField == null) {
return false;
}
final PsiClass objectPropertyClass = getPropertyClass(handlerField);
if (objectPropertyClass == null || !InheritanceUtil.isInheritor(objectPropertyClass, JavaFxCommonClassNames.JAVAFX_EVENT_EVENT_HANDLER)) {
return false;
}
return true;
}
}
@@ -2,7 +2,10 @@ package org.jetbrains.plugins.javaFX.fxml.descriptors;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ArrayUtil;
import com.intellij.xml.XmlAttributeDescriptor;
import org.jetbrains.annotations.Nullable;
@@ -92,10 +95,27 @@ public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor
}
return null;
}
@Nullable
@Override
public String validateValue(XmlElement context, String value) {
if (context instanceof XmlAttributeValue) {
final XmlAttributeValue xmlAttributeValue = (XmlAttributeValue)context;
final PsiElement parent = xmlAttributeValue.getParent();
if (parent instanceof XmlAttribute && JavaFxPsiUtil.checkIfAttributeHandler((XmlAttribute)parent)) {
final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(context.getContainingFile());
if (value.startsWith("#")) {
if (controllerClass == null) {
return "No controller specified for top level element";
}
}
else {
if (JavaFxPsiUtil.parseInjectedLanguages((XmlFile)context.getContainingFile()).isEmpty()) {
return "Page language not specified.";
}
}
}
}
return null;
}
@@ -115,7 +135,8 @@ public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor
}
@Override
public void init(PsiElement element) {}
public void init(PsiElement element) {
}
@Override
public Object[] getDependences() {
@@ -17,14 +17,10 @@ package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ProcessingContext;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
/**
@@ -43,20 +39,8 @@ class JavaFxEventHandlerReferenceProvider extends JavaFxControllerBasedReference
final XmlAttribute attribute = (XmlAttribute)xmlAttributeValue.getContext();
if (attribute == null) return PsiReference.EMPTY_ARRAY;
final String attributeName = attribute.getName();
final XmlTag xmlTag = attribute.getParent();
final XmlElementDescriptor descriptor = xmlTag.getDescriptor();
if (descriptor == null) return PsiReference.EMPTY_ARRAY;
final PsiElement currentTagClass = descriptor.getDeclaration();
if (!(currentTagClass instanceof PsiClass)) return PsiReference.EMPTY_ARRAY;
final PsiField handlerField = ((PsiClass)currentTagClass).findFieldByName(attributeName, true);
if (handlerField == null) {
return PsiReference.EMPTY_ARRAY;
}
final PsiClass objectPropertyClass = JavaFxPsiUtil.getPropertyClass(handlerField);
if (objectPropertyClass == null || !InheritanceUtil.isInheritor(objectPropertyClass, JavaFxCommonClassNames.JAVAFX_EVENT_EVENT_HANDLER)) {
return PsiReference.EMPTY_ARRAY;
}
if (!JavaFxPsiUtil.checkIfAttributeHandler(attribute)) return PsiReference.EMPTY_ARRAY;
final PsiElement currentTagClass = attribute.getParent().getDescriptor().getDeclaration();
final String eventHandlerName = attValueString.substring(1);
final PsiMethod[] methods = controllerClass.findMethodsByName(eventHandlerName, true);
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<GridPane xmlns:fx="http://javafx.com/fxml">
<Button onAction= <error descr="No controller specified for top level element">"#foo"</error> text="foo" fx:id="b1" />
</GridPane>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<GridPane xmlns:fx="http://javafx.com/fxml">
<Button onAction=<error descr="Page language not specified.">"foo"</error> text="foo" fx:id="b1" />
</GridPane>
@@ -134,6 +134,14 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
doTest();
}
public void testHandlerWithoutController() throws Exception {
doTest();
}
public void testHandlerWithoutPageLanguage() throws Exception {
doTest();
}
public void testIncludeBtn() throws Exception {
configureByFiles(null, getTestName(true) + ".fxml", "btn.fxml");
doDoTest(false, false);