Skip to content

Commit

Permalink
Improve ETagRequired error range
Browse files Browse the repository at this point in the history
Fixes eclipse-lemminx#876

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Sep 23, 2020
1 parent 3ea8abb commit c41d538
Show file tree
Hide file tree
Showing 9 changed files with 384 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,33 @@ public int getStartTagCloseOffset() {
return startTagCloseOffset;
}

public int getBestStartTagCloseOffset() {
if (isStartTagClosed()) {
return getStartTagCloseOffset();
}
String text = getOwnerDocument().getText();
int endOffset = text.length() - 1;
DOMNode nextNode = getFirstChild();
if (nextNode == null) {
nextNode = getNextSibling();
}
if (nextNode != null) {
endOffset = ((DOMElement) nextNode).getStartTagOpenOffset() - 1;
}
if (nextNode == null) {
DOMElement parent = getParentElement();
if (parent != null && parent.hasEndTag()) {
endOffset = parent.getEndTagOpenOffset() - 1;
}
}
// remove spaces
while (Character.isWhitespace(text.charAt(endOffset))) {
endOffset--;
}
endOffset++;
return endOffset;
}

/**
* Returns the end tag open offset and {@link DOMNode#NULL_VALUE} if it doesn't
* exist.
Expand Down Expand Up @@ -397,12 +424,23 @@ public boolean isEndTagClosed() {
* Returns true if the given element is an orphan end tag (which has no start
* tag, eg: </a>) and false otherwise.
*
* @param tagName the end tag name.
* @return true if the given element is an orphan end tag (which has no start
* tag, eg: </a>) and false otherwise.
*/
public boolean isOrphanEndTag(String tagName) {
return isSameTag(tagName) && hasEndTag() && !hasStartTag();
public boolean isOrphanEndTag() {
return hasEndTag() && !hasStartTag();
}

/**
* Returns true if the given element is an orphan end tag (which has no start
* tag, eg: </a>) of the given tag name and false otherwise.
*
* @param tagName the end tag name.
* @return true if the given element is an orphan end tag (which has no start
* tag, eg: </a>) of the given tag name and false otherwise.
*/
public boolean isOrphanEndTagOf(String tagName) {
return isSameTag(tagName) && isOrphanEndTag();
}

@Override
Expand All @@ -423,7 +461,7 @@ public DOMElement getOrphanEndElement(int offset, String tagName) {
for (DOMNode child : children) {
if (child.isElement()) {
DOMElement childElement = (DOMElement) child;
if (childElement.isOrphanEndTag(tagName)) {
if (childElement.isOrphanEndTagOf(tagName)) {
return childElement;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ public DOMElement getOrphanEndElement(int offset, String tagName) {
}
// emp| </employe>
DOMElement nextElement = (DOMElement) next;
if (nextElement.isOrphanEndTag(tagName)) {
if (nextElement.isOrphanEndTagOf(tagName)) {
return nextElement;
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ boolean hasNextElementName() {
stream.advanceWhileChar(ELEMENT_NAME_PREDICATE);
return true;
}

public static boolean isStartElementName(Integer ch) {
return START_ELEMENT_NAME_PREDICATE.test(ch);
}

/**
* Returns true if the current token is an attribute name and false otherwise.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public static Range toLSPRange(XMLLocator location, XMLSchemaErrorCode code, Obj
case TargetNamespace_1:
return XMLPositionUtility.selectRootAttributeValue(DOMAttr.XMLNS_ATTR, document);
case TargetNamespace_2:
return XMLPositionUtility.selectRootStartTag(document);
return XMLPositionUtility.selectRootStartTagName(document);
default:
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,19 +141,13 @@ public static Range toLSPRange(XMLLocator location, XMLSyntaxErrorCode code, Obj
return XMLPositionUtility.selectAttributeNameFromGivenNameAt(attrName, offset, document);
}
case MarkupEntityMismatch:
return XMLPositionUtility.selectRootStartTag(document);
case ElementUnterminated: {
String text = document.getText();
if (offset < text.length()) {
DOMNode element = document.findNodeAt(offset);
if (element.isElement() && !((DOMElement) element).isStartTagClosed()) {
// ex : <foo attr="" |
int endOffset = offset;
// remove spaces
while (Character.isWhitespace(text.charAt(endOffset))) {
endOffset--;
}
endOffset++;
return XMLPositionUtility.createRange(element.getStart() + 1, endOffset, document);
DOMNode node = document.findNodeAt(offset);
if (node.isElement()) {
return XMLPositionUtility.selectStartTag((DOMElement) node);
}
}
return XMLPositionUtility.selectRootStartTag(document);
Expand Down Expand Up @@ -206,7 +200,7 @@ public static Range toLSPRange(XMLLocator location, XMLSyntaxErrorCode code, Obj
*/
String text = document.getText();
char ch = text.charAt(offset);
while(Character.isWhitespace(ch)) {
while (Character.isWhitespace(ch)) {
offset--;
ch = text.charAt(offset);
}
Expand All @@ -216,7 +210,7 @@ public static Range toLSPRange(XMLLocator location, XMLSyntaxErrorCode code, Obj
return XMLPositionUtility.selectEndTagName(offset, document);
case ETagRequired: {
String tag = getString(arguments[0]);
return XMLPositionUtility.selectChildEndTag(tag, offset, document);
return XMLPositionUtility.selectStartTagNameOfUnclosedElement(tag, offset, document);
}
case SemicolonRequiredInReference: {
EntityReferenceRange range = XMLPositionUtility.selectEntityReference(offset + 1, document, false);
Expand Down
Loading

0 comments on commit c41d538

Please sign in to comment.