diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java index 340bb5bcab5d..37ce955a9f22 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInsight.completion; import com.intellij.application.options.editor.WebEditorOptions; @@ -288,7 +274,7 @@ public class XmlTagInsertHandler implements InsertHandler { if (toInsertCDataEnd) template.addTextSegment("\n]]>"); - if ((!(tag instanceof HtmlTag) || !HtmlUtil.isSingleHtmlTag(tag.getName())) && tag.getAttributes().length == 0) { + if ((!(tag instanceof HtmlTag) || !HtmlUtil.isSingleHtmlTag(tag, true)) && tag.getAttributes().length == 0) { if (WebEditorOptions.getInstance().isAutomaticallyInsertClosingTag()) { final String name = descriptor.getName(tag); if (name != null) { @@ -310,7 +296,7 @@ public class XmlTagInsertHandler implements InsertHandler { } } else if (completionChar == Lookup.AUTO_INSERT_SELECT_CHAR || completionChar == Lookup.NORMAL_SELECT_CHAR || completionChar == Lookup.REPLACE_SELECT_CHAR) { - if (WebEditorOptions.getInstance().isAutomaticallyInsertClosingTag() && isHtmlCode && HtmlUtil.isSingleHtmlTag(tag.getName())) { + if (WebEditorOptions.getInstance().isAutomaticallyInsertClosingTag() && isHtmlCode && HtmlUtil.isSingleHtmlTag(tag, true)) { template.addTextSegment(HtmlUtil.isHtmlTag(tag) ? ">" : closeTag(tag)); } else { diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java index 3f8308e1f7f8..b9c0a41191d7 100644 --- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInsight.editorActions; import com.intellij.application.options.editor.WebEditorOptions; @@ -174,7 +160,7 @@ public class XmlGtTypedHandler extends TypedHandlerDelegate { ((XmlToken)elementAtCaret).getTokenType() == XmlTokenType.XML_TAG_NAME)) { name = name.substring(0, offset - elementAtCaret.getTextOffset()); } - if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(name)) return Result.CONTINUE; + if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(tag, true)) return Result.CONTINUE; if (name.isEmpty()) return Result.CONTINUE; int tagOffset = tag.getTextRange().getStartOffset(); diff --git a/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlExtraClosingTagInspection.java b/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlExtraClosingTagInspection.java index 6c1c8c152b2c..581ae7426c46 100644 --- a/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlExtraClosingTagInspection.java +++ b/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlExtraClosingTagInspection.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2013 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInspection.htmlInspections; @@ -53,7 +39,8 @@ public class HtmlExtraClosingTagInspection extends HtmlLocalInspectionTool { protected void checkTag(@NotNull final XmlTag tag, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) { final TextRange range = XmlTagUtil.getEndTagRange(tag); - if (range != null && tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(tag.getName()) && tag.getLanguage().isKindOf(HTMLLanguage.INSTANCE)) { + if (range != null && tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(tag, true) + && tag.getLanguage().isKindOf(HTMLLanguage.INSTANCE)) { holder.registerProblem(tag, XmlErrorMessages.message("extra.closing.tag.for.empty.element"), ProblemHighlightType.LIKE_UNUSED_SYMBOL, range.shiftRight(-tag.getTextRange().getStartOffset()), new RemoveExtraClosingTagIntentionAction()); } diff --git a/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlMissingClosingTagInspection.java b/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlMissingClosingTagInspection.java index 10302e24e98a..dd9bcd6c2aa1 100644 --- a/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlMissingClosingTagInspection.java +++ b/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlMissingClosingTagInspection.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInspection.htmlInspections; import com.intellij.codeInsight.daemon.XmlErrorMessages; @@ -55,7 +41,7 @@ public class HtmlMissingClosingTagInspection extends HtmlLocalInspectionTool { return; } final String tagName = tagNameElement.getText(); - if (HtmlUtil.isSingleHtmlTag(tagName) || XmlTagUtil.getEndTagNameElement(tag) != null) { + if (HtmlUtil.isSingleHtmlTag(tag, true) || XmlTagUtil.getEndTagNameElement(tag) != null) { return; } diff --git a/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongClosingTagNameInspection.java b/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongClosingTagNameInspection.java index 0623926b7f59..0e31de55e925 100644 --- a/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongClosingTagNameInspection.java +++ b/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/XmlWrongClosingTagNameInspection.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInspection.htmlInspections; @@ -55,7 +41,7 @@ public class XmlWrongClosingTagNameInspection implements Annotator { if (endTagName != null && !(tag instanceof HtmlTag) && !tag.getName().equals(endTagName.getText())) { registerProblemStart(holder, tag, start, endTagName); } - else if (endTagName == null && !(tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(tag.getName()))) { + else if (endTagName == null && !(tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(tag, true))) { final PsiErrorElement errorElement = PsiTreeUtil.getChildOfType(tag, PsiErrorElement.class); endTagName = findEndTagName(errorElement); if (endTagName != null) { diff --git a/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java b/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java index 7889d6eefb13..92c5b789ecfe 100644 --- a/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java +++ b/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java @@ -69,7 +69,7 @@ public class CheckEmptyTagInspection extends XmlSuppressableInspectionTool { (language.isKindOf(HTMLLanguage.INSTANCE) || language.isKindOf(XHTMLLanguage.INSTANCE)) || (language.isKindOf(HTMLLanguage.INSTANCE) && - !HtmlUtil.isSingleHtmlTagL(tagName) && + !HtmlUtil.isSingleHtmlTag(tag, false) && tagName.indexOf(':') == -1 && !XmlExtension.isCollapsible(tag)); } diff --git a/xml/xml-psi-impl/src/com/intellij/lang/html/HTMLParser.java b/xml/xml-psi-impl/src/com/intellij/lang/html/HTMLParser.java index 89bb48e4fc85..aedaa2b297e5 100644 --- a/xml/xml-psi-impl/src/com/intellij/lang/html/HTMLParser.java +++ b/xml/xml-psi-impl/src/com/intellij/lang/html/HTMLParser.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. /* * @author max @@ -30,15 +16,26 @@ public class HTMLParser implements PsiParser { @Override @NotNull - public ASTNode parse(final IElementType root, final PsiBuilder builder) { - parseWithoutBuildingTree(root, builder); + public ASTNode parse(@NotNull final IElementType root, @NotNull final PsiBuilder builder) { + parseWithoutBuildingTree(root, builder, createHtmlParsing(builder)); return builder.getTreeBuilt(); } - public static void parseWithoutBuildingTree(IElementType root, PsiBuilder builder) { + public static void parseWithoutBuildingTree(@NotNull IElementType root, @NotNull PsiBuilder builder) { + parseWithoutBuildingTree(root, builder, new HtmlParsing(builder)); + } + + private static void parseWithoutBuildingTree(@NotNull IElementType root, @NotNull PsiBuilder builder, + @NotNull HtmlParsing htmlParsing) { builder.enforceCommentTokens(TokenSet.EMPTY); final PsiBuilder.Marker file = builder.mark(); - new HtmlParsing(builder).parseDocument(); + htmlParsing.parseDocument(); file.done(root); } + + // to be able to manage what tags treated as single + @NotNull + protected HtmlParsing createHtmlParsing(@NotNull PsiBuilder builder) { + return new HtmlParsing(builder); + } } \ No newline at end of file diff --git a/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java b/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java index b56e759593c9..de4d81b4bd5f 100644 --- a/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java +++ b/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2009 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. /* * @author max @@ -181,7 +167,7 @@ public class HtmlParsing { continue; } - if (HtmlUtil.isSingleHtmlTagL(tagName)) { + if (originalTagName != null && isSingleTag(tagName, originalTagName)) { final PsiBuilder.Marker footer = mark(); if (token() == XmlTokenType.XML_END_TAG_START) { advance(); @@ -290,6 +276,10 @@ public class HtmlParsing { } } + protected boolean isSingleTag(@NotNull String tagName, @NotNull String originalTagName) { + return HtmlUtil.isSingleHtmlTagL(tagName); + } + private boolean hasTags() { return !myTagNamesStack.isEmpty(); } diff --git a/xml/xml-psi-impl/src/com/intellij/xml/XmlExtension.java b/xml/xml-psi-impl/src/com/intellij/xml/XmlExtension.java index 2caa19441237..28d4499bc55f 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/XmlExtension.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/XmlExtension.java @@ -192,6 +192,8 @@ public abstract class XmlExtension { return false; } + public boolean isSingleTagException(@NotNull String name) { return false; } + public static boolean shouldIgnoreSelfClosingTag(@NotNull XmlTag tag) { final XmlExtension extension = getExtensionByElement(tag); return extension != null && extension.isSelfClosingTagAllowed(tag); 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 ae87cd4f1b95..c7990ad76131 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 @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.xml.util; import com.intellij.codeInspection.InspectionProfile; @@ -51,10 +37,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.*; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; -import com.intellij.xml.Html5SchemaProvider; -import com.intellij.xml.XmlAttributeDescriptor; -import com.intellij.xml.XmlElementDescriptor; -import com.intellij.xml.XmlNSDescriptor; +import com.intellij.xml.*; import com.intellij.xml.impl.schema.XmlAttributeDescriptorImpl; import com.intellij.xml.impl.schema.XmlElementDescriptorImpl; import com.intellij.xml.util.documentation.MimeTypeDictionary; @@ -150,6 +133,13 @@ public class HtmlUtil { ContainerUtil.addAll(HTML5_TAGS_SET, HTML5_TAGS); } + public static boolean isSingleHtmlTag(@NotNull XmlTag tag, boolean lowerCase) { + final XmlExtension extension = XmlExtension.getExtensionByElement(tag); + final String name = tag.getName(); + boolean result = EMPTY_TAGS_MAP.contains(lowerCase ? name.toLowerCase(Locale.US) : name); + return result && (extension == null || !extension.isSingleTagException(name)); + } + public static boolean isSingleHtmlTag(String tagName) { return EMPTY_TAGS_MAP.contains(tagName.toLowerCase(Locale.US)); }