From 6bf206241f95a1e246d91395a1de3c65bf44f696 Mon Sep 17 00:00:00 2001 From: maxonfjvipon Date: Wed, 22 May 2024 14:12:32 +0300 Subject: [PATCH] fix(#3195): PhiMojo skips failed --- .../main/java/org/eolang/maven/PhiMojo.java | 97 ++++++++++++++----- .../test/java/org/eolang/maven/FakeMaven.java | 2 + .../java/org/eolang/maven/PhiMojoTest.java | 56 +++++++++++ 3 files changed, 129 insertions(+), 26 deletions(-) diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/PhiMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/PhiMojo.java index 13e34989c0..aafb9a6b55 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/PhiMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/PhiMojo.java @@ -36,6 +36,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import net.sf.saxon.expr.instruct.TerminationException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @@ -87,6 +88,21 @@ public final class PhiMojo extends SafeMojo { ) private File phiOutputDir; + /** + * Whether {@link PhiMojo} should fail on critical errors or not. + * @checkstyle MemberNameCheck (10 lines) + */ + @Parameter(property = "eo.phiFailOnCritical", required = true, defaultValue = "true") + @SuppressWarnings({"PMD.ImmutableField", "PMD.LongVariable"}) + private boolean phiFailOnCritical = true; + + /** + * Whether {@link PhiMojo} should skip XMIRs that failed on critical errors. + * @checkstyle MemberNameCheck (10 lines) + */ + @Parameter(property = "eo.phiSkipFailed", required = true, defaultValue = "false") + private boolean phiSkipFailed; + /** * Pass XMIR to Optimizations train or not. * This flag is used for test in order not to optimize XMIR twice: @@ -100,12 +116,7 @@ public final class PhiMojo extends SafeMojo { @Override public void exec() { final Home home = new HmBase(this.phiOutputDir); - final Train train; - if (this.phiOptimize) { - train = new ParsingTrain(); - } else { - train = new TrDefault<>(); - } + final Train train = this.train(); final int count = new SumOf( new Threads<>( Runtime.getRuntime().availableProcessors(), @@ -127,8 +138,18 @@ public void exec() { String.format(".%s", PhiMojo.EXT) ) ); + int amount; try { home.save(PhiMojo.translated(train, xml), relative); + Logger.info( + this, + "Translated to phi: %[file]s (%[size]s) -> %[file]s (%[size]s)", + processed, + xmir.toFile().length(), + relative, + this.phiOutputDir.toPath().resolve(relative).toFile().length() + ); + amount = 1; } catch (final ImpossibleToPhiTranslationException exception) { Logger.debug( this, @@ -139,16 +160,20 @@ public void exec() { String.format("Couldn't translate %s to phi", processed), exception ); + } catch (final IllegalArgumentException exception) { + if (exception.getCause() instanceof TerminationException + && this.phiSkipFailed) { + Logger.info( + this, + "%[file]s failed on critical error, but skipped because phiSkipFailed=true", + processed + ); + amount = 0; + } else { + throw exception; + } } - Logger.info( - this, - "Translated to phi: %[file]s (%[size]s) -> %[file]s (%[size]s)", - processed, - xmir.toFile().length(), - relative, - this.phiOutputDir.toPath().resolve(relative).toFile().length() - ); - return 1; + return amount; }, new Walk(this.phiInputDir.toPath()) ) @@ -167,6 +192,36 @@ count, new Rel(this.phiInputDir), new Rel(this.phiOutputDir) } } + /** + * Build transformations train depends on flags. + * @return Transformations train + */ + private Train train() { + final Train train; + if (this.phiOptimize) { + train = new ParsingTrain(); + } else { + train = new TrDefault<>(); + } + final Train.Temporary dependent; + if (this.phiFailOnCritical) { + dependent = new TrClasspath<>( + "/org/eolang/parser/fail-on-critical.xsl", + "/org/eolang/maven/phi/to-phi.xsl" + ); + } else { + dependent = new TrClasspath<>("/org/eolang/maven/phi/to-phi.xsl"); + } + return new TrJoined<>( + train, + new TrClasspath<>( + "/org/eolang/parser/critical-errors/duplicate-names.xsl", + "/org/eolang/maven/phi/incorrect-inners.xsl" + ).back(), + dependent.back() + ); + } + /** * Translate given xmir to phi calculus expression. * @param train Train that optimize and translates given xmir @@ -176,17 +231,7 @@ count, new Rel(this.phiInputDir), new Rel(this.phiOutputDir) */ private static String translated(final Train train, final XML xmir) throws ImpossibleToPhiTranslationException { - final XML translated = new Xsline( - new TrJoined<>( - train, - new TrClasspath<>( - "/org/eolang/parser/critical-errors/duplicate-names.xsl", - "/org/eolang/maven/phi/incorrect-inners.xsl", - "/org/eolang/parser/fail-on-critical.xsl", - "/org/eolang/maven/phi/to-phi.xsl" - ).back() - ) - ).pass(xmir); + final XML translated = new Xsline(train).pass(xmir); Logger.debug(PhiMojo.class, "XML after translation to phi:\n%s", translated); final List phi = translated.xpath("phi/text()"); if (phi.isEmpty()) { diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/FakeMaven.java b/eo-maven-plugin/src/test/java/org/eolang/maven/FakeMaven.java index aae29eb992..9a9a4406c0 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/FakeMaven.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/FakeMaven.java @@ -239,6 +239,8 @@ public FakeMaven execute(final Class mojo) throws IO this.params.putIfAbsent("rewriteBinaries", true); this.params.putIfAbsent("offline", false); this.params.putIfAbsent("phiOptimize", false); + this.params.putIfAbsent("phiFailOnCritical", true); + this.params.putIfAbsent("phiSkipFailed", false); this.params.putIfAbsent( "eoPortalDir", new File("../eo-runtime/src/main/rust/eo") diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/PhiMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/PhiMojoTest.java index 6a54cc04b7..78ee57ef2b 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/PhiMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/PhiMojoTest.java @@ -80,6 +80,62 @@ void convertsXmirsToPhiWithoutErrorsWithoutOptimizations( ); } + @Test + void doesNotFailOnCritical(@TempDir final Path temp) { + Assertions.assertDoesNotThrow( + () -> new FakeMaven(temp) + .with("phiFailOnCritical", false) + .withProgram( + "# This is the default 64+ symbols comment in front of named abstract object.", + "[] > with-duplicates", + " true > x", + " false > x" + ) + .execute(new FakeMaven.Phi()), + "PhiMojo should not fail on critical errors with 'phiFailsOnCritical' = false" + ); + } + + @Test + void skipsFailedOnCriticalError(@TempDir final Path temp) { + Assertions.assertDoesNotThrow( + () -> new FakeMaven(temp) + .with("phiFailOnCritical", true) + .with("phiSkipFailed", true) + .withProgram( + "# This is the default 64+ symbols comment in front of named abstract object.", + "[] > with-duplicates", + " true > x", + " false > x" + ) + .execute(new FakeMaven.Phi()), + "PhiMojo should not fail on critical errors with 'phiSkipFailed' = true" + ); + } + + @Test + void doesNotSaveSkippedFile(@TempDir final Path temp) throws IOException { + MatcherAssert.assertThat( + "Skipped file should not be saved after PhiMojo is done", + new FakeMaven(temp) + .with("phiFailOnCritical", true) + .with("phiSkipFailed", true) + .withProgram( + "# This is the default 64+ symbols comment in front of named abstract object.", + "[] > with-duplicates", + " true > x", + " false > x" + ) + .execute(new FakeMaven.Phi()) + .result(), + Matchers.not( + Matchers.hasKey( + String.format("target/phi/foo/x/main.%s", PhiMojo.EXT) + ) + ) + ); + } + @ParameterizedTest @ClasspathSource(value = "org/eolang/maven/phi/xmir", glob = "**.xmir") void convertsXmirsToPhiWithoutErrorsWithOptimizations(