diff --git a/.vscode/java.test.config b/.vscode/java.test.config new file mode 100644 index 0000000000..2515dcec1d --- /dev/null +++ b/.vscode/java.test.config @@ -0,0 +1,28 @@ +{ + "run": { + "default": "", + "items": [ + { + "name": "lsp4xml", + "projectName": "lsp4xml", + "workingDirectory": "", + "args": [], + "vmargs": [], + "preLaunchTask": "" + } + ] + }, + "debug": { + "default": "", + "items": [ + { + "name": "lsp4xml", + "projectName": "lsp4xml", + "workingDirectory": "", + "args": [], + "vmargs": [], + "preLaunchTask": "" + } + ] + } +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 6b2ff90811..94ba4e71b1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,6 +10,38 @@ //Use consistent indentation "editor.detectIndentation": false, "editor.tabSize": 4, - "editor.insertSpaces": false + "editor.insertSpaces": false, + "java.test.defaultConfig": "config-41b2e8", + "java.test.config": [ + { + "run": { + "default": "", + "items": [ + { + "name": "lsp4xml", + "projectName": "lsp4xml", + "workingDirectory": "", + "args": [], + "vmargs": [], + "preLaunchTask": "" + } + ] + }, + "debug": { + "default": "", + "items": [ + { + "name": "lsp4xml", + "projectName": "lsp4xml", + "workingDirectory": "", + "args": [], + "vmargs": [], + "preLaunchTask": "" + } + ] + }, + "name": "config-41b2e8" + } + ] } \ No newline at end of file diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMAttr.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMAttr.java index 2a57d8c0ef..755eabb3cf 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMAttr.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMAttr.java @@ -25,10 +25,14 @@ public class DOMAttr extends DOMNode implements org.w3c.dom.Attr { private DOMNode nodeAttrValue; - private String value; + private String quotelessValue;//Value without quotes + + private String originalValue;//Exact value from document private final DOMNode ownerElement; + private boolean hasDelimiter; // has '=' + class AttrNameOrValue extends DOMNode { private final DOMAttr ownerAttr; @@ -110,7 +114,7 @@ public DOMElement getOwnerElement() { */ @Override public String getValue() { - return value; + return quotelessValue; } /* @@ -157,23 +161,71 @@ public DOMNode getNodeAttrName() { return nodeAttrName; } + public void setDelimiter(boolean hasDelimiter) { + this.hasDelimiter = hasDelimiter; + } + + public boolean hasDelimiter() { + return this.hasDelimiter; + } + + /** + * Get original attribute value from the document. + * + * This will include quotations (", '). + * @return attribute value with quotations if it had them. + */ + public String getOriginalValue() { + return originalValue; + } + public void setValue(String value, int start, int end) { - this.value = getValue(value); + this.originalValue = value; + this.quotelessValue = convertToQuotelessValue(value); this.nodeAttrValue = start != -1 ? new AttrNameOrValue(start, end, this) : null; } - private static String getValue(String value) { + /** + * Returns a String of 'value' without surrounding quotes if it had them. + * @param value + * @return + */ + public static String convertToQuotelessValue(String value) { if (value == null) { return null; } if (value.isEmpty()) { return value; } - int start = value.charAt(0) == '\"' ? 1 : 0; - int end = value.charAt(value.length() - 1) == '\"' ? value.length() - 1 : value.length(); + char quoteValue = value.charAt(0); + int start = quoteValue == '\"' || quoteValue == '\'' ? 1 : 0; + quoteValue = value.charAt(value.length() - 1); + int end = quoteValue == '\"' || quoteValue == '\'' ? value.length() - 1 : value.length(); return value.substring(start, end); } + /** + * Checks if 'value' has matching surrounding quotations. + * @param value + * @return + */ + public static boolean isQuoted(String value) { + if (value == null) { + return false; + } + if (value.isEmpty()) { + return false; + } + char quoteValueStart = value.charAt(0); + boolean start = quoteValueStart == '\"' || quoteValueStart == '\'' ? true : false; + if(start == false) { + return false; + } + char quoteValueEnd = value.charAt(value.length() - 1); + boolean end = (quoteValueEnd == '\"' || quoteValueEnd == '\'') && quoteValueEnd == quoteValueStart ? true : false; + return end; + } + public DOMNode getNodeAttrValue() { return nodeAttrValue; } @@ -201,7 +253,7 @@ public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((value == null) ? 0 : value.hashCode()); + result = prime * result + ((quotelessValue == null) ? 0 : quotelessValue.hashCode()); return result; } @@ -219,10 +271,10 @@ public boolean equals(Object obj) { return false; } else if (!name.equals(other.name)) return false; - if (value == null) { - if (other.value != null) + if (quotelessValue == null) { + if (other.quotelessValue != null) return false; - } else if (!value.equals(other.value)) + } else if (!quotelessValue.equals(other.quotelessValue)) return false; return true; } diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMParser.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMParser.java index ccbeca2e8f..07cb3db6a0 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMParser.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/DOMParser.java @@ -189,6 +189,15 @@ public DOMDocument parse(TextDocument document, URIResolverExtensionManager reso break; } + case DelimiterAssign: { + if(attr != null) { + //Sets the value to the '=' position in case there is no AttributeValue + attr.setValue(null, scanner.getTokenOffset(), scanner.getTokenEnd()); + attr.setDelimiter(true); + } + break; + } + case AttributeValue: { String value = scanner.getTokenText(); if (curr.hasAttributes() && attr != null) { diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/Constants.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/Constants.java index fade442531..dce65b6732 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/Constants.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/Constants.java @@ -60,7 +60,7 @@ public class Constants { public static final Pattern ATTRIBUTE_NAME_REGEX = Pattern.compile("^[^\\s\"'<>/=\\x00-\\x0F\\x7F\\x80-\\x9F]*"); - public static final Pattern ATTRIBUTE_VALUE_REGEX = Pattern.compile("^[^\\s\"'`=<>\\/]+"); + public static final Pattern ATTRIBUTE_VALUE_REGEX = Pattern.compile("^(\"[^\"]*\"?)|(\'[^\']*\'?)"); public static final Pattern URL_VALUE_REGEX = Pattern.compile("^(\"|\')[^<>\"]*(\"|\')"); diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/MultiLineStream.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/MultiLineStream.java index f78f787cfd..01a552a0c6 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/MultiLineStream.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/dom/parser/MultiLineStream.java @@ -323,6 +323,7 @@ private Matcher getCachedMatcher(Pattern regex) { matcher = regex.matcher(source); regexpCache.put(regex, matcher); } + matcher.reset(); // Cached regex caused issues, needed to reset it. return matcher; } 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 664ac23b71..0e97c0d627 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 @@ -318,22 +318,26 @@ TokenType internalScan() { hasSpaceAfterTag = false; return finishToken(offset, TokenType.AttributeValue); } - int ch = stream.peekChar(); - if (ch == _SQO || ch == _DQO || ch == _SIQ) { // " || " || ' - stream.advance(1); // consume quote - if (stream.advanceUntilChar(ch)) { - stream.advance(1); // consume quote - } - if ("type".equals(lastAttributeName)) { - lastTypeValue = stream.getSource().substring(offset + 1, stream.pos() - 1); - } - state = ScannerState.WithinTag; - hasSpaceAfterTag = false; - return finishToken(offset, TokenType.AttributeValue); - } + hasSpaceAfterTag = true; state = ScannerState.WithinTag; - hasSpaceAfterTag = false; - return internalScan(); // no advance yet - jump to WithinTag + return internalScan(); + + // int ch = stream.peekChar(); + // if (ch == _SQO || ch == _DQO || ch == _SIQ) { // " || " || ' + // stream.advance(1); // consume quote + // if (stream.advanceUntilChar(ch)) { + // stream.advance(1); // consume quote + // } + // if ("type".equals(lastAttributeName)) { + // lastTypeValue = stream.getSource().substring(offset + 1, stream.pos() - 1); + // } + // state = ScannerState.WithinTag; + // hasSpaceAfterTag = false; + // return finishToken(offset, TokenType.AttributeValue); + // } + // state = ScannerState.WithinTag; + // hasSpaceAfterTag = false; + // return internalScan(); // no advance yet - jump to WithinTag // DTD diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/utils/XMLGenerator.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/utils/XMLGenerator.java index 61997afcac..1b4eb0ef28 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/utils/XMLGenerator.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/utils/XMLGenerator.java @@ -154,9 +154,9 @@ private int generate(Collection attributes, int level, i String value = generateAttributeValue(defaultValue, enumerationValues, canSupportSnippets, snippetIndex, false); if (attributesSize != 1) { - xml.addAttribute(attributeDeclaration.getName(), value, attributeIndex, level, tagName); + xml.addAttribute(attributeDeclaration.getName(), value, level, true); } else { - xml.addSingleAttribute(attributeDeclaration.getName(), value); + xml.addSingleAttribute(attributeDeclaration.getName(), value, true); } attributeIndex++; } 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 8c0324c62c..add3c3fc1c 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 @@ -119,12 +119,12 @@ private void format(DOMNode node, int level, int end, XMLBuilder xml) { List attributes = element.getAttributeNodes(); if (attributes.size() == 1) { DOMAttr singleAttribute = attributes.get(0); - xml.addSingleAttribute(singleAttribute.getName(), singleAttribute.getValue()); + xml.addSingleAttribute(singleAttribute.getName(), singleAttribute.getOriginalValue()); } else { int attributeIndex = 0; for (DOMAttr attr : attributes) { String attributeName = attr.getName(); - xml.addAttribute(attributeName, attr.getValue(), attributeIndex, level, tag); + xml.addAttribute(attr, level); attributeIndex++; } } @@ -205,7 +205,7 @@ private void format(DOMNode node, int level, int end, XMLBuilder xml) { if (value == null) { continue; } - xml.addSingleAttribute(name, value); + xml.addSingleAttribute(name, value, true); } } xml.endPrologOrPI(); diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/settings/XMLFormattingOptions.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/settings/XMLFormattingOptions.java index 7fe2addda8..1e9ec9344d 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/settings/XMLFormattingOptions.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/settings/XMLFormattingOptions.java @@ -10,6 +10,8 @@ */ package org.eclipse.lsp4xml.settings; +import java.util.Objects; + import org.eclipse.lsp4j.FormattingOptions; /** @@ -27,6 +29,14 @@ public class XMLFormattingOptions extends FormattingOptions { private static final String JOIN_CONTENT_LINES = "joinContentLines"; private static final String ENABLED = "enabled"; private static final String SPACE_BEFORE_EMPTY_CLOSE_TAG = "spaceBeforeEmptyCloseTag"; + private static final String QUOTATIONS = "quotations"; + + // Values for QUOTATIONS + public static final String DOUBLE_QUOTES_VALUE = "doubleQuotes"; + public static final String SINGLE_QUOTES_VALUE = "singleQuotes"; + enum Quotations { + doubleQuotes, singleQuotes + } public XMLFormattingOptions() { this(false); @@ -53,6 +63,7 @@ public void initializeDefaultSettings() { this.setJoinContentLines(false); this.setEnabled(true); this.setSpaceBeforeEmptyCloseTag(true); + this.setQuotations(DOUBLE_QUOTES_VALUE); } public XMLFormattingOptions(int tabSize, boolean insertSpaces, boolean initializeDefaultSettings) { @@ -168,6 +179,46 @@ public boolean isSpaceBeforeEmptyCloseTag() { } } + public void setQuotations(final String quotations) { + this.putString(XMLFormattingOptions.QUOTATIONS, quotations); + } + + /** + * Returns the value of the format.quotations preference. + * + * If invalid or null, the default is {@link XMLFormattingOptions#DOUBLE_QUOTES_VALUE}. + */ + public String getQuotations() { + final String value = this.getString(XMLFormattingOptions.QUOTATIONS); + if ((value != null) && isValidQuotations()) { + return value; + } else { + this.setQuotations(XMLFormattingOptions.DOUBLE_QUOTES_VALUE); + return DOUBLE_QUOTES_VALUE;// default + } + } + + /** + * If the quotations preference is a valid option. + * + * Keep up to date with new preferences. + * @return + */ + private boolean isValidQuotations() { + final String value = this.getString(XMLFormattingOptions.QUOTATIONS); + return SINGLE_QUOTES_VALUE.equals(value) || DOUBLE_QUOTES_VALUE.equals(value); + } + + /** + * Checks if {@code quotation} equals the current value for {@code format.quotations}. + * @param quotation + * @return + */ + public boolean isQuotations(String quotation) { + String value = getQuotations(); + return Objects.equals(value, quotation); + } + public XMLFormattingOptions merge(FormattingOptions formattingOptions) { formattingOptions.entrySet().stream().forEach(entry -> { String key = entry.getKey(); 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 e2c9adbc2e..92c442e291 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 @@ -12,6 +12,7 @@ import static org.eclipse.lsp4xml.utils.StringUtils.normalizeSpace; +import org.eclipse.lsp4xml.dom.DOMAttr; import org.eclipse.lsp4xml.dom.DOMComment; import org.eclipse.lsp4xml.dom.DOMDocumentType; import org.eclipse.lsp4xml.dom.DOMNode; @@ -32,7 +33,7 @@ public class XMLBuilder { public XMLBuilder(XMLFormattingOptions formattingOptions, String whitespacesIndent, String lineDelimiter) { this.whitespacesIndent = whitespacesIndent; - this.formattingOptions = formattingOptions; + this.formattingOptions = formattingOptions != null ? formattingOptions : new XMLFormattingOptions(true); this.lineDelimiter = lineDelimiter; this.xml = new StringBuilder(); } @@ -93,17 +94,40 @@ public XMLBuilder selfCloseElement() { } public XMLBuilder addSingleAttribute(String name, String value) { + return addSingleAttribute(name, value, false); + } + + /** + * Used when only one attribute is being added to a node. + * + * It will not perform any linefeeds and only basic indentation. + * + * @param name attribute name + * @param value attribute value + * @return + */ + public XMLBuilder addSingleAttribute(String name, String value, boolean surroundWithQuotes) { xml.append(" "); - xml.append(name); - xml.append("=\""); - if (value != null) { - xml.append(value); - } - xml.append("\""); + addAttributeContents(name, true, value, surroundWithQuotes); + return this; } - public XMLBuilder addAttribute(String name, String value, int index, int level, String tagName) { + public XMLBuilder addAttribute(String name, String value, int level) { + return addAttribute(name, value, level, false); + } + + /** + * Used when you are knowingly adding multiple attributes. + * + * It will do linefeeds and indentation. + * + * @param name + * @param value + * @param level + * @return + */ + public XMLBuilder addAttribute(String name, String value, int level, boolean surroundWithQuotes) { if (isSplitAttributes()) { linefeed(); indent(level + splitAttributesIndent); @@ -111,15 +135,72 @@ public XMLBuilder addAttribute(String name, String value, int index, int level, xml.append(" "); } - xml.append(name); - xml.append("=\""); - if (value != null) { - xml.append(value); + addAttributeContents(name, true, value, surroundWithQuotes); + return this; + } + + public XMLBuilder addAttribute(DOMAttr attr, int level) { + return addAttribute(attr, level, false); + } + + public XMLBuilder addAttribute(DOMAttr attr, int level, boolean surroundWithQuotes) { + if (isSplitAttributes()) { + linefeed(); + indent(level + splitAttributesIndent); + } else { + xml.append(" "); } - xml.append("\""); + + addAttributeContents(attr.getName(), attr.hasDelimiter(), attr.getOriginalValue(), surroundWithQuotes); return this; } + /** + * Builds the attribute name, '=', and value. + * + * Never puts quotes around unquoted values unless indicated to by 'surroundWithQuotes' + */ + private void addAttributeContents(String name, Boolean equalsSign, String originalValue, boolean surroundWithQuotes) { + if(name != null) { + xml.append(name); + } + if(equalsSign) { + xml.append("="); + } + if(originalValue != null) { + String quote = formattingOptions.isQuotations(XMLFormattingOptions.DOUBLE_QUOTES_VALUE) ? "\"" : "'"; + + if(DOMAttr.isQuoted(originalValue)) { + if(originalValue.charAt(0) == '\'' && formattingOptions.isQuotations(XMLFormattingOptions.DOUBLE_QUOTES_VALUE) || + originalValue.charAt(0) == '\"' && formattingOptions.isQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE)) { + + originalValue = DOMAttr.convertToQuotelessValue(originalValue); + xml.append(quote); + if (originalValue != null) { + xml.append(originalValue); + } + xml.append(quote); + return; + } + else { + xml.append(originalValue); + return; + } + } + else if(surroundWithQuotes) { + xml.append(quote); + if (originalValue != null) { + xml.append(originalValue); + } + xml.append(quote); + return; + } + else { + xml.append(originalValue); + } + } + } + public XMLBuilder linefeed() { xml.append(lineDelimiter); if (whitespacesIndent != null) { diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/dom/parser/XMLScannerTest.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/dom/parser/XMLScannerTest.java index a598c55919..4e6958dc56 100644 --- a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/dom/parser/XMLScannerTest.java +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/dom/parser/XMLScannerTest.java @@ -545,11 +545,11 @@ public void testName34() { assertOffsetAndToken(4, TokenType.Whitespace); assertOffsetAndToken(5, TokenType.AttributeName); assertOffsetAndToken(8, TokenType.DelimiterAssign); - assertOffsetAndToken(9, TokenType.AttributeValue); + assertOffsetAndToken(9, TokenType.AttributeName); assertOffsetAndToken(12, TokenType.Whitespace); assertOffsetAndToken(13, TokenType.AttributeName); assertOffsetAndToken(16, TokenType.DelimiterAssign); - assertOffsetAndToken(17, TokenType.AttributeValue); + assertOffsetAndToken(17, TokenType.AttributeName); assertOffsetAndToken(24, TokenType.StartTagClose); } @@ -562,7 +562,7 @@ public void testName35() { assertOffsetAndToken(4, TokenType.Whitespace); assertOffsetAndToken(5, TokenType.AttributeName); assertOffsetAndToken(8, TokenType.DelimiterAssign); - assertOffsetAndToken(9, TokenType.AttributeValue); + assertOffsetAndToken(9, TokenType.AttributeName); assertOffsetAndToken(12, TokenType.StartTagSelfClose); } diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/extensions/contentmodel/XMLSyntaxDiagnosticsTest.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/extensions/contentmodel/XMLSyntaxDiagnosticsTest.java index 736f44deaf..572dc8c1d3 100644 --- a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/extensions/contentmodel/XMLSyntaxDiagnosticsTest.java +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/extensions/contentmodel/XMLSyntaxDiagnosticsTest.java @@ -257,7 +257,7 @@ public void testPseudoAttrNameExpected() throws Exception { @Test public void testQuoteRequiredInXMLDecl() throws Exception { String xml = ""; - testDiagnosticsFor(xml, d(0, 15, 0, 23, XMLSyntaxErrorCode.QuoteRequiredInXMLDecl)); + testDiagnosticsFor(xml, d(0, 13, 0, 14, XMLSyntaxErrorCode.QuoteRequiredInXMLDecl)); } @Test diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/XMLFormatterTest.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/XMLFormatterTest.java index f8160475c6..640b06307e 100644 --- a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/XMLFormatterTest.java +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/services/XMLFormatterTest.java @@ -1304,6 +1304,153 @@ public void testIncompleteAttlistInternalDecl() throws BadLocationException { ""; format(content, expected, formattingOptions, "test.dtd"); } + + @Test + public void testUseDoubleQuotesFromDoubleQuotes() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setQuotations(XMLFormattingOptions.DOUBLE_QUOTES_VALUE); + + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseInvalidValueFromDoubleQuotes() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setQuotations("INVALID_VALUE"); + + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseSingleQuotesFromSingleQuotes() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE); + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseSingleQuotesFromDoubleQuotes() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE); + + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseDoubleQuotesFromSingleQuotes() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseSingleQuotesNoQuotes() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE); + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseSingleQuotesNoQuotesSplit() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE); + formattingOptions.setSplitAttributes(true); + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testAttValueOnlyStartQuote() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE); + String content = + " "; + String expected = + " "; + format(content, expected, formattingOptions); + } + + @Test + public void testUseDoubleQuotesMultipleAttributes() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseSingleQuotesMultipleAttributes() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE); + + String content = + " "; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseDoubleQuotesMultipleAttributesSplit() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setSplitAttributes(true); + + String content = + " \n"; + String expected = + ""; + format(content, expected, formattingOptions); + } + + @Test + public void testUseSingleQuotesMultipleAttributesSplit() throws BadLocationException { + XMLFormattingOptions formattingOptions = createDefaultFormattingOptions(); + formattingOptions.setSplitAttributes(true); + formattingOptions.setQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE); + String content = + " \n"; + String expected = + ""; + format(content, expected, formattingOptions); + } @Test diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/settings/SettingsTest.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/settings/SettingsTest.java index 589f324684..afe3cc9bfe 100644 --- a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/settings/SettingsTest.java +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/settings/SettingsTest.java @@ -55,7 +55,8 @@ public void initializationOptionsSettings() { " \"splitAttributes\": true,\r\n" + // " \"joinCDATALines\": true,\r\n" + // " \"formatComments\": true,\r\n" + // - " \"joinCommentLines\": true\r\n" + // + " \"joinCommentLines\": true,\r\n" + // + " \"quotations\": " + XMLFormattingOptions.DOUBLE_QUOTES_VALUE + "\r\n" + // " }\r\n" + " }\r\n" + " }\r\n" + @@ -103,19 +104,28 @@ public void formatSettings() { sharedXMLFormattingOptions.setTabSize(10); sharedXMLFormattingOptions.setInsertSpaces(true); sharedXMLFormattingOptions.setJoinCommentLines(true); + sharedXMLFormattingOptions.setQuotations(XMLFormattingOptions.SINGLE_QUOTES_VALUE); // formatting options coming from request FormattingOptions formattingOptions = new FormattingOptions(); formattingOptions.setTabSize(5); formattingOptions.setInsertSpaces(false); + + XMLFormattingOptions xmlFormattingOptions = new XMLFormattingOptions(formattingOptions); + + xmlFormattingOptions.setQuotations("InvalidValue"); // set a value that is not recognized + Assert.assertEquals(5, xmlFormattingOptions.getTabSize()); // value coming from the request formattingOptions Assert.assertFalse(xmlFormattingOptions.isInsertSpaces()); // formattingOptions doesn't defines insert spaces // flag Assert.assertFalse(xmlFormattingOptions.isJoinCommentLines());//Since default for JoinCommentLines is False + // Assumes the "InvalidValue" will be overridden + Assert.assertTrue(xmlFormattingOptions.getQuotations().equals(XMLFormattingOptions.DOUBLE_QUOTES_VALUE)); + // merge with shared sharedXMLFormattingOptions (formatting settings created in // the InitializeParams xmlFormattingOptions.merge(sharedXMLFormattingOptions); @@ -125,5 +135,7 @@ public void formatSettings() { Assert.assertFalse(xmlFormattingOptions.isInsertSpaces()); // insert spaces is kept as false because only the request's // formattingOptions object is allowed to define it. Assert.assertTrue(xmlFormattingOptions.isJoinCommentLines()); + + Assert.assertTrue(xmlFormattingOptions.getQuotations().equals(XMLFormattingOptions.SINGLE_QUOTES_VALUE)); } }