javafx: check that refs from .fxml are public or @FXML (IDEA-99996)

This commit is contained in:
Anna Kozlova
2013-01-30 14:00:33 +04:00
parent 4ef22db9c9
commit aa1c9755d4
7 changed files with 80 additions and 8 deletions
+1
View File
@@ -17,5 +17,6 @@
<codeInsight.unresolvedReferenceQuickFixProvider implementation="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxEventHandlerReference$JavaFxUnresolvedReferenceHandlerQuickfixProvider"/>
<codeInsight.unresolvedReferenceQuickFixProvider implementation="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxTagNameReference$JavaFxUnresolvedTagRefsProvider"/>
<multiHostInjector implementation="org.jetbrains.plugins.javaFX.fxml.ScriptLanguageInjector"/>
<annotator language="XML" implementationClass="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxRefsAnnotator"/>
</extensions>
</idea-plugin>
@@ -26,7 +26,7 @@ public class JavaFxCommonClassNames {
@NonNls public static final String JAVAFX_ANCHOR_PANE = "javafx.scene.layout.AnchorPane";
@NonNls public static final String JAVAFX_EVENT = "javafx.event.Event";
@NonNls public static final String JAVAFX_BEANS_DEFAULT_PROPERTY = "javafx.beans.DefaultProperty";
@NonNls public static final String JAVAFX_FXML_FXML = "javafx.fxml.FXML";
@NonNls public static final String JAVAFX_FXML_ANNOTATION = "javafx.fxml.FXML";
@NonNls public static final String JAVAFX_BEANS_PROPERTY_OBJECT_PROPERTY = "javafx.beans.property.ObjectProperty";
@NonNls public static final String JAVAFX_EVENT_EVENT_HANDLER = "javafx.event.EventHandler";
public static final String JAVAFX_SCENE_NODE = "javafx.scene.Node";
@@ -73,13 +73,11 @@ public class JavaFxEventHandlerReference extends PsiReferenceBase<XmlAttributeVa
public static boolean isHandlerMethod(PsiMethod psiMethod) {
if (!psiMethod.hasModifierProperty(PsiModifier.STATIC) && PsiType.VOID.equals(psiMethod.getReturnType())) {
if (psiMethod.hasModifierProperty(PsiModifier.PUBLIC) || AnnotationUtil.isAnnotated(psiMethod, JavaFxCommonClassNames.JAVAFX_FXML_FXML, false)) {
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
if (parameters.length == 1) {
final PsiType parameterType = parameters[0].getType();
if (InheritanceUtil.isInheritor(parameterType, JavaFxCommonClassNames.JAVAFX_EVENT)) {
return true;
}
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
if (parameters.length == 1) {
final PsiType parameterType = parameters[0].getType();
if (InheritanceUtil.isInheritor(parameterType, JavaFxCommonClassNames.JAVAFX_EVENT)) {
return true;
}
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.intention.AddAnnotationFix;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.psi.*;
import com.intellij.psi.presentation.java.SymbolPresentationUtil;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
import java.util.Collections;
/**
* User: anna
*/
public class JavaFxRefsAnnotator implements Annotator {
@Override
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
final PsiFile containingFile = element.getContainingFile();
if (!JavaFxFileTypeFactory.isFxml(containingFile)) return;
if (element instanceof XmlAttributeValue) {
final PsiReference[] references = element.getReferences();
for (PsiReference reference : references) {
final PsiElement resolve = reference.resolve();
if (resolve instanceof PsiMember) {
if (!((PsiMember)resolve).hasModifierProperty(PsiModifier.PUBLIC) &&
!AnnotationUtil.isAnnotated((PsiMember)resolve, Collections.singleton(JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION))) {
final String symbolPresentation = "'" + SymbolPresentationUtil.getSymbolPresentableText(resolve) + "'";
final Annotation annotation = holder.createErrorAnnotation(element,
symbolPresentation + (resolve instanceof PsiClass ? " should be public" : " should be public or annotated with @FXML"));
if (!(resolve instanceof PsiClass)) {
annotation.registerUniversalFix(new AddAnnotationFix(JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION, (PsiMember)resolve, ArrayUtil.EMPTY_STRING_ARRAY), null, null);
}
}
}
}
}
}
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.text.*?>
<GridPane fx:controller=<error descr="'PackageLocalController' should be public">"PackageLocalController"</error> xmlns:fx="http://javafx.com/fxml">
</GridPane>
@@ -0,0 +1 @@
class PackageLocalController{}
@@ -62,6 +62,11 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
public void testControllerIdRef() throws Exception {
doTestIdController();
}
public void testPackageLocalController() throws Exception {
configureByFiles(null, getTestName(true) + ".fxml", getTestName(false) + ".java");
doDoTest(false, false);
}
private void doTestIdController() throws Exception {
final String controllerClassName = getTestName(false) + "Controller";