package org.jetbrains.plugins.javaFX.fxml.descriptors; import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import com.intellij.xml.XmlAttributeDescriptor; import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.XmlElementsGroup; import com.intellij.xml.XmlNSDescriptor; import com.intellij.xml.impl.schema.AnyXmlAttributeDescriptor; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.javaFX.fxml.FxmlConstants; import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames; import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil; import java.util.ArrayList; import java.util.List; /** * User: anna * Date: 1/10/13 */ public class JavaFxPropertyElementDescriptor implements XmlElementDescriptor { private final PsiClass myPsiClass; private final String myName; private final boolean myStatic; public JavaFxPropertyElementDescriptor(PsiClass psiClass, String name, boolean isStatic) { myPsiClass = psiClass; myName = name; myStatic = isStatic; } public boolean isStatic() { return myStatic; } @Override public String getQualifiedName() { return getName(); } @Override public String getDefaultName() { return getName(); } @Override public XmlElementDescriptor[] getElementsDescriptors(XmlTag context) { final PsiElement declaration = getDeclaration(); if (declaration instanceof PsiField) { final PsiType psiType = ((PsiField)declaration).getType(); final ArrayList descriptors = new ArrayList(); collectDescriptorsByCollection(psiType, declaration.getResolveScope(), descriptors, declaration.getProject()); for (String name : FxmlConstants.FX_DEFAULT_ELEMENTS) { descriptors.add(new JavaFxDefaultPropertyElementDescriptor(name, null)); } if (!descriptors.isEmpty()) return descriptors.toArray(new XmlElementDescriptor[descriptors.size()]); } return XmlElementDescriptor.EMPTY_ARRAY; } public static void collectDescriptorsByCollection(PsiType psiType, GlobalSearchScope resolveScope, final List descriptors, final Project project) { final PsiType collectionItemType = JavaGenericsUtil.getCollectionItemType(psiType, resolveScope); if (collectionItemType != null) { final PsiClass aClass = PsiUtil.resolveClassInType(collectionItemType); if (aClass != null) { ClassInheritorsSearch.search(aClass, aClass.getUseScope(), true, true, false).forEach(new Processor() { @Override public boolean process(PsiClass aClass) { descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass)); return true; } }); descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass)); } } else if (InheritanceUtil.isInheritor(psiType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY)) { final PsiType propertyType = JavaFxPsiUtil.getPropertyType(psiType, project); final PsiClass aClass = PsiUtil.resolveClassInType(propertyType); if (aClass != null) { descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass)); } } } @Nullable @Override public XmlElementDescriptor getElementDescriptor(XmlTag childTag, XmlTag contextTag) { final String name = childTag.getName(); if (FxmlConstants.FX_DEFAULT_ELEMENTS.contains(name)) { return new JavaFxDefaultPropertyElementDescriptor(name, childTag); } return new JavaFxClassBackedElementDescriptor(name, childTag); } @Override public XmlAttributeDescriptor[] getAttributesDescriptors(@Nullable XmlTag context) { return XmlAttributeDescriptor.EMPTY; } @Nullable @Override public XmlAttributeDescriptor getAttributeDescriptor(@NonNls String attributeName, @Nullable XmlTag context) { final PsiElement element = getDeclaration(); if (element instanceof PsiField) { final PsiType type = ((PsiField)element).getType(); if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) { return new AnyXmlAttributeDescriptor(attributeName); } } return null; } @Nullable @Override public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attribute) { return getAttributeDescriptor(attribute.getName(), attribute.getParent()); } @Override public XmlNSDescriptor getNSDescriptor() { return null; } @Nullable @Override public XmlElementsGroup getTopGroup() { return null; } @Override public int getContentType() { return CONTENT_TYPE_UNKNOWN; } @Nullable @Override public String getDefaultValue() { return null; } @Override public PsiElement getDeclaration() { if (myPsiClass == null) return null; final PsiField field = myPsiClass.findFieldByName(myName, true); if (field != null) { return field; } return JavaFxPsiUtil.findPropertySetter(myName, myPsiClass); } @Override public String getName(PsiElement context) { return getName(); } @Override public String getName() { if (myPsiClass != null && myStatic) { return StringUtil.getQualifiedName(myPsiClass.getName(), myName); } return myName; } @Override public void init(PsiElement element) {} @Override public Object[] getDependences() { return ArrayUtil.EMPTY_OBJECT_ARRAY; } }