javafx: treat initialize method of a controller as an entry point, invoked implicitly by FXMLLoader (IDEA-158967)

This commit is contained in:
Anna Kozlova
2016-08-26 16:17:42 +03:00
parent a0dcb10ff9
commit 475c9f1c45
3 changed files with 41 additions and 31 deletions
@@ -32,8 +32,10 @@ import com.intellij.util.CommonProcessors;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
public class JavaFxEntryPoint extends EntryPoint {
public static final String INITIALIZE_METHOD_NAME = "initialize";
public boolean ADD_JAVAFX_TO_ENTRIES = true;
@NotNull
@@ -49,11 +51,21 @@ public class JavaFxEntryPoint extends EntryPoint {
public boolean isEntryPoint(@NotNull PsiElement psiElement) {
if (psiElement instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)psiElement;
if (method.getParameterList().getParameters().length == 1 &&
final int paramsCount = method.getParameterList().getParameters().length;
final String methodName = method.getName();
final PsiClass containingClass = method.getContainingClass();
if (paramsCount == 1 &&
PsiType.VOID.equals(method.getReturnType()) &&
"start".equals(method.getName())) {
return InheritanceUtil.isInheritor(method.getContainingClass(), true, JavaFxCommonNames.JAVAFX_APPLICATION_APPLICATION);
"start".equals(methodName)) {
return InheritanceUtil.isInheritor(containingClass, true, JavaFxCommonNames.JAVAFX_APPLICATION_APPLICATION);
}
if (paramsCount == 0 && INITIALIZE_METHOD_NAME.equals(methodName) &&
method.hasModifierProperty(PsiModifier.PUBLIC) &&
containingClass != null &&
JavaFxPsiUtil.isControllerClass(containingClass)) {
return true;
}
}
else if (psiElement instanceof PsiClass) {
return InheritanceUtil.isInheritor((PsiClass)psiElement, true, JavaFxCommonNames.JAVAFX_APPLICATION_APPLICATION);
@@ -44,6 +44,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassTagDescriptorBase;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyTagDescriptor;
import org.jetbrains.plugins.javaFX.indexing.JavaFxControllerClassIndex;
import java.util.*;
import java.util.function.BiConsumer;
@@ -1143,6 +1144,29 @@ public class JavaFxPsiUtil {
return Pair.create(tagClass, false);
}
public static boolean isControllerClass(@NotNull PsiClass psiClass) {
final Project project = psiClass.getProject();
final GlobalSearchScope resolveScope = psiClass.getResolveScope();
if (isControllerClassName(project, psiClass.getQualifiedName(), resolveScope)) {
return true;
}
final Ref<Boolean> refFound = new Ref<>(false);
ClassInheritorsSearch.search(psiClass, resolveScope, true, true, false).forEach((aClass) -> {
if (isControllerClassName(project, aClass.getQualifiedName(), resolveScope)) {
refFound.set(true);
return false;
}
return true;
});
return refFound.get();
}
private static boolean isControllerClassName(@NotNull Project project,
@Nullable String qualifiedName,
@NotNull GlobalSearchScope resolveScope) {
return qualifiedName != null && !JavaFxControllerClassIndex.findFxmlWithController(project, qualifiedName, resolveScope).isEmpty();
}
private static class JavaFxControllerCachedValueProvider implements CachedValueProvider<PsiClass> {
private final Project myProject;
private final PsiFile myContainingFile;
@@ -16,22 +16,19 @@
package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.UseScopeEnlarger;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PropertyUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
import org.jetbrains.plugins.javaFX.indexing.JavaFxControllerClassIndex;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
/**
* User: anna
@@ -59,7 +56,7 @@ public class JavaFxScopeEnlarger extends UseScopeEnlarger {
element instanceof PsiMethod && needToEnlargeMethodScope((PsiMethod)element) ||
element instanceof PsiParameter) {
if (InheritanceUtil.isInheritor(containingClass, JavaFxCommonNames.JAVAFX_SCENE_NODE) ||
isControllerClass(containingClass)) {
JavaFxPsiUtil.isControllerClass(containingClass)) {
final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(element.getProject());
return new GlobalFxmlSearchScope(projectScope);
}
@@ -69,29 +66,6 @@ public class JavaFxScopeEnlarger extends UseScopeEnlarger {
return null;
}
public boolean isControllerClass(PsiClass psiClass) {
final Project project = psiClass.getProject();
final GlobalSearchScope resolveScope = psiClass.getResolveScope();
if (isControllerClassName(project, psiClass.getQualifiedName(), resolveScope)) {
return true;
}
final Ref<Boolean> refFound = new Ref<>(false);
ClassInheritorsSearch.search(psiClass, resolveScope, true, true, false).forEach((aClass) -> {
if (isControllerClassName(project, aClass.getQualifiedName(), resolveScope)) {
refFound.set(true);
return false;
}
return true;
});
return refFound.get();
}
private static boolean isControllerClassName(@NotNull Project project,
@Nullable String qualifiedName,
@NotNull GlobalSearchScope resolveScope) {
return qualifiedName != null && !JavaFxControllerClassIndex.findFxmlWithController(project, qualifiedName, resolveScope).isEmpty();
}
private static boolean needToEnlargeFieldScope(PsiField field) {
return !field.hasModifierProperty(PsiModifier.PUBLIC) &&
AnnotationUtil.isAnnotated(field, JavaFxCommonNames.JAVAFX_FXML_ANNOTATION, false);