From ca91d8164b502f78bdad69035adeec10f5a160f5 Mon Sep 17 00:00:00 2001 From: Yegor Bugayenko Date: Wed, 24 Aug 2022 09:27:33 +0300 Subject: [PATCH] #107 better error message --- src/main/java/org/xembly/Directives.java | 3 +- src/main/java/org/xembly/Verbs.java | 24 +++++++-- src/test/java/org/xembly/DirectivesTest.java | 9 ++-- src/test/java/org/xembly/VerbsTest.java | 54 ++++++++++++++++++++ 4 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 src/test/java/org/xembly/VerbsTest.java diff --git a/src/main/java/org/xembly/Directives.java b/src/main/java/org/xembly/Directives.java index 6fd91afa..d697c64b 100644 --- a/src/main/java/org/xembly/Directives.java +++ b/src/main/java/org/xembly/Directives.java @@ -102,9 +102,8 @@ public Directives() { /** * Public ctor. * @param text Xembly script - * @throws SyntaxException If syntax is broken */ - public Directives(final String text) throws SyntaxException { + public Directives(final String text) { this(new Verbs(text).directives()); } diff --git a/src/main/java/org/xembly/Verbs.java b/src/main/java/org/xembly/Verbs.java index 5387c940..43cd0726 100644 --- a/src/main/java/org/xembly/Verbs.java +++ b/src/main/java/org/xembly/Verbs.java @@ -70,13 +70,21 @@ public Collection directives() { new CommonTokenStream(lexer) ); lexer.removeErrorListeners(); - lexer.addErrorListener(this.errors()); + lexer.addErrorListener(Verbs.errors()); parser.removeErrorListeners(); - parser.addErrorListener(this.errors()); + parser.addErrorListener(Verbs.errors()); try { return parser.directives().ret; } catch (final ParsingException ex) { - throw new SyntaxException(this.text, ex); + throw new SyntaxException( + String.format( + "%s \"%s\" in \"%s\"", + ex.getClass().getCanonicalName(), + ex.getLocalizedMessage(), + this.text + ), + ex + ); } } @@ -84,7 +92,7 @@ public Collection directives() { * Errors listener. * @return Listener */ - private ANTLRErrorListener errors() { + private static ANTLRErrorListener errors() { return new BaseErrorListener() { // @checkstyle ParameterNumberCheck (10 lines) @Override @@ -92,7 +100,13 @@ public void syntaxError(final Recognizer recognizer, final Object symbol, final int line, final int position, final String msg, final RecognitionException error) { - throw new SyntaxException(Verbs.this.text, error); + throw new SyntaxException( + String.format( + "\"%s\" at line #%d, position #%d, symbol %s", + msg, line, position, symbol + ), + error + ); } }; } diff --git a/src/test/java/org/xembly/DirectivesTest.java b/src/test/java/org/xembly/DirectivesTest.java index 937a58a6..2251b611 100644 --- a/src/test/java/org/xembly/DirectivesTest.java +++ b/src/test/java/org/xembly/DirectivesTest.java @@ -90,9 +90,12 @@ void throwsOnBrokenGrammar() { @Test void throwsOnBrokenXmlContent() { - Assertions.assertThrows( - SyntaxException.class, - () -> new Directives("ADD '\u001b';") + MatcherAssert.assertThat( + Assertions.assertThrows( + SyntaxException.class, + () -> new Directives("ADD 't';\nADD '\u001b';") + ).getMessage(), + Matchers.containsString("ADD") ); } diff --git a/src/test/java/org/xembly/VerbsTest.java b/src/test/java/org/xembly/VerbsTest.java new file mode 100644 index 00000000..084b7df2 --- /dev/null +++ b/src/test/java/org/xembly/VerbsTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013-2022, xembly.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: 1) Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. 2) Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. 3) Neither the name of the xembly.org nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.xembly; + +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Test case for {@link Verbs}. + * + * @since 0.29 + */ +final class VerbsTest { + + @Test + void throwsOnBrokenSyntax() { + MatcherAssert.assertThat( + Assertions.assertThrows( + SyntaxException.class, + () -> new Verbs("ADD 't';\nADD 'x';broken").directives() + ).getMessage(), + Matchers.containsString("token recognition error at: 'b'") + ); + } +}