From 526e2b027da666ded82f60260f225cc8de3374c4 Mon Sep 17 00:00:00 2001 From: azerr Date: Fri, 25 Sep 2020 10:18:56 +0200 Subject: [PATCH] Fix StringIndexOutOfBoundsException in EntityNotDeclaredCodeAction.getEntityName Fixes #862 Signed-off-by: azerr --- .../EntityNotDeclaredCodeAction.java | 41 +++++++++---------- .../contentmodel/DTDDiagnosticsTest.java | 22 ++++++++++ 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/EntityNotDeclaredCodeAction.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/EntityNotDeclaredCodeAction.java index 01df5e81d..b52941abf 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/EntityNotDeclaredCodeAction.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/codeactions/EntityNotDeclaredCodeAction.java @@ -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: in the subset. // If the subset does not exist, add subset too - + // ie: // @@ -69,7 +69,7 @@ public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument documen // Case 2: + // // ]> addDoctypeAndEntityCodeAction(entityName, diagnostic, document, sharedSettings, codeActions); } @@ -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 @@ -113,7 +112,7 @@ private void addEntityCodeAction(String entityName, Diagnostic diagnostic, DOMDo } else { insertString.startUnindentedDoctypeInternalSubset(); } - + if (insertPosition.getLine() > 0) { insertString.linefeed(); } @@ -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 @@ -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(); @@ -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) { @@ -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(); } } \ No newline at end of file diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDiagnosticsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDiagnosticsTest.java index 844306f9c..bc427c1bd 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDiagnosticsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDiagnosticsTest.java @@ -424,6 +424,28 @@ public void EntityNotDeclaredDoctypeNoSubsetEndBracketNewLine() throws Exception testCodeActionsFor(xml, d, ca(d, te(2, 0, 2, 0, "[\n\t\n]"))); } + @Test + public void Issue862() throws Exception { + String xml = "\n" + // + "\n" + // + "
\n" + // + "  \n" + // + "
"; + + Diagnostic d = d(4, 1, 4, 7, DTDErrorCode.EntityNotDeclared, + "The entity \"nbsp\" was referenced, but not declared."); + XMLAssert.testDiagnosticsFor(xml, d); + + xml = "\n" + // + "\n" + // + "
\n" + // + " &|nbsp;\n" + // set the range + "
"; + testCodeActionsFor(xml, d, ca(d, te(2, 0, 2, 0, "[\n\t\n]"))); + } + @Test public void EntityNotDeclaredDoctypeEmptySubset() throws Exception { String xml = "\n" + //