mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
no XSL in invalid tags
This commit is contained in:
@@ -43,334 +43,347 @@ import java.util.Set;
|
||||
|
||||
public class XsltSupport {
|
||||
|
||||
public static final String XALAN_EXTENSION_PREFIX = "http://xml.apache.org/xalan/";
|
||||
public static final String XSLT_NS = "http://www.w3.org/1999/XSL/Transform";
|
||||
public static final String PLUGIN_EXTENSIONS_NS = "urn:idea:xslt-plugin#extensions";
|
||||
public static final Key<ParameterizedCachedValue<XsltChecker.LanguageLevel, PsiFile>> FORCE_XSLT_KEY = Key.create("FORCE_XSLT");
|
||||
public static final String XALAN_EXTENSION_PREFIX = "http://xml.apache.org/xalan/";
|
||||
public static final String XSLT_NS = "http://www.w3.org/1999/XSL/Transform";
|
||||
public static final String PLUGIN_EXTENSIONS_NS = "urn:idea:xslt-plugin#extensions";
|
||||
public static final Key<ParameterizedCachedValue<XsltChecker.LanguageLevel, PsiFile>> FORCE_XSLT_KEY = Key.create("FORCE_XSLT");
|
||||
|
||||
private static final Map<String, String> XPATH_ATTR_MAP = new THashMap<String, String>(10);
|
||||
private static final Map<String, Set<String>> XPATH_AVT_MAP = new THashMap<String, Set<String>>(10);
|
||||
private static final Map<String, String> XPATH_ATTR_MAP = new THashMap<String, String>(10);
|
||||
private static final Map<String, Set<String>> XPATH_AVT_MAP = new THashMap<String, Set<String>>(10);
|
||||
|
||||
static {
|
||||
XPATH_ATTR_MAP.put("select", "");
|
||||
XPATH_ATTR_MAP.put("match", "");
|
||||
XPATH_ATTR_MAP.put("test", "");
|
||||
XPATH_ATTR_MAP.put("use-when", "");
|
||||
XPATH_ATTR_MAP.put("group-by", "");
|
||||
XPATH_ATTR_MAP.put("group-adjacent", "");
|
||||
XPATH_ATTR_MAP.put("count", "number");
|
||||
XPATH_ATTR_MAP.put("from", "number");
|
||||
XPATH_ATTR_MAP.put("value", "number");
|
||||
XPATH_ATTR_MAP.put("use", "key");
|
||||
static {
|
||||
XPATH_ATTR_MAP.put("select", "");
|
||||
XPATH_ATTR_MAP.put("match", "");
|
||||
XPATH_ATTR_MAP.put("test", "");
|
||||
XPATH_ATTR_MAP.put("use-when", "");
|
||||
XPATH_ATTR_MAP.put("group-by", "");
|
||||
XPATH_ATTR_MAP.put("group-adjacent", "");
|
||||
XPATH_ATTR_MAP.put("count", "number");
|
||||
XPATH_ATTR_MAP.put("from", "number");
|
||||
XPATH_ATTR_MAP.put("value", "number");
|
||||
XPATH_ATTR_MAP.put("use", "key");
|
||||
|
||||
XPATH_AVT_MAP.put("element", new THashSet<String>(Arrays.asList("name", "namespace")));
|
||||
XPATH_AVT_MAP.put("attribute", new THashSet<String>(Arrays.asList("name", "namespace")));
|
||||
XPATH_AVT_MAP.put("namespace", new THashSet<String>(Arrays.asList("name")));
|
||||
XPATH_AVT_MAP.put("processing-instruction", new THashSet<String>(Arrays.asList("name")));
|
||||
XPATH_AVT_MAP.put("element", new THashSet<String>(Arrays.asList("name", "namespace")));
|
||||
XPATH_AVT_MAP.put("attribute", new THashSet<String>(Arrays.asList("name", "namespace")));
|
||||
XPATH_AVT_MAP.put("namespace", new THashSet<String>(Arrays.asList("name")));
|
||||
XPATH_AVT_MAP.put("processing-instruction", new THashSet<String>(Arrays.asList("name")));
|
||||
|
||||
XPATH_AVT_MAP.put("number", new THashSet<String>(Arrays.asList("format", "lang", "letter-value", "grouping-separator", "grouping-size", "ordinal")));
|
||||
XPATH_AVT_MAP.put("sort", new THashSet<String>(Arrays.asList("lang", "data-type", "order", "case-order", "collation")));
|
||||
XPATH_AVT_MAP.put("number", new THashSet<String>(
|
||||
Arrays.asList("format", "lang", "letter-value", "grouping-separator", "grouping-size", "ordinal")));
|
||||
XPATH_AVT_MAP.put("sort", new THashSet<String>(Arrays.asList("lang", "data-type", "order", "case-order", "collation")));
|
||||
|
||||
XPATH_AVT_MAP.put("message", new THashSet<String>(Arrays.asList("terminate")));
|
||||
XPATH_AVT_MAP.put("value-of", new THashSet<String>(Arrays.asList("separator")));
|
||||
XPATH_AVT_MAP.put("message", new THashSet<String>(Arrays.asList("terminate")));
|
||||
XPATH_AVT_MAP.put("value-of", new THashSet<String>(Arrays.asList("separator")));
|
||||
|
||||
XPATH_AVT_MAP.put("result-document", new THashSet<String>(Arrays.asList("format", "href", "method", "byte-order-mark",
|
||||
"cdata-section-elements", "doctype-public", "doctype-system", "encoding", "escape-uri-attributes", "include-content-type",
|
||||
"indent", "media-type", "normalization-form", "omit-xml-declaration", "standalone", "undeclare-prefixes", "output-version")));
|
||||
}
|
||||
XPATH_AVT_MAP.put("result-document", new THashSet<String>(Arrays.asList("format", "href", "method", "byte-order-mark",
|
||||
"cdata-section-elements", "doctype-public", "doctype-system",
|
||||
"encoding", "escape-uri-attributes", "include-content-type",
|
||||
"indent", "media-type", "normalization-form",
|
||||
"omit-xml-declaration", "standalone", "undeclare-prefixes",
|
||||
"output-version")));
|
||||
}
|
||||
|
||||
private XsltSupport() {
|
||||
}
|
||||
private XsltSupport() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiFile[] getFiles(XmlAttribute attribute) {
|
||||
final XmlAttributeValue value = attribute.getValueElement();
|
||||
if (value != null) {
|
||||
final List<PsiFile> files = new SmartList<PsiFile>();
|
||||
InjectedLanguageUtil.enumerate(value, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
if (injectedPsi instanceof XPathFile) {
|
||||
files.add(injectedPsi);
|
||||
}
|
||||
@NotNull
|
||||
public static PsiFile[] getFiles(XmlAttribute attribute) {
|
||||
final XmlAttributeValue value = attribute.getValueElement();
|
||||
if (value != null) {
|
||||
final List<PsiFile> files = new SmartList<PsiFile>();
|
||||
InjectedLanguageUtil.enumerate(value, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
if (injectedPsi instanceof XPathFile) {
|
||||
files.add(injectedPsi);
|
||||
}
|
||||
});
|
||||
return files.isEmpty() ? PsiFile.EMPTY_ARRAY : PsiUtilCore.toPsiFileArray(files);
|
||||
}
|
||||
});
|
||||
return files.isEmpty() ? PsiFile.EMPTY_ARRAY : PsiUtilCore.toPsiFileArray(files);
|
||||
}
|
||||
return PsiFile.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
public static boolean isXsltAttribute(@NotNull XmlAttribute attribute) {
|
||||
return isXsltTag(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isXsltTag(@NotNull XmlTag tag) {
|
||||
if (!tag.isValid()) return false;
|
||||
final String s = tag.getNamespace();
|
||||
return XSLT_NS.equals(s) || s.startsWith(XALAN_EXTENSION_PREFIX);
|
||||
}
|
||||
|
||||
private static boolean isXsltCoreTag(@NotNull XmlTag tag) {
|
||||
return tag.isValid() && XSLT_NS.equals(tag.getNamespace());
|
||||
}
|
||||
|
||||
public static boolean isXPathAttribute(@NotNull XmlAttribute attribute) {
|
||||
if (attribute.getValueElement() == null) return false;
|
||||
|
||||
final String name = attribute.getName();
|
||||
if (isXsltAttribute(attribute)) {
|
||||
final String tagName = attribute.getParent().getLocalName();
|
||||
final String s = XPATH_ATTR_MAP.get(name);
|
||||
if ((s == null || s.length() > 0) && !tagName.equals(s)) {
|
||||
if (!isAttributeValueTemplate(attribute, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return PsiFile.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
public static boolean isXsltAttribute(@NotNull XmlAttribute attribute) {
|
||||
return isXsltTag(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isXsltTag(@NotNull XmlTag tag) {
|
||||
final String s = tag.getNamespace();
|
||||
return XSLT_NS.equals(s) || s.startsWith(XALAN_EXTENSION_PREFIX);
|
||||
}
|
||||
|
||||
private static boolean isXsltCoreTag(@NotNull XmlTag tag) {
|
||||
return tag.isValid() && XSLT_NS.equals(tag.getNamespace());
|
||||
}
|
||||
|
||||
public static boolean isXPathAttribute(@NotNull XmlAttribute attribute) {
|
||||
if (attribute.getValueElement() == null) return false;
|
||||
|
||||
final String name = attribute.getName();
|
||||
if (isXsltAttribute(attribute)) {
|
||||
final String tagName = attribute.getParent().getLocalName();
|
||||
final String s = XPATH_ATTR_MAP.get(name);
|
||||
if ((s == null || s.length() > 0) && !tagName.equals(s)) {
|
||||
if (!isAttributeValueTemplate(attribute, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!isAttributeValueTemplate(attribute, false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final PsiFile file = attribute.getContainingFile();
|
||||
if (file != null) {
|
||||
XsltChecker.LanguageLevel level = getXsltLanguageLevel(file);
|
||||
if (level != XsltChecker.LanguageLevel.NONE) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isAttributeValueTemplate(@NotNull XmlAttribute attribute, boolean isXsltAttribute) {
|
||||
return (!isXsltAttribute || mayBeAVT(attribute)) && getAVTOffset(attribute.getValue(), 0) != -1;
|
||||
}
|
||||
|
||||
public static boolean isVariableOrParamName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isVariableOrParam(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isVariableOrParam(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return ("variable".equals(localName) || "param".equals(localName)) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isVariable(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isVariable(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isVariable(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return "variable".equals(localName) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isParam(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isParam(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isParam(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return "param".equals(localName) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isPatternAttribute(@NotNull XmlAttribute attribute) {
|
||||
if (!isXsltAttribute(attribute)) return false;
|
||||
|
||||
final String name = attribute.getName();
|
||||
if ("match".equals(name)) {
|
||||
return true;
|
||||
} else if ("count".equals(name) || "from".equals(name)) {
|
||||
return "number".equals(attribute.getParent().getLocalName());
|
||||
}
|
||||
else {
|
||||
if (!isAttributeValueTemplate(attribute, false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isTemplateCall(@NotNull XmlTag tag) {
|
||||
return "call-template".equals(tag.getLocalName()) && hasNameAttribute(tag) && isXsltCoreTag(tag);
|
||||
final PsiFile file = attribute.getContainingFile();
|
||||
if (file != null) {
|
||||
XsltChecker.LanguageLevel level = getXsltLanguageLevel(file);
|
||||
if (level != XsltChecker.LanguageLevel.NONE) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isFunction(@NotNull XmlTag tag) {
|
||||
return "function".equals(tag.getLocalName()) && hasNameAttribute(tag) && isXsltCoreTag(tag);
|
||||
private static boolean isAttributeValueTemplate(@NotNull XmlAttribute attribute, boolean isXsltAttribute) {
|
||||
return (!isXsltAttribute || mayBeAVT(attribute)) && getAVTOffset(attribute.getValue(), 0) != -1;
|
||||
}
|
||||
|
||||
public static boolean isVariableOrParamName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isVariableOrParam(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isVariableOrParam(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return ("variable".equals(localName) || "param".equals(localName)) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isVariable(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isVariable(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isVariable(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return "variable".equals(localName) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isParam(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isParam(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isParam(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return "param".equals(localName) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isPatternAttribute(@NotNull XmlAttribute attribute) {
|
||||
if (!isXsltAttribute(attribute)) return false;
|
||||
|
||||
final String name = attribute.getName();
|
||||
if ("match".equals(name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isApplyTemplates(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return "apply-templates".equals(localName) && isXsltCoreTag(tag);
|
||||
else if ("count".equals(name) || "from".equals(name)) {
|
||||
return "number".equals(attribute.getParent().getLocalName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasNameAttribute(@NotNull XmlTag tag) {
|
||||
return tag.getAttribute("name", null) != null;
|
||||
public static boolean isTemplateCall(@NotNull XmlTag tag) {
|
||||
return "call-template".equals(tag.getLocalName()) && hasNameAttribute(tag) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isFunction(@NotNull XmlTag tag) {
|
||||
return "function".equals(tag.getLocalName()) && hasNameAttribute(tag) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isApplyTemplates(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return "apply-templates".equals(localName) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
private static boolean hasNameAttribute(@NotNull XmlTag tag) {
|
||||
return tag.getAttribute("name", null) != null;
|
||||
}
|
||||
|
||||
public static boolean isTemplateCallName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isTemplateCall(attribute.getParent());
|
||||
}
|
||||
|
||||
private static boolean isXsltNameAttribute(@NotNull XmlAttribute attribute) {
|
||||
return "name".equals(attribute.getName()) && isXsltAttribute(attribute);
|
||||
}
|
||||
|
||||
public static boolean isTemplateName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isTemplate(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isFunctionName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isFunction(attribute.getParent());
|
||||
}
|
||||
|
||||
public static boolean isTemplate(@NotNull XmlTag element) {
|
||||
return isTemplate(element, true);
|
||||
}
|
||||
|
||||
public static boolean isTemplate(@NotNull XmlTag element, boolean requireName) {
|
||||
return "template".equals(element.getLocalName()) && (!requireName || hasNameAttribute(element)) && isXsltCoreTag(element);
|
||||
}
|
||||
|
||||
public static boolean isXsltFile(@NotNull PsiFile psiFile) {
|
||||
if (psiFile.getFileType() != StdFileTypes.XML) return false;
|
||||
|
||||
if (!(psiFile instanceof XmlFile)) return false;
|
||||
|
||||
final XsltChecker.LanguageLevel level = getXsltLanguageLevel(psiFile);
|
||||
return level != XsltChecker.LanguageLevel.NONE;
|
||||
}
|
||||
|
||||
public static XsltChecker.LanguageLevel getXsltLanguageLevel(@NotNull PsiFile psiFile) {
|
||||
final CachedValuesManager mgr = CachedValuesManager.getManager(psiFile.getProject());
|
||||
return mgr.getParameterizedCachedValue(psiFile, FORCE_XSLT_KEY, XsltSupportProvider.INSTANCE, false, psiFile);
|
||||
}
|
||||
|
||||
public static boolean isXsltRootTag(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return ("stylesheet".equals(localName) || "transform".equals(localName)) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isTemplateCallParamName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isTemplateCallParam(attribute.getParent());
|
||||
}
|
||||
|
||||
private static boolean isTemplateCallParam(@NotNull XmlTag parent) {
|
||||
return "with-param".equals(parent.getLocalName()) && hasNameAttribute(parent) && isXsltCoreTag(parent);
|
||||
}
|
||||
|
||||
public static boolean isTopLevelElement(XmlTag tag) {
|
||||
XmlTag p = tag;
|
||||
// not really necessary, XSLT doesn't allow literal result elements on top level anyway
|
||||
while ((p = p.getParentTag()) != null) {
|
||||
if (isXsltTag(p)) {
|
||||
return isXsltRootTag(p);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isTemplateCallName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isTemplateCall(attribute.getParent());
|
||||
public static boolean isIncludeOrImportHref(XmlAttribute xmlattribute) {
|
||||
if (xmlattribute == null || !isXsltAttribute(xmlattribute)) return false;
|
||||
final String localName = xmlattribute.getParent().getLocalName();
|
||||
return isIncludeOrImport(localName) && "href".equals(xmlattribute.getName());
|
||||
}
|
||||
|
||||
private static boolean isIncludeOrImport(String localName) {
|
||||
// treat import and include the same. right now it doesn't seem necessary to distinguish them
|
||||
return ("import".equals(localName) || "include".equals(localName));
|
||||
}
|
||||
|
||||
public static boolean isIncludeOrImport(XmlTag tag) {
|
||||
if (tag == null) return false;
|
||||
return isIncludeOrImport(tag.getLocalName()) && isXsltCoreTag(tag) && tag.getAttribute("href", null) != null;
|
||||
}
|
||||
|
||||
public static boolean isImport(XmlTag tag) {
|
||||
if (tag == null) return false;
|
||||
return "import".equals(tag.getLocalName()) && isXsltCoreTag(tag) && tag.getAttribute("href", null) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getAttValueToken(@NotNull XmlAttribute attribute) {
|
||||
final XmlAttributeValue valueElement = attribute.getValueElement();
|
||||
if (valueElement != null) {
|
||||
final PsiElement firstChild = valueElement.getFirstChild();
|
||||
if (firstChild != null) {
|
||||
final PsiElement nextSibling = firstChild.getNextSibling();
|
||||
return nextSibling instanceof XmlToken && ((XmlToken)nextSibling).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN
|
||||
? nextSibling
|
||||
: null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isXsltNameAttribute(@NotNull XmlAttribute attribute) {
|
||||
return "name".equals(attribute.getName()) && isXsltAttribute(attribute);
|
||||
public static boolean isMode(XmlAttribute xmlattribute) {
|
||||
if ("mode".equals(xmlattribute.getName())) {
|
||||
final XmlTag parent = xmlattribute.getParent();
|
||||
return isApplyTemplates(parent) || isTemplate(parent, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isTemplateName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isTemplate(attribute.getParent());
|
||||
public static int getAVTOffset(String value, int i) {
|
||||
do {
|
||||
i = value.indexOf('{', i);
|
||||
if (i != -1 && i == value.indexOf("{{", i)) {
|
||||
i += 2;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (i != -1);
|
||||
return i;
|
||||
}
|
||||
|
||||
public static boolean isFunctionName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isFunction(attribute.getParent());
|
||||
public static boolean mayBeAVT(@NotNull XmlAttribute attribute) {
|
||||
if (isXsltAttribute(attribute)) {
|
||||
final String tagName = attribute.getParent().getLocalName();
|
||||
|
||||
final Set<String> allowedAttrs = XPATH_AVT_MAP.get(tagName);
|
||||
if (allowedAttrs == null) return isExtensionAvtAttribute(attribute);
|
||||
|
||||
return allowedAttrs.contains(attribute.getName());
|
||||
}
|
||||
|
||||
public static boolean isTemplate(@NotNull XmlTag element) {
|
||||
return isTemplate(element, true);
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isTemplate(@NotNull XmlTag element, boolean requireName) {
|
||||
return "template".equals(element.getLocalName()) && (!requireName || hasNameAttribute(element)) && isXsltCoreTag(element);
|
||||
}
|
||||
private static boolean isExtensionAvtAttribute(XmlAttribute attribute) {
|
||||
final String namespace = attribute.getParent().getNamespace();
|
||||
return namespace.startsWith(XALAN_EXTENSION_PREFIX) && "file".equals(attribute.getName());
|
||||
}
|
||||
|
||||
public static boolean isXsltFile(@NotNull PsiFile psiFile) {
|
||||
if (psiFile.getFileType() != StdFileTypes.XML) return false;
|
||||
public static Icon createXsltIcon(Icon icon) {
|
||||
return LayeredIcon.create(icon, XpathIcons.Xslt_filetype_overlay);
|
||||
}
|
||||
|
||||
if (!(psiFile instanceof XmlFile)) return false;
|
||||
private static class XsltSupportProvider implements ParameterizedCachedValueProvider<XsltChecker.LanguageLevel, PsiFile> {
|
||||
public static final ParameterizedCachedValueProvider<XsltChecker.LanguageLevel, PsiFile> INSTANCE = new XsltSupportProvider();
|
||||
|
||||
final XsltChecker.LanguageLevel level = getXsltLanguageLevel(psiFile);
|
||||
return level != XsltChecker.LanguageLevel.NONE;
|
||||
}
|
||||
public CachedValueProvider.Result<XsltChecker.LanguageLevel> compute(PsiFile psiFile) {
|
||||
if (!(psiFile instanceof XmlFile)) {
|
||||
return CachedValueProvider.Result.create(XsltChecker.LanguageLevel.NONE);
|
||||
}
|
||||
|
||||
public static XsltChecker.LanguageLevel getXsltLanguageLevel(@NotNull PsiFile psiFile) {
|
||||
final CachedValuesManager mgr = CachedValuesManager.getManager(psiFile.getProject());
|
||||
return mgr.getParameterizedCachedValue(psiFile, FORCE_XSLT_KEY, XsltSupportProvider.INSTANCE, false, psiFile);
|
||||
}
|
||||
|
||||
public static boolean isXsltRootTag(@NotNull XmlTag tag) {
|
||||
final String localName = tag.getLocalName();
|
||||
return ("stylesheet".equals(localName) || "transform".equals(localName)) && isXsltCoreTag(tag);
|
||||
}
|
||||
|
||||
public static boolean isTemplateCallParamName(@NotNull XmlAttribute attribute) {
|
||||
return isXsltNameAttribute(attribute) && isTemplateCallParam(attribute.getParent());
|
||||
}
|
||||
|
||||
private static boolean isTemplateCallParam(@NotNull XmlTag parent) {
|
||||
return "with-param".equals(parent.getLocalName()) && hasNameAttribute(parent) && isXsltCoreTag(parent);
|
||||
}
|
||||
|
||||
public static boolean isTopLevelElement(XmlTag tag) {
|
||||
XmlTag p = tag;
|
||||
// not really necessary, XSLT doesn't allow literal result elements on top level anyway
|
||||
while ((p = p.getParentTag()) != null) {
|
||||
if (isXsltTag(p)) {
|
||||
return isXsltRootTag(p);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isIncludeOrImportHref(XmlAttribute xmlattribute) {
|
||||
if (xmlattribute == null || !isXsltAttribute(xmlattribute)) return false;
|
||||
final String localName = xmlattribute.getParent().getLocalName();
|
||||
return isIncludeOrImport(localName) && "href".equals(xmlattribute.getName());
|
||||
}
|
||||
|
||||
private static boolean isIncludeOrImport(String localName) {
|
||||
// treat import and include the same. right now it doesn't seem necessary to distinguish them
|
||||
return ("import".equals(localName) || "include".equals(localName));
|
||||
}
|
||||
|
||||
public static boolean isIncludeOrImport(XmlTag tag) {
|
||||
if (tag == null) return false;
|
||||
return isIncludeOrImport(tag.getLocalName()) && isXsltCoreTag(tag) && tag.getAttribute("href", null) != null;
|
||||
}
|
||||
|
||||
public static boolean isImport(XmlTag tag) {
|
||||
if (tag == null) return false;
|
||||
return "import".equals(tag.getLocalName()) && isXsltCoreTag(tag) && tag.getAttribute("href", null) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getAttValueToken(@NotNull XmlAttribute attribute) {
|
||||
final XmlAttributeValue valueElement = attribute.getValueElement();
|
||||
if (valueElement != null) {
|
||||
final PsiElement firstChild = valueElement.getFirstChild();
|
||||
if (firstChild != null) {
|
||||
final PsiElement nextSibling = firstChild.getNextSibling();
|
||||
return nextSibling instanceof XmlToken && ((XmlToken)nextSibling).getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN ? nextSibling : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isMode(XmlAttribute xmlattribute) {
|
||||
if ("mode".equals(xmlattribute.getName())) {
|
||||
final XmlTag parent = xmlattribute.getParent();
|
||||
return isApplyTemplates(parent) || isTemplate(parent, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getAVTOffset(String value, int i) {
|
||||
do {
|
||||
i = value.indexOf('{', i);
|
||||
if (i != -1 && i == value.indexOf("{{", i)) {
|
||||
i += 2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (i != -1);
|
||||
return i;
|
||||
}
|
||||
|
||||
public static boolean mayBeAVT(@NotNull XmlAttribute attribute) {
|
||||
if (isXsltAttribute(attribute)) {
|
||||
final String tagName = attribute.getParent().getLocalName();
|
||||
|
||||
final Set<String> allowedAttrs = XPATH_AVT_MAP.get(tagName);
|
||||
if (allowedAttrs == null) return isExtensionAvtAttribute(attribute);
|
||||
|
||||
return allowedAttrs.contains(attribute.getName());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isExtensionAvtAttribute(XmlAttribute attribute) {
|
||||
final String namespace = attribute.getParent().getNamespace();
|
||||
return namespace.startsWith(XALAN_EXTENSION_PREFIX) && "file".equals(attribute.getName());
|
||||
}
|
||||
|
||||
public static Icon createXsltIcon(Icon icon) {
|
||||
return LayeredIcon.create(icon, XpathIcons.Xslt_filetype_overlay);
|
||||
}
|
||||
|
||||
private static class XsltSupportProvider implements ParameterizedCachedValueProvider<XsltChecker.LanguageLevel, PsiFile> {
|
||||
public static final ParameterizedCachedValueProvider<XsltChecker.LanguageLevel, PsiFile> INSTANCE = new XsltSupportProvider();
|
||||
|
||||
public CachedValueProvider.Result<XsltChecker.LanguageLevel> compute(PsiFile psiFile) {
|
||||
if (!(psiFile instanceof XmlFile)) {
|
||||
return CachedValueProvider.Result.create(XsltChecker.LanguageLevel.NONE);
|
||||
}
|
||||
|
||||
final XmlFile xmlFile = (XmlFile)psiFile;
|
||||
if (psiFile instanceof PsiFileEx) {
|
||||
if (((PsiFileEx)psiFile).isContentsLoaded()) {
|
||||
final XmlDocument doc = xmlFile.getDocument();
|
||||
if (doc != null) {
|
||||
final XmlTag rootTag = doc.getRootTag();
|
||||
if (rootTag != null) {
|
||||
XmlAttribute v;
|
||||
XsltChecker.LanguageLevel level;
|
||||
if (isXsltRootTag(rootTag)) {
|
||||
v = rootTag.getAttribute("version");
|
||||
level = v != null ? XsltChecker.getLanguageLevel(v.getValue()) : XsltChecker.LanguageLevel.NONE;
|
||||
} else {
|
||||
v = rootTag.getAttribute("version", XSLT_NS);
|
||||
level = v != null ? XsltChecker.getLanguageLevel(v.getValue()) : XsltChecker.LanguageLevel.NONE;
|
||||
}
|
||||
return CachedValueProvider.Result.create(level, rootTag);
|
||||
}
|
||||
final XmlFile xmlFile = (XmlFile)psiFile;
|
||||
if (psiFile instanceof PsiFileEx) {
|
||||
if (((PsiFileEx)psiFile).isContentsLoaded()) {
|
||||
final XmlDocument doc = xmlFile.getDocument();
|
||||
if (doc != null) {
|
||||
final XmlTag rootTag = doc.getRootTag();
|
||||
if (rootTag != null) {
|
||||
XmlAttribute v;
|
||||
XsltChecker.LanguageLevel level;
|
||||
if (isXsltRootTag(rootTag)) {
|
||||
v = rootTag.getAttribute("version");
|
||||
level = v != null ? XsltChecker.getLanguageLevel(v.getValue()) : XsltChecker.LanguageLevel.NONE;
|
||||
}
|
||||
else {
|
||||
v = rootTag.getAttribute("version", XSLT_NS);
|
||||
level = v != null ? XsltChecker.getLanguageLevel(v.getValue()) : XsltChecker.LanguageLevel.NONE;
|
||||
}
|
||||
return CachedValueProvider.Result.create(level, rootTag);
|
||||
}
|
||||
}
|
||||
|
||||
final XsltChecker xsltChecker = new XsltChecker();
|
||||
NanoXmlUtil.parseFile(psiFile, xsltChecker);
|
||||
return CachedValueProvider.Result.create(xsltChecker.getLanguageLevel(), psiFile);
|
||||
}
|
||||
}
|
||||
|
||||
final XsltChecker xsltChecker = new XsltChecker();
|
||||
NanoXmlUtil.parseFile(psiFile, xsltChecker);
|
||||
return CachedValueProvider.Result.create(xsltChecker.getLanguageLevel(), psiFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user