package com.intellij.javascript.flex.mxml.schema;
import com.intellij.javascript.flex.FlexPredefinedTagNames;
import com.intellij.lang.javascript.JavaScriptSupportLoader;
import com.intellij.openapi.module.Module;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class FxDefinitionBackedDescriptor extends ClassBackedElementDescriptor {
private final XmlTag myXmlTag;
public FxDefinitionBackedDescriptor(Module module, XmlTag xmlTag) {
super(xmlTag.getName(), "", CodeContext.getContext(JavaScriptSupportLoader.MXML_URI3, module), module.getProject());
myXmlTag = xmlTag;
}
@Override
public PsiElement getDeclaration() {
return getDeclarationByFxDefinitionTag(myXmlTag);
}
@Override
public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, @Nullable XmlTag context) {
final ClassBackedElementDescriptor descriptor = getClassBackedDescriptor();
return descriptor == null ? null : descriptor.getAttributeDescriptor(attributeName, context);
}
@Override
public XmlAttributeDescriptor[] getAttributesDescriptors(@Nullable XmlTag _context) {
final ClassBackedElementDescriptor descriptor = getClassBackedDescriptor();
return descriptor == null ? XmlAttributeDescriptor.EMPTY : descriptor.getAttributesDescriptors(_context);
}
@Nullable
private ClassBackedElementDescriptor getClassBackedDescriptor() {
final XmlTag tag = PsiTreeUtil.getParentOfType(getDeclaration(), XmlTag.class);
final XmlTag[] subTags = tag == null ? XmlTag.EMPTY : tag.getSubTags();
if (subTags.length == 1) {
final XmlElementDescriptor descriptor = subTags[0].getDescriptor();
return descriptor instanceof ClassBackedElementDescriptor ? (ClassBackedElementDescriptor)descriptor : null;
}
return null;
}
@Nullable
private static XmlAttributeValue getDeclarationByFxDefinitionTag(final @NotNull XmlTag xmlTag) {
if (!xmlTag.isValid() || xmlTag.getParent() instanceof XmlDocument) {
return null;
}
XmlTag rootTag = xmlTag;
XmlTag parent;
while ((parent = rootTag.getParentTag()) != null) {
rootTag = parent;
}
final XmlTag[] subTags = rootTag.getSubTags();
final XmlTag libraryTag = subTags.length > 0 &&
FlexPredefinedTagNames.LIBRARY.equals(subTags[0].getLocalName()) &&
JavaScriptSupportLoader.MXML_URI3.equals(subTags[0].getNamespace()) ? subTags[0] : null;
final XmlTag[] definitionTags =
libraryTag == null ? XmlTag.EMPTY : libraryTag.findSubTags(CodeContext.DEFINITION_TAG_NAME, JavaScriptSupportLoader.MXML_URI3);
final String localName = xmlTag.getLocalName();
for (final XmlTag definitionTag : definitionTags) {
final XmlAttribute nameAttribute = definitionTag.getAttribute(MxmlLanguageTagsUtil.NAME_ATTRIBUTE);
final XmlAttributeValue attributeValue = nameAttribute == null ? null : nameAttribute.getValueElement();
if (attributeValue != null && localName.equals(attributeValue.getValue())) {
return attributeValue;
}
}
return null;
}
@Nullable
static XmlElementDescriptor getFxDefinitionBackedDescriptor(final @NotNull Module module, final @NotNull XmlTag xmlTag) {
final XmlAttributeValue declaration = getDeclarationByFxDefinitionTag(xmlTag);
if (declaration != null) {
return new FxDefinitionBackedDescriptor(module, xmlTag);
}
return null;
}
}