Skip to content

Commit

Permalink
Fix StringIndexOutOfBoundsException in
Browse files Browse the repository at this point in the history
EntityNotDeclaredCodeAction.getEntityName

Fixes #862

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
azerr authored and angelozerr committed Sep 25, 2020
1 parent 8cc0bd7 commit 526e2b0
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 21 deletions.
Expand Up @@ -46,19 +46,19 @@ public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument documen
SharedSettings sharedSettings, IComponentProvider componentProvider) {

try {
String entityName = getEntityName(diagnostic, range, document);
String entityName = getEntityName(diagnostic, document);

if (entityName == null) {
return;
}

DOMDocumentType docType = document.getDoctype();
if (docType != null) {

// Case 1: <!DOCTYPE exists
// Add <!ENTITY nbsp "entity-value"> in the subset.
// If the subset does not exist, add subset too

// ie:
// <!DOCTYPE article [
// <!ELEMENT article (#PCDATA)>
Expand All @@ -69,7 +69,7 @@ public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument documen
// Case 2: <!DOCTYPE does not exist
// Generate:
// <!DOCTYPE article [
// <!ENTITY nbsp "entity-value">
// <!ENTITY nbsp "entity-value">
// ]>
addDoctypeAndEntityCodeAction(entityName, diagnostic, document, sharedSettings, codeActions);
}
Expand All @@ -79,11 +79,10 @@ public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument documen
}

/**
* Add a code action that inserts entity declaration to the
* current DOCTYPE's internal subset
* Add a code action that inserts entity declaration to the current DOCTYPE's
* internal subset
*
* If the internal subset does not exist, the code action
* inserts it as well
* If the internal subset does not exist, the code action inserts it as well
*
* @param entityName the entity name for the entity declaration
* @param diagnostic the code action's diagnostic
Expand Down Expand Up @@ -113,7 +112,7 @@ private void addEntityCodeAction(String entityName, Diagnostic diagnostic, DOMDo
} else {
insertString.startUnindentedDoctypeInternalSubset();
}

if (insertPosition.getLine() > 0) {
insertString.linefeed();
}
Expand All @@ -136,8 +135,8 @@ private void addEntityCodeAction(String entityName, Diagnostic diagnostic, DOMDo
}

/**
* Add a code action that inserts the DOCTYPE declaration containing
* an internal subset with an entity declaration
* Add a code action that inserts the DOCTYPE declaration containing an internal
* subset with an entity declaration
*
* @param entityName the entity name for the entity declaration
* @param diagnostic the code action's diagnostic
Expand All @@ -161,14 +160,12 @@ private void addDoctypeAndEntityCodeAction(String entityName, Diagnostic diagnos
if (insertPosition.getCharacter() > 0) {
insertString.linefeed();
}
insertString.startDoctype().addParameter(root.getTagName())
.startDoctypeInternalSubset().linefeed().indent(1);
insertString.startDoctype().addParameter(root.getTagName()).startDoctypeInternalSubset().linefeed().indent(1);

addEntityDeclaration(entityName, insertString);

insertString.linefeed()
.endDoctypeInternalSubset().closeStartElement();

insertString.linefeed().endDoctypeInternalSubset().closeStartElement();

Position rootStartPosition = document.positionAt(root.getStart());
if (insertPosition.getLine() == rootStartPosition.getLine()) {
insertString.linefeed();
Expand Down Expand Up @@ -219,12 +216,12 @@ private Position getEntityInsertPosition(DOMDocument document) throws BadLocatio
* https://github.com/microsoft/language-server-protocol/issues/887
*
* @param diagnostic the diagnostic
* @param range the error range
* @param doc the DOM document
* @return entity name from the error range and error message.
* @throws BadLocationException
*/
private String getEntityName(Diagnostic diagnostic, Range range, DOMDocument doc) throws BadLocationException {
private static String getEntityName(Diagnostic diagnostic, DOMDocument doc) throws BadLocationException {
Range range = diagnostic.getRange();
String name = doc.getText().substring(doc.offsetAt(range.getStart()), doc.offsetAt(range.getEnd()));
String removedAmpAndSemiColon = name.substring(1, name.length() - 1);
if (diagnostic.getMessage().indexOf("\"" + removedAmpAndSemiColon + "\"") < 0) {
Expand All @@ -233,8 +230,10 @@ private String getEntityName(Diagnostic diagnostic, Range range, DOMDocument doc
return removedAmpAndSemiColon;
}

private void addEntityDeclaration(String entityName, XMLBuilder builder) {
builder.addDeclTagStart("ENTITY").addParameter(entityName)
.addParameter("\"entity-value\"").closeStartElement();
private static void addEntityDeclaration(String entityName, XMLBuilder builder) {
builder.addDeclTagStart("ENTITY") //
.addParameter(entityName) //
.addParameter("\"entity-value\"")//
.closeStartElement();
}
}
Expand Up @@ -424,6 +424,28 @@ public void EntityNotDeclaredDoctypeNoSubsetEndBracketNewLine() throws Exception
testCodeActionsFor(xml, d, ca(d, te(2, 0, 2, 0, "[\n\t<!ENTITY nbsp \"entity-value\">\n]")));
}

@Test
public void Issue862() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
"<!DOCTYPE article\n" + //
">\n" + //
"<article>\n" + //
" &nbsp;\n" + //
"</article>";

Diagnostic d = d(4, 1, 4, 7, DTDErrorCode.EntityNotDeclared,
"The entity \"nbsp\" was referenced, but not declared.");
XMLAssert.testDiagnosticsFor(xml, d);

xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
"<!DOCTYPE article\n" + //
">\n" + //
"<article>\n" + //
" &|nbsp;\n" + // set the range
"</article>";
testCodeActionsFor(xml, d, ca(d, te(2, 0, 2, 0, "[\n\t<!ENTITY nbsp \"entity-value\">\n]")));
}

@Test
public void EntityNotDeclaredDoctypeEmptySubset() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
Expand Down

0 comments on commit 526e2b0

Please sign in to comment.