vue: Col component should be processed deeply

- when parsing Vue files, distinguish between single html tag "col" and possible (for example, defined in iview) tag "Col"
- for parsing, allow to override HtmlParsing isSingleTag method
- for html-tag-related inspections, create new XmlExtension method isSingleTagException to exclude some of html single tags for this xml dialect,
- and introduce new HtmlUtil isSingleTag method, which would take dialect into account
- vue highlighting filter is not needed any more

relates to WEB-31108 "closing tag matches nothing" shows on the correct tag of vue file
This commit is contained in:
Irina.Chernushina
2018-03-01 18:55:00 +01:00
parent dd60293bac
commit bf36bd9aac
10 changed files with 46 additions and 136 deletions
@@ -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<LookupElement> {
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<LookupElement> {
}
}
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 {
@@ -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();
@@ -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());
}
@@ -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;
}
@@ -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) {
@@ -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));
}
@@ -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);
}
}
@@ -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();
}
@@ -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);
@@ -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));
}