From 1ff8ae8a98ac43dbb0f648fa517117ff1872d8a8 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 29 Jan 2014 21:04:59 +0400 Subject: [PATCH] fill in empty tags from R# schema #WEB-6626 fixed --- .../com/intellij/xml/util/HTMLControls.java | 109 ++++++++++++ .../com/intellij/xml/util/HtmlControls.xml | 160 ++++++++++++++++++ .../src/com/intellij/xml/util/HtmlUtil.java | 8 +- 3 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 xml/xml-psi-impl/src/com/intellij/xml/util/HTMLControls.java create mode 100644 xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HTMLControls.java b/xml/xml-psi-impl/src/com/intellij/xml/util/HTMLControls.java new file mode 100644 index 000000000000..38f798eedb7a --- /dev/null +++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HTMLControls.java @@ -0,0 +1,109 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.xml.util; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.util.xmlb.Converter; +import com.intellij.util.xmlb.XmlSerializer; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Tag; +import org.jdom.Document; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.InputStream; +import java.util.Collections; +import java.util.List; + +/** + * @author Dennis.Ushakov + */ +public class HTMLControls { + private static Logger LOG = Logger.getInstance(HTMLControls.class); + private static Control[] ourControls; + + public static Control[] getControls() { + if (ourControls == null) { + ourControls = loadControls(); + } + return ourControls; + } + + private static Control[] loadControls() { + Document document; + try { + @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") + final InputStream stream = HTMLControls.class.getResourceAsStream("HtmlControls.xml"); + document = JDOMUtil.loadDocument(CharsetToolkit.inputStreamSkippingBOM(stream)); + stream.close(); + } + catch (Exception e) { + LOG.error(e); + return new Control[0]; + } + if (!document.getRootElement().getName().equals("htmlControls")) { + LOG.error("HTMLControls storage is broken"); + } + return XmlSerializer.deserialize(document, Control[].class); + } + + public enum TagState { REQUIRED, OPTIONAL, FORBIDDEN } + + @Tag("control") + public static class Control { + @Attribute("name") + public String name; + @Attribute(value = "startTag", converter = TagStateConverter.class) + public TagState startTag; + @Attribute(value = "endTag", converter = TagStateConverter.class) + public TagState endTag; + @Attribute("emptyAllowed") + public boolean emptyAllowed; + @Attribute(value = "autoClosedBy", converter = AutoCloseConverter.class) + public List autoClosedBy = Collections.emptyList(); + } + + private static class TagStateConverter extends Converter { + @Nullable + @Override + public TagState fromString(@NotNull String value) { + return TagState.valueOf(value.toUpperCase()); + } + + @NotNull + @Override + public String toString(@NotNull TagState state) { + return state.name().toLowerCase(); + } + } + + private static class AutoCloseConverter extends Converter> { + @Nullable + @Override + public List fromString(@NotNull String value) { + return StringUtil.split(value, ","); + } + + @NotNull + @Override + public String toString(@NotNull List o) { + return StringUtil.join(o, ", "); + } + } +} diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml new file mode 100644 index 000000000000..4dc51494808f --- /dev/null +++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java index 15ff3f19a379..eb6bbd74cc12 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java @@ -104,9 +104,6 @@ public class HtmlUtil { private HtmlUtil() { } - @NonNls private static final String[] EMPTY_TAGS = { - "base", "hr", "meta", "link", "frame", "br", "basefont", "param", "img", "area", "input", "isindex", "col", /*html 5*/ "source", "wbr" - }; private static final Set EMPTY_TAGS_MAP = new THashSet(); @NonNls private static final String[] OPTIONAL_END_TAGS = { //"html", @@ -150,7 +147,10 @@ public class HtmlUtil { private static final Set HTML5_TAGS_SET = new THashSet(); static { - ContainerUtil.addAll(EMPTY_TAGS_MAP, EMPTY_TAGS); + for (HTMLControls.Control control : HTMLControls.getControls()) { + final String tagName = control.name.toLowerCase(); + if (control.endTag == HTMLControls.TagState.FORBIDDEN) EMPTY_TAGS_MAP.add(tagName); + } ContainerUtil.addAll(EMPTY_ATTRS_MAP, EMPTY_ATTRS); ContainerUtil.addAll(OPTIONAL_END_TAGS_MAP, OPTIONAL_END_TAGS); ContainerUtil.addAll(BLOCK_TAGS_MAP, BLOCK_TAGS);