Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error ranges fixed #325

Merged
merged 1 commit into from
Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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