From 2558ded5805e8f3a59ce98e6545b2c54931983b1 Mon Sep 17 00:00:00 2001 From: maxonfjvipon Date: Wed, 27 Dec 2023 15:11:40 +0300 Subject: [PATCH 1/2] fix(#2739): added failing on errors to UnphiMojo --- .../main/java/org/eolang/maven/UnphiMojo.java | 38 ++++-- .../java/org/eolang/maven/UnphiMojoTest.java | 15 +++ .../main/java/org/eolang/parser/EoSyntax.java | 74 ----------- .../java/org/eolang/parser/ParsingErrors.java | 119 ++++++++++++++++++ .../java/org/eolang/parser/PhiSyntax.java | 42 +++++-- .../java/org/eolang/parser/PhiSyntaxTest.java | 49 ++++++++ 6 files changed, 240 insertions(+), 97 deletions(-) create mode 100644 eo-parser/src/main/java/org/eolang/parser/ParsingErrors.java create mode 100644 eo-parser/src/test/java/org/eolang/parser/PhiSyntaxTest.java diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/UnphiMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/UnphiMojo.java index 8175fffa03..38633ed048 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/UnphiMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/UnphiMojo.java @@ -24,19 +24,25 @@ package org.eolang.maven; import com.jcabi.log.Logger; +import com.jcabi.xml.XML; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import javax.naming.CannotProceedException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.cactoos.experimental.Threads; import org.cactoos.iterable.Mapped; +import org.cactoos.list.ListOf; import org.cactoos.number.SumOf; import org.cactoos.text.TextOf; import org.eolang.maven.util.HmBase; import org.eolang.maven.util.Home; import org.eolang.maven.util.Walk; +import org.eolang.parser.ParsingException; import org.eolang.parser.PhiSyntax; /** @@ -73,30 +79,33 @@ public final class UnphiMojo extends SafeMojo { @Override public void exec() { + final List errors = new ListOf<>(); final Home home = new HmBase(this.unphiOutputDir); final int count = new SumOf( new Threads<>( Runtime.getRuntime().availableProcessors(), new Mapped<>( phi -> () -> { - final Path relative = Paths.get( - this.unphiInputDir.toPath().relativize(phi).toString().replace( + final Path relative = this.unphiInputDir.toPath().relativize(phi); + final Path xmir = Paths.get( + relative.toString().replace( String.format(".%s", PhiMojo.EXT), String.format(".%s", TranspileMojo.EXT) ) ); - home.save( - new PhiSyntax( - phi.getFileName().toString().replace(".phi", ""), - new TextOf(phi) - ).parsed().toString(), - relative - ); + final XML parsed = new PhiSyntax( + phi.getFileName().toString().replace(".phi", ""), + new TextOf(phi) + ).parsed(); + home.save(parsed.toString(), xmir); Logger.info( this, "Parsed to xmir: %s -> %s", - phi, this.unphiOutputDir.toPath().resolve(relative) + phi, this.unphiOutputDir.toPath().resolve(xmir) ); + if (parsed.nodes("//errors[count(error)=0]").isEmpty()) { + errors.add(relative); + } return 1; }, new Walk(this.unphiInputDir.toPath()) @@ -104,5 +113,14 @@ public void exec() { ) ).intValue(); Logger.info(this, "Parsed %d phi files to xmir", count); + if (!errors.isEmpty()) { + throw new IllegalStateException( + String.format( + "%d files with parsing errors were found: %s", + errors.size(), + Arrays.toString(errors.toArray()) + ) + ); + } } } diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/UnphiMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/UnphiMojoTest.java index e667b05dba..9ff66434a6 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/UnphiMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/UnphiMojoTest.java @@ -40,6 +40,7 @@ import org.eolang.parser.EoSyntax; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -69,6 +70,20 @@ void createsFile(@TempDir final Path temp) throws Exception { ); } + @Test + void failsIfParsedWithErrors(@TempDir final Path temp) throws IOException { + new HmBase(temp).save( + "std ↦ Φ.org.eolang.io.stdout, y ↦ Φ.org.eolang.x", + Paths.get("target/phi/std.phi") + ); + Assertions.assertThrows( + IllegalStateException.class, + () -> new FakeMaven(temp) + .execute(UnphiMojo.class), + "UnphiMojo execution should fail because of parsing errors" + ); + } + @ParameterizedTest @ClasspathSource(value = "org/eolang/maven/unphi", glob = "**.yaml") void checksUnphiPacks(final String pack, @TempDir final Path temp) throws Exception { diff --git a/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java b/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java index a9d763fd5c..f4b036f481 100644 --- a/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java +++ b/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java @@ -137,78 +137,4 @@ private Text normalize() { private List lines() { return new ListOf<>(new Split(new TextOf(this.input), "\r?\n")); } - - /** - * Accumulates all parsing errors. - * - * @since 0.30.0 - */ - private static final class ParsingErrors extends BaseErrorListener - implements ANTLRErrorListener, Iterable { - /** - * Errors accumulated. - */ - private final List errors; - - /** - * The source. - */ - private final List lines; - - /** - * Ctor. - * @param src The source in lines - */ - private ParsingErrors(final List src) { - this.errors = new LinkedList<>(); - this.lines = src; - } - - // @checkstyle ParameterNumberCheck (10 lines) - @Override - public void syntaxError(final Recognizer recognizer, - final Object symbol, final int line, - final int position, final String msg, - final RecognitionException error - ) { - this.errors.add( - new ParsingException( - String.format( - "[%d:%d] %s: \"%s\"", - line, position, msg, - // @checkstyle AvoidInlineConditionalsCheck (1 line) - this.lines.size() < line ? "EOF" : this.lines.get(line - 1) - ), - error, - line - ) - ); - } - - @Override - public Iterator iterator() { - return new org.cactoos.iterable.Joined<>( - new Mapped>( - error -> new Directives() - .xpath("/program/errors") - .add("error") - .attr("line", error.line()) - .attr("severity", "critical") - .set(error.getMessage()) - .up(), - this.errors - ) - ).iterator(); - } - - /** - * How many errors? - * @return Count of errors accumulated - */ - public int size() { - return this.errors.size(); - } - - } - } diff --git a/eo-parser/src/main/java/org/eolang/parser/ParsingErrors.java b/eo-parser/src/main/java/org/eolang/parser/ParsingErrors.java new file mode 100644 index 0000000000..20794d87bc --- /dev/null +++ b/eo-parser/src/main/java/org/eolang/parser/ParsingErrors.java @@ -0,0 +1,119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 Objectionary.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.eolang.parser; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import org.antlr.v4.runtime.ANTLRErrorListener; +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; +import org.cactoos.Text; +import org.cactoos.iterable.Mapped; +import org.cactoos.list.ListOf; +import org.xembly.Directive; +import org.xembly.Directives; + +/** + * Accumulates all parsing errors. + * @since 0.30.0 + */ +final class ParsingErrors extends BaseErrorListener + implements ANTLRErrorListener, Iterable { + /** + * Errors accumulated. + */ + private final List errors; + + /** + * The source. + */ + private final List lines; + + /** + * Ctor. + * @param lines The source in lines + */ + ParsingErrors(final Text... lines) { + this(new ListOf<>(lines)); + } + + /** + * Ctor. + * @param src The source in lines + */ + ParsingErrors(final List src) { + this.errors = new LinkedList<>(); + this.lines = src; + } + + // @checkstyle ParameterNumberCheck (10 lines) + @Override + public void syntaxError( + final Recognizer recognizer, + final Object symbol, + final int line, + final int position, + final String msg, + final RecognitionException error + ) { + this.errors.add( + new ParsingException( + String.format( + "[%d:%d] %s: \"%s\"", + line, position, msg, + // @checkstyle AvoidInlineConditionalsCheck (1 line) + this.lines.size() < line ? "EOF" : this.lines.get(line - 1) + ), + error, + line + ) + ); + } + + @Override + public Iterator iterator() { + return new org.cactoos.iterable.Joined<>( + new Mapped>( + error -> new Directives() + .xpath("/program/errors") + .add("error") + .attr("line", error.line()) + .attr("severity", "critical") + .set(error.getMessage()) + .up(), + this.errors + ) + ).iterator(); + } + + /** + * How many errors? + * @return Count of errors accumulated + */ + public int size() { + return this.errors.size(); + } +} \ No newline at end of file diff --git a/eo-parser/src/main/java/org/eolang/parser/PhiSyntax.java b/eo-parser/src/main/java/org/eolang/parser/PhiSyntax.java index effa593b8c..c06438cdd0 100644 --- a/eo-parser/src/main/java/org/eolang/parser/PhiSyntax.java +++ b/eo-parser/src/main/java/org/eolang/parser/PhiSyntax.java @@ -50,6 +50,14 @@ public final class PhiSyntax implements Syntax { */ private final Text input; + /** + * Ctor for the tests. + * @param input Input + */ + PhiSyntax(final String input) { + this("test", () -> input); + } + /** * Ctor. * @param nme Name of the program @@ -63,25 +71,33 @@ public PhiSyntax(final String nme, final Text inpt) { @Override public XML parsed() throws IOException { final XePhiListener xel = new XePhiListener(this.name); - new ParseTreeWalker().walk( - xel, - new PhiParser( - new CommonTokenStream( - new PhiLexer( - CharStreams.fromStream( - new InputStreamOf(this.input) - ) - ) - ) - ).program() + final ParsingErrors spy = new ParsingErrors(this.input); + final PhiLexer lexer = new PhiLexer( + CharStreams.fromStream( + new InputStreamOf(this.input) + ) + ); + lexer.addErrorListener(spy); + final PhiParser parser = new PhiParser( + new CommonTokenStream(lexer) ); + parser.removeErrorListeners(); + parser.addErrorListener(spy); + new ParseTreeWalker().walk(xel, parser.program()); final XML dom = new XMLDocument( new Xembler( - new Directives(xel) + new Directives(xel).append(spy) ).domQuietly() ); new Schema(dom).check(); - Logger.debug(this, "Input of PHI calculus compiled, no errors"); + if (spy.size() == 0) { + Logger.debug(this, "Input of PHI calculus compiled, no errors"); + } else { + Logger.debug( + this, "Input of PHI calculus failed to compile (%d errors)", + spy.size() + ); + } return dom; } } diff --git a/eo-parser/src/test/java/org/eolang/parser/PhiSyntaxTest.java b/eo-parser/src/test/java/org/eolang/parser/PhiSyntaxTest.java new file mode 100644 index 0000000000..2ca386e0b2 --- /dev/null +++ b/eo-parser/src/test/java/org/eolang/parser/PhiSyntaxTest.java @@ -0,0 +1,49 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 Objectionary.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.eolang.parser; + +import com.jcabi.matchers.XhtmlMatchers; +import java.io.IOException; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; + +/** + * Test cases for {@link PhiSyntax}. + * + * @since 0.35.0 + */ +class PhiSyntaxTest { + @Test + void addsError() throws IOException { + MatcherAssert.assertThat( + new PhiSyntax( + "empty ↦ Φ.org.eolang.bytes" + ).parsed(), + XhtmlMatchers.hasXPath( + "//errors[count(error)>0]" + ) + ); + } +} From 7bc20cee5b932542ae1b89abd8e72bf5a2d08f09 Mon Sep 17 00:00:00 2001 From: maxonfjvipon Date: Wed, 27 Dec 2023 15:15:16 +0300 Subject: [PATCH 2/2] fix(#2739): checkstyle --- .../src/main/java/org/eolang/maven/UnphiMojo.java | 2 -- eo-parser/src/main/java/org/eolang/parser/EoSyntax.java | 8 -------- .../src/main/java/org/eolang/parser/ParsingErrors.java | 2 +- .../src/test/java/org/eolang/parser/PhiSyntaxTest.java | 2 +- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/UnphiMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/UnphiMojo.java index 38633ed048..834c1b1ef1 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/UnphiMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/UnphiMojo.java @@ -30,7 +30,6 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.List; -import javax.naming.CannotProceedException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @@ -42,7 +41,6 @@ import org.eolang.maven.util.HmBase; import org.eolang.maven.util.Home; import org.eolang.maven.util.Walk; -import org.eolang.parser.ParsingException; import org.eolang.parser.PhiSyntax; /** diff --git a/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java b/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java index f4b036f481..6200d5f8d1 100644 --- a/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java +++ b/eo-parser/src/main/java/org/eolang/parser/EoSyntax.java @@ -27,24 +27,16 @@ import com.jcabi.xml.XML; import com.jcabi.xml.XMLDocument; import java.io.IOException; -import java.util.Iterator; -import java.util.LinkedList; import java.util.List; -import org.antlr.v4.runtime.ANTLRErrorListener; -import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.RecognitionException; -import org.antlr.v4.runtime.Recognizer; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.cactoos.Input; import org.cactoos.Text; -import org.cactoos.iterable.Mapped; import org.cactoos.list.ListOf; import org.cactoos.text.FormattedText; import org.cactoos.text.Joined; import org.cactoos.text.Split; import org.cactoos.text.TextOf; -import org.xembly.Directive; import org.xembly.Directives; import org.xembly.Xembler; diff --git a/eo-parser/src/main/java/org/eolang/parser/ParsingErrors.java b/eo-parser/src/main/java/org/eolang/parser/ParsingErrors.java index 20794d87bc..ece28dda71 100644 --- a/eo-parser/src/main/java/org/eolang/parser/ParsingErrors.java +++ b/eo-parser/src/main/java/org/eolang/parser/ParsingErrors.java @@ -116,4 +116,4 @@ public Iterator iterator() { public int size() { return this.errors.size(); } -} \ No newline at end of file +} diff --git a/eo-parser/src/test/java/org/eolang/parser/PhiSyntaxTest.java b/eo-parser/src/test/java/org/eolang/parser/PhiSyntaxTest.java index 2ca386e0b2..835c490614 100644 --- a/eo-parser/src/test/java/org/eolang/parser/PhiSyntaxTest.java +++ b/eo-parser/src/test/java/org/eolang/parser/PhiSyntaxTest.java @@ -26,7 +26,6 @@ import com.jcabi.matchers.XhtmlMatchers; import java.io.IOException; import org.hamcrest.MatcherAssert; -import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; /** @@ -38,6 +37,7 @@ class PhiSyntaxTest { @Test void addsError() throws IOException { MatcherAssert.assertThat( + "Result XML must contain errors", new PhiSyntax( "empty ↦ Φ.org.eolang.bytes" ).parsed(),