mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
HTML: add unknown boolean attribute inspection
This commit is contained in:
@@ -71,10 +71,13 @@ html.inspections.non.existent.internet.resource.name=Non-existent web resource
|
||||
|
||||
html.inspections.unknown.tag=Unknown HTML tag
|
||||
html.inspections.unknown.attribute=Unknown HTML tag attribute
|
||||
html.inspections.unknown.boolean.attribute=Unknown HTML boolean tag attribute
|
||||
html.inspections.unknown.tag.checkbox.title=Custom HTML tags:
|
||||
html.inspections.unknown.tag.title=Edit custom tags
|
||||
html.inspections.unknown.tag.attribute.checkbox.title=Custom HTML tag attributes:
|
||||
html.inspections.unknown.tag.boolean.attribute.checkbox.title=Custom HTML boolean tag attributes:
|
||||
html.inspections.unknown.tag.attribute.title=Edit custom attributes
|
||||
html.inspections.unknown.tag.boolean.attribute.title=Edit custom boolean attributes
|
||||
xml.schema.create.complex.type.intention.name=Create Complex Type {0}
|
||||
xml.schema.create.attribute.intention.name=Create Attribute {0}
|
||||
xml.schema.create.element.intention.name=Create Element {0}
|
||||
@@ -130,6 +133,7 @@ no.ignored.resources=No ignored resources
|
||||
custom.html.tag=Custom Html Tag
|
||||
add.custom.html.tag=Add {0} to custom html tags
|
||||
add.custom.html.attribute=Add {0} to custom html attributes
|
||||
add.custom.html.boolean.attribute=Add {0} to custom html boolean attributes
|
||||
add.optional.html.attribute=Add {0} to not required html attributes
|
||||
fix.html.family=Fix Html
|
||||
|
||||
|
||||
@@ -421,6 +421,9 @@
|
||||
<localInspection language="XML" shortName="HtmlUnknownAttribute" bundle="messages.XmlBundle" key="html.inspections.unknown.attribute" groupName="HTML"
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.htmlInspections.HtmlUnknownAttributeInspection"/>
|
||||
<localInspection language="XML" bundle="messages.XmlBundle" key="html.inspections.unknown.boolean.attribute" groupName="HTML"
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.htmlInspections.HtmlUnknownBooleanAttributeInspection"/>
|
||||
<localInspection language="XML" shortName="XmlUnboundNsPrefix" bundle="messages.XmlBundle" key="xml.inspections.unbound.prefix"
|
||||
groupKey="xml.inspections.group.name" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlUnboundNsPrefixInspection"/>
|
||||
|
||||
@@ -17,7 +17,9 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.CreateNSDeclarationIntentionFix;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.InsertRequiredAttributeFix;
|
||||
import com.intellij.codeInspection.htmlInspections.AddAttributeValueIntentionFix;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.psi.xml.XmlToken;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -35,4 +37,10 @@ public class XmlQuickFixFactoryImpl extends XmlQuickFixFactory {
|
||||
public LocalQuickFix createNSDeclarationIntentionFix(@NotNull PsiElement element, @NotNull String namespacePrefix, @Nullable XmlToken token) {
|
||||
return new CreateNSDeclarationIntentionFix(element, namespacePrefix, token);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LocalQuickFixAndIntentionActionOnPsiElement addAttributeValueFix(@NotNull XmlAttribute attribute) {
|
||||
return new AddAttributeValueIntentionFix(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.intellij.codeInspection.htmlInspections;
|
||||
|
||||
import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.XmlErrorMessages;
|
||||
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.XmlElementFactory;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AddAttributeValueIntentionFix extends LocalQuickFixAndIntentionActionOnPsiElement {
|
||||
public AddAttributeValueIntentionFix(@Nullable PsiElement element) {
|
||||
super(element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return XmlErrorMessages.message("add.attribute.value.quickfix.text");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@Nullable("is null when called from inspection") final Editor editor,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
final XmlAttribute attribute = PsiTreeUtil.getNonStrictParentOfType(startElement, XmlAttribute.class);
|
||||
if (attribute == null || attribute.getValue() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(attribute.getContainingFile())) {
|
||||
return;
|
||||
}
|
||||
|
||||
new WriteCommandAction(project) {
|
||||
@Override
|
||||
protected void run(@NotNull final Result result) {
|
||||
final XmlAttribute attributeWithValue = XmlElementFactory.getInstance(getProject()).createXmlAttribute(attribute.getName(), "");
|
||||
final PsiElement newAttribute = attribute.replace(attributeWithValue);
|
||||
|
||||
if (editor != null && newAttribute != null && newAttribute instanceof XmlAttribute && newAttribute.isValid()) {
|
||||
final XmlAttributeValue valueElement = ((XmlAttribute)newAttribute).getValueElement();
|
||||
if (valueElement != null) {
|
||||
editor.getCaretModel().moveToOffset(valueElement.getTextOffset());
|
||||
AutoPopupController.getInstance(newAttribute.getProject()).scheduleAutoPopup(editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.intellij.codeInspection.htmlInspections;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class HtmlUnknownBooleanAttributeInspection extends HtmlUnknownBooleanAttributeInspectionBase {
|
||||
|
||||
public HtmlUnknownBooleanAttributeInspection() {
|
||||
super("");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
return HtmlUnknownTagInspection.createOptionsPanel(this);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.psi.xml.XmlToken;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -34,4 +35,7 @@ public abstract class XmlQuickFixFactory {
|
||||
public abstract LocalQuickFix createNSDeclarationIntentionFix(@NotNull final PsiElement element,
|
||||
@NotNull String namespacePrefix,
|
||||
@Nullable final XmlToken token);
|
||||
|
||||
@NotNull
|
||||
public abstract LocalQuickFixAndIntentionActionOnPsiElement addAttributeValueFix(@NotNull XmlAttribute attribute);
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<body>
|
||||
This inspection highlights HTML none-boolean tag attributes without value as invalid, and lets mark such attributes as Custom to avoid highlighting them as
|
||||
invalid.<br>
|
||||
</body>
|
||||
</html>
|
||||
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.intention.QuickFixes;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.psi.xml.XmlToken;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -38,4 +39,10 @@ public class EmptyXmlQuickFixFactory extends XmlQuickFixFactory {
|
||||
@Nullable XmlToken token) {
|
||||
return QuickFixes.EMPTY_ACTION;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LocalQuickFixAndIntentionActionOnPsiElement addAttributeValueFix(@NotNull XmlAttribute attribute) {
|
||||
return QuickFixes.EMPTY_FIX;
|
||||
}
|
||||
}
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.codeInspection.htmlInspections;
|
||||
|
||||
import com.intellij.codeInsight.daemon.XmlErrorMessages;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.codeInspection.XmlQuickFixFactory;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.html.HtmlTag;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.xml.XmlAttributeDescriptor;
|
||||
import com.intellij.xml.XmlBundle;
|
||||
import com.intellij.xml.XmlElementDescriptor;
|
||||
import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
|
||||
import com.intellij.xml.util.HtmlUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class HtmlUnknownBooleanAttributeInspectionBase extends HtmlUnknownElementInspection {
|
||||
private static final Key<HtmlUnknownElementInspection> BOOLEAN_ATTRIBUTE_KEY = Key.create(BOOLEAN_ATTRIBUTE_SHORT_NAME);
|
||||
private static final Logger LOG = Logger.getInstance(HtmlUnknownBooleanAttributeInspectionBase.class);
|
||||
|
||||
public HtmlUnknownBooleanAttributeInspectionBase(String defaultValues) {
|
||||
super(defaultValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nls
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return XmlBundle.message("html.inspections.unknown.boolean.attribute");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNls
|
||||
@NotNull
|
||||
public String getShortName() {
|
||||
return BOOLEAN_ATTRIBUTE_SHORT_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCheckboxTitle() {
|
||||
return XmlBundle.message("html.inspections.unknown.tag.boolean.attribute.checkbox.title");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getPanelTitle() {
|
||||
return XmlBundle.message("html.inspections.unknown.tag.boolean.attribute.title");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected Logger getLogger() {
|
||||
return LOG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkAttribute(@NotNull final XmlAttribute attribute, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
|
||||
if (attribute.getValueElement() == null) {
|
||||
final XmlTag tag = attribute.getParent();
|
||||
|
||||
if (tag instanceof HtmlTag) {
|
||||
XmlElementDescriptor elementDescriptor = tag.getDescriptor();
|
||||
if (elementDescriptor == null || elementDescriptor instanceof AnyXmlElementDescriptor) {
|
||||
return;
|
||||
}
|
||||
|
||||
XmlAttributeDescriptor attributeDescriptor = elementDescriptor.getAttributeDescriptor(attribute);
|
||||
if (attributeDescriptor != null) {
|
||||
String name = attribute.getName();
|
||||
if (!HtmlUtil.isBooleanAttribute(attributeDescriptor) && (!isCustomValuesEnabled() || !isCustomValue(name))) {
|
||||
LocalQuickFix[] quickFixes = new LocalQuickFix[]{
|
||||
new AddCustomHtmlElementIntentionAction(BOOLEAN_ATTRIBUTE_KEY, name, XmlBundle.message("add.custom.html.boolean.attribute", name)),
|
||||
XmlQuickFixFactory.getInstance().addAttributeValueFix(attribute),
|
||||
new RemoveAttributeIntentionAction(name),
|
||||
};
|
||||
|
||||
registerProblemOnAttributeName(attribute, XmlErrorMessages.message("attribute.is.not.boolean", attribute.getName()), holder,
|
||||
quickFixes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ wrong.root.element=Wrong root element
|
||||
unbound.namespace=Namespace ''{0}'' is not bound
|
||||
unbound.namespace.no.param=Namespace is not bound
|
||||
attribute.is.not.allowed.here=Attribute {0} is not allowed here
|
||||
attribute.is.not.boolean=Attribute {0} is not boolean
|
||||
empty.attribute.is.not.allowed=Empty attribute {0} is not allowed
|
||||
duplicate.attribute=Duplicate attribute {0}
|
||||
duplicate.id.reference=Duplicate id reference
|
||||
@@ -27,6 +28,7 @@ insert.required.attribute.quickfix.text=Insert required attribute {0}
|
||||
insert.required.attribute.quickfix.family=Insert required attribute
|
||||
remove.attribute.quickfix.text=Remove attribute {0}
|
||||
remove.attribute.quickfix.family=Remove attribute
|
||||
add.attribute.value.quickfix.text=Add attribute value
|
||||
remove.extra.closing.tag.quickfix=Remove extra closing tag
|
||||
create.namespace.declaration.quickfix=Create {0} declaration
|
||||
select.namespace.title={0} To Import
|
||||
|
||||
+1
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
* Date: 16-Dec-2005
|
||||
*/
|
||||
public interface XmlEntitiesInspection {
|
||||
@NonNls String BOOLEAN_ATTRIBUTE_SHORT_NAME = "HtmlUnknownBooleanAttribute";
|
||||
@NonNls String ATTRIBUTE_SHORT_NAME = "HtmlUnknownAttribute";
|
||||
@NonNls String TAG_SHORT_NAME = "HtmlUnknownTag";
|
||||
@NonNls String REQUIRED_ATTRIBUTES_SHORT_NAME = "RequiredAttributes";
|
||||
|
||||
@@ -57,10 +57,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Maxim.Mossienko
|
||||
@@ -140,7 +137,7 @@ public class HtmlUtil {
|
||||
|
||||
static {
|
||||
for (HTMLControls.Control control : HTMLControls.getControls()) {
|
||||
final String tagName = control.name.toLowerCase();
|
||||
final String tagName = control.name.toLowerCase(Locale.US);
|
||||
if (control.endTag == HTMLControls.TagState.FORBIDDEN) EMPTY_TAGS_MAP.add(tagName);
|
||||
AUTO_CLOSE_BY_MAP.put(tagName, new THashSet<String>(control.autoClosedBy));
|
||||
}
|
||||
@@ -153,7 +150,7 @@ public class HtmlUtil {
|
||||
}
|
||||
|
||||
public static boolean isSingleHtmlTag(String tagName) {
|
||||
return EMPTY_TAGS_MAP.contains(tagName.toLowerCase());
|
||||
return EMPTY_TAGS_MAP.contains(tagName.toLowerCase(Locale.US));
|
||||
}
|
||||
|
||||
public static boolean isSingleHtmlTagL(String tagName) {
|
||||
@@ -161,7 +158,7 @@ public class HtmlUtil {
|
||||
}
|
||||
|
||||
public static boolean isOptionalEndForHtmlTag(String tagName) {
|
||||
return OPTIONAL_END_TAGS_MAP.contains(tagName.toLowerCase());
|
||||
return OPTIONAL_END_TAGS_MAP.contains(tagName.toLowerCase(Locale.US));
|
||||
}
|
||||
|
||||
public static boolean isOptionalEndForHtmlTagL(String tagName) {
|
||||
@@ -174,11 +171,11 @@ public class HtmlUtil {
|
||||
}
|
||||
|
||||
public static boolean isSingleHtmlAttribute(String attrName) {
|
||||
return EMPTY_ATTRS_MAP.contains(attrName.toLowerCase());
|
||||
return EMPTY_ATTRS_MAP.contains(attrName.toLowerCase(Locale.US));
|
||||
}
|
||||
|
||||
public static boolean isHtmlBlockTag(String tagName) {
|
||||
return BLOCK_TAGS_MAP.contains(tagName.toLowerCase());
|
||||
return BLOCK_TAGS_MAP.contains(tagName.toLowerCase(Locale.US));
|
||||
}
|
||||
|
||||
public static boolean isPossiblyInlineTag(String tagName) {
|
||||
@@ -190,7 +187,7 @@ public class HtmlUtil {
|
||||
}
|
||||
|
||||
public static boolean isInlineTagContainer(String tagName) {
|
||||
return INLINE_ELEMENTS_CONTAINER_MAP.contains(tagName.toLowerCase());
|
||||
return INLINE_ELEMENTS_CONTAINER_MAP.contains(tagName.toLowerCase(Locale.US));
|
||||
}
|
||||
|
||||
public static boolean isInlineTagContainerL(String tagName) {
|
||||
@@ -241,6 +238,21 @@ public class HtmlUtil {
|
||||
return HtmlDescriptorsTable.getHtmlTagNames();
|
||||
}
|
||||
|
||||
public static boolean isBooleanAttribute(@NotNull XmlAttributeDescriptor descriptor) {
|
||||
final String[] values = descriptor.getEnumeratedValues();
|
||||
if (values == null) {
|
||||
return false;
|
||||
}
|
||||
if (values.length == 2) {
|
||||
return values[0].isEmpty() && values[1].equals(descriptor.getName())
|
||||
|| values[1].isEmpty() && values[0].equals(descriptor.getName());
|
||||
}
|
||||
else if (values.length == 1) {
|
||||
return descriptor.getName().equals(values[0]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static XmlAttributeDescriptor[] getCustomAttributeDescriptors(XmlElement context) {
|
||||
String entitiesString = getEntitiesString(context, XmlEntitiesInspection.ATTRIBUTE_SHORT_NAME);
|
||||
if (entitiesString == null) return XmlAttributeDescriptor.EMPTY;
|
||||
|
||||
Reference in New Issue
Block a user