SLING-7710 - [HTL] Enhance error reporting for plugin errors
authorRadu Cotescu <radu@apache.org>
Tue, 12 Jun 2018 14:34:15 +0000 (16:34 +0200)
committerRadu Cotescu <radu@apache.org>
Tue, 12 Jun 2018 14:35:38 +0000 (16:35 +0200)
* improved error reporting for missing required plugin identifiers
* corrected line and column reporting (both start now at 1)

src/main/java/org/apache/sling/scripting/sightly/compiler/SightlyCompiler.java
src/main/java/org/apache/sling/scripting/sightly/compiler/SightlyCompilerException.java
src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/MarkupHandler.java
src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java

index 7c14e0e..60f37ea 100644 (file)
@@ -163,7 +163,13 @@ public final class SightlyCompiler {
 
     private ScriptError getScriptError(String documentFragment, String offendingInput, int lineOffset, int columnOffset, String message) {
         if (StringUtils.isNotEmpty(offendingInput)) {
-            int offendingInputIndex = documentFragment.indexOf(offendingInput);
+            String longestContiguousOffendingSequence = null;
+            if (documentFragment.contains(offendingInput)) {
+                longestContiguousOffendingSequence = offendingInput;
+            } else {
+                longestContiguousOffendingSequence = getContiguousOffendingSequence(offendingInput);
+            }
+            int offendingInputIndex = documentFragment.indexOf(longestContiguousOffendingSequence);
             if (offendingInputIndex > -1) {
                 String textBeforeError = documentFragment.substring(0, offendingInputIndex);
                 int line = lineOffset;
@@ -182,19 +188,36 @@ public final class SightlyCompiler {
                 if (column != columnOffset) {
                     column +=columnOffset;
                 }
-                return new ScriptError(line, column, offendingInput + ": " + message);
+                return new ScriptError(line, column, longestContiguousOffendingSequence + ": " + message);
             }
         }
         return new ScriptError(lineOffset, columnOffset, message);
     }
 
+    private String getContiguousOffendingSequence(String input) {
+        if (input != null) {
+            StringBuilder longestSequence = new StringBuilder();
+            char[] inputCharArray = input.toCharArray();
+            for (int index = inputCharArray.length - 1; index >= 0; index--) {
+                char c = inputCharArray[index];
+                if (!Character.isWhitespace(c)) {
+                    longestSequence.insert(0, c);
+                } else {
+                    break;
+                }
+            }
+            return longestSequence.toString();
+        }
+        return null;
+    }
+
     private static class ScriptError {
 
         private int lineNumber;
         private int column;
         private String errorMessage;
 
-        public ScriptError(int lineNumber, int column, String errorMessage) {
+        ScriptError(int lineNumber, int column, String errorMessage) {
             this.lineNumber = lineNumber;
             this.column = column;
             this.errorMessage = errorMessage;
index 49f338e..b964ada 100644 (file)
@@ -22,7 +22,7 @@ package org.apache.sling.scripting.sightly.compiler;
 public final class SightlyCompilerException extends RuntimeException {
 
     private String offendingInput;
-    private int line;
+    private int line = 1;
     private int column;
 
     /**
index 0e41724..618c509 100644 (file)
@@ -88,9 +88,8 @@ public class MarkupHandler {
             try {
                 handlePlugin(name, StringUtils.defaultString(value, ""), context);
             } catch (SightlyCompilerException e) {
-                if (StringUtils.isEmpty(e.getOffendingInput())) {
-                    throw new SightlyCompilerException(e.getMessage(),
-                            name + (StringUtils.isNotEmpty(value) ? "=" + quoteChar + value + quoteChar : ""));
+                if (StringUtils.isEmpty(e.getOffendingInput()) && StringUtils.isNotEmpty(value)) {
+                    throw new SightlyCompilerException(e.getMessage(), name + "=" + quoteChar + value + quoteChar );
                 }
                 throw e;
             }
index 43611d7..977e375 100644 (file)
@@ -18,6 +18,8 @@
  ******************************************************************************/
 package org.apache.sling.scripting.sightly.impl.html.dom;
 
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.scripting.sightly.compiler.SightlyCompilerException;
 import org.apache.sling.scripting.sightly.impl.html.dom.template.Template;
 import org.apache.sling.scripting.sightly.impl.html.dom.template.TemplateAttribute;
 import org.apache.sling.scripting.sightly.impl.html.dom.template.TemplateCommentNode;
@@ -51,6 +53,8 @@ public class TreeTraverser {
     }
 
     private void traverseElement(TemplateElementNode elem) {
+        SightlyCompilerException bubbledError = null;
+        StringBuilder offendingInput = new StringBuilder();
         if ("ROOT".equalsIgnoreCase(elem.getName())) {
             traverseChildren(elem);
             return;
@@ -59,13 +63,38 @@ public class TreeTraverser {
 
         if (elem.isStartElement()) {
             handler.onOpenTagStart("<" + tagName, tagName);
-            for (TemplateAttribute attribute : elem.getAttributes()) {
-                handler.onAttribute(attribute.getName(), attribute.getValue(), attribute.getQuoteChar());
+            try {
+                for (TemplateAttribute attribute : elem.getAttributes()) {
+                    handler.onAttribute(attribute.getName(), attribute.getValue(), attribute.getQuoteChar());
+                }
+            } catch (SightlyCompilerException e) {
+                if (StringUtils.isEmpty(e.getOffendingInput())) {
+                    bubbledError = e;
+                    offendingInput.append("<").append(tagName);
+                    for (TemplateAttribute attribute : elem.getAttributes()) {
+                        String quoteChar = String.valueOf(attribute.getQuoteChar());
+                        offendingInput.append(" ").append(attribute.getName());
+                        if (StringUtils.isNotEmpty(attribute.getValue())) {
+                            offendingInput.append("=").append(quoteChar).append(attribute.getValue()).append(quoteChar);
+                        }
+                    }
+                } else {
+                    throw e;
+                }
             }
             if (elem.hasEndSlash()) {
                 handler.onOpenTagEnd("/>");
+                if (bubbledError != null) {
+                    offendingInput.append("/>");
+                }
             } else {
                 handler.onOpenTagEnd(">");
+                if (bubbledError != null) {
+                    offendingInput.append(">");
+                }
+            }
+            if (bubbledError != null) {
+                throw new SightlyCompilerException(bubbledError.getMessage(), offendingInput.toString());
             }
         } else {
             handler.onOpenTagStart("", tagName);