Skip to content

Commit

Permalink
DTD Error Ranges Adjusted
Browse files Browse the repository at this point in the history
Fixes eclipse-lemminx#225

Signed-off-by: Nikolas Komonen <[email protected]>
  • Loading branch information
NikolasKomonen committed Jan 11, 2019
1 parent 393ca72 commit 27fb6c8
Show file tree
Hide file tree
Showing 14 changed files with 222 additions and 27 deletions.
2 changes: 2 additions & 0 deletions org.eclipse.lsp4xml/delete.dtd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<!ENTITY asdasds
<!ELEMENT asdasd>
1 change: 1 addition & 0 deletions org.eclipse.lsp4xml/delete.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<aplsepgflespglse </aplsepgflespglse>
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ private String toString(int indent) {
return result.toString();
}

/**
* Returns the node before
*/
public DOMNode findNodeBefore(int offset) {
List<DOMNode> children = getChildren();
int idx = findFirst(children, c -> offset <= c.start) - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ else if((curr.isClosed())) {
DTDAttlistDecl attribute = (DTDAttlistDecl) curr;
if(isInitialDeclaration == false) {
// All additional declarations are created as new DTDAttlistDecl's
DTDAttlistDecl child = new DTDAttlistDecl(-1, -1, attribute.getParentDocumentType()); // Wont use these values
DTDAttlistDecl child = new DTDAttlistDecl(attribute.getStart(), attribute.getEnd(), attribute.getParentDocumentType());
attribute.addAdditionalAttDecl(child);
child.parent = attribute;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class DTDAttlistDecl extends DTDDeclNode {

public DTDAttlistDecl(int start, int end, DOMDocumentType parentDocumentType) {
super(start, end, parentDocumentType);
declType = new DTDDeclParameter(parentDocumentType, start + 2, start + 9);
setDeclType(start + 2, start + 9);
}

public DOMDocumentType getParentDocumentType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public class DTDDeclNode extends DOMNode{
protected final DOMDocumentType parentDocumentType;
protected final DOMDocument parentDocument;

DTDDeclParameter unrecognized; // holds all content after parsing goes wrong in a DTD declaration (ENTITY, ATTLIST, ELEMENT).
DTDDeclParameter declType;
public DTDDeclParameter unrecognized; // holds all content after parsing goes wrong in a DTD declaration (ENTITY, ATTLIST, ...).
public DTDDeclParameter declType; // represents the actual name of the decl eg: ENTITY, ATTLIST, ...

ArrayList<DTDDeclParameter> parameters;

Expand Down Expand Up @@ -98,6 +98,10 @@ public ArrayList<DTDDeclParameter> getParameters() {
return parameters;
}

public void setDeclType(int start, int end) {
declType = new DTDDeclParameter(parentDocumentType, start, end);
}

public String getDeclType() {
if(declType != null) {
return declType.getParameter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ public DTDDeclParameter(DOMDocumentType doctype, int start, int end) {
this.end = end;
}

public int getStart() {
return start;
}

public int getEnd() {
return end;
}

public String getParameter() {
if (parameter == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public class DTDElementDecl extends DTDDeclNode {
*/

DTDDeclParameter name;
DTDDeclParameter category;
DTDDeclParameter content;
public DTDDeclParameter name;
public DTDDeclParameter category;
public DTDDeclParameter content;


public DTDElementDecl(int start, int end, DOMDocumentType parentDocumentType) {
super(start, end, parentDocumentType);
declType = new DTDDeclParameter(parentDocumentType, start + 2, start + 9);
setDeclType(start + 2, start + 9);
}

public DOMDocumentType getParentDocumentType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class DTDEntityDecl extends DTDDeclNode implements Entity {

public DTDEntityDecl(int start, int end, DOMDocumentType parentDocumentType) {
super(start, end, parentDocumentType);
declType = new DTDDeclParameter(parentDocumentType, start + 2, start + 8);
setDeclType(start + 2, start + 8);
}

public String getPercent() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class DTDNotationDecl extends DTDDeclNode {

public DTDNotationDecl(int start, int end, DOMDocumentType parentDocumentType) {
super(start, end, parentDocumentType);
declType = new DTDDeclParameter(parentDocumentType, start + 2, start + 10);
setDeclType(start + 2, start + 10);
}

void setName(int start, int end) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import java.util.Map;

import org.apache.xerces.xni.XMLLocator;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4xml.commons.BadLocationException;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.extensions.contentmodel.participants.codeactions.ElementDeclUnterminatedCodeAction;
Expand All @@ -30,12 +32,40 @@
*/
public enum DTDErrorCode implements IXMLErrorCode {

MSG_ELEMENT_NOT_DECLARED, MSG_CONTENT_INCOMPLETE, MSG_CONTENT_INVALID, MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
MSG_ATTRIBUTE_NOT_DECLARED, MSG_ATTRIBUTE_VALUE_NOT_IN_LIST, MSG_FIXED_ATTVALUE_INVALID,
MSG_ELEMENT_WITH_ID_REQUIRED, IDInvalidWithNamespaces, IDREFInvalidWithNamespaces, IDREFSInvalid,


MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL ,
ElementDeclUnterminated,
EntityDeclUnterminated,
AttlistDeclUnterminated,
NotationDeclUnterminated,
MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN,

MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL, MSG_MARKUP_NOT_RECOGNIZED_IN_DTD, ElementDeclUnterminated,
MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN;
MSG_ELEMENT_NOT_DECLARED,
IDREFSInvalid,
MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
MSG_FIXED_ATTVALUE_INVALID,
IDInvalidWithNamespaces,
MSG_ELEMENT_WITH_ID_REQUIRED,
MSG_CONTENT_INCOMPLETE,
MSG_CONTENT_INVALID,
MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
IDREFInvalidWithNamespaces,
MSG_ATTRIBUTE_NOT_DECLARED,
MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL,
MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL,
MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL,
ExternalIDorPublicIDRequired,
QuoteRequiredInPublicID,
AttNameRequiredInAttDef,
OpenQuoteExpected,
LessthanInAttValue,
AttTypeRequiredInAttDef,
MSG_SPACE_REQUIRED_AFTER_NOTATION_NAME_IN_NOTATIONDECL,
SpaceRequiredAfterSYSTEM,
OpenQuoteMissingInDecl,
QuoteRequiredInSystemID;

private final String code;

Expand Down Expand Up @@ -87,7 +117,7 @@ public static Range toLSPRange(XMLLocator location, DTDErrorCode code, Object[]
case MSG_CONTENT_INVALID:
return XMLPositionUtility.selectStartTag(offset, document);
case MSG_ATTRIBUTE_NOT_DECLARED:
return XMLPositionUtility.selectAttributeNameAt(offset, document);
return XMLPositionUtility.selectAttributeValueAt((String)arguments[1], offset, document);
case MSG_FIXED_ATTVALUE_INVALID: {
String attrName = (String) arguments[1];
return XMLPositionUtility.selectAttributeValueAt(attrName, offset, document);
Expand All @@ -96,6 +126,7 @@ public static Range toLSPRange(XMLLocator location, DTDErrorCode code, Object[]
String attrName = (String) arguments[0];
return XMLPositionUtility.selectAttributeValueAt(attrName, offset, document);
}

case MSG_ELEMENT_WITH_ID_REQUIRED: {
DOMElement element = document.getDocumentElement();
if (element != null) {
Expand All @@ -109,14 +140,52 @@ public static Range toLSPRange(XMLLocator location, DTDErrorCode code, Object[]
return XMLPositionUtility.selectAttributeValueByGivenValueAt(attrValue, offset, document);
}

case MSG_MARKUP_NOT_RECOGNIZED_IN_DTD: {
return XMLPositionUtility.selectWholeTag(offset + 1, document);
}

// ---------- DTD Doc type
case MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN:
case QuoteRequiredInPublicID: {
return XMLPositionUtility.getLastValidDTDDeclParameterOrUnrecognized(offset, document);
}

case ExternalIDorPublicIDRequired: {
return XMLPositionUtility.getLastValidDTDDeclParameter(offset, document);
}

case QuoteRequiredInSystemID:
case OpenQuoteMissingInDecl:
case SpaceRequiredAfterSYSTEM:
case MSG_SPACE_REQUIRED_AFTER_NOTATION_NAME_IN_NOTATIONDECL:
case AttTypeRequiredInAttDef:
case LessthanInAttValue:
case OpenQuoteExpected:
case AttNameRequiredInAttDef:
case EntityDeclUnterminated:
case AttlistDeclUnterminated:
case NotationDeclUnterminated:
case ElementDeclUnterminated: {
return XMLPositionUtility.selectDTDElementDeclAt(offset, document);
return XMLPositionUtility.getLastValidDTDDeclParameterOrUnrecognized(offset, document);
//return XMLPositionUtility.selectDTDElementDeclAt(offset, document);
}

case MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN: {
return XMLPositionUtility.getElementDeclMissingContentOrCategory(offset, document);
}


case MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL:
case MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL:
case MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL:
case MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL: {
return XMLPositionUtility.selectDTDElementDeclTagAt(offset, document);
return XMLPositionUtility.selectDTDDeclTagNameAt(offset, document);
}
default:
try {
return new Range(new Position(0, 0), document.positionAt(document.getEnd()));
} catch (BadLocationException e) {

}
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*/
package org.eclipse.lsp4xml.utils;

import java.util.ArrayList;
import java.util.List;

import org.apache.xerces.xni.XMLLocator;
Expand All @@ -23,6 +24,9 @@
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.dom.DOMNode;
import org.eclipse.lsp4xml.dom.DOMProcessingInstruction;
import org.eclipse.lsp4xml.dom.DTDAttlistDecl;
import org.eclipse.lsp4xml.dom.DTDDeclNode;
import org.eclipse.lsp4xml.dom.DTDDeclParameter;
import org.eclipse.lsp4xml.dom.DTDElementDecl;

/**
Expand Down Expand Up @@ -359,14 +363,119 @@ public static Range selectDTDElementDeclAt(int offset, DOMDocument document) {
return null;
}

public static Range selectDTDElementDeclTagAt(int offset, DOMDocument document) {
/**
* Will give the range for the last VALID DTD Decl parameter at 'offset'.
* An unrecognized Parameter is not considered VALID,
*
* eg: <!ELEMENT elementName (content) UNRECOGNIZED_CONTENT
* will give the range 1 character after '(content)'
*/
public static Range getLastValidDTDDeclParameter(int offset, DOMDocument document) {
DOMNode node = document.findNodeAt(offset);
if (node != null && node.isDTDElementDecl()) {
DTDElementDecl elementDecl = (DTDElementDecl) node;
return createRange(elementDecl.getStart(), elementDecl.getEndElementTag(), document);
if (node != null && node instanceof DTDDeclNode) {
DTDDeclNode decl = (DTDDeclNode) node;
ArrayList<DTDDeclParameter> params = decl.getParameters();
DTDDeclParameter finalParam;
if(params != null && params.size() == 0) {
return createRange(decl.declType.getStart(), decl.declType.getEnd(), document);
}
else if(params.get(params.size() - 1).equals(decl.unrecognized)) {
finalParam = params.get(params.size() - 2);
}
else {
finalParam = params.get(params.size() - 1);
}
return createRange(finalParam.getEnd(), finalParam.getEnd() + 1, document);
}
return null;
}

/**
* Will give the range for the last VALID DTD Decl parameter at 'offset'.
* An unrecognized Parameter is not considered VALID,
*
* eg: <!ELEMENT elementName (content) UNRECOGNIZED_CONTENT
* will give the range 1 character after '(content)'
*/
public static Range getLastValidDTDDeclParameterOrUnrecognized(int offset, DOMDocument document) {
DOMNode node = document.findNodeAt(offset);
if (node != null && node instanceof DTDDeclNode) {
DTDDeclNode decl = (DTDDeclNode) node;
if(decl instanceof DTDAttlistDecl) {
DTDAttlistDecl attlist = (DTDAttlistDecl) decl;
ArrayList<DTDAttlistDecl> internal = attlist.getInternalChildren();
if(internal != null && internal.size() > 0) {
decl = internal.get(internal.size() - 1); //get last internal decl
}
}
ArrayList<DTDDeclParameter> params = decl.getParameters();
if(params == null || params.size() == 0) {
return createRange(decl.declType.getStart(), decl.declType.getEnd(), document);
}
DTDDeclParameter finalParam = params.get(params.size() - 1);
if(params.get(params.size() - 1).equals(decl.unrecognized)) {
return createRange(finalParam.getStart(), finalParam.getEnd(), document);
}
return createRange(finalParam.getEnd(), finalParam.getEnd() + 1, document);
}
return null;
}

/**
* Will give the range for the last VALID DTD Decl parameter at 'offset'.
* An unrecognized Parameter is not considered VALID,
*
* eg: <!ELEMENT elementName (content) UNRECOGNIZED_CONTENT
* will give the range 1 character after '(content)'
*/
public static Range getLastDTDDeclParameter(int offset, DOMDocument document) {
DOMNode node = document.findNodeAt(offset);
if (node != null && node instanceof DTDDeclNode) {
DTDDeclNode decl = (DTDDeclNode) node;
ArrayList<DTDDeclParameter> params = decl.getParameters();
DTDDeclParameter lastParam;
if(params != null && params.size() > 0) {
lastParam = params.get(params.size() - 1);
return createRange(lastParam.getStart(), lastParam.getEnd(), document);
}
}
return null;
}

public static Range selectDTDDeclTagNameAt(int offset, DOMDocument document) {
DOMNode node = document.findNodeAt(offset);
if (node != null && node instanceof DTDDeclNode) {
DTDDeclNode declNode = (DTDDeclNode) node;
return createRange(declNode.declType.getStart(), declNode.declType.getEnd(), document);
}
return null;
}

public static Range selectWholeTag(int offset, DOMDocument document) {
DOMNode node = document.findNodeAt(offset);
if(node != null) {
return createRange(node.getStart(), node.getEnd(), document);
}
return null;
}

public static Range getElementDeclMissingContentOrCategory(int offset, DOMDocument document) {
DOMNode node = document.findNodeAt(offset);
if (node != null && node instanceof DTDElementDecl) {
DTDElementDecl declNode = (DTDElementDecl) node;
ArrayList<DTDDeclParameter> params = declNode.getParameters();
if(params.size() == 0) {
return null;
}
if(params.size() == 1) {
DTDDeclParameter param = params.get(0);
return createRange(param.getEnd(), param.getEnd() + 1, document);
}
else {
return createRange(params.get(1).getStart(), params.get(1).getEnd(), document);
}
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void MSG_ATTRIBUTE_NOT_DECLARED() throws Exception {
" <heading>Reminder</heading>\r\n" + //
" <body>Don't forget me this weekend</body>\r\n" + //
"</note> ";
XMLAssert.testDiagnosticsFor(xml, d(10, 10, 14, DTDErrorCode.MSG_ATTRIBUTE_NOT_DECLARED));
XMLAssert.testDiagnosticsFor(xml, d(10, 15, 17, DTDErrorCode.MSG_ATTRIBUTE_NOT_DECLARED));
}

@Test
Expand Down
Loading

0 comments on commit 27fb6c8

Please sign in to comment.