From 5082892530a27f4a101035c436b318ea905628a5 Mon Sep 17 00:00:00 2001 From: azerr Date: Tue, 2 Jun 2020 19:52:54 +0200 Subject: [PATCH] Quickfix to close open tag doesn't deal with attributes Fixes #646 Signed-off-by: azerr --- .../participants/XMLSyntaxErrorCode.java | 60 +++- .../codeactions/CloseStartTagCodeAction.java | 152 ++++++++++ .../codeactions/ETagRequiredCodeAction.java | 21 +- .../ElementUnterminatedCodeAction.java | 49 +--- .../MarkupEntityMismatchCodeAction.java | 68 +---- .../XMLSyntaxDiagnosticsTest.java | 274 +++++++++++++----- 6 files changed, 412 insertions(+), 212 deletions(-) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/CloseStartTagCodeAction.java diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/XMLSyntaxErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/XMLSyntaxErrorCode.java index 49cde4521..5a255cede 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/XMLSyntaxErrorCode.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/XMLSyntaxErrorCode.java @@ -22,6 +22,8 @@ import org.apache.xerces.xni.XMLLocator; import org.eclipse.lemminx.dom.DOMDocument; import org.eclipse.lemminx.dom.DOMDocumentType; +import org.eclipse.lemminx.dom.DOMElement; +import org.eclipse.lemminx.dom.DOMNode; import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.ETagRequiredCodeAction; import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.ElementUnterminatedCodeAction; import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.EqRequiredInAttributeCodeAction; @@ -44,7 +46,8 @@ public enum XMLSyntaxErrorCode implements IXMLErrorCode { AttributeNotUnique, // https://wiki.xmldation.com/Support/Validator/AttributeNotUnique AttributeNSNotUnique, // https://wiki.xmldation.com/Support/Validator/AttributeNSNotUnique - AttributePrefixUnbound, ContentIllegalInProlog, // https://wiki.xmldation.com/Support/Validator/ContentIllegalInProlog + AttributePrefixUnbound, // + ContentIllegalInProlog, // https://wiki.xmldation.com/Support/Validator/ContentIllegalInProlog DashDashInComment, // https://wiki.xmldation.com/Support/Validator/DashDashInComment ElementUnterminated, // https://wiki.xmldation.com/Support/Validator/ElementUnterminated ElementPrefixUnbound, // https://wiki.xmldation.com/Support/Validator/ElementPrefixUnbound @@ -53,11 +56,30 @@ public enum XMLSyntaxErrorCode implements IXMLErrorCode { ETagRequired, // https://wiki.xmldation.com/Support/Validator/ETagRequired ETagUnterminated, // https://wiki.xmldation.com/Support/Validator/ETagUnterminated EqRequiredInAttribute, // https://wiki.xmldation.com/Support/Validator/EqRequiredInAttribute - the_element_type_lmsg("the-element-type-lmsg"), EqRequiredInXMLDecl, IllegalQName, InvalidCommentStart, - LessthanInAttValue, MarkupEntityMismatch, MarkupNotRecognizedInContent, NameRequiredInReference, OpenQuoteExpected, - PITargetRequired, PseudoAttrNameExpected, QuoteRequiredInXMLDecl, RootElementTypeMustMatchDoctypedecl, - SDDeclInvalid, SemicolonRequiredInReference, SpaceRequiredBeforeEncodingInXMLDecl, SpaceRequiredBeforeStandalone, SpaceRequiredInPI, - VersionInfoRequired, VersionNotSupported, XMLDeclUnterminated, CustomETag, PrematureEOF, DoctypeNotAllowed, NoMorePseudoAttributes; + EqRequiredInXMLDecl, // + IllegalQName, // + InvalidCommentStart, // + LessthanInAttValue, // + MarkupEntityMismatch, // + MarkupNotRecognizedInContent, // + NameRequiredInReference, // + OpenQuoteExpected, // + PITargetRequired, // + PseudoAttrNameExpected, // + QuoteRequiredInXMLDecl, // + RootElementTypeMustMatchDoctypedecl, // + SDDeclInvalid, // + SemicolonRequiredInReference, // + SpaceRequiredBeforeEncodingInXMLDecl, // + SpaceRequiredBeforeStandalone, // + SpaceRequiredInPI, // + VersionInfoRequired, // + VersionNotSupported, // + XMLDeclUnterminated, // + CustomETag, // + PrematureEOF, // + DoctypeNotAllowed, // + NoMorePseudoAttributes; private final String code; @@ -108,13 +130,30 @@ public static Range toLSPRange(XMLLocator location, XMLSyntaxErrorCode code, Obj case SpaceRequiredBeforeEncodingInXMLDecl: case VersionInfoRequired: case ElementPrefixUnbound: - case ElementUnterminated: case RootElementTypeMustMatchDoctypedecl: return XMLPositionUtility.selectStartTagName(offset, document); case EqRequiredInAttribute: { String attrName = getString(arguments[1]); return XMLPositionUtility.selectAttributeNameFromGivenNameAt(attrName, offset, document); } + case MarkupEntityMismatch: + case ElementUnterminated: { + String text = document.getText(); + if (offset < text.length()) { + DOMNode element = document.findNodeAt(offset); + if (element.isElement() && !((DOMElement) element).isStartTagClosed()) { + // ex : codeActions, + SharedSettings sharedSettings, IComponentProvider componentProvider) { + Range diagnosticRange = diagnostic.getRange(); + try { + int startOffset = document.offsetAt(diagnosticRange.getStart()); + DOMNode node = document.findNodeAt(startOffset); + if (node != null && node.isElement()) { + int diagnosticEndOffset = document.offsetAt(diagnosticRange.getEnd()); + DOMElement element = (DOMElement) node; + if (!element.hasStartTag()) { + // + DOMElement parent = element.getParentElement(); + if (parent != null && parent.getTagName() != null) { + // + // Replace with 'b' closing tag + String tagName = parent.getTagName(); + Range replaceRange = XMLPositionUtility.selectEndTagName(element); + CodeAction replaceTagAction = CodeActionFactory.replace("Replace with '" + tagName + "' closing tag", + replaceRange, tagName, document.getTextDocument(), diagnostic); + codeActions.add(replaceTagAction); + } + } else { + // + boolean startTagClosed = element.isStartTagClosed(); + char c = document.getText().charAt(diagnosticEndOffset - 1); + if (c != '/') { + if (startTagClosed) { + // ex : + // // Close with ' + String tagName = element.getTagName(); + if (tagName != null) { + String label = ""; + String insertText = label; + Position endPosition = null; + if (!element.hasChildNodes()) { + int endOffset = element.getStartTagCloseOffset() + 1; + endPosition = document.positionAt(endOffset); + } else { + String text = document.getText(); + // the element have some children(Text node, Element node, etc) + int endOffset = element.getLastChild().getEnd() - 1; + if (endOffset < text.length()) { + // remove whitespaces + char ch = text.charAt(endOffset); + while (Character.isWhitespace(ch)) { + endOffset--; + ch = text.charAt(endOffset); + } + } + endOffset++; + endPosition = document.positionAt(endOffset); + if (hasElements(element)) { + // The element have element node as children + // the must be inserted with a new line and indent + LineIndentInfo indentInfo = document + .getLineIndentInfo(diagnosticRange.getStart().getLine()); + insertText = indentInfo.getLineDelimiter() + indentInfo.getWhitespacesIndent() + + insertText; + } + } + CodeAction closeEndTagAction = CodeActionFactory.insert("Close with '" + label + "'", + endPosition, insertText, document.getTextDocument(), diagnostic); + codeActions.add(closeEndTagAction); + } + + } else { + // ex : '", + diagnosticRange.getEnd(), "/>", document.getTextDocument(), diagnostic); + codeActions.add(autoCloseAction); + // // Close with '> + String tagName = element.getTagName(); + if (tagName != null) { + String insertText = ">"; + CodeAction closeEndTagAction = CodeActionFactory.insert( + "Close with '" + insertText + "'", diagnosticRange.getEnd(), insertText, + document.getTextDocument(), diagnostic); + codeActions.add(closeEndTagAction); + } + } + } + + if (!startTagClosed) { + // Close with '> + CodeAction closeAction = CodeActionFactory.insert("Close with '>'", diagnosticRange.getEnd(), + ">", document.getTextDocument(), diagnostic); + codeActions.add(closeAction); + } + } + } + } catch (BadLocationException e) { + // do nothing + } + } + + /** + * Returns true if the given element has elements as children and false + * otherwise. + * + * @param element the DOM element. + * + * @return true if the given element has elements as children and false + * otherwise. + */ + private static boolean hasElements(DOMElement element) { + for (DOMNode node : element.getChildren()) { + if (node.isElement()) { + return true; + } + } + return false; + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/ETagRequiredCodeAction.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/ETagRequiredCodeAction.java index 8d808a28b..b40282257 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/ETagRequiredCodeAction.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/ETagRequiredCodeAction.java @@ -11,26 +11,9 @@ *******************************************************************************/ package org.eclipse.lemminx.extensions.contentmodel.participants.codeactions; -import java.util.List; - -import org.eclipse.lemminx.dom.DOMDocument; -import org.eclipse.lemminx.services.extensions.ICodeActionParticipant; -import org.eclipse.lemminx.services.extensions.IComponentProvider; -import org.eclipse.lemminx.settings.SharedSettings; -import org.eclipse.lsp4j.CodeAction; -import org.eclipse.lsp4j.Diagnostic; -import org.eclipse.lsp4j.Range; - /** - * ETagRequiredCodeAction + * Code action to fix ETagRequired error. */ -public class ETagRequiredCodeAction implements ICodeActionParticipant { - - @Override - public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List codeActions, - SharedSettings sharedSettings, IComponentProvider componentProvider) { - MarkupEntityMismatchCodeAction.createEndTagInsertCodeAction(diagnostic, range, document, codeActions, componentProvider); - } +public class ETagRequiredCodeAction extends CloseStartTagCodeAction { - } \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/ElementUnterminatedCodeAction.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/ElementUnterminatedCodeAction.java index b61cb27a7..2326d150f 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/ElementUnterminatedCodeAction.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/ElementUnterminatedCodeAction.java @@ -12,56 +12,9 @@ */ package org.eclipse.lemminx.extensions.contentmodel.participants.codeactions; -import java.util.List; - -import org.eclipse.lemminx.commons.BadLocationException; -import org.eclipse.lemminx.commons.CodeActionFactory; -import org.eclipse.lemminx.dom.DOMDocument; -import org.eclipse.lemminx.dom.DOMElement; -import org.eclipse.lemminx.dom.DOMNode; -import org.eclipse.lemminx.services.extensions.ICodeActionParticipant; -import org.eclipse.lemminx.services.extensions.IComponentProvider; -import org.eclipse.lemminx.settings.SharedSettings; -import org.eclipse.lsp4j.CodeAction; -import org.eclipse.lsp4j.Diagnostic; -import org.eclipse.lsp4j.Range; - /** * Code action to fix ElementUnterminated error. * */ -public class ElementUnterminatedCodeAction implements ICodeActionParticipant { - - @Override - public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List codeActions, - SharedSettings sharedSettings, IComponentProvider componentProvider) { - Range diagnosticRange = diagnostic.getRange(); - // Close with '/> - CodeAction autoCloseAction = CodeActionFactory.insert("Close with '/>'", diagnosticRange.getEnd(), "/>", - document.getTextDocument(), diagnostic); - codeActions.add(autoCloseAction); - - // Close with '> - CodeAction closeAction = CodeActionFactory.insert("Close with '>'", diagnosticRange.getEnd(), ">", - document.getTextDocument(), diagnostic); - codeActions.add(closeAction); - - // Close with '$tag> - try { - int offset = document.offsetAt(range.getStart()); - DOMNode node = document.findNodeAt(offset); - if (node != null && node.isElement()) { - String tagName = ((DOMElement) node).getTagName(); - if (tagName != null) { - String insertText = ">"; - CodeAction closeEndTagAction = CodeActionFactory.insert("Close with '" + insertText + "'", - diagnosticRange.getEnd(), insertText, document.getTextDocument(), diagnostic); - codeActions.add(closeEndTagAction); - } - } - } catch (BadLocationException e) { - // do nothing - } - } - +public class ElementUnterminatedCodeAction extends CloseStartTagCodeAction { } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/MarkupEntityMismatchCodeAction.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/MarkupEntityMismatchCodeAction.java index a7b79628b..c0087e47d 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/MarkupEntityMismatchCodeAction.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/MarkupEntityMismatchCodeAction.java @@ -11,77 +11,11 @@ *******************************************************************************/ package org.eclipse.lemminx.extensions.contentmodel.participants.codeactions; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.eclipse.lemminx.commons.BadLocationException; -import org.eclipse.lemminx.commons.CodeActionFactory; -import org.eclipse.lemminx.dom.DOMDocument; -import org.eclipse.lemminx.dom.DOMElement; -import org.eclipse.lemminx.dom.DOMNode; -import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSyntaxErrorCode; -import org.eclipse.lemminx.services.extensions.ICodeActionParticipant; -import org.eclipse.lemminx.services.extensions.IComponentProvider; -import org.eclipse.lemminx.settings.SharedSettings; -import org.eclipse.lsp4j.CodeAction; -import org.eclipse.lsp4j.Diagnostic; -import org.eclipse.lsp4j.Position; -import org.eclipse.lsp4j.Range; - /** * MarkupEntityMismatchCodeAction is a code action that triggers when the end * tag of the root element is missing. This will provide a codeaction that * inserts that missing end tag. */ -public class MarkupEntityMismatchCodeAction implements ICodeActionParticipant { - private static final Logger LOGGER = Logger.getLogger(MarkupEntityMismatchCodeAction.class.getName()); - - @Override - public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List codeActions, - SharedSettings sharedSettings, IComponentProvider componentProvider) { - createEndTagInsertCodeAction(diagnostic, range, document, codeActions, componentProvider); - } - - public static void createEndTagInsertCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, - List codeActions, IComponentProvider componentProvider) { - try { - int offset = document.offsetAt(diagnostic.getRange().getStart()); - DOMNode node = document.findNodeAt(offset); - if (!node.isElement()) { - return; - } - - DOMElement element = (DOMElement) node; - int startOffset = element.getStartTagOpenOffset(); - if (startOffset == -1) { - return; - } - Position startPosition = document.positionAt(startOffset); - Position endPosition; - - XMLSyntaxErrorCode code = XMLSyntaxErrorCode.get(diagnostic.getCode().getLeft()); - switch (code) { - case MarkupEntityMismatch: - endPosition = document.positionAt(document.getEnd()); - if (endPosition.getLine() > startPosition.getLine()) { - endPosition.setCharacter(startPosition.getCharacter()); - } - break; - case ETagRequired: - endPosition = document.positionAt(element.getStartTagCloseOffset() + 1); - break; - default: - return; - } - - String elementName = element.getTagName(); - CodeAction action = CodeActionFactory.insert("Close with ''", endPosition, - "", document.getTextDocument(), diagnostic); - codeActions.add(action); - } catch (BadLocationException e) { - LOGGER.log(Level.WARNING, "Exception while resolving the code action for " + diagnostic.getCode() + ":", e); - } - } +public class MarkupEntityMismatchCodeAction extends CloseStartTagCodeAction { } \ No newline at end of file diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSyntaxDiagnosticsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSyntaxDiagnosticsTest.java index f2932f912..0c31b1e3e 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSyntaxDiagnosticsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/XMLSyntaxDiagnosticsTest.java @@ -31,7 +31,7 @@ * */ public class XMLSyntaxDiagnosticsTest { - + /** * AttributeNotUnique tests * @@ -66,9 +66,9 @@ public void testAttributeNSNotUnique() throws Exception { @Test public void testAttributeNSNotUnique2() throws Exception { - String xml = "\r\n" + - "\r\n" + // + ""; testDiagnosticsFor(xml, d(2, 1, 2, 10, XMLSyntaxErrorCode.AttributeNSNotUnique)); } @@ -120,7 +120,7 @@ public void testEncodingUTF_16() throws Exception { String xml = ""; testDiagnosticsFor(xml); } - + /** * DashDashInComment tests * @@ -142,7 +142,7 @@ public void testDashDashInComment() throws Exception { * @throws Exception */ @Test - public void testElementUnterminated() throws Exception { + public void elementUnterminated() throws Exception { String xml = "\r\n" + // " \r\n" + // @@ -152,8 +152,69 @@ public void testElementUnterminated() throws Exception { " "; Diagnostic d = d(1, 11, 1, 16, XMLSyntaxErrorCode.ElementUnterminated); testDiagnosticsFor(xml, d); - testCodeActionsFor(xml, d, ca(d, te(1, 16, 1, 16, "/>")), ca(d, te(1, 16, 1, 16, ">")), - ca(d, te(1, 16, 1, 16, ">"))); + testCodeActionsFor(xml, d, // + ca(d, te(1, 16, 1, 16, "/>")), // + ca(d, te(1, 16, 1, 16, ">")), // + ca(d, te(1, 16, 1, 16, ">"))); + } + + @Test + public void testElementUnterminatedEndsWithSlash() throws Exception { + String xml = "\r\n" + // + " "; + Diagnostic d = d(1, 3, 1, 15, XMLSyntaxErrorCode.ElementUnterminated); + testDiagnosticsFor(xml, d); + testCodeActionsFor(xml, d, // + ca(d, te(1, 15, 1, 15, ">"))); + } + + @Test + public void testElementUnterminatedEndsWithSlashAndSpaces() throws Exception { + String xml = "\r\n" + // + " "; + Diagnostic d = d(1, 3, 1, 15, XMLSyntaxErrorCode.ElementUnterminated); + testDiagnosticsFor(xml, d); + testCodeActionsFor(xml, d, // + ca(d, te(1, 15, 1, 15, ">"))); + } + + @Test + public void testElementUnterminatedEndsWithAttributes() throws Exception { + String xml = "\r\n" + // + " "; + Diagnostic d = d(1, 3, 1, 13, XMLSyntaxErrorCode.ElementUnterminated); + testDiagnosticsFor(xml, d); + testCodeActionsFor(xml, d, // + ca(d, te(1, 13, 1, 13, "/>")), // + ca(d, te(1, 13, 1, 13, ">")), // + ca(d, te(1, 13, 1, 13, ">"))); + } + + @Test + public void testElementUnterminatedEndsAndSpaces() throws Exception { + String xml = "\r\n" + // + " "; + Diagnostic d = d(1, 3, 1, 13, XMLSyntaxErrorCode.ElementUnterminated); + testDiagnosticsFor(xml, d); + testCodeActionsFor(xml, d, // + ca(d, te(1, 13, 1, 13, "/>")), // + ca(d, te(1, 13, 1, 13, ">")), // + ca(d, te(1, 13, 1, 13, ">"))); + } + + @Test + public void testETagRequiredWithReplace() throws Exception { + String xml = "\r\n" + // + " \r\n" + // + " "; + Diagnostic d = d(2, 4, 2, 5, XMLSyntaxErrorCode.ETagRequired); + testDiagnosticsFor(xml, d); + testCodeActionsFor(xml, d, // + ca(d, te(2, 4, 2, 5, "b"))); } /** @@ -217,7 +278,7 @@ public void testETagRequired() throws Exception { " "; Diagnostic d = d(1, 5, 1, 7, XMLSyntaxErrorCode.ETagRequired); testDiagnosticsFor(xml, d); - testCodeActionsFor(xml, d, ca(d, te(1, 8, 1, 8, ""))); + testCodeActionsFor(xml, d, ca(d, te(1, 12, 1, 12, ""))); } @Test @@ -230,10 +291,10 @@ public void testETagRequired2() throws Exception { @Test public void testETagRequired3() throws Exception { - String xml = "\r\n" + - " Name\r\n" + - " \r\n" + - " \r\n" + + String xml = "\r\n" + // + " Name\r\n" + // + " \r\n" + // + " \r\n" + // ""; Diagnostic d = d(3, 5, 3, 7, XMLSyntaxErrorCode.ETagRequired); testDiagnosticsFor(xml, d); @@ -261,8 +322,7 @@ public void testETagUnterminated() throws Exception { */ @Test public void testETagUnterminated2() throws Exception { - String xml = - "\r\n" + // + String xml = "\r\n" + // " \r\n" + // " \r\n" + // " def\r\n" + // + ""; + Diagnostic d = d(1, 1, 1, 4, XMLSyntaxErrorCode.ETagRequired); + testDiagnosticsFor(xml, d); + testCodeActionsFor(xml, d, ca(d, te(1, 8, 1, 8, ""))); + } + @Test public void testIllegalQName() throws Exception { String xml = "100"; @@ -290,20 +360,19 @@ public void testLessThanAttValue() throws Exception { @Test public void testMarkupEntityMismatch() throws Exception { - String xml = "\r\n" - + "\r\n" - + "\r\n" - + ""; - + String xml = "\r\n" + // + "\r\n" + + // + "\r\n" + // + ""; Diagnostic d = d(1, 1, 1, 9, XMLSyntaxErrorCode.MarkupEntityMismatch); testDiagnosticsFor(xml, d); - testCodeActionsFor(xml, d, ca(d, te(3, 0, 3, 0, ""))); + testCodeActionsFor(xml, d, ca(d, te(3, 19, 3, 19, "\r\n"))); } @Test public void testMarkupEntityMismatch2() throws Exception { String xml = ""; - Diagnostic d = d(0, 1, 0, 4, XMLSyntaxErrorCode.MarkupEntityMismatch); testDiagnosticsFor(xml, d); testCodeActionsFor(xml, d, ca(d, te(0, 5, 0, 5, ""))); @@ -312,11 +381,89 @@ public void testMarkupEntityMismatch2() throws Exception { @Test public void testMarkupEntityMismatch3() throws Exception { String xml = "")), // + ca(d, te(0, 4, 0, 4, ">")), // + ca(d, te(0, 4, 0, 4, ">"))); + } + + @Test + public void testMarkupEntityMismatchWithoutCloseAndNewLine() throws Exception { + String xml = "")), // + ca(d, te(0, 4, 0, 4, ">")), // + ca(d, te(0, 4, 0, 4, ">"))); + } + + @Test + public void testMarkupEntityMismatchWithoutCloseAndSpaces() throws Exception { + String xml = "")), // + ca(d, te(0, 4, 0, 4, ">")), // + ca(d, te(0, 4, 0, 4, ">"))); + } + + @Test + public void testMarkupEntityMismatchWithAttributes() throws Exception { + String xml = "")), // + ca(d, te(0, 9, 0, 9, ">")), // + ca(d, te(0, 9, 0, 9, ">"))); + } + + @Test + public void testMarkupEntityMismatchWithAttributesAndSlash() throws Exception { + String xml = ""))); + } + + @Test + public void testMarkupEntityMismatchWithText() throws Exception { + String xml = "def"; + Diagnostic d = d(0, 1, 0, 4, XMLSyntaxErrorCode.MarkupEntityMismatch); + testDiagnosticsFor(xml, d); + testCodeActionsFor(xml, d, ca(d, te(0, 8, 0, 8, ""))); + } + + @Test + public void testMarkupEntityMismatchWithTextAndNewLine() throws Exception { + String xml = "def\r\n"; + Diagnostic d = d(0, 1, 0, 4, XMLSyntaxErrorCode.MarkupEntityMismatch); + testDiagnosticsFor(xml, d); + testCodeActionsFor(xml, d, ca(d, te(0, 8, 0, 8, ""))); + } + + @Test + public void testMarkupEntityMismatchMultiLine() throws Exception { + String xml = ""))); + } + @Test public void testMarkupNotRecognizedInContent() throws Exception { String xml = "\r\n" + "<- almost a comment-->\r\n" + "2.012.001"; @@ -339,12 +486,11 @@ public void testOpenQuoteExpected() throws Exception { @Test public void testMissingQuotesForAttribute() throws Exception { - String xml = - "\r\n" + - "\r\n" + - " \r\n" + - " \r\n" + - ""; + String xml = "\r\n" + // + "\r\n" + // + " \r\n" + // + " \r\n" + // + ""; Diagnostic diagnostic1 = d(2, 7, 2, 10, XMLSyntaxErrorCode.OpenQuoteExpected); testDiagnosticsFor(xml, diagnostic1); testCodeActionsFor(xml, diagnostic1, ca(diagnostic1, te(2, 11, 2, 11, "\"\""))); @@ -352,11 +498,10 @@ public void testMissingQuotesForAttribute() throws Exception { @Test public void testMissingQuotesForAttributeSelfClosing() throws Exception { - String xml = - "\r\n" + - "\r\n" + - " \r\n" + - ""; + String xml = "\r\n" + // + "\r\n" + // + " \r\n" + // + ""; Diagnostic diagnostic1 = d(2, 7, 2, 10, XMLSyntaxErrorCode.OpenQuoteExpected); testDiagnosticsFor(xml, diagnostic1); testCodeActionsFor(xml, diagnostic1, ca(diagnostic1, te(2, 11, 2, 11, "\"\""))); @@ -364,11 +509,10 @@ public void testMissingQuotesForAttributeSelfClosing() throws Exception { @Test public void testMissingQuotesForAttributeSelfClosing2() throws Exception { - String xml = - "\r\n" + - "\r\n" + - " \r\n" + - ""; + String xml = "\r\n" + // + "\r\n" + // + " \r\n" + // + ""; Diagnostic diagnostic1 = d(2, 7, 2, 10, XMLSyntaxErrorCode.OpenQuoteExpected); testDiagnosticsFor(xml, diagnostic1); testCodeActionsFor(xml, diagnostic1, ca(diagnostic1, te(2, 11, 2, 11, "\"\""))); @@ -376,11 +520,10 @@ public void testMissingQuotesForAttributeSelfClosing2() throws Exception { @Test public void testMissingQuotesForAttributeUsingNextValue() throws Exception { - String xml = - "\r\n" + - "\r\n" + - " \r\n" + - ""; + String xml = "\r\n" + // + "\r\n" + // + " \r\n" + // + ""; Diagnostic diagnostic1 = d(2, 7, 2, 10, XMLSyntaxErrorCode.OpenQuoteExpected); testDiagnosticsFor(xml, diagnostic1); testCodeActionsFor(xml, diagnostic1, ca(diagnostic1, te(2, 11, 2, 15, "\"two\""))); @@ -388,11 +531,10 @@ public void testMissingQuotesForAttributeUsingNextValue() throws Exception { @Test public void testMissingQuotesForAttributeSingleQuotes() throws Exception { - String xml = - "\r\n" + - "\r\n" + - " \r\n" + - ""; + String xml = "\r\n" + // + "\r\n" + // + " \r\n" + // + ""; Diagnostic diagnostic1 = d(2, 7, 2, 10, XMLSyntaxErrorCode.OpenQuoteExpected); testDiagnosticsFor(xml, diagnostic1); SharedSettings settings = new SharedSettings(); @@ -404,7 +546,9 @@ public void testMissingQuotesForAttributeSingleQuotes() throws Exception { @Test public void testOpenQuoteExpectedDisabledPreference() throws Exception { String xml = " 10000000"; - testDiagnosticsFor(xml, null, null, null, true, XMLAssert.getContentModelSettings(false, true)); //validation is disabled + testDiagnosticsFor(xml, null, null, null, true, XMLAssert.getContentModelSettings(false, true)); // validation + // is + // disabled } @Test @@ -427,14 +571,12 @@ public void testQuoteRequiredInXMLDecl() throws Exception { @Test public void testRootElementTypeMustMatchDoctypedecl() throws Exception { - String xml = - "\r\n" + - "\r\n" + - "\r\n" + - "]> \r\n" + - ""; - + String xml = "\r\n" + // + "\r\n" + // + "\r\n" + // + "]> \r\n" + // + ""; String expectedMessage = "Document root element \"abcd\", must match DOCTYPE root \"efgh\"."; Diagnostic d = d(5, 1, 5, 5, XMLSyntaxErrorCode.RootElementTypeMustMatchDoctypedecl, expectedMessage); testDiagnosticsFor(xml, d); @@ -443,14 +585,12 @@ public void testRootElementTypeMustMatchDoctypedecl() throws Exception { @Test public void testRootElementTypeMustMatchDoctypedecl2() throws Exception { - String xml = - "\r\n" + - "\r\n" + - "\r\n" + - "]> \r\n" + - "test"; - + String xml = "\r\n" + // + "\r\n" + // + "\r\n" + // + "]> \r\n" + // + "test"; String expectedMessage = "Document root element \"abcd\", must match DOCTYPE root \"efgh\"."; Diagnostic d = d(5, 1, 5, 5, XMLSyntaxErrorCode.RootElementTypeMustMatchDoctypedecl, expectedMessage); testDiagnosticsFor(xml, d);