javafx: cache java structure needed to validate .fxml

(cherry picked from commit 2466b2d96cb0b5ed83d345c7f41cb370f2a951e6)
This commit is contained in:
anna
2013-03-26 21:43:11 +01:00
parent 0943cd4807
commit 82189d6670
2 changed files with 78 additions and 52 deletions
@@ -417,30 +417,35 @@ public class JavaFxPsiUtil {
return null;
}
public static boolean hasBuilder(final PsiClass psiClass) {
public static boolean hasBuilder(@NotNull final PsiClass psiClass) {
final Project project = psiClass.getProject();
final PsiClass builderClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_FXML_BUILDER,
GlobalSearchScope.allScope(project));
if (builderClass != null) {
//todo cache this info
final PsiMethod[] buildMethods = builderClass.findMethodsByName("build", false);
if (buildMethods.length == 1 && buildMethods[0].getParameterList().getParametersCount() == 0) {
if (ClassInheritorsSearch.search(builderClass).forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass aClass) {
PsiType returnType = null;
final PsiMethod method = MethodSignatureUtil.findMethodBySuperMethod(aClass, buildMethods[0], false);
if (method != null) {
returnType = method.getReturnType();
return CachedValuesManager.getManager(project).getCachedValue(psiClass, new CachedValueProvider<Boolean>() {
@Nullable
@Override
public Result<Boolean> compute() {
final PsiClass builderClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_FXML_BUILDER,
GlobalSearchScope.allScope(project));
if (builderClass != null) {
final PsiMethod[] buildMethods = builderClass.findMethodsByName("build", false);
if (buildMethods.length == 1 && buildMethods[0].getParameterList().getParametersCount() == 0) {
if (ClassInheritorsSearch.search(builderClass).forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass aClass) {
PsiType returnType = null;
final PsiMethod method = MethodSignatureUtil.findMethodBySuperMethod(aClass, buildMethods[0], false);
if (method != null) {
returnType = method.getReturnType();
}
return !Comparing.equal(psiClass, PsiUtil.resolveClassInClassTypeOnly(returnType));
}
})) {
return Result.create(false, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
return !Comparing.equal(psiClass, PsiUtil.resolveClassInClassTypeOnly(returnType));
}
})) {
return false;
}
return Result.create(true, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
}
return true;
});
}
public static String isClassAcceptable(@Nullable XmlTag parentTag, final PsiClass aClass) {
@@ -502,27 +507,35 @@ public class JavaFxPsiUtil {
return false;
}
public static PsiType getWrappedPropertyType(PsiField field, Project project, final Map<String, PsiType> typeMap) {
PsiType substitute = null;
public static PsiType getWrappedPropertyType(PsiField field, final Project project, final Map<String, PsiType> typeMap) {
final PsiType fieldType = field.getType();
for (String typeName : typeMap.keySet()) {
if (InheritanceUtil.isInheritor(fieldType, typeName)) {
substitute = typeMap.get(typeName);
break;
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(fieldType);
final PsiClass fieldClass = resolveResult.getElement();
if (fieldClass == null) return fieldType;
return CachedValuesManager.getManager(project).getCachedValue(fieldClass, new CachedValueProvider<PsiType>() {
@Nullable
@Override
public Result<PsiType> compute() {
PsiType substitute = null;
for (String typeName : typeMap.keySet()) {
if (InheritanceUtil.isInheritor(fieldType, typeName)) {
substitute = typeMap.get(typeName);
break;
}
}
if (substitute == null) {
final PsiClass aClass = JavaPsiFacade.getInstance(project)
.findClass(JavaFxCommonClassNames.JAVAFX_BEANS_VALUE_OBSERVABLE_VALUE, GlobalSearchScope.allScope(project));
LOG.assertTrue(aClass != null);
final PsiSubstitutor substitutor =
TypeConversionUtil.getSuperClassSubstitutor(aClass, fieldClass, resolveResult.getSubstitutor());
final PsiMethod[] values = aClass.findMethodsByName("getValue", false);
substitute = substitutor.substitute(values[0].getReturnType());
}
return Result.create(substitute, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
}
if (substitute == null) {
final PsiClass aClass = JavaPsiFacade.getInstance(project)
.findClass(JavaFxCommonClassNames.JAVAFX_BEANS_VALUE_OBSERVABLE_VALUE, GlobalSearchScope.allScope(project));
LOG.assertTrue(aClass != null);
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(fieldType);
final PsiClass fieldClass = resolveResult.getElement();
LOG.assertTrue(fieldClass != null);
final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(aClass, fieldClass, resolveResult.getSubstitutor());
final PsiMethod[] values = aClass.findMethodsByName("getValue", false);
substitute = substitutor.substitute(values[0].getReturnType());
}
return substitute;
});
}
private static class JavaFxControllerCachedValueProvider implements CachedValueProvider<PsiClass> {
@@ -9,8 +9,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
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.*;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
@@ -224,19 +223,33 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
return XmlAttributeDescriptor.EMPTY;
}
private <T> void collectProperties(List<T> children, Function<PsiField, T> factory, boolean acceptPrimitive) {
final PsiField[] fields = myPsiClass.getAllFields();
if (fields.length > 0) {
for (PsiField field : fields) {
if (field.hasModifierProperty(PsiModifier.STATIC)) continue;
final PsiType fieldType = field.getType();
if (!JavaFxPsiUtil.isReadOnly(myPsiClass, field) &&
InheritanceUtil.isInheritor(fieldType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY) ||
fieldType.equalsToText(CommonClassNames.JAVA_LANG_STRING) ||
(acceptPrimitive && fieldType instanceof PsiPrimitiveType) ||
GenericsHighlightUtil.getCollectionItemType(field.getType(), myPsiClass.getResolveScope()) != null) {
children.add(factory.fun(field));
private <T> void collectProperties(final List<T> children, final Function<PsiField, T> factory, final boolean acceptPrimitive) {
final List<PsiField> fieldList =
CachedValuesManager.getManager(myPsiClass.getProject()).getCachedValue(myPsiClass, new CachedValueProvider<List<PsiField>>() {
@Nullable
@Override
public Result<List<PsiField>> compute() {
List<PsiField> acceptableFields = new ArrayList<PsiField>();
final PsiField[] fields = myPsiClass.getAllFields();
if (fields.length > 0) {
for (PsiField field : fields) {
if (field.hasModifierProperty(PsiModifier.STATIC)) continue;
final PsiType fieldType = field.getType();
if (!JavaFxPsiUtil.isReadOnly(myPsiClass, field) &&
InheritanceUtil.isInheritor(fieldType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY) ||
fieldType.equalsToText(CommonClassNames.JAVA_LANG_STRING) ||
(acceptPrimitive && fieldType instanceof PsiPrimitiveType) ||
GenericsHighlightUtil.getCollectionItemType(field.getType(), myPsiClass.getResolveScope()) != null) {
acceptableFields.add(field);
}
}
}
return Result.create(acceptableFields, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
});
if (fieldList != null) {
for (PsiField field : fieldList) {
children.add(factory.fun(field));
}
}
}