fill in empty tags from R# schema

#WEB-6626 fixed
This commit is contained in:
Dennis Ushakov
2014-01-31 13:28:29 +04:00
parent f485ada0b5
commit 1ff8ae8a98
3 changed files with 273 additions and 4 deletions
@@ -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<String> autoClosedBy = Collections.emptyList();
}
private static class TagStateConverter extends Converter<TagState> {
@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<List<String>> {
@Nullable
@Override
public List<String> fromString(@NotNull String value) {
return StringUtil.split(value, ",");
}
@NotNull
@Override
public String toString(@NotNull List<String> o) {
return StringUtil.join(o, ", ");
}
}
}
@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8" ?>
<htmlControls namespace="System.Web.UI.HtmlControls">
<control name="A" type="HtmlAnchor" startTag="required" endTag="Required" emptyAllowed="false">
<attribute name="href" type="%URL" />
</control>
<control name="Acronym" type="HtmlGenericControl" startTag="required" endTag="Required" emptyAllowed="false"/>
<control name="address" type="HtmlGenericControl" startTag="required" endTag="Required" emptyAllowed="false"/>
<control name="applet" type="HtmlGenericControl" startTag="required" endTag="Required" emptyAllowed="false">
<attribute name="codetype" type="%URL" />
</control>
<control name="area" type="HtmlGenericControl" startTag="required" endTag="Forbidden" emptyAllowed="true">
<attribute name="href" type="%URL" />
</control>
<control name="B" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="base" type="HtmlGenericControl" startTag="required" endTag="Forbidden" emptyAllowed="true">
<attribute name="codetype" type="%URL" />
</control>
<control name="baseFont" type="HtmlGenericControl" startTag="required" endTag="Forbidden" emptyAllowed="true"/>
<control name="bdo" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="big" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="blockQuote" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
<attribute name="cite" type="%URL" />
</control>
<control name="body" type="HtmlGenericControl" startTag="optional" endTag="optional" emptyAllowed="false" onlyOnce="true" />
<control name="br" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
<control name="button" type="HtmlButton" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="Caption" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="center" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="cite" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="code" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="col" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
<control name="colGroup" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="colGroup"/>
<control name="DD" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="dt, dd"/>
<control name="del" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
<attribute name="cite" type="%URL" />
</control>
<control name="dfn" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="dir" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="div" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="dl" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="dt" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="dt, dd"/>
<control name="EM" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="embed" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="true" />
<control name="FieldSet" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="font" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="form" type="HtmlForm" startTag="required" endTag="required" emptyAllowed="false">
<attribute name="action" type="%URL" />
</control>
<control name="frame" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true">
<attribute name="src" type="%URL" />
</control>
<control name="frameSet" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="H1" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="H2" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="H3" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="H4" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="H5" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="H6" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="head" type="HtmlHead" startTag="optional" endTag="optional" emptyAllowed="false" onlyOnce="true" autoClosedBy="body">
<attribute name="profile" type="%URL" />
</control>
<control name="hr" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
<control name="html" type="HtmlGenericControl" startTag="optional" endTag="optional" emptyAllowed="false" onlyOnce="true" />
<control name="I" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="IFrame" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
<attribute name="src" type="%URL" />
</control>
<control name="img" type="HtmlImage" startTag="required" endTag="forbidden" emptyAllowed="true">
<attribute name="src" type="%URL" />
<attribute name="usemap" type="%URL" />
</control>
<control name="input" startTag="required" endTag="forbidden" emptyAllowed="true">
<type name="HtmlInputButton" typeAttribute="BUTTON|SUBMIT|RESET" />
<type name="HtmlInputCheckBox" typeAttribute="CheckBox" />
<type name="HtmlInputFile" typeAttribute="file" />
<type name="HtmlInputHidden" typeAttribute="hidden" />
<type name="HtmlInputImage" typeAttribute="image" />
<type name="HtmlInputRadioButton" typeAttribute="radio" />
<type name="HtmlInputText" typeAttribute="TEXT|PASSWORD" />
</control>
<control name="ins" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
<attribute name="cite" type="%URL" />
</control>
<control name="isIndex" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
<control name="KBD" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="Label" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="legend" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="li" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="li"/>
<control name="link" type="HtmlLink" startTag="required" endTag="forbidden" emptyAllowed="true">
<attribute name="href" type="%URL" />
</control>
<control name="Map" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="menu" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="meta" type="HtmlMeta" startTag="required" endTag="forbidden" emptyAllowed="true"/>
<control name="noembed" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="true"/>
<control name="NoFrames" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="noScript" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="nobr" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="Object" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
<attribute name="classid" type="%URL" />
<attribute name="codebase" type="%URL" />
<attribute name="data" type="%URL" />
<attribute name="name" type="%URL" />
<attribute name="usemap" type="%URL" />
</control>
<control name="ol" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="option" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="option"/>
<control name="P" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="p"/>
<control name="param" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
<control name="pre" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="Q" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
<attribute name="cite" type="%URL" />
</control>
<control name="S" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="samp" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="script" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="select" type="HtmlSelect" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="small" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="source" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true">
<attribute name="src" type="%URL" />
</control>
<control name="span" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="strike" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="strong" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="style" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="sub" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="sup" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="Table" type="HtmlTable" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="tbody" type="HtmlGenericControl" startTag="optional" endTag="optional" emptyAllowed="false" autoClosedBy="tfoot, thead, tbody"/>
<control name="td" type="HtmlTableCell" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="td, th"/>
<control name="textArea" type="HtmlTextArea" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="tfoot" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="tfoot, thead, tbody"/>
<control name="th" type="HtmlTableCell" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="td, th"/>
<control name="thead" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="tfoot, thead, tbody"/>
<control name="title" type="HtmlTitle" startTag="required" endTag="required" emptyAllowed="false" onlyOnce="true" />
<control name="tr" type="HtmlTableRow" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="tr"/>
<control name="track" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true" />
<control name="tt" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="U" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="UL" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="VAR" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
<control name="wbr" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
</htmlControls>
@@ -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<String> EMPTY_TAGS_MAP = new THashSet<String>();
@NonNls private static final String[] OPTIONAL_END_TAGS = {
//"html",
@@ -150,7 +147,10 @@ public class HtmlUtil {
private static final Set<String> HTML5_TAGS_SET = new THashSet<String>();
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);