package org.angularjs.codeInsight.tags;
import com.intellij.lang.javascript.psi.stubs.JSImplicitElement;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.html.dtd.HtmlNSDescriptorImpl;
import com.intellij.psi.impl.source.xml.XmlDocumentImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
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.angularjs.codeInsight.DirectiveUtil;
import org.angularjs.codeInsight.attributes.AngularAttributeDescriptor;
import org.angularjs.codeInsight.attributes.AngularJSAttributeDescriptorsProvider;
import org.angularjs.index.AngularIndexUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Dennis.Ushakov
*/
public class AngularJSTagDescriptor implements XmlElementDescriptor {
protected final String myName;
private final JSImplicitElement myDeclaration;
public AngularJSTagDescriptor(String name, JSImplicitElement declaration) {
myName = name;
myDeclaration = declaration;
}
@Override
public String getQualifiedName() {
return myName;
}
@Override
public String getDefaultName() {
return myName;
}
@Override
public XmlElementDescriptor[] getElementsDescriptors(XmlTag context) {
XmlDocumentImpl xmlDocument = PsiTreeUtil.getParentOfType(context, XmlDocumentImpl.class);
if (xmlDocument == null) return EMPTY_ARRAY;
return xmlDocument.getRootTagNSDescriptor().getRootElementsDescriptors(xmlDocument);
}
@Override
public XmlElementDescriptor getElementDescriptor(XmlTag childTag, XmlTag contextTag) {
XmlTag parent = contextTag.getParentTag();
if (parent == null) return null;
final XmlNSDescriptor descriptor = parent.getNSDescriptor(childTag.getNamespace(), true);
return descriptor == null ? null : descriptor.getElementDescriptor(childTag);
}
@Override
public XmlAttributeDescriptor[] getAttributesDescriptors(@Nullable XmlTag context) {
final JSImplicitElement declaration = getDeclaration();
final String string = declaration.getTypeString();
final String attributes = string.split(";", -1)[3];
final String[] split = attributes.split(",");
final XmlAttributeDescriptor[] result;
if (context != null && AngularIndexUtil.hasAngularJS2(context.getProject())) {
result = AngularAttributeDescriptor.getFieldBasedDescriptors(declaration);
} else if (split.length == 1 && split[0].isEmpty()) {
result = XmlAttributeDescriptor.EMPTY;
} else {
result = new XmlAttributeDescriptor[split.length];
for (int i = 0; i < split.length; i++) {
result[i] = new AnyXmlAttributeDescriptor(DirectiveUtil.getAttributeName(split[i]));
}
}
final XmlAttributeDescriptor[] commonAttributes = HtmlNSDescriptorImpl.getCommonAttributeDescriptors(context);
return ArrayUtil.mergeArrays(result, commonAttributes);
}
@Nullable
@Override
public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attribute) {
return getAttributeDescriptor(attribute.getName(), attribute.getParent());
}
@Nullable
@Override
public XmlAttributeDescriptor getAttributeDescriptor(@NonNls final String attributeName, @Nullable XmlTag context) {
final XmlAttributeDescriptor descriptor = ContainerUtil.find(getAttributesDescriptors(context),
descriptor1 -> attributeName.equals(descriptor1.getName()));
if (descriptor != null) return descriptor;
return context != null ? AngularJSAttributeDescriptorsProvider.getAngular2Descriptor(attributeName, context.getProject()) : null;
}
@Override
public XmlNSDescriptor getNSDescriptor() {
return null;
}
@Nullable
@Override
public XmlElementsGroup getTopGroup() {
return null;
}
@Override
public int getContentType() {
return CONTENT_TYPE_ANY;
}
@Nullable
@Override
public String getDefaultValue() {
return null;
}
@Override
public JSImplicitElement getDeclaration() {
return myDeclaration;
}
@Override
public String getName(PsiElement context) {
return getName();
}
@Override
public String getName() {
return myName;
}
@Override
public void init(PsiElement element) {
}
@NotNull
@Override
public Object[] getDependences() {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
}