From 5fa57a38b72c21a6ed439f7a9c1847e5076fc8b1 Mon Sep 17 00:00:00 2001 From: Nikolas Komonen Date: Wed, 19 Dec 2018 15:21:03 -0500 Subject: [PATCH] DTD Formatting implemented Fixes #221 and #268 Signed-off-by: Nikolas Komonen --- .../eclipse/lsp4xml/dom/DOMDocumentType.java | 96 ++++----- .../java/org/eclipse/lsp4xml/dom/DOMNode.java | 4 + .../org/eclipse/lsp4xml/dom/DOMParser.java | 83 +++----- .../eclipse/lsp4xml/dom/DTDAttlistDecl.java | 41 ++-- .../org/eclipse/lsp4xml/dom/DTDDeclNode.java | 43 +++- .../eclipse/lsp4xml/dom/DTDDeclParameter.java | 37 ++++ .../eclipse/lsp4xml/dom/DTDElementDecl.java | 31 +-- .../eclipse/lsp4xml/dom/DTDEntityDecl.java | 63 +++--- .../eclipse/lsp4xml/dom/DTDNotationDecl.java | 37 ++-- .../lsp4xml/dom/parser/XMLScanner.java | 25 +-- .../lsp4xml/services/XMLFormatter.java | 159 +++++++++------ .../org/eclipse/lsp4xml/utils/XMLBuilder.java | 32 ++- .../dom/DOMParserForInternalDTDTest.java | 47 ++++- .../eclipse/lsp4xml/dom/DOMParserTest.java | 188 ++++++------------ 14 files changed, 472 insertions(+), 414 deletions(-) create mode 100644 org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDDeclParameter.java diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMDocumentType.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMDocumentType.java index 4a5789dd04..e3c70a1860 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMDocumentType.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMDocumentType.java @@ -16,27 +16,20 @@ * A doctype node. * */ -public class DOMDocumentType extends DOMNode implements org.w3c.dom.DocumentType { +public class DOMDocumentType extends DTDDeclNode implements org.w3c.dom.DocumentType { public enum DocumentTypeKind { PUBLIC, SYSTEM, INVALID } - - // Offset values relative to start of the XML Document - Integer nameStart, nameEnd; - Integer kindStart, kindEnd; - Integer publicIdStart, publicIdEnd; - Integer systemIdStart, systemIdEnd; - Integer internalSubsetStart, internalSubsetEnd; - - private String name; - private String kind; // SYSTEM || PUBLIC - private String publicId; - private String systemId; - private String internalSubset; + DTDDeclParameter name; + DTDDeclParameter kind; // SYSTEM || PUBLIC + DTDDeclParameter publicId; + DTDDeclParameter systemId; + DTDDeclParameter internalSubset; private String content; // || + //private String unrecognizedParameters; public DOMDocumentType(int start, int end, DOMDocument ownerDocument) { super(start, end, ownerDocument); @@ -49,43 +42,30 @@ public String getContent() { return content; } - void setEnd(int end) { - this.end = end; - this.content = getOwnerDocument().getText().substring(start, end); - } - /** * The text immediately after DOCTYPE, " */ - Integer elementNameStart, elementNameEnd; - Integer attributeNameStart, attributeNameEnd; - Integer attributeTypeStart, attributeTypeEnd; - Integer attributeValueStart, attributeValueEnd; - - String elementName; - String attributeName; - String attributeType; - String attributeValue; + DTDDeclParameter elementName; + DTDDeclParameter attributeName; + DTDDeclParameter attributeType; + DTDDeclParameter attributeValue; ArrayList internalChildren; @@ -65,8 +60,11 @@ public String getNodeName() { * @return the element name */ public String getElementName() { - elementName = getValueFromOffsets(parentDocumentType, elementName, elementNameStart, elementNameEnd); - return elementName; + return elementName != null ? elementName.getParameter() : null; + } + + public void setElementName(int start, int end) { + elementName = addNewParameter(start, end); } /** @@ -75,18 +73,27 @@ public String getElementName() { * @return the attribute name */ public String getAttributeName() { - attributeName = getValueFromOffsets(parentDocumentType, attributeName, attributeNameStart, attributeNameEnd); - return attributeName; + return attributeName != null ? attributeName.getParameter() : null; + } + + public void setAttributeName(int start, int end) { + attributeName = addNewParameter(start, end); } public String getAttributeType() { - attributeType = getValueFromOffsets(parentDocumentType, attributeType, attributeTypeStart, attributeTypeEnd); - return attributeType; + return attributeType != null ? attributeType.getParameter() : null; + } + + public void setAttributeType(int start, int end) { + attributeType = addNewParameter(start, end); } public String getAttributeValue() { - attributeValue = getValueFromOffsets(parentDocumentType, attributeValue, attributeValueStart, attributeValueEnd); - return attributeValue; + return attributeValue != null ? attributeValue.getParameter() : null; + } + + public void setAttributeValue(int start, int end) { + attributeValue = addNewParameter(start, end); } @Override diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDDeclNode.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDDeclNode.java index 12c3103baf..cf0a3cb594 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDDeclNode.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDDeclNode.java @@ -12,6 +12,8 @@ package org.eclipse.lsp4xml.dom; +import java.util.ArrayList; + /** * DTDNode */ @@ -25,14 +27,22 @@ public class DTDDeclNode extends DOMNode{ */ protected final DOMDocumentType parentDocumentType; + protected final DOMDocument parentDocument; - Integer unrecognizedStart, unrecognizedEnd; + DTDDeclParameter unrecognized; // holds all content after parsing goes wrong in a DTD declaration (ENTITY, ATTLIST, ELEMENT). - String unrecognized; // holds all content after parsing goes wrong in a DTD declaration (ENTITY, ATTLIST, ELEMENT). + ArrayList parameters; public DTDDeclNode(int start, int end, DOMDocumentType parentDocumentType) { super(start, end, parentDocumentType != null ? parentDocumentType.getOwnerDocument() : null); this.parentDocumentType = parentDocumentType; + this.parentDocument = null; + } + + public DTDDeclNode(int start, int end, DOMDocument parentDocumentType) { + super(start, end, parentDocumentType != null ? parentDocumentType : null); + this.parentDocument = parentDocumentType; + this.parentDocumentType = null; } @Override @@ -46,8 +56,11 @@ public short getNodeType() { } public String getUnrecognized() { - unrecognized = getValueFromOffsets(parentDocumentType, unrecognized, unrecognizedStart, unrecognizedEnd); - return unrecognized; + return unrecognized.getParameter(); + } + + public void setUnrecognized(int start, int end) { + unrecognized = addNewParameter(start, end); } public static String getValueFromOffsets(DOMDocumentType document, String value, Integer start, Integer end) { @@ -55,7 +68,27 @@ public static String getValueFromOffsets(DOMDocumentType document, String value, return document.getSubstring(start, end); } return value; + } + + public DTDDeclParameter addNewParameter(int start, int end) { + if(parameters == null) { + parameters = new ArrayList(); + } + DTDDeclParameter parameter = new DTDDeclParameter(parentDocumentType == null ? parentDocument.getDoctype() : parentDocumentType, start, end); + parameters.add(parameter); + this.end = end; // updates end position of the node. + return parameter; } - + public void updateLastParameterEnd(int end) { + if(parameters != null && parameters.size() > 0) { + DTDDeclParameter last = parameters.get(parameters.size() - 1); + last.end = end; + this.end = end; + } + } + + public ArrayList getParameters() { + return parameters; + } } \ No newline at end of file diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDDeclParameter.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDDeclParameter.java new file mode 100644 index 0000000000..4352f910e7 --- /dev/null +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDDeclParameter.java @@ -0,0 +1,37 @@ +package org.eclipse.lsp4xml.dom; + +/** + * DTDDeclParameter + */ +public class DTDDeclParameter { + + String parameter; + + int start, end; + + DOMDocumentType parentDoctype; + + public DTDDeclParameter(DOMDocumentType doctype, int start, int end) { + this.parentDoctype = doctype; + this.start = start; + this.end = end; + } + + + public String getParameter() { + if (parameter == null) { + parameter = parentDoctype.getSubstring(start, end); + } + return parameter; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof DTDDeclParameter)) { + return false; + } + DTDDeclParameter temp = (DTDDeclParameter) obj; + return start == temp.start && end == temp.end; + } + +} \ No newline at end of file diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDElementDecl.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDElementDecl.java index 7d9673288b..16e6582b2c 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDElementDecl.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDElementDecl.java @@ -27,13 +27,9 @@ public class DTDElementDecl extends DTDDeclNode { */ - Integer nameStart, nameEnd; // - Integer categoryStart, categoryEnd; // - Integer contentStart,contentEnd; // - - String name; - String category; - String content; + DTDDeclParameter name; + DTDDeclParameter category; + DTDDeclParameter content; public DTDElementDecl(int start, int end, DOMDocumentType parentDocumentType) { @@ -50,18 +46,27 @@ public String getNodeName() { } public String getName() { - name = getValueFromOffsets(parentDocumentType, name, nameStart, nameEnd); - return name; + return name != null ? name.getParameter() : null; + } + + public void setName(int start, int end) { + name = addNewParameter(start, end); } public String getCategory() { - category = getValueFromOffsets(parentDocumentType, category, categoryStart, categoryEnd); - return category; + return category != null ? category.getParameter() : null; + } + + public void setCategory(int start, int end) { + category = addNewParameter(start, end); } public String getContent() { - content = getValueFromOffsets(parentDocumentType, content, contentStart, contentEnd); - return content; + return content != null ? content.getParameter() : null; + } + + public void setContent(int start, int end) { + content = addNewParameter(start, end); } @Override diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDEntityDecl.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDEntityDecl.java index 809ce6a2ed..bd9d971778 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDEntityDecl.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDEntityDecl.java @@ -46,19 +46,12 @@ public class DTDEntityDecl extends DTDDeclNode implements Entity { * * */ - - String name; - String value; - String kind; - String publicId; - String systemId; - - Integer percentStart, percentEnd; - Integer nameStart, nameEnd; - Integer valueStart, valueEnd; - Integer kindStart, kindEnd; - Integer publicIdStart, publicIdEnd; - Integer systemIdStart, systemIdEnd; + DTDDeclParameter percent; + DTDDeclParameter name; + DTDDeclParameter value; + DTDDeclParameter kind; + DTDDeclParameter publicId; + DTDDeclParameter systemId; public DTDEntityDecl(int start, int end, DOMDocumentType parentDocumentType) { @@ -66,10 +59,11 @@ public DTDEntityDecl(int start, int end, DOMDocumentType parentDocumentType) { } public String getPercent() { - if(percentStart != null && percentEnd != null) { - return "%"; - } - return null; + return percent != null ? percent.getParameter() : null; + } + + public void setPercent(int start, int end) { + percent = addNewParameter(start, end); } /* @@ -79,18 +73,27 @@ public String getPercent() { */ @Override public String getNodeName() { - name = getValueFromOffsets(parentDocumentType, name, nameStart, nameEnd); - return name; + return name != null ? name.getParameter() : null; + } + + public void setNodeName(int start, int end) { + name = addNewParameter(start, end); } public String getValue() { - value = getValueFromOffsets(parentDocumentType, value, valueStart, valueEnd); - return value; + return value != null ? value.getParameter() : null; + } + + public void setValue(int start, int end) { + value = addNewParameter(start, end); } public String getKind() { - kind = getValueFromOffsets(parentDocumentType, kind, kindStart, kindEnd); - return kind; + return kind != null ? kind.getParameter() : null; + } + + public void setKind(int start, int end) { + kind = addNewParameter(start, end); } @Override @@ -125,8 +128,11 @@ public String getNotationName() { */ @Override public String getPublicId() { - publicId = getValueFromOffsets(parentDocumentType, publicId, publicIdStart, publicIdEnd); - return publicId; + return publicId != null ? publicId.getParameter() : null; + } + + public void setPublicId(int start, int end) { + publicId = addNewParameter(start, end); } /* @@ -136,8 +142,11 @@ public String getPublicId() { */ @Override public String getSystemId() { - systemId = getValueFromOffsets(parentDocumentType, systemId, systemIdStart, systemIdEnd); - return systemId; + return systemId != null ? systemId.getParameter() : null; + } + + public void setSystemId(int start, int end) { + systemId = addNewParameter(start, end); } /* diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDNotationDecl.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDNotationDecl.java index f8b1aaa041..2c4d258919 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDNotationDecl.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DTDNotationDecl.java @@ -33,58 +33,45 @@ public class DTDNotationDecl extends DTDDeclNode { * */ - Integer nameStart, nameEnd; - Integer kindStart, kindEnd; - Integer publicIdStart, publicIdEnd; - Integer systemIdStart, systemIdEnd; - - String name; - String kind; - String publicId; - String systemId; + DTDDeclParameter name; + DTDDeclParameter kind; + DTDDeclParameter publicId; + DTDDeclParameter systemId; public DTDNotationDecl(int start, int end, DOMDocumentType parentDocumentType) { super(start, end, parentDocumentType); } void setName(int start, int end) { - nameStart = start; - nameEnd = end; + name = addNewParameter(start, end); } public String getName() { - name = getValueFromOffsets(parentDocumentType, name, nameStart, nameEnd); - return name; + return name != null ? name.getParameter() : null; } void setKind(int start, int end) { - kindStart = start; - kindEnd = end; + kind = addNewParameter(start, end); } public String getKind() { - kind = getValueFromOffsets(parentDocumentType, kind, kindStart, kindEnd); - return kind; + return kind != null ? kind.getParameter() : null; } void setPublicId(int start, int end) { - publicIdStart = start; - publicIdEnd = end; + publicId = addNewParameter(start, end); } public String getPublicId() { - publicId = getValueFromOffsets(parentDocumentType, publicId, publicIdStart, publicIdEnd); - return publicId; + return publicId != null ? publicId.getParameter() : null; } void setSystemId(int start, int end) { - systemIdStart = start; - systemIdEnd = end; + systemId = addNewParameter(start, end); } public String getSystemId() { - systemId = getValueFromOffsets(parentDocumentType, systemId, systemIdStart, systemIdEnd); - return systemId; + return systemId != null ? systemId.getParameter() : null; } @Override diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/XMLScanner.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/XMLScanner.java index 00d307250b..37d858eaa7 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/XMLScanner.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/XMLScanner.java @@ -34,7 +34,7 @@ public class XMLScanner implements Scanner { String url; boolean isInsideDTDContent = false; // Either internal dtd in xml file OR external dtd in dtd file boolean isDeclCompleted = false; // If any type of DTD declaration was supplied with all the required properties - + TokenType tempToken; /** * boolean completedInitialAttDef; * @@ -394,7 +394,7 @@ TokenType internalScan() { state = ScannerState.DTDAfterDoctypeSYSTEM; return finishToken(offset, TokenType.DTDDocTypeKindSYSTEM); } - state = ScannerState.DTDWithinDoctype; + state = ScannerState.DTDUnrecognizedParameters; return internalScan(); case DTDAfterDoctypePUBLIC: @@ -435,7 +435,7 @@ TokenType internalScan() { return internalScan(); case DTDWithinContent: - if (stream.advanceIfChar(_CSB)) { // ] + if (stream.advanceIfChar(_CSB) || stream.peekChar() == _RAN) { // ] || > state = ScannerState.DTDWithinDoctype; isInsideDTDContent = false; return finishToken(offset, TokenType.DTDEndInternalSubset); @@ -469,13 +469,13 @@ TokenType internalScan() { } } - if (stream.advanceIfChar(_CSB)) { // ] - state = ScannerState.DTDWithinDoctype; - isInsideDTDContent = false; - return finishToken(offset, TokenType.DTDEndInternalSubset); - } + // if (stream.advanceIfChar(_CSB)) { // ] + // state = ScannerState.DTDWithinDoctype; + // isInsideDTDContent = false; + // return finishToken(offset, TokenType.DTDEndInternalSubset); + // } - stream.advanceUntilAnyOfChars(_LAN, _CSB); // < || ] + stream.advanceUntilAnyOfChars(_RAN, _LAN, _CSB); // > || < || ] return finishToken(offset, TokenType.Content); @@ -486,12 +486,13 @@ TokenType internalScan() { } if(stream.advanceIfChar(_RAN)) { // > - state = ScannerState.DTDWithinContent; - return finishToken(offset, TokenType.DTDEndTag); + state = isInsideDTDContent ? ScannerState.DTDWithinContent : ScannerState.WithinContent; + tempToken = isInsideDTDContent ? TokenType.DTDEndTag : TokenType.EndTagClose; + return finishToken(offset, tempToken); } if(stream.peekChar() == _LAN) { // < - state = ScannerState.DTDWithinContent; + state = isInsideDTDContent ? ScannerState.DTDWithinContent : ScannerState.WithinContent; return internalScan(); } diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/XMLFormatter.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/XMLFormatter.java index 048c3244ca..407773aff5 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/XMLFormatter.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/services/XMLFormatter.java @@ -30,6 +30,7 @@ import org.eclipse.lsp4xml.dom.DOMParser; import org.eclipse.lsp4xml.dom.DOMProcessingInstruction; import org.eclipse.lsp4xml.dom.DOMText; +import org.eclipse.lsp4xml.dom.DTDDeclParameter; import org.eclipse.lsp4xml.services.extensions.XMLExtensionsRegistry; import org.eclipse.lsp4xml.settings.XMLFormattingOptions; import org.eclipse.lsp4xml.utils.XMLBuilder; @@ -66,7 +67,7 @@ public List format(TextDocument document, Range range, XMLFo // Parse the content to format to create an XML document with full data (CData, // comments, etc) String text = document.getText().substring(start, end); - DOMDocument doc = DOMParser.getInstance().parse(text, null, null); + DOMDocument doc = DOMParser.getInstance().parse(text, document.getUri(), null); // Format the content XMLBuilder xml = new XMLBuilder(formattingOptions, "", document.lineDelimiter(startPosition.getLine())); @@ -86,9 +87,14 @@ public List format(TextDocument document, Range range, XMLFo private void format(DOMNode node, int level, int end, XMLBuilder xml) { if (node.getNodeType() != DOMNode.DOCUMENT_NODE) { - boolean doLineFeed = !(node.isComment() && ((DOMComment) node).isCommentSameLineEndTag()) + boolean doLineFeed; + if(node.getOwnerDocument().isDTD()) { + doLineFeed = false; + } else { + doLineFeed = !(node.isComment() && ((DOMComment) node).isCommentSameLineEndTag()) && (!isPreviousNodeType(node, DOMNode.TEXT_NODE) || xml.isJoinContentLines()) && (!node.isText() || ((xml.isJoinContentLines() && !isFirstChildNode(node)))); + } if (level > 0 && doLineFeed) { // add new line + indent @@ -96,66 +102,7 @@ private void format(DOMNode node, int level, int end, XMLBuilder xml) { xml.indent(level); } // generate start element - if (node.isCDATA()) { - DOMCDATASection cdata = (DOMCDATASection) node; - xml.startCDATA(); - xml.addContentCDATA(cdata.getData()); - xml.endCDATA(); - } else if (node.isComment()) { - DOMComment comment = (DOMComment) node; - xml.startComment(comment); - xml.addContentComment(comment.getData()); - xml.endComment(); - if (level == 0) { - xml.linefeed(); - } - } else if (node.isProcessingInstruction()) { - DOMProcessingInstruction processingInstruction = (DOMProcessingInstruction) node; - xml.startPrologOrPI(processingInstruction.getTarget()); - xml.addContentPI(processingInstruction.getData()); - xml.endPrologOrPI(); - if (level == 0) { - xml.linefeed(); - } - } else if (node.isProlog()) { - DOMProcessingInstruction processingInstruction = (DOMProcessingInstruction) node; - xml.startPrologOrPI(processingInstruction.getTarget()); - if (node.hasAttributes()) { - // generate attributes - String[] attributes = new String[3]; - attributes[0] = "version"; - attributes[1] = "encoding"; - attributes[2] = "standalone"; - - for (int i = 0; i < attributes.length; i++) { - String name = attributes[i]; - String value = node.getAttribute(attributes[i]); - if (value == null) { - continue; - } - xml.addSingleAttribute(name, value); - } - } - xml.endPrologOrPI(); - xml.linefeed(); - } else if (node.isDoctype()) { - DOMDocumentType documentType = (DOMDocumentType) node; - xml.startDoctype(documentType.getName()); - xml.setDoctypeInternalSubset(documentType.getInternalSubset()); - xml.endDoctype(); - xml.linefeed(); - } else if (node.isText()) { - DOMText text = (DOMText) node; - if (text.hasData()) { - // Generate content - String content = text.getData(); - if (!content.isEmpty()) { - xml.addContent(content); - } - - } - return; - } else if (node.isElement()) { + if (node.isElement()) { DOMElement element = (DOMElement) node; String tag = element.getTagName(); if (element.hasEndTag() && !element.hasStartTag()) { @@ -217,6 +164,82 @@ private void format(DOMNode node, int level, int end, XMLBuilder xml) { } } return; + + } else if (node.isCDATA()) { + DOMCDATASection cdata = (DOMCDATASection) node; + xml.startCDATA(); + xml.addContentCDATA(cdata.getData()); + xml.endCDATA(); + } else if (node.isComment()) { + DOMComment comment = (DOMComment) node; + xml.startComment(comment); + xml.addContentComment(comment.getData()); + xml.endComment(); + if (level == 0) { + xml.linefeed(); + } + } else if (node.isProcessingInstruction()) { + DOMProcessingInstruction processingInstruction = (DOMProcessingInstruction) node; + xml.startPrologOrPI(processingInstruction.getTarget()); + xml.addContentPI(processingInstruction.getData()); + xml.endPrologOrPI(); + if (level == 0) { + xml.linefeed(); + } + } else if (node.isProlog()) { + DOMProcessingInstruction processingInstruction = (DOMProcessingInstruction) node; + xml.startPrologOrPI(processingInstruction.getTarget()); + if (node.hasAttributes()) { + // generate attributes + String[] attributes = new String[3]; + attributes[0] = "version"; + attributes[1] = "encoding"; + attributes[2] = "standalone"; + + for (int i = 0; i < attributes.length; i++) { + String name = attributes[i]; + String value = node.getAttribute(attributes[i]); + if (value == null) { + continue; + } + xml.addSingleAttribute(name, value); + } + } + xml.endPrologOrPI(); + xml.linefeed(); + } else if (node.isText()) { + DOMText text = (DOMText) node; + if (text.hasData()) { + // Generate content + String content = text.getData(); + if (!content.isEmpty()) { + xml.addContent(content); + } + + } + return; + } else if (node.isDoctype()) { + boolean isDTD = node.getOwnerDocument().isDTD(); + level = isDTD ? -1 : level; + DOMDocumentType documentType = (DOMDocumentType) node; + if(!isDTD) { + xml.startDoctype(); + ArrayList params = documentType.getParameters(); + for (DTDDeclParameter param : params) { + if(!documentType.isInternalSubset(param)) { + xml.addParameter(param.getParameter()); + } else { + xml.startDoctypeInternalSubset(); + formatDTD(documentType, level, end, xml); + xml.endDoctypeInternalSubset(); + } + } + xml.endDoctype(); + xml.linefeed(); + } else { + formatDTD(documentType, level, end, xml); + } + return; } } else if (node.hasChildNodes()) { // Other nodes kind like root @@ -226,6 +249,18 @@ private void format(DOMNode node, int level, int end, XMLBuilder xml) { } } + private static boolean formatDTD(DOMDocumentType doctype, int level, int end, XMLBuilder xml) { + DOMNode previous = null; + for (DOMNode decl : doctype.getChildren()) { + if(!decl.isText() && previous != null && !previous.isText()) xml.linefeed(); + xml.addDeclTag(decl, level + 1); // level + 1 since 'level' is for the doctype tag + previous = decl; + + } + + return true; + } + private static boolean isFirstChildNode(DOMNode node) { return node.equals(node.getParentNode().getFirstChild()); } diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/utils/XMLBuilder.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/utils/XMLBuilder.java index b1381c93b5..ec4a50829b 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/utils/XMLBuilder.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/utils/XMLBuilder.java @@ -13,6 +13,8 @@ import static org.eclipse.lsp4xml.utils.StringUtils.normalizeSpace; import org.eclipse.lsp4xml.dom.DOMComment; +import org.eclipse.lsp4xml.dom.DOMDocumentType; +import org.eclipse.lsp4xml.dom.DOMNode; import org.eclipse.lsp4xml.settings.XMLFormattingOptions; /** @@ -206,21 +208,29 @@ public XMLBuilder addContentComment(String content) { return this; } - public XMLBuilder startDoctype(String name) { + public XMLBuilder addDeclTag(DOMNode tag, int level) { + indent(level); + xml.append(tag.getNodeAsString()); + return this; + } + + public XMLBuilder startDoctype() { xml.append(" \n" + + " ]\n" + + ">"; + + DOMDocument actual = createDOMDocument(dtd); + Assert.assertEquals(1, actual.getChildren().size()); + Assert.assertTrue(actual.getChild(0).isDoctype()); + DOMDocumentType documentType = (DOMDocumentType) actual.getChild(0); + Assert.assertEquals(0, documentType.getStart()); + Assert.assertEquals(74, documentType.getEnd()); + Assert.assertEquals("foo", documentType.getName()); + Assert.assertTrue(documentType.isClosed()); + + // expectedInternalChildren = expectedTemp.getInternalChildren(); ArrayList actualInternalChildren = actualTemp.getInternalChildren(); @@ -1037,72 +1007,52 @@ private static void compareTrees(DOMNode expectedNode, DOMNode actualNode) { assertEquals(true, actualNode.isDTDElementDecl()); DTDElementDecl expectedTemp = (DTDElementDecl) expectedNode; DTDElementDecl actualTemp = (DTDElementDecl) actualNode; - assertEquals(expectedTemp.nameStart, actualTemp.nameStart); - assertEquals(expectedTemp.nameEnd, actualTemp.nameEnd); - assertEquals(expectedTemp.categoryStart, actualTemp.categoryStart); - assertEquals(expectedTemp.categoryEnd, actualTemp.categoryEnd); - assertEquals(expectedTemp.contentStart, actualTemp.contentStart); - assertEquals(expectedTemp.contentEnd, actualTemp.contentEnd); - assertEquals(expectedTemp.unrecognizedStart, actualTemp.unrecognizedStart); - assertEquals(expectedTemp.unrecognizedEnd, actualTemp.unrecognizedEnd); + assertEquals(expectedTemp.name, actualTemp.name); + assertEquals(expectedTemp.category, actualTemp.category); + assertEquals(expectedTemp.content, actualTemp.content); + assertEquals(expectedTemp.unrecognized, actualTemp.unrecognized); } else if(expectedNode.isDTDEntityDecl()) { assertEquals(true, actualNode.isDTDEntityDecl()); DTDEntityDecl expectedTemp = (DTDEntityDecl) expectedNode; DTDEntityDecl actualTemp = (DTDEntityDecl) actualNode; - assertEquals(expectedTemp.nameStart, actualTemp.nameStart); - assertEquals(expectedTemp.nameEnd, actualTemp.nameEnd); - assertEquals(expectedTemp.valueStart, actualTemp.valueStart); - assertEquals(expectedTemp.valueEnd, actualTemp.valueEnd); - assertEquals(expectedTemp.kindStart, actualTemp.kindStart); - assertEquals(expectedTemp.kindEnd, actualTemp.kindEnd); - assertEquals(expectedTemp.publicIdStart, actualTemp.publicIdStart); - assertEquals(expectedTemp.publicIdEnd, actualTemp.publicIdEnd); - assertEquals(expectedTemp.systemIdStart, actualTemp.systemIdStart); - assertEquals(expectedTemp.systemIdEnd, actualTemp.systemIdEnd); - assertEquals(expectedTemp.unrecognizedStart, actualTemp.unrecognizedStart); - assertEquals(expectedTemp.unrecognizedEnd, actualTemp.unrecognizedEnd); + assertEquals(expectedTemp.name, actualTemp.name); + assertEquals(expectedTemp.value, actualTemp.value); + assertEquals(expectedTemp.kind, actualTemp.kind); + assertEquals(expectedTemp.publicId, actualTemp.publicId); + assertEquals(expectedTemp.systemId, actualTemp.systemId); + assertEquals(expectedTemp.unrecognized, actualTemp.unrecognized); } else if(expectedNode.isDTDNotationDecl()) { assertEquals(true, actualNode.isDTDNotationDecl()); DTDNotationDecl expectedTemp = (DTDNotationDecl) expectedNode; DTDNotationDecl actualTemp = (DTDNotationDecl) actualNode; - assertEquals(expectedTemp.nameStart, actualTemp.nameStart); - assertEquals(expectedTemp.nameEnd, actualTemp.nameEnd); - assertEquals(expectedTemp.kindStart, actualTemp.kindStart); - assertEquals(expectedTemp.kindEnd, actualTemp.kindEnd); - assertEquals(expectedTemp.publicIdStart, actualTemp.publicIdStart); - assertEquals(expectedTemp.publicIdEnd, actualTemp.publicIdEnd); - assertEquals(expectedTemp.systemIdStart, actualTemp.systemIdStart); - assertEquals(expectedTemp.systemIdEnd, actualTemp.systemIdEnd); - assertEquals(expectedTemp.unrecognizedStart, actualTemp.unrecognizedStart); - assertEquals(expectedTemp.unrecognizedEnd, actualTemp.unrecognizedEnd); + assertEquals(expectedTemp.name, actualTemp.name); + assertEquals(expectedTemp.kind, actualTemp.kind); + assertEquals(expectedTemp.publicId, actualTemp.publicId); + assertEquals(expectedTemp.systemId, actualTemp.systemId); + assertEquals(expectedTemp.unrecognized, actualTemp.unrecognized); } else if(expectedNode.isDoctype()) { assertEquals(true, actualNode.isDoctype()); DOMDocumentType expectedTemp = (DOMDocumentType) expectedNode; DOMDocumentType actualTemp = (DOMDocumentType) actualNode; - assertEquals(expectedTemp.nameStart, actualTemp.nameStart); - assertEquals(expectedTemp.nameEnd, actualTemp.nameEnd); - assertEquals(expectedTemp.kindStart, actualTemp.kindStart); - assertEquals(expectedTemp.kindEnd, actualTemp.kindEnd); - assertEquals(expectedTemp.publicIdStart, actualTemp.publicIdStart); - assertEquals(expectedTemp.publicIdEnd, actualTemp.publicIdEnd); - assertEquals(expectedTemp.systemIdStart, actualTemp.systemIdStart); - assertEquals(expectedTemp.systemIdEnd, actualTemp.systemIdEnd); - assertEquals(expectedTemp.internalSubsetStart, actualTemp.internalSubsetStart); - assertEquals(expectedTemp.internalSubsetEnd, actualTemp.internalSubsetEnd); + assertEquals(expectedTemp.name, actualTemp.name); + assertEquals(expectedTemp.kind, actualTemp.kind); + assertEquals(expectedTemp.publicId, actualTemp.publicId); + assertEquals(expectedTemp.systemId, actualTemp.systemId); + assertEquals(expectedTemp.internalSubset, actualTemp.internalSubset); } else if(expectedNode.isGenericDTDDecl()) { DTDDeclNode expectedTemp = (DTDDeclNode) expectedNode; DTDDeclNode actualTemp = (DTDDeclNode) actualNode; - assertEquals(expectedTemp.unrecognizedStart, actualTemp.unrecognizedStart); - assertEquals(expectedTemp.unrecognizedEnd, actualTemp.unrecognizedEnd); + assertEquals(expectedTemp.unrecognized.start, actualTemp.unrecognized.start); + assertEquals(expectedTemp.unrecognized.end, actualTemp.unrecognized.end); } assertEquals(expectedNode.isClosed(), actualNode.isClosed()); @@ -1117,25 +1067,13 @@ else if(expectedNode.isGenericDTDDecl()) { } public static void assertInternalAttlist(DTDAttlistDecl expected, DTDAttlistDecl actual) { - assertEquals(expected.attributeNameStart, actual.attributeNameStart); - assertEquals(expected.attributeNameEnd, actual.attributeNameEnd); - assertEquals(expected.attributeTypeStart, actual.attributeTypeStart); - assertEquals(expected.attributeTypeEnd, actual.attributeTypeEnd); - assertEquals(expected.attributeValueStart, actual.attributeValueStart); - assertEquals(expected.attributeValueEnd, actual.attributeValueEnd); - } - - public static void assertInternalNotation(DTDNotationDecl expected, DTDNotationDecl actual) { - assertEquals(expected.nameStart, actual.nameStart); - assertEquals(expected.nameEnd, actual.nameEnd); - assertEquals(expected.kindStart, actual.kindStart); - assertEquals(expected.kindEnd, actual.kindEnd); - assertEquals(expected.publicIdStart, actual.publicIdStart); - assertEquals(expected.publicIdEnd, actual.publicIdEnd); - assertEquals(expected.systemIdStart, actual.systemIdStart); - assertEquals(expected.systemIdEnd, actual.systemIdEnd); + assertEquals(expected.elementName, actual.elementName); + assertEquals(expected.attributeName, actual.attributeName); + assertEquals(expected.attributeType, actual.attributeType); + assertEquals(expected.attributeValue, actual.attributeValue); } + public void insertIntoAttributes(DOMNode n, String key, String value) { n.setAttribute(key, value); }