From 4b004d3b92cd9f1b33752f2c7bdceb95510e7359 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 29 Apr 2016 21:15:20 +0300 Subject: [PATCH] fold entities to their char value #WEB-422 fixed --- .../src/messages/ApplicationBundle.properties | 1 + .../editor/XmlCodeFoldingOptionsProvider.java | 1 + .../src/com/intellij/xml/XmlFoldingTest.java | 3 +- xml/tests/testData/folding/entities.html | 10 +++++ .../intellij/lang/XmlCodeFoldingSettings.java | 1 + .../options/editor/XmlFoldingSettings.java | 9 +++++ .../intellij/lang/XmlCodeFoldingBuilder.java | 40 ++++++++++++++++--- 7 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 xml/tests/testData/folding/entities.html diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 0601f5484249..4a8c3bad5ad4 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -371,6 +371,7 @@ checkbox.show.tabs.tooltips=Show tabs tooltips group.code.folding=Code Folding checkbox.collapse.xml.tags=XML tags checkbox.collapse.html.style.attribute=HTML 'style' attribute +checkbox.collapse.entities=XML entities checkbox.collapse.anonymous.classes=Anonymous classes checkbox.collapse.closures="Closures" (anonymous classes implementing one method, before Java 8) checkbox.collapse.generic.constructor.parameters=Generic constructor and method parameters diff --git a/xml/impl/src/com/intellij/application/options/editor/XmlCodeFoldingOptionsProvider.java b/xml/impl/src/com/intellij/application/options/editor/XmlCodeFoldingOptionsProvider.java index 2c685dfa2faa..a31aff914c6a 100644 --- a/xml/impl/src/com/intellij/application/options/editor/XmlCodeFoldingOptionsProvider.java +++ b/xml/impl/src/com/intellij/application/options/editor/XmlCodeFoldingOptionsProvider.java @@ -28,5 +28,6 @@ public class XmlCodeFoldingOptionsProvider extends BeanConfigurable +> +> + + Document +> +> +©< +> +> diff --git a/xml/xml-psi-api/src/com/intellij/lang/XmlCodeFoldingSettings.java b/xml/xml-psi-api/src/com/intellij/lang/XmlCodeFoldingSettings.java index 21533ae59176..ae2a895c90bd 100644 --- a/xml/xml-psi-api/src/com/intellij/lang/XmlCodeFoldingSettings.java +++ b/xml/xml-psi-api/src/com/intellij/lang/XmlCodeFoldingSettings.java @@ -3,4 +3,5 @@ package com.intellij.lang; public interface XmlCodeFoldingSettings { boolean isCollapseXmlTags(); boolean isCollapseHtmlStyleAttribute(); + boolean isCollapseEntities(); } diff --git a/xml/xml-psi-impl/src/com/intellij/application/options/editor/XmlFoldingSettings.java b/xml/xml-psi-impl/src/com/intellij/application/options/editor/XmlFoldingSettings.java index cc2d115a8c27..6d06f8670640 100644 --- a/xml/xml-psi-impl/src/com/intellij/application/options/editor/XmlFoldingSettings.java +++ b/xml/xml-psi-impl/src/com/intellij/application/options/editor/XmlFoldingSettings.java @@ -45,12 +45,21 @@ public class XmlFoldingSettings implements XmlCodeFoldingSettings, PersistentSta return COLLAPSE_HTML_STYLE_ATTRIBUTE; } + public boolean isCollapseEntities() { + return COLLAPSE_ENTITIES; + } + + public void setCollapseEntities(boolean COLLAPSE_ENTITIES) { + this.COLLAPSE_ENTITIES = COLLAPSE_ENTITIES; + } + public void setCollapseHtmlStyleAttribute(boolean value) { this.COLLAPSE_HTML_STYLE_ATTRIBUTE = value; } @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_XML_TAGS = false; @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_HTML_STYLE_ATTRIBUTE = true; + @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_ENTITIES = true; @Override public XmlFoldingSettings getState() { diff --git a/xml/xml-psi-impl/src/com/intellij/lang/XmlCodeFoldingBuilder.java b/xml/xml-psi-impl/src/com/intellij/lang/XmlCodeFoldingBuilder.java index 724c2b061122..6bad0fd8d0ab 100644 --- a/xml/xml-psi-impl/src/com/intellij/lang/XmlCodeFoldingBuilder.java +++ b/xml/xml-psi-impl/src/com/intellij/lang/XmlCodeFoldingBuilder.java @@ -25,9 +25,12 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.UnfairTextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.impl.source.html.HtmlFileImpl; +import com.intellij.psi.impl.source.xml.XmlEntityRefImpl; +import com.intellij.psi.impl.source.xml.XmlTokenImpl; import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiUtilCore; import com.intellij.psi.xml.*; @@ -96,12 +99,12 @@ public abstract class XmlCodeFoldingBuilder implements FoldingBuilder, DumbAware for (PsiElement grandChild : grandChildren) { ProgressManager.checkCanceled(); - if (grandChild instanceof XmlComment) { + if (grandChild instanceof XmlComment || isEntity(grandChild)) { addToFold(foldings, grandChild, document); } } } - else if(child instanceof XmlAttribute && isAttributeShouldBeFolded((XmlAttribute)child)) { + else if (isEntity(child) || child instanceof XmlAttribute && isAttributeShouldBeFolded((XmlAttribute)child)) { addToFold(foldings, child, document); } else { @@ -180,6 +183,9 @@ public abstract class XmlCodeFoldingBuilder implements FoldingBuilder, DumbAware final XmlAttributeValue valueElement = ((XmlAttribute)element).getValueElement(); return valueElement != null ? valueElement.getValueTextRange() : null; } + else if (isEntity(element)) { + return element.getTextRange(); + } else { return null; } @@ -205,8 +211,9 @@ public abstract class XmlCodeFoldingBuilder implements FoldingBuilder, DumbAware int startLine = document.getLineNumber(range.getStartOffset()); int endLine = document.getLineNumber(range.getEndOffset() - 1); - if (startLine < endLine || elementToFold instanceof XmlAttribute) { - if (range.getStartOffset() + MIN_TEXT_RANGE_LENGTH < range.getEndOffset()) { + final boolean entity = isEntity(elementToFold); + if (startLine < endLine || elementToFold instanceof XmlAttribute || entity) { + if (range.getStartOffset() + MIN_TEXT_RANGE_LENGTH < range.getEndOffset() || entity) { foldings.add(new FoldingDescriptor(elementToFold.getNode(), range)); return true; } @@ -224,6 +231,23 @@ public abstract class XmlCodeFoldingBuilder implements FoldingBuilder, DumbAware psi instanceof XmlAttribute || psi instanceof XmlConditionalSection ) return "..."; + if (isEntity(psi)) { + final XmlEntityDecl resolve = XmlEntityRefImpl.resolveEntity((XmlElement)psi, psi.getText(), psi.getContainingFile()); + final XmlAttributeValue value = resolve != null ? resolve.getValueElement() : null; + if (value != null) { + return getEntityValue(value); + } + } + return null; + } + + private static String getEntityValue(XmlAttributeValue value) { + final String result = value.getValue(); + final int i = result.indexOf('#'); + if (i > 0) { + final int charNum = StringUtil.parseInt(StringUtil.trimEnd(result.substring(i + 1), ";"), -1); + return charNum >= 0 ? String.valueOf((char)charNum) : null; + } return null; } @@ -232,7 +256,13 @@ public abstract class XmlCodeFoldingBuilder implements FoldingBuilder, DumbAware final PsiElement psi = node.getPsi(); final XmlCodeFoldingSettings foldingSettings = getFoldingSettings(); return (psi instanceof XmlTag && foldingSettings.isCollapseXmlTags()) - || (psi instanceof XmlAttribute && foldingSettings.isCollapseHtmlStyleAttribute()); + || (psi instanceof XmlAttribute && foldingSettings.isCollapseHtmlStyleAttribute()) + || isEntity(psi) && foldingSettings.isCollapseEntities(); + } + + protected boolean isEntity(PsiElement psi) { + return psi instanceof XmlEntityRef || + (psi instanceof XmlTokenImpl && ((XmlTokenImpl)psi).getElementType() == XmlTokenType.XML_CHAR_ENTITY_REF); } private static boolean isAttributeShouldBeFolded(XmlAttribute child) {