Skip to content

Commit

Permalink
Error ranges fixed
Browse files Browse the repository at this point in the history
Fixes eclipse-lemminx#321, eclipse-lemminx#318, eclipse-lemminx#317

Signed-off-by: Nikolas <nikolaskomonen@gmail.com>
  • Loading branch information
NikolasKomonen committed Mar 14, 2019
1 parent d091cb7 commit 5f56d6a
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ public enum XMLSchemaErrorCode implements IXMLErrorCode {
cvc_datatype_valid_1_2_1("cvc-datatype-valid.1.2.1"), // https://wiki.xmldation.com/Support/Validator/cvc-datatype-valid-1-2-1
cvc_elt_1_a("cvc-elt.1.a"), // https://wiki.xmldation.com/Support/Validator/cvc-elt-1
cvc_elt_3_1("cvc-elt.3.1"), // https://wiki.xmldation.com/Support/Validator/cvc-elt-3-1
cvc_elt_3_2_1("cvc-elt.3.2.1"), //https://wiki.xmldation.com/Support/Validator/cvc-elt-3-2-1
cvc_elt_4_2("cvc-elt.4.2"), // https://wiki.xmldation.com/Support/Validator/cvc-elt-4-2
cvc_type_3_1_1("cvc-type.3.1.1"), // https://wiki.xmldation.com/Support/Validator/cvc-type-3-1-1
cvc_type_3_1_2("cvc-type.3.1.2"), // https://wiki.xmldation.com/Support/Validator/cvc-type-3-1-2
cvc_type_3_1_3("cvc-type.3.1.3"), // https://wiki.xmldation.com/Support/Validator/cvc-type-3-1-3,
cvc_attribute_3("cvc-attribute.3"), // https://wiki.xmldation.com/Support/Validator/cvc-attribute-3
cvc_enumeration_valid("cvc-enumeration-valid"), // https://wiki.xmldation.com/Support/Validator/cvc-enumeration-valid
Expand Down Expand Up @@ -148,7 +150,8 @@ public static Range toLSPRange(XMLLocator location, XMLSchemaErrorCode code, Obj
return XMLPositionUtility.selectAllAttributes(offset, document);
case cvc_complex_type_2_1:
case cvc_type_3_1_3:
return XMLPositionUtility.selectText(offset, document);
case cvc_elt_3_2_1:
return XMLPositionUtility.selectContent(offset, document);
case cvc_enumeration_valid:
case cvc_datatype_valid_1_2_1:
case cvc_maxlength_valid:
Expand All @@ -165,9 +168,11 @@ public static Range toLSPRange(XMLLocator location, XMLSchemaErrorCode code, Obj
return range;
} else {
// Try with text
return XMLPositionUtility.selectText(offset, document);
return XMLPositionUtility.selectContent(offset, document);
}
}
case cvc_type_3_1_2:
return XMLPositionUtility.selectStartTag(offset, document);
default:
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,16 @@ public static Range toLSPRange(XMLLocator location, XMLSyntaxErrorCode code, Obj
return XMLPositionUtility.selectAttributeValueByGivenValueAt(attrValue, offset, document);
}
case ETagUnterminated:
return XMLPositionUtility.selectPreviousEndTag(offset - 1, document);
/**
* Cases:
*
* <a> </b>
*
* <a> <b> </b> </c>
*
* <a> <a> </a> </b
*/
return XMLPositionUtility.selectPreviousNodesEndTag(offset, document);
case CustomETag:
return XMLPositionUtility.selectEndTag(offset, document);
case ETagRequired: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public static Range toLSPRange(XMLLocator location, XSDErrorCode code, Object[]
return XMLPositionUtility.selectAttributeValueAt(attrName, offset, document);
}
case s4s_elt_character:
return XMLPositionUtility.selectText(offset, document);
return XMLPositionUtility.selectContent(offset, document);
case src_resolve_4_2:
case src_resolve:
String attrValue = (String) arguments[2];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,9 @@ private static Object[] cvc_2_4_b_solution(Object[] arguments) {
}
element = "- " + (String) arguments[0];
return new Object[] { element, missingChildElements , schema };
}
}

public static Object[] enumeration_valid_solution(Object[] arguments) {
return new Object[] { (String) arguments[0], reformatArrayElementNames((String)arguments[1])};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,42 @@ public static Range selectFirstNonWhitespaceText(int offset, DOMDocument documen
/**
* Finds the offset of the first tag it comes across behind the given offset.
*
* This includes the tag it starts in if offset is within a tag's content.
* <p>This will include the tag it starts in if the offset is within a tag's content: </p>
* <p>
* {@code <a> <b> | </b> </a> } , will give {@code </b>}
* </p>
*
* or within an unclosed end tag:
*
* <p>
* {@code <a> <b> </b> </a| <c>} , will give {@code </a>}
* </p>
*
*
* <p>
* {@code <a> <b|> </b> </a>} , will give {@code </a>}
* </p>
*
* eg:
* <a> <b> | </b> </a> , will give 'b'
* <a> <b|> </b> </a> , will give 'a'
*/
public static Range selectPreviousEndTag(int offset, DOMDocument document) {
public static Range selectPreviousNodesEndTag(int offset, DOMDocument document) {

DOMNode node = null;
DOMNode nodeAt = document.findNodeAt(offset);
if(nodeAt != null && nodeAt.isElement()) {
node = nodeAt;
} else {
DOMNode nodeBefore = document.findNodeBefore(offset);
if(nodeBefore != null && nodeBefore.isElement()) {
node = nodeBefore;
}
}
if(node != null) {
DOMElement element = (DOMElement) node;
if(element.isClosed() && element.getEndTagCloseOffset() == null) {
return selectEndTag(element.getEnd(), document);
}
}

// boolean firstBracket = false;
int i = offset;
char c = document.getText().charAt(i);
Expand All @@ -337,18 +366,15 @@ public static Range createRange(int startOffset, int endOffset, DOMDocument docu
}
}

public static Range selectText(int offset, DOMDocument document) {
public static Range selectContent(int offset, DOMDocument document) {
DOMNode node = document.findNodeAt(offset);
if (node != null) {
if (node.hasChildNodes()) {
// <root>BAD TEXT</root>
for (DOMNode child : node.getChildren()) {
if (child.isText()) {
return createRange(child.getStart(), child.getEnd(), document);
}
if (node.isElement()) {
DOMElement element = (DOMElement) node;
if(node.hasChildNodes()) {
return createRange(element.getStartTagCloseOffset() + 1, element.getEndTagOpenOffset(), document);
}
} else if (node.isElement()) {
// node has NONE text (ex: <root></root>, select the start tag
// node has NO content (ex: <root></root>, select the start tag
return selectStartTag(node);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import org.eclipse.lsp4xml.XMLAssert;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.XMLSchemaErrorCode;
import org.eclipse.lsp4xml.extensions.contentmodel.settings.ContentModelSettings;
import org.junit.Ignore;
import org.junit.Test;

/**
Expand Down Expand Up @@ -315,6 +314,43 @@ public void cvc_elt_3_1() throws Exception {

}

@Test
public void cvc_type_3_2_1() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + //
"<invoice xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n" + //
" xsi:noNamespaceSchemaLocation=\"src/test/resources/xsd/invoice.xsd\">\r\n" + //
" <date xsi:nil=\"true\">2017-11-30</date>\r\n" + // <- error
" <number>0</number>\r\n" + //
" <products>\r\n" + //
" <product price=\"1\" description=\"\"/>\r\n" + //
" </products>\r\n" + //
" <payments>\r\n" + //
" <payment amount=\"1\" method=\"credit\"/>\r\n" + //
" </payments>\r\n" + //
"</invoice>";
testDiagnosticsFor(xml, d(3, 23, 3, 33, XMLSchemaErrorCode.cvc_elt_3_2_1));
}

@Test
public void cvc_type_3_1_2() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + //
"<invoice xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n" + //
" xsi:noNamespaceSchemaLocation=\"src/test/resources/xsd/invoice.xsd\">\r\n" + //
" <date>2017-11-30</date>\r\n" + //
" <number><a></a></number>\r\n" + //<- error
" <products>\r\n" + //
" <product price=\"1\" description=\"\"/>\r\n" + //
" </products>\r\n" + //
" <payments>\r\n" + //
" <payment amount=\"1\" method=\"credit\"/>\r\n" + //
" </payments>\r\n" + //
"</invoice>";
testDiagnosticsFor(xml,
d(4, 3, 4, 9, XMLSchemaErrorCode.cvc_type_3_1_2),
d(4,10,4,17, XMLSchemaErrorCode.cvc_datatype_valid_1_2_1),
d(4,10,4,17, XMLSchemaErrorCode.cvc_type_3_1_3));
}

private static void testDiagnosticsFor(String xml, Diagnostic... expected) {
XMLAssert.testDiagnosticsFor(xml, "src/test/resources/catalogs/catalog.xml", expected);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,25 @@ public void testETagUnterminated() throws Exception {
testDiagnosticsFor(xml, d(0, 26, 0, 31, XMLSyntaxErrorCode.ETagUnterminated));
}

/**
* Test ETagUnterminated
*
* @see https://wiki.xmldation.com/Support/Validator/ETagUnterminated
* @throws Exception
*/
@Test
public void testETagUnterminated2() throws Exception {
String xml =
"<a>\r\n" + //
" <b>\r\n" + //
" <c></c>\r\n" + //
" </b\r\n" + // <- error
"</a>";
testDiagnosticsFor(xml, d(3, 4, 3, 5, XMLSyntaxErrorCode.ETagUnterminated));
}



@Test
public void testIllegalQName() throws Exception {
String xml = "<a Ccy:\"JPY\">100</a>";
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.lsp4xml/src/test/resources/xsd/invoice.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<xsd:documentation>An invoice type...</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="date" type="xsd:date"></xsd:element>
<xsd:element name="date" type="xsd:date" nillable="true"></xsd:element>
<xsd:element name="number" type="xsd:int"></xsd:element>
<xsd:element name="products" type="productsType"></xsd:element>
<xsd:element name="payments" type="paymentsType"></xsd:element>
Expand Down

0 comments on commit 5f56d6a

Please sign in to comment.