diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/CopyMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/CopyMojo.java deleted file mode 100644 index 1ddbf3add8c..00000000000 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/CopyMojo.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com - * SPDX-License-Identifier: MIT - */ -package org.eolang.maven; - -import com.jcabi.log.Logger; -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.util.Collection; -import java.util.regex.Pattern; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.cactoos.io.InputOf; -import org.cactoos.text.TextOf; -import org.cactoos.text.UncheckedText; - -/** - * Copy all {@code .eo} files from the {@code src/main/eo} directory - * to the {@code target/classes/EO-SOURCES} directory - * and replace {@code 0.0.0} versions in them to the right version numbers. - * - * @since 0.11 - */ -@Mojo( - name = "copy", - defaultPhase = LifecyclePhase.PREPARE_PACKAGE, - threadSafe = true -) -@SuppressWarnings("PMD.ImmutableField") -public final class CopyMojo extends SafeMojo { - - /** - * Dir with sources. - */ - static final String DIR = "EO-SOURCES"; - - /** - * Replacer or version. - */ - private static final Pattern REPLACE = Pattern.compile( - "^(\\+rt .+):0\\.0\\.0(.*)$", - Pattern.MULTILINE - ); - - /** - * Target directory with resources to be packaged in JAR. - * - * @checkstyle MemberNameCheck (7 lines) - */ - @Parameter( - property = "eo.outputDir", - required = true, - defaultValue = "${project.build.outputDirectory}" - ) - private File outputDir; - - /** - * The version to use for 0.0.0 replacements. - * - * @checkstyle MemberNameCheck (7 lines) - */ - @Parameter( - property = "eo.version", - required = true, - defaultValue = "${project.version}" - ) - private String version; - - @Override - public void exec() throws IOException { - final Path target = this.outputDir.toPath().resolve(CopyMojo.DIR); - final Collection sources = new Walk(this.sourcesDir.toPath()); - for (final Path src : sources) { - new Saved( - CopyMojo.REPLACE - .matcher(new UncheckedText(new TextOf(new InputOf(src))).asString()) - .replaceAll(String.format("$1:%s$2", this.version)), - target.resolve( - src.toAbsolutePath().toString().substring( - this.sourcesDir.toPath().toAbsolutePath().toString().length() + 1 - ) - ) - ).value(); - } - if (sources.isEmpty()) { - Logger.warn( - this, "No sources copied from %[file]s to %[file]s", - this.sourcesDir, target - ); - } else { - Logger.info( - this, "%d source(s) copied from %[file]s to %[file]s", - sources.size(), this.sourcesDir, target - ); - } - } - -} diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/DpsWithRuntime.java b/eo-maven-plugin/src/main/java/org/eolang/maven/DpsWithRuntime.java index a7774f4b1af..a3c606ae122 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/DpsWithRuntime.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/DpsWithRuntime.java @@ -11,6 +11,7 @@ import java.net.URL; import java.util.Iterator; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; import org.apache.maven.model.Dependency; import org.cactoos.list.ListOf; import org.cactoos.scalar.Sticky; @@ -95,21 +96,23 @@ private static Unchecked mavenDependency() { "https://repo.maven.apache.org/maven2/%s/maven-metadata.xml", "org/eolang/eo-runtime" ); - try { - return DpsWithRuntime.dependency( - new Xnav(new XMLDocument(new URL(url)).inner()) - .element("metadata") - .element("versioning") - .element("latest") - .text() - .get() - ); - } catch (final IOException ex) { - throw new IllegalStateException( - String.format("Can't get eo-runtime dependency by the URL: %s", url), - ex - ); - } + return DpsWithRuntime.dependency( + () -> { + try { + return new Xnav(new XMLDocument(new URL(url)).inner()) + .element("metadata") + .element("versioning") + .element("latest") + .text() + .get(); + } catch (final IOException ex) { + throw new IllegalStateException( + String.format("Can't get eo-runtime dependency by the URL: %s", url), + ex + ); + } + } + ); } /** @@ -128,14 +131,14 @@ private static boolean isRuntime(final Dependency other) { * @param version Version of eo-runtime * @return Maven Dependency. */ - private static Unchecked dependency(final String version) { + private static Unchecked dependency(final Supplier version) { return new Unchecked<>( new Synced<>( new Sticky<>( () -> new Dep() .withGroupId("org.eolang") .withArtifactId("eo-runtime") - .withVersion(version) + .withVersion(version.get()) .withClassifier("") ) ) diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/EmptyDirectoriesIn.java b/eo-maven-plugin/src/main/java/org/eolang/maven/EmptyDirectoriesIn.java new file mode 100644 index 00000000000..4eafc9dda3f --- /dev/null +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/EmptyDirectoriesIn.java @@ -0,0 +1,72 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com + * SPDX-License-Identifier: MIT + */ +package org.eolang.maven; + +import com.jcabi.log.Logger; +import java.io.File; +import java.nio.file.Path; + +/** + * Delete empty directories in provided root. + * + * @since 0.55 + */ +final class EmptyDirectoriesIn { + /** + * Root path. + */ + private final File root; + + /** + * Ctor. + * @param root Root directory. + */ + EmptyDirectoriesIn(final Path root) { + this(root.toFile()); + } + + /** + * Ctor. + * @param root Root directory + */ + EmptyDirectoriesIn(final File root) { + this.root = root; + } + + /** + * Clear empty directories in {@code this.root}. + */ + void clear() { + if (!this.root.isDirectory()) { + throw new IllegalStateException( + Logger.format("Provided path %[file]s is not a directory", this.root) + ); + } + this.delete(this.root); + } + + /** + * Recursively delete empty directories. + * @param dir Directory to delete + * @checkstyle NestedIfDepthCheck (20 lines) + */ + private void delete(final File dir) { + if (!dir.isDirectory()) { + return; + } + final File[] before = dir.listFiles(); + if (before != null) { + for (final File file : before) { + if (file.isDirectory()) { + this.delete(file); + } + } + } + final File[] after = dir.listFiles(); + if (after != null && after.length == 0 && !dir.equals(this.root) && dir.delete()) { + Logger.debug(EmptyDirectoriesIn.class, "Deleted empty directory %[file]s", dir); + } + } +} diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/PlaceMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/PlaceMojo.java index f86e004710d..503cde52466 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/PlaceMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/PlaceMojo.java @@ -10,6 +10,7 @@ import java.nio.file.Path; import java.util.Collection; import java.util.Optional; +import java.util.function.Supplier; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.cactoos.io.InputOf; @@ -67,17 +68,16 @@ private long placeDependency(final Path home, final String dep) { Logger.debug(this, "Found placed binaries from %s", dep); } final Path dir = home.resolve(dep); - final long copied = new BinariesDependency(dir, dep, this.rewriteBinaries).place(); - this.placedTojos.placeJar(dep); + final long copied = new PlaceMojo.PlacedDependency(dir, dep, this.rewriteBinaries).get(); if (copied > 0) { Logger.debug( this, "Placed %d binary file(s) out of %d, found in %s, to %[file]s", - copied, new Walk(dir).size(), dep, this.outputDir + copied, new Walk(dir).size(), dep, this.classesDir ); } else { Logger.debug( this, "No binary file(s) out of %d were placed from %s, to %[file]s", - new Walk(dir).size(), dep, this.outputDir + new Walk(dir).size(), dep, this.classesDir ); } return copied; @@ -88,7 +88,7 @@ copied, new Walk(dir).size(), dep, this.outputDir * * @since 0.30 */ - private final class BinariesDependency { + private final class PlacedDependency implements Supplier { /** * Directory to read from. @@ -111,7 +111,7 @@ private final class BinariesDependency { * @param dependency The name of dependency * @param rwte Rewrite binaries in output directory or not */ - private BinariesDependency( + private PlacedDependency( final Path directory, final String dependency, final boolean rwte @@ -121,14 +121,11 @@ private BinariesDependency( this.rewrite = rwte; } - /** - * Place all binaries from this dependency. - * @return How many binaries placed - */ - private long place() { + @Override + public Long get() { return new Walk(this.dir) - .includes(PlaceMojo.this.includeBinaries) - .excludes(PlaceMojo.this.excludeBinaries) + .includes(PlaceMojo.this.placeBinaries) + .excludes(PlaceMojo.this.skipBinaries) .stream() .filter(this::isNotAlreadyPlaced) .peek(this::printLogInfoAboutBinary) @@ -142,15 +139,14 @@ private long place() { * @return True if the file is not already placed. */ private boolean isNotAlreadyPlaced(final Path file) { - final Path target = PlaceMojo.this.outputDir.toPath().resolve( + final Path target = PlaceMojo.this.classesDir.toPath().resolve( this.dir.relativize(file) ); final Optional tojo = PlaceMojo.this.placedTojos.find(target); final boolean res; if (tojo.isPresent() && Files.exists(target) - && (this.sameLength(target, file) - || !tojo.get().unplaced()) + && (this.sameLength(target, file) || !tojo.get().unplaced()) ) { Logger.debug( this, @@ -169,7 +165,7 @@ private boolean isNotAlreadyPlaced(final Path file) { * @param file The file to place. */ private void printLogInfoAboutBinary(final Path file) { - final Path target = PlaceMojo.this.outputDir.toPath().resolve( + final Path target = PlaceMojo.this.classesDir.toPath().resolve( this.dir.relativize(file) ); final Optional tojo = PlaceMojo.this.placedTojos.find(target); @@ -204,17 +200,17 @@ private void placeBinary(final Path file) { final Path target = new FpIfTargetExists( new FpFork(this.rewrite, generated, new FpIgnore()), generated - ).apply(file, PlaceMojo.this.outputDir.toPath().resolve(path)); + ).apply(file, PlaceMojo.this.classesDir.toPath().resolve(path)); PlaceMojo.this.placedTojos.placeClass( target, - PlaceMojo.this.outputDir.toPath().relativize(target).toString(), + PlaceMojo.this.classesDir.toPath().relativize(target).toString(), this.dep ); } catch (final IOException ex) { throw new IllegalStateException( Logger.format( "Failed to place %[file]s to home %[file]s with path %s", - file, PlaceMojo.this.outputDir, path + file, PlaceMojo.this.classesDir, path ), ex ); diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/SafeMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/SafeMojo.java index 7516d51c1da..b394a9510b5 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/SafeMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/SafeMojo.java @@ -121,18 +121,6 @@ abstract class SafeMojo extends AbstractMojo { ) protected File targetDir; - /** - * Output. - * @checkstyle MemberNameCheck (10 lines) - * @checkstyle VisibilityModifierCheck (10 lines) - */ - @Parameter( - property = "eo.outputDir", - required = true, - defaultValue = "${project.build.outputDirectory}" - ) - protected File outputDir; - /** * Current scope (either "compile" or "test"). * @checkstyle VisibilityModifierCheck (5 lines) @@ -174,6 +162,18 @@ abstract class SafeMojo extends AbstractMojo { ) protected File transpiled; + /** + * Generated sourced directory. + * @checkstyle VisibilityModifierCheck (10 lines) + * @checkstyle MemberNameCheck (7 lines) + */ + @Parameter( + property = "eo.generatedDir", + required = true, + defaultValue = "${project.build.directory}/generated-sources" + ) + protected File generatedDir; + /** * The path of the file where XSL measurements (time of execution * in milliseconds) will be stored. @@ -281,16 +281,6 @@ abstract class SafeMojo extends AbstractMojo { @Parameter(property = "eo.skipZeroVersions", required = true, defaultValue = "true") protected boolean skipZeroVersions; - /** - * Place only binaries that have EO sources inside jar. - * @since 0.31 - * @checkstyle MemberNameCheck (10 lines) - * @checkstyle VisibilityModifierCheck (7 lines) - */ - @Parameter - @SuppressWarnings("PMD.LongVariable") - protected boolean placeBinariesThatHaveSources; - /** * Fail resolution process on conflicting dependencies. * @@ -313,22 +303,34 @@ abstract class SafeMojo extends AbstractMojo { protected boolean discoverSelf; /** - * List of inclusion GLOB filters for finding class files. + * List of inclusion GLOB filters for finding class files while placing them from where + * they were resolved to classes directory. * @since 0.15 * @checkstyle MemberNameCheck (10 lines) * @checkstyle VisibilityModifierCheck (7 lines) */ @Parameter - protected Set includeBinaries = new SetOf<>("**"); + protected Set placeBinaries = new SetOf<>("**"); /** - * List of exclusion GLOB filters for finding class files. + * List of exclusion GLOB filters for finding class files while placing them from where + * they were resolved to classed directory. * @since 0.15 * @checkstyle MemberNameCheck (10 lines) * @checkstyle VisibilityModifierCheck (7 lines) */ @Parameter - protected Set excludeBinaries = new SetOf<>(); + protected Set skipBinaries = new SetOf<>(); + + /** + * List of inclusion GLOB filters for unplacing and unspiling (ONLY these files will stay). + * @see Placing and Unplacing in JAR Artifacts + * @since 0.24 + * @checkstyle MemberNameCheck (7 lines) + * @checkstyle VisibilityModifierCheck (7 lines) + */ + @Parameter + protected Set keepBinaries = new SetOf<>(); /** * Add eo-runtime dependency to the classpath. diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/TjsPlaced.java b/eo-maven-plugin/src/main/java/org/eolang/maven/TjsPlaced.java index 373bd133188..ce33546e150 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/TjsPlaced.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/TjsPlaced.java @@ -69,7 +69,8 @@ public void close() throws IOException { * @return All classes. */ Collection classes() { - return this.allBinaries().stream() + return this.allBinaries() + .stream() .filter(TjPlaced::isClass) .collect(Collectors.toList()); } @@ -79,7 +80,8 @@ Collection classes() { * @return All jars. */ Collection jars() { - return this.allBinaries().stream() + return this.allBinaries() + .stream() .filter(TjPlaced::isJar) .collect(Collectors.toList()); } @@ -124,31 +126,18 @@ Optional find(final Path target) { * @param target Path to the class. * @param related Related. * @param dep Dependency. - * @return Placed class. */ - TjPlaced placeClass( + void placeClass( final Path target, final String related, final String dep ) { - return new TjPlaced( - this.all.value().add(target.toString()) - .set(Attribute.KIND.getKey(), "class") - .set(Attribute.HASH.getKey(), new FileHash(target)) - .set(Attribute.RELATED.getKey(), related) - .set(Attribute.DEPENDENCY.getKey(), dep) - .set(Attribute.UNPLACED.getKey(), "false") - ); - } - - /** - * Place jar into placed tojos file. - * @param name Name of the jar. - */ - void placeJar(final String name) { - this.all.value().add(name) - .set(Attribute.KIND.getKey(), "jar") - .set(Attribute.DEPENDENCY.getKey(), String.format("%s.jar", name)) + this.all.value() + .add(target.toString()) + .set(Attribute.KIND.getKey(), "class") + .set(Attribute.HASH.getKey(), new FileHash(target)) + .set(Attribute.RELATED.getKey(), related) + .set(Attribute.DEPENDENCY.getKey(), dep) .set(Attribute.UNPLACED.getKey(), "false"); } diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/TranspileMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/TranspileMojo.java index 9f4e635da16..a20b9bfdf30 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/TranspileMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/TranspileMojo.java @@ -18,15 +18,16 @@ import com.yegor256.xsline.Xsline; import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.function.Supplier; +import java.util.regex.Pattern; import java.util.stream.Collectors; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; @@ -71,6 +72,11 @@ public final class TranspileMojo extends SafeMojo { */ private static final String PRE = "7-pre"; + /** + * Pattern for replacing EO in package. + */ + private static final Pattern PACKAGE = Pattern.compile("EO"); + /** * Parsing train with XSLs. */ @@ -93,28 +99,6 @@ public final class TranspileMojo extends SafeMojo { ) ); - /** - * Target directory. - * @checkstyle MemberNameCheck (7 lines) - */ - @Parameter( - property = "eo.generatedDir", - required = true, - defaultValue = "${project.build.directory}/generated-sources" - ) - private File generatedDir; - - /** - * Output. - * @checkstyle MemberNameCheck (7 lines) - */ - @Parameter( - property = "eo.outputDir", - required = true, - defaultValue = "${project.build.outputDirectory}" - ) - private File outputDir; - /** * Add to source root. * @@ -133,13 +117,13 @@ public final class TranspileMojo extends SafeMojo { private boolean addTestSourcesRoot; @Override - public void exec() { + public void exec() throws IOException { final Collection sources = this.scopedTojos().withShaken(); final Function transform = this.transpilation(); final int saved = new Threaded<>( sources, tojo -> this.transpiled(tojo, transform) - ).total(); + ).total() + TranspileMojo.pinfos(this.generatedDir.toPath()); Logger.info( this, "Transpiled %d XMIRs, created %d Java files in %[file]s", sources.size(), saved, this.generatedDir @@ -246,7 +230,6 @@ private int javaGenerated( final Path tgt = new Place(jname).make( this.generatedDir.toPath(), TranspileMojo.JAVA ); - this.pinfo(tgt, jname, clazz.attribute("package").text().orElse("")); final Supplier che = new CachePath( this.cache.toPath().resolve(TranspileMojo.CACHE), this.plugin.getVersion(), @@ -304,42 +287,41 @@ private int javaGenerated( } /** - * Save {@code package-info.java} next to Java file. - * - *

Each .java file that we create must have a corresponding - * {@code package-info.java} file. The presence of this file enables - * us to use {@code XmirPackage} annotation, passing information about - * EO objects from XMIR to Java runtime.

- * - * @param java Full path to .java file - * @param oname Java object name (e.g. "EOorg.EOeolang.EOio.EOstdio") - * @param pname Package name (e.g. "org.eolang.io") - * @throws IOException If fails to save file + * Create {@code package-info.java} files in all the directories + * in {@link TranspileMojo#generatedDir}. + * @param generated Path to generated sources + * @return Amount of created files + * @throws IOException If fails to create a file */ - private void pinfo(final Path java, final String oname, final String pname) - throws IOException { - final Path pinfo = java.getParent().resolve("package-info.java"); - if (!pinfo.toFile().exists() && !pname.isEmpty()) { - if (pinfo.getParent().toFile().mkdirs()) { - Logger.debug(this, "Directory created for %[file]s", pinfo); - } - String pkg = oname; - if (oname.contains(".")) { - pkg = pkg.substring(0, pkg.lastIndexOf('.')); + private static int pinfos(final Path generated) throws IOException { + final int size; + if (Files.exists(generated)) { + final List dirs = Files.walk(generated) + .filter(file -> Files.isDirectory(file) && !file.equals(generated)) + .collect(Collectors.toList()); + for (final Path dir : dirs) { + final String pkg = generated.relativize(dir).toString() + .replace(File.separator, "."); + new Saved( + String.join( + "\n", + "/**", + " * This file was auto-generated by eo-maven-plugin,", + " * don't modify it, all changes will be lost anyway.", + " */", + String.format( + "// @org.eolang.XmirPackage(\"%s\")", + TranspileMojo.PACKAGE.matcher(pkg).replaceAll("") + ), + String.format("package %s;", pkg) + ), + dir.resolve("package-info.java") + ).value(); } - Files.write( - pinfo, - String.join( - "\n", - "/**", - " * This file was auto-generated by eo-maven-plugin,", - " * don't modify it, all changes will be lost anyway.", - " */", - String.format("// @org.eolang.XmirPackage(\"%s\")", pname), - String.format("package %s;", pkg) - ).getBytes(StandardCharsets.UTF_8) - ); - Logger.debug(this, "Saved %[file]s (%[size]s)", pinfo, pinfo.toFile().length()); + size = dirs.size(); + } else { + size = 0; } + return size; } } diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/UnplaceMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/UnplaceMojo.java index 9ea644052ad..2fec28c1fa8 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/UnplaceMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/UnplaceMojo.java @@ -6,22 +6,16 @@ import com.jcabi.log.Logger; import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; -import java.util.Set; -import java.util.stream.Collectors; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.cactoos.list.ListOf; -import org.cactoos.set.SetOf; /** - * It deletes binary files, which were previously copied by "place" mojo. + * It deletes binary files, which were previously copied by "place" mojo so + * these binaries are not got into result JAR. * * @since 0.11 * @checkstyle ExecutableStatementCountCheck (500 lines) @@ -33,242 +27,115 @@ ) @SuppressWarnings("PMD.ImmutableField") public final class UnplaceMojo extends SafeMojo { - - /** - * List of inclusion GLOB filters for unplacing (these files will be removed for sure). - * @see Placing and Unplacing in JAR Artifacts - * @since 0.24 - * @checkstyle MemberNameCheck (7 lines) - */ - @Parameter - private Set removeBinaries = new SetOf<>(); - - /** - * List of inclusion GLOB filters for placing (ONLY these files will stay). - * @see Placing and Unplacing in JAR Artifacts - * @since 0.24 - * @checkstyle MemberNameCheck (7 lines) - */ - @Parameter - private Set keepBinaries = new SetOf<>(); - @Override - @SuppressWarnings("PMD.AvoidAccessToStaticMembersViaThis") public void exec() throws IOException { if (this.placedTojos.isEmpty()) { - Logger.info( - this, - "The list of placed binaries is absent: %[file]s", - this.placed - ); + Logger.info(this, "The list of placed binaries is absent: %[file]s", this.placed); } else { - this.unplaceClasses(); - this.unplaceJars(); + this.unplace(); } } /** - * Mark dependencies as unplaced if all related binaries are unplaced. - */ - private void unplaceJars() { - final Set used = this.placedTojos.classes() - .stream() - .map(TjPlaced::dependency) - .collect(Collectors.toSet()); - this.placedTojos.jars().stream() - .filter(dep -> used.contains(dep.identifier())) - .forEach(TjPlaced::unplace); - } - - /** - * Place what's necessary. - * @throws IOException If fails + * Unplace what's necessary. */ @SuppressWarnings("PMD.AvoidAccessToStaticMembersViaThis") - private void unplaceClasses() throws IOException { - final Collection classes = this.placedTojos.classes(); - int deleted = 0; - if (!this.keepBinaries.isEmpty()) { - deleted += this.keepThem(classes); - } - deleted += this.killThem(classes); - if (classes.isEmpty()) { - Logger.info( - this, "No binaries were placed into %[file]s, nothing to uplace", - this.placed - ); - } else if (deleted == 0) { - Logger.info( - this, "No binaries out of %d deleted in %[file]s", - classes.size(), this.placed - ); - } else if (deleted == classes.size()) { - Logger.info( - this, "All %d binari(es) deleted, which were found in %[file]s", - classes.size(), this.placed - ); + private void unplace() { + final Path classes = this.classesDir.toPath(); + final Walk binaries = new Walk(classes); + if (binaries.isEmpty()) { + Logger.warn(this, "No classes found in %[file]s", classes); } else { - Logger.info( - this, "Just %d binari(es) out of %d deleted in %[file]s", - deleted, classes.size(), this.placed - ); - } - } - - /** - * Keep those we must keep selectively. - * @param all All binaries found - * @return Number of files deleted - * @throws IOException If fails - */ - @SuppressWarnings("PMD.CognitiveComplexity") - private int killThem(final Iterable all) throws IOException { - int unplaced = 0; - for (final TjPlaced tojo : all) { - final String related = tojo.related(); - final Path path = Paths.get(tojo.identifier()); - final String hash = new FileHash(path).toString(); - if (!tojo.sameHash(hash)) { - if (hash.isEmpty()) { - Logger.debug( - this, "The binary %s of %s is gone, won't unplace", - related, tojo.dependency() - ); - continue; - } - if (!UnplaceMojo.inside(related, this.removeBinaries)) { - Logger.warn( - this, "The binary %s of %s looks different, won't unplace", - related, tojo.dependency() - ); - continue; - } + final Collection available = binaries.excludes(this.keepBinaries); + final int unplaced = new Threaded<>( + this.placedTojos.classes(), + tojo -> this.unplace(tojo, available) + ).total(); + new EmptyDirectoriesIn(classes).clear(); + if (unplaced == 0) { Logger.info( - this, - "The binary %s of %s looks different, but its unplacing is mandatory as 'mandatoryUnplace' option specifies", - related, tojo.dependency() + this, "No binaries out of %d deleted in %[file]s", + binaries.size(), this.placed ); - } - if (UnplaceMojo.inside(related, this.keepBinaries) - && !UnplaceMojo.inside(related, this.removeBinaries)) { - continue; - } - if (UnplaceMojo.delete(path)) { - unplaced += 1; - tojo.unplace(); - Logger.debug( - this, "Binary %[file]s of %s deleted", - path, tojo.dependency() + } else if (unplaced == available.size()) { + Logger.info( + this, "All %d binari(es) deleted, which were found in %[file]s", + binaries.size(), this.placed ); } else { - Logger.debug( - this, "Binary %[file]s of %s already deleted", - path, tojo.dependency() + Logger.info( + this, "Just %d binari(es) out of %d deleted in %[file]s", + unplaced, binaries.size(), this.placed ); } } - return unplaced; } /** - * Keep those we must keep selectively. - * @param tojos All binaries found - * @return Number of files deleted - * @throws IOException If fails + * Unplace provided tojo. + * @param tojo Placed tojo + * @param classes All available classes + * @return Amount of unplaced binaries + * @throws IOException If fails to unplace */ - @SuppressWarnings("PMD.AvoidAccessToStaticMembersViaThis") - private int keepThem(final Iterable tojos) throws IOException { - int deleted = 0; - int remained = 0; - for (final TjPlaced tojo : tojos) { - final String related = tojo.related(); - final Path path = Paths.get(tojo.identifier()); - if (!this.keepBinaries.isEmpty() - && UnplaceMojo.inside(related, this.keepBinaries)) { - remained += 1; - continue; + private int unplace(final TjPlaced tojo, final Collection classes) throws IOException { + final String related = tojo.related(); + final Path path = Paths.get(tojo.identifier()); + final String hash = new FileHash(path).toString(); + final int unplaced; + final boolean inside = classes.stream().anyMatch(path::equals); + if (tojo.sameHash(hash)) { + if (inside) { + Logger.debug( + this, "The binary %s of %s looks the same, so it's unplaced", + related, tojo.dependency() + ); + unplaced = UnplaceMojo.unplaced(tojo, path); + } else { + Logger.debug( + this, "The binary %s of %s looks the same, but can't be unplaced", + related, tojo.dependency() + ); + unplaced = 0; } - if (UnplaceMojo.delete(path)) { - deleted += 1; + } else { + if (hash.isEmpty()) { + Logger.debug( + this, "The binary %s of %s is gone, won't unplace", + related, tojo.dependency() + ); + unplaced = 0; + } else if (inside) { Logger.debug( this, - "The binary %s of %s is removed since it doesn't match 'selectivelyPlace' list of globs", + "The binary %s of %s looks different, but its unplacing is mandatory", related, tojo.dependency() ); + unplaced = UnplaceMojo.unplaced(tojo, path); } else { Logger.debug( - this, "Binary %[file]s of %s already deleted", - path, tojo.dependency() + this, + "The binary %s of %s looks different, but can't be unplaced", + related, tojo.dependency() ); + unplaced = 0; } } - Logger.info( - this, - "Because of 'selectivelyPlace' list of globs: %d files remained and %d deleted", - remained, deleted - ); - return deleted; - } - - /** - * This file is matched by one of the globs? - * @param related The related name of the file - * @param globs The globs - * @return TRUE if inside this list of globx - */ - private static boolean inside(final String related, final Iterable globs) { - return new ListOf<>(globs).stream().anyMatch( - glob -> UnplaceMojo.matches(related, glob) - ); - } - - /** - * The file matches the glob? - * @param related The related name of the file - * @param glob The glob - * @return TRUE if matches - */ - private static boolean matches(final String related, final String glob) { - return FileSystems.getDefault().getPathMatcher( - String.format("glob:%s", glob) - ).matches(Paths.get(related)); - } - - /** - * Delete file and its parent if it's empty. - * @param file The file - * @return TRUE if deleted - * @throws IOException If fails - */ - private static boolean delete(final Path file) throws IOException { - Path dir = file.getParent(); - boolean deleted = false; - if (Files.exists(file)) { - Files.delete(file); - deleted = true; - } - while (UnplaceMojo.isEmpty(dir)) { - final Path curdir = dir; - dir = curdir.getParent(); - Files.delete(curdir); - Logger.debug(UnplaceMojo.class, "Empty directory deleted too: %[file]s", dir); - } - return deleted; + return unplaced; } /** - * Check if folder is empty. - * @param path Folder to be checked - * @return True if folder is empty and False otherwise - * @throws IOException In case of I/O issues + * Unplaced and deleted binary. + * @param tojo Placed tojo + * @param path Path to binary + * @return Amount of unplaced binaries + * @throws IOException If fails to delete binary */ - private static boolean isEmpty(final Path path) throws IOException { - boolean empty = false; - if (Files.isDirectory(path)) { - try (DirectoryStream directory = Files.newDirectoryStream(path)) { - empty = !directory.iterator().hasNext(); - } + private static int unplaced(final TjPlaced tojo, final Path path) throws IOException { + tojo.unplace(); + if (Files.deleteIfExists(path)) { + Logger.debug(UnplaceMojo.class, "Deleted binary %s", path); } - return empty; + return 1; } } diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/UnspileMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/UnspileMojo.java index 56d95083b7d..b31d85fef2e 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/UnspileMojo.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/UnspileMojo.java @@ -7,21 +7,21 @@ import com.jcabi.log.Logger; import java.io.File; import java.io.IOException; -import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.PathMatcher; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.regex.Pattern; import java.util.stream.Collectors; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.cactoos.set.SetOf; /** * Goes through all .class files and deletes those that - * were created from autogenerated sources. + * were created from autogenerated sources so these binaries + * are not got into result JAR. * * @since 0.1 */ @@ -32,99 +32,78 @@ ) @SuppressWarnings("PMD.ImmutableField") public final class UnspileMojo extends SafeMojo { - - /** - * Directory with Java classes. - * @checkstyle MemberNameCheck (7 lines) - */ - @Parameter( - property = "eo.classesDir", - required = true, - defaultValue = "${project.build.directory}/classes" - ) - private File classesDir; - /** - * Directory with generated sources. - * @checkstyle MemberNameCheck (7 lines) + * Pattern for matching paths ended with .class. */ - @Parameter( - property = "eo.generatedDir", - required = true, - defaultValue = "${project.build.directory}/generated-sources" - ) - private File generatedDir; + private static final Pattern JAVA = Pattern.compile("\\.java$"); /** - * List of inclusion GLOB filters for finding .class files. + * Inner auto generated classes. + *

These globs are used for inner classes which may look like: + * - EOorg/EOeolang/EOnumber$1$2$4.class + * - EOorg/EOeolang/EOsys/EOsocket$EOΦorgeolangsyssocketα0ρ.class

*/ - @Parameter - private Set includes = new SetOf<>("**/*.class"); + private static final Collection INNER = List.of( + "**/EO*$[1-9]*.class", "**/*$EOΦ*.class" + ); @Override public void exec() throws IOException { - final List all = new Walk(this.classesDir.toPath()).stream() - .filter( - file -> this.includes.stream().anyMatch( - glob -> UnspileMojo.matcher(glob).matches(file) - ) - ) - .collect(Collectors.toList()); - int unspiled = 0; - for (final Path path : all) { - if (this.delete(path)) { - unspiled += 1; - } - } - if (all.isEmpty()) { - Logger.warn( - this, "No .class files in %[file]s including %s, nothing to unspile", - this.classesDir, this.includes - ); - } else if (unspiled == 0) { - Logger.info( - this, "No .class files out of %d deleted in %[file]s including %s", - all.size(), this.classesDir, this.includes - ); + final Walk classes = new Walk(this.classesDir.toPath()); + if (classes.isEmpty()) { + Logger.warn(this, "No .class files in %[file]s, nothing to unspile", this.classesDir); } else { - Logger.info( - this, "Deleted %d .class files out of %d in %[file]s", - unspiled, all.size(), this.classesDir - ); + this.unspile(classes); } } /** - * Create glob matcher from text. - * @param text The pattern - * @return Matcher + * Unspile classes. + * @param classes Collection of compiled classes */ - private static PathMatcher matcher(final String text) { - return FileSystems.getDefault() - .getPathMatcher(String.format("glob:%s", text)); - } - - /** - * Delete .class file if .java file is present. - * @param file EO file - * @return TRUE if deleted - * @throws IOException If fails - */ - private boolean delete(final Path file) throws IOException { - final String name = file.toString().substring( - this.classesDir.toString().length() + 1 - ); - final Path java = this.generatedDir.toPath().resolve( - name.replaceAll("\\.class$", ".java") + private void unspile(final Walk classes) { + final Path generated = this.generatedDir.toPath(); + final Set included = new Walk(generated) + .stream() + .map( + path -> UnspileMojo.JAVA.matcher( + generated.relativize(path).toString() + ).replaceAll(".class").replace(File.separatorChar, '/') + ) + .collect(Collectors.toSet()); + included.addAll(UnspileMojo.INNER); + final Collection filtered = new ArrayList<>( + classes.excludes(this.keepBinaries).includes(included) ); - boolean deleted = false; - if (Files.exists(java)) { - Files.delete(file); - Logger.debug(this, "Deleted %[file]s since %[file]s is present", file, java); - deleted = true; + if (filtered.isEmpty()) { + Logger.info( + this, "No .class files out of %d deleted in %[file]s", + classes.size(), this.classesDir.toPath() + ); } else { - Logger.debug(this, "Not deleted %[file]s since %[file]s is absent", file, java); + final int unspiled = new Threaded<>( + filtered, + path -> { + final int deleted; + if (Files.deleteIfExists(path)) { + Logger.debug( + this, + "Deleted %[file]s since was compiled from %[file]s", + path, generated + ); + deleted = 1; + } else { + deleted = 0; + } + return deleted; + } + ).total(); + new EmptyDirectoriesIn(this.classesDir).clear(); + Logger.info( + this, + "Deleted %d .class files in %[file]s", + unspiled, this.classesDir.toPath() + ); } - return deleted; } } diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/CleanMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/CleanMojoTest.java index b39c05f96a1..39759f9ee47 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/CleanMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/CleanMojoTest.java @@ -49,7 +49,7 @@ void makesFullCompilingLifecycleSuccessfully(@Mktmp final Path temp) throws IOEx new FakeMaven(temp) .withHelloWorld() .with("includeSources", new SetOf<>("**.eo")) - .with("outputDir", temp.resolve("out").toFile()) + .with("classesDir", temp.resolve("out").toFile()) .with("placed", temp.resolve("list").toFile()) .with("cache", temp.resolve("cache/parsed").toFile()) .with("skipZeroVersions", true) diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/CopyMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/CopyMojoTest.java deleted file mode 100644 index 88afa4e303b..00000000000 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/CopyMojoTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com - * SPDX-License-Identifier: MIT - */ -package org.eolang.maven; - -import com.yegor256.Mktmp; -import com.yegor256.MktmpResolver; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.cactoos.bytes.BytesOf; -import org.cactoos.text.TextOf; -import org.hamcrest.MatcherAssert; -import org.hamcrest.Matchers; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -/** - * Test case for {@link CopyMojo}. - * - * @since 0.1 - */ -@ExtendWith(MktmpResolver.class) -final class CopyMojoTest { - - @Test - void copiesSources(@Mktmp final Path temp) throws Exception { - final Path src = temp.resolve("src"); - final Path classes = temp.resolve("classes"); - new Saved( - "+rt foo:0.0.0\n\n[args] > main\n \"0.0.0\" > @\n", - src.resolve("foo/main.eo") - ).value(); - final String ver = "1.1.1"; - new FakeMaven(temp) - .with("sourcesDir", src.toFile()) - .with("outputDir", classes.toFile()) - .with("skip", false) - .with("version", ver) - .execute(CopyMojo.class); - final Path out = classes.resolve("EO-SOURCES/foo/main.eo"); - MatcherAssert.assertThat( - "Expected EO source file to be copied, but it was not found", - Files.exists(out), - Matchers.is(true) - ); - MatcherAssert.assertThat( - "EO file should contain the correct version information, but it doesn't", - new TextOf(new BytesOf(Files.readAllBytes(out))).asString(), - Matchers.allOf( - Matchers.containsString("+rt foo:"), - Matchers.containsString("0.0.0"), - Matchers.containsString(ver) - ) - ); - } - - @Test - void skipsCopyMojo(@Mktmp final Path temp) throws IOException { - final Path classes = temp.resolve("classes"); - new FakeMaven(temp) - .withProgram( - "+rt foo:0.0.0", - "", - "", - "[args] > main", - " \"0.0.0\" > @" - ) - .with("sourcesDir", temp.toFile()) - .with("outputDir", temp.resolve("classes").toFile()) - .with("skip", true) - .with("version", "1.1.1") - .execute(CopyMojo.class); - final Path out = classes.resolve("EO-SOURCES/foo/main.eo"); - MatcherAssert.assertThat( - "CopyMojo must skip copying, but it doesn't", - Files.exists(out), - Matchers.is(false) - ); - } - -} 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 c67bb1a6bb8..1a20ac6eb7c 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 @@ -48,7 +48,7 @@ "JTCOP.RuleCorrectTestName" }) @NotThreadSafe -public final class FakeMaven { +final class FakeMaven { /** * Test workspace where we place all programs, files, compilation results, etc. @@ -77,7 +77,7 @@ public final class FakeMaven { * * @param workspace Test temporary directory. */ - public FakeMaven(final Path workspace) { + FakeMaven(final Path workspace) { this(workspace, true); } @@ -123,7 +123,7 @@ private FakeMaven( * @param value Parameter value * @return The same maven instance. */ - public FakeMaven with(final String param, final Object value) { + FakeMaven with(final String param, final Object value) { this.params.put(param, value); return this; } @@ -137,7 +137,7 @@ public FakeMaven with(final String param, final Object value) { * @return Workspace after executing Mojo. * @throws IOException If some problem with filesystem is happened. */ - public FakeMaven execute(final Iterable> mojo) + FakeMaven execute(final Iterable> mojo) throws IOException { for (final Class clazz : mojo) { this.execute(clazz); @@ -150,7 +150,7 @@ public FakeMaven execute(final Iterable> mojo) * * @return TjSmart of the current eo-foreign.file. */ - public TjSmart foreign() { + TjSmart foreign() { return new TjSmart( Catalogs.INSTANCE.make(this.foreignPath()) ); @@ -166,15 +166,14 @@ public TjSmart foreign() { * @checkstyle ExecutableStatementCountCheck (100 lines) * @checkstyle JavaNCSSCheck (100 lines) */ - public FakeMaven execute(final Class mojo) throws IOException { + FakeMaven execute(final Class mojo) throws IOException { if (this.defaults) { final Path transpiled = this.workspace.resolve("transpiled"); final Path placed = Paths.get("placed.json"); new Saved(new TextOf(""), transpiled).value(); this.params.putIfAbsent("targetDir", this.targetPath().toFile()); this.params.putIfAbsent( - "xslMeasures", - this.targetPath().resolve("measures.csv").toFile() + "xslMeasures", this.targetPath().resolve("measures.csv").toFile() ); this.params.putIfAbsent("foreign", this.foreignPath().toFile()); this.params.putIfAbsent("foreignFormat", "csv"); @@ -189,16 +188,10 @@ public FakeMaven execute(final Class mojo) throws IO this.params.putIfAbsent("placed", this.workspace.resolve(placed).toFile()); this.params.putIfAbsent("placedFormat", "json"); this.params.putIfAbsent( - "sourcesDir", - this.workspace.resolve(".").toFile() + "sourcesDir", this.workspace.resolve(".").toFile() ); this.params.putIfAbsent( - "outputDir", - this.workspace.resolve("target/classes").toFile() - ); - this.params.putIfAbsent( - "cache", - this.workspace.resolve("eo/cache/parsed").toFile() + "cache", this.workspace.resolve("eo/cache/parsed").toFile() ); this.params.putIfAbsent("generateSodgXmlFiles", true); this.params.putIfAbsent("generateXemblyFiles", true); @@ -221,12 +214,10 @@ public FakeMaven execute(final Class mojo) throws IO ).toFile() ); this.params.putIfAbsent( - "phiOutputDir", - this.workspace.resolve("target/phi").toFile() + "phiOutputDir", this.workspace.resolve("target/phi").toFile() ); this.params.putIfAbsent( - "unphiInputDir", - this.workspace.resolve("target/phi").toFile() + "unphiInputDir", this.workspace.resolve("target/phi").toFile() ); this.params.putIfAbsent( "unphiOutputDir", @@ -235,8 +226,7 @@ public FakeMaven execute(final Class mojo) throws IO ).toFile() ); this.params.putIfAbsent( - "classesDir", - this.workspace.resolve("target/classes").toFile() + "classesDir", this.classesPath().toFile() ); } final Moja moja = new Moja<>(mojo); @@ -253,7 +243,7 @@ public FakeMaven execute(final Class mojo) throws IO * @return The same maven instance. * @throws IOException If method can't save eo program to the workspace. */ - public FakeMaven withProgram(final Input input) throws IOException { + FakeMaven withProgram(final Input input) throws IOException { return this.withProgram(new UncheckedText(new TextOf(input)).asString()); } @@ -261,7 +251,7 @@ public FakeMaven withProgram(final Input input) throws IOException { * Path to compilation target directory. * @return Path to target dir. */ - public Path targetPath() { + Path targetPath() { return this.workspace.resolve("target"); } @@ -269,10 +259,18 @@ public Path targetPath() { * Path to generated directory. * @return Path to generated dir. */ - public Path generatedPath() { + Path generatedPath() { return this.targetPath().resolve("generated"); } + /** + * Path to classes directory. + * @return Path to classes directory + */ + Path classesPath() { + return this.targetPath().resolve("classes"); + } + /** * Foreign tojos for eo-foreign.* file. * @return Foreign tojos. @@ -450,18 +448,6 @@ static String suffix(final int index) { return suffix; } - /** - * Plugin descriptor with test version. - * @return Plugin descriptor. - */ - static PluginDescriptor pluginDescriptor() { - final PluginDescriptor descriptor = new PluginDescriptor(); - descriptor.setGroupId("org.eolang"); - descriptor.setArtifactId("eo-maven-plugin"); - descriptor.setVersion(FakeMaven.pluginVersion()); - return descriptor; - } - /** * Ensures the map of allowed params for the Mojo. * @@ -496,6 +482,18 @@ private static String tojoId(final int id) { return String.format("foo.x.main%s", FakeMaven.suffix(id)); } + /** + * Plugin descriptor with test version. + * @return Plugin descriptor. + */ + private static PluginDescriptor pluginDescriptor() { + final PluginDescriptor descriptor = new PluginDescriptor(); + descriptor.setGroupId("org.eolang"); + descriptor.setArtifactId("eo-maven-plugin"); + descriptor.setVersion(FakeMaven.pluginVersion()); + return descriptor; + } + /** * Looks for all declared fields for mojo and its parents. * @@ -733,13 +731,10 @@ public Iterator> iterator() { private static final class DummyCentral implements BiConsumer { @Override - public void accept( - final Dependency dependency, - final Path path - ) { + public void accept(final Dependency dependency, final Path path) { try { Files.createDirectories(path); - final String other = DummyCentral.jarName(dependency); + final String other = DummyCentral.className(dependency); Files.createFile(path.resolve(other)); } catch (final IOException ex) { throw new IllegalStateException( @@ -750,12 +745,12 @@ public void accept( } /** - * Dependency jar name. + * Dependency class name. * * @param dependency Dependency - * @return Jar file name + * @return Class file name */ - private static String jarName(final Dependency dependency) { + private static String className(final Dependency dependency) { final List parts = new ArrayList<>(3); if (dependency.getArtifactId() != null && !dependency.getArtifactId().isEmpty()) { parts.add(dependency.getArtifactId()); @@ -766,7 +761,7 @@ private static String jarName(final Dependency dependency) { if (dependency.getClassifier() != null && !dependency.getClassifier().isEmpty()) { parts.add(dependency.getClassifier()); } - return String.format("%s.jar", String.join("-", parts)); + return String.format("%s.class", String.join("-", parts)); } } } diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/PlaceMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/PlaceMojoTest.java index b0d9a420c81..e53d69b33d8 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/PlaceMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/PlaceMojoTest.java @@ -125,7 +125,7 @@ void placesDefaultJnaBinaries(@Mktmp final Path temp) throws Exception { .execute(new FakeMaven.Place()) .result() .get(PlaceMojoTest.TARGET_CLASSES), - new ContainsFiles("**/jna-*.jar") + new ContainsFiles("**/jna-*.class") ); } @@ -169,7 +169,7 @@ void placesMissing(@Mktmp final Path temp) throws IOException { /** * Test case for {@link PlaceMojo#execute()}. * Since for tests we are using dummy maven central, then instead of unpacking - * of classes from jar it just copies the jar itself to target/classes folder. + * of classes from jar it just copies the just simple .class files to target/classes folder. * * @param temp Temporary directory * @throws IOException If fails @@ -185,11 +185,11 @@ void placesAllEoRuntimeClasses(@Mktmp final Path temp) throws IOException { .execute(new FakeMaven.Place()) .result() .get(PlaceMojoTest.TARGET_CLASSES), - new ContainsFiles("**/eo-runtime-*.jar") + new ContainsFiles("**/eo-runtime-*.class") ); MatcherAssert.assertThat( - "PlaceMojo have to place jar file, but doesn't", - maven.placed().jars().size(), + "PlaceMojo have to place class file, but doesn't", + maven.placed().classes().size(), Matchers.is(1) ); } @@ -205,12 +205,7 @@ void placesWithoutEoRuntimeClasses(@Mktmp final Path temp) throws IOException { .execute(new FakeMaven.Place()) .result() .get(PlaceMojoTest.TARGET_CLASSES), - Matchers.not(new ContainsFiles("**/eo-runtime-*.jar")) - ); - MatcherAssert.assertThat( - "PlaceMojo have not to place jar file, but doesn't", - maven.placed().jars().isEmpty(), - Matchers.is(true) + Matchers.not(new ContainsFiles("**/eo-runtime-*.class")) ); } diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/ResolveMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/ResolveMojoTest.java index de846eac714..d7339d39cc9 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/ResolveMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/ResolveMojoTest.java @@ -31,14 +31,14 @@ final class ResolveMojoTest { /** - * The message that the JAR file must exist. + * The message that the .class file must exist. */ - private static final String JAR_MUST_EXIST = "The jar file must exist, but it doesn't"; + private static final String CLASS_MUST_EXIST = "The class file must exist, but it doesn't"; /** - * The message that the JAR file must not exist. + * The message that the .class file must not exist. */ - private static final String JAR_NOT_EXIST = "The jar file must not exist, but it doesn't"; + private static final String CLASS_NOT_EXIST = "The class file must not exist, but it doesn't"; @Test void resolvesWithSingleDependency(@Mktmp final Path temp) throws IOException { @@ -59,8 +59,8 @@ void resolvesWithSingleDependency(@Mktmp final Path temp) throws IOException { FileMatchers.anExistingDirectory() ); MatcherAssert.assertThat( - ResolveMojoTest.JAR_MUST_EXIST, - path.resolve("eo-runtime-0.7.0.jar").toFile(), + ResolveMojoTest.CLASS_MUST_EXIST, + path.resolve("eo-runtime-0.7.0.class").toFile(), FileMatchers.anExistingFile() ); } @@ -98,9 +98,9 @@ void resolvesWithoutAnyDependencies(@Mktmp final Path temp) throws IOException { FileMatchers.anExistingDirectory() ); MatcherAssert.assertThat( - ResolveMojoTest.JAR_MUST_EXIST, + ResolveMojoTest.CLASS_MUST_EXIST, path, - new ContainsFiles("**/eo-runtime-*.jar") + new ContainsFiles("**/eo-runtime-*.class") ); } @@ -109,9 +109,9 @@ void resolvesWithEoRuntimeDependency(@Mktmp final Path temp) throws IOException final FakeMaven maven = new FakeMaven(temp); maven.withHelloWorld().execute(new FakeMaven.Resolve()); MatcherAssert.assertThat( - ResolveMojoTest.JAR_MUST_EXIST, + ResolveMojoTest.CLASS_MUST_EXIST, maven.targetPath(), - new ContainsFiles("**/eo-runtime-*.jar") + new ContainsFiles("**/eo-runtime-*.class") ); } @@ -122,9 +122,9 @@ void resolvesWithoutEoRuntimeDependency(@Mktmp final Path temp) throws IOExcepti .with("ignoreRuntime", true) .execute(new FakeMaven.Resolve()); MatcherAssert.assertThat( - ResolveMojoTest.JAR_NOT_EXIST, + ResolveMojoTest.CLASS_NOT_EXIST, maven.targetPath(), - Matchers.not(new ContainsFiles("**/eo-runtime-*.jar")) + Matchers.not(new ContainsFiles("**/eo-runtime-*.class")) ); } @@ -140,9 +140,9 @@ void resolvesIfRuntimeDependencyComesFromTojos(@Mktmp final Path temp) throws IO ) .execute(new FakeMaven.Resolve()); MatcherAssert.assertThat( - ResolveMojoTest.JAR_MUST_EXIST, + ResolveMojoTest.CLASS_MUST_EXIST, maven.targetPath(), - new ContainsFiles("**/eo-runtime-0.22.1.jar") + new ContainsFiles("**/eo-runtime-0.22.1.class") ); } @@ -155,9 +155,9 @@ void resolvesIfRuntimeDependencyComesFromTojosButParamIsFalse(@Mktmp final Path .with("ignoreRuntime", true) .execute(new FakeMaven.Resolve()); MatcherAssert.assertThat( - ResolveMojoTest.JAR_NOT_EXIST, + ResolveMojoTest.CLASS_NOT_EXIST, maven.targetPath(), - Matchers.not(new ContainsFiles("**/eo-runtime-*.jar")) + Matchers.not(new ContainsFiles("**/eo-runtime-*.class")) ); } @@ -174,9 +174,9 @@ void resolvesWithRuntimeDependencyFromPom(@Mktmp final Path temp) throws IOExcep .with("project", project) .execute(new FakeMaven.Resolve()); MatcherAssert.assertThat( - ResolveMojoTest.JAR_MUST_EXIST, + ResolveMojoTest.CLASS_MUST_EXIST, maven.targetPath(), - new ContainsFiles("**/eo-runtime-0.7.0.jar") + new ContainsFiles("**/eo-runtime-0.7.0.class") ); } @@ -191,9 +191,9 @@ void resolvesWithoutTransitiveDependencies(@Mktmp final Path temp) throws IOExce ) .execute(new FakeMaven.Resolve()); MatcherAssert.assertThat( - ResolveMojoTest.JAR_MUST_EXIST, + ResolveMojoTest.CLASS_MUST_EXIST, maven.targetPath(), - new ContainsFiles("**/eo-runtime-*.jar") + new ContainsFiles("**/eo-runtime-*.class") ); } @@ -275,9 +275,9 @@ void resolvesWithConflictingDependenciesNoFail(@Mktmp final Path temp) throws IO maven.with("ignoreVersionConflicts", true) .execute(new FakeMaven.Resolve()); MatcherAssert.assertThat( - ResolveMojoTest.JAR_MUST_EXIST, + ResolveMojoTest.CLASS_MUST_EXIST, maven.targetPath(), - new ContainsFiles("**/eo-runtime-*.jar") + new ContainsFiles("**/eo-runtime-*.class") ); } } diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/TranspileMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/TranspileMojoTest.java index 2b0f266d944..728cd66990a 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/TranspileMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/TranspileMojoTest.java @@ -99,6 +99,48 @@ void doesNotTouchAtom(@Mktmp final Path temp) throws IOException { ); } + @Test + void createsPackageInfoFilesForAllPackages(@Mktmp final Path temp) throws IOException { + MatcherAssert.assertThat( + "TranspileMojo must generate package-info.java files for all of the packages", + new FakeMaven(temp) + .withProgram( + "+package com.example.custom\n", + "# Simple.", + "[] > simple" + ) + .execute(new FakeMaven.Transpile()) + .result(), + Matchers.allOf( + Matchers.hasKey("target/generated/EOcom/package-info.java"), + Matchers.hasKey("target/generated/EOcom/EOexample/package-info.java"), + Matchers.hasKey("target/generated/EOcom/EOexample/EOcustom/package-info.java") + ) + ); + } + + @Test + void savesValidContentToPackageInfoFile(@Mktmp final Path temp) throws Exception { + MatcherAssert.assertThat( + "TranspileMojo must save valid content to package-info.java file", + new TextOf( + new FakeMaven(temp) + .withProgram( + "+package com.example\n", + "# Simple.", + "[] > simple" + ) + .execute(new FakeMaven.Transpile()) + .result() + .get("target/generated/EOcom/EOexample/package-info.java") + ).asString(), + Matchers.allOf( + Matchers.containsString("// @org.eolang.XmirPackage(\"com.example\")"), + Matchers.containsString("package EOcom.EOexample;") + ) + ); + } + @Test void recompilesIfModified(@Mktmp final Path temp) throws IOException { final FakeMaven maven = new FakeMaven(temp); diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java index 7d26f9af962..cf59b44094c 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java @@ -10,21 +10,12 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.security.SecureRandom; -import java.util.Collections; -import java.util.List; -import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.stream.Stream; -import org.cactoos.text.TextOf; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.hamcrest.io.FileMatchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link UnplaceMojo}. @@ -35,253 +26,108 @@ @SuppressWarnings({"PMD.AvoidDuplicateLiterals", "PMD.TooManyMethods"}) @ExtendWith(MktmpResolver.class) final class UnplaceMojoTest { - - /** - * Binary glob pattern. - */ - private static final Set GLOB_PATTERN = Collections.singleton("**.class"); - - /** - * Default jar name. - */ - private static final String DEFAULT_JAR = "eo-lib"; - @Test - void cleansClasses(@Mktmp final Path temp) throws IOException { - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - final Path placed = UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); + void cleansAllTheFiles(@Mktmp final Path temp) throws IOException { + final FakeMaven maven = new FakeMaven(temp); + final Path clazz = UnplaceMojoTest.placed(temp, maven, "class"); + final Path text = UnplaceMojoTest.placed(temp, maven, "txt"); + final Path bin = UnplaceMojoTest.placed(temp, maven, "so"); MatcherAssert.assertThat( - "After executing UnplaceMojo, all class files should be removed", - new FakeMaven(temp) - .with("placed", placed.toFile()) + "After executing UnplaceMojo, all the placed files must be removed", + maven .execute(UnplaceMojo.class) - .result() - .values() - .stream() - .noneMatch(UnplaceMojoTest::isClass), - Matchers.is(true) + .result(), + Matchers.allOf( + Matchers.not(Matchers.hasValue(clazz)), + Matchers.not(Matchers.hasValue(text)), + Matchers.not(Matchers.hasValue(bin)) + ) ); } @Test - void cleansBinariesWithJar(@Mktmp final Path temp) throws IOException { - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - UnplaceMojoTest.placeJar(temp, UnplaceMojoTest.DEFAULT_JAR); - final Path placed = UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - final List tojos = new TjsPlaced(placed).allBinaries(); - new FakeMaven(temp) - .with("placed", placed.toFile()) - .execute(UnplaceMojo.class); - final int expected = 5; - MatcherAssert.assertThat( - String.format( - "Expected %d binaries, but it's not", - expected - ), - tojos.size(), - Matchers.equalTo(expected) - ); + void keepsClasses(@Mktmp final Path temp) throws IOException { + final FakeMaven maven = new FakeMaven(temp).with("keepBinaries", Set.of("**/*.class")); + final Path clazz = UnplaceMojoTest.placed(temp, maven, "class"); + final Path text = UnplaceMojoTest.placed(clazz, maven, "txt"); MatcherAssert.assertThat( - "All binaries should be marked as unplaced after cleanup", - tojos.stream().allMatch(TjPlaced::unplaced), - Matchers.is(true) + "UnplaceMojo must keep .class files and remove .txt file", + maven + .execute(UnplaceMojo.class) + .result(), + Matchers.allOf( + Matchers.hasValue(clazz), + Matchers.not(Matchers.hasValue(text)) + ) ); } @Test - void keepsJarBecauseItIsStillInUse(@Mktmp final Path temp) throws IOException { - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - final String other = "other-jar"; - UnplaceMojoTest.placeJar(temp, other); - final Path placed = UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - final List tojos = new TjsPlaced(placed).allBinaries(); - new FakeMaven(temp) - .with("placed", placed.toFile()) - .execute(UnplaceMojo.class); - final int expected = 5; - MatcherAssert.assertThat( - String.format( - "Expected %d binaries, but got a different number", - expected - ), - tojos.size(), - Matchers.equalTo(expected) - ); + void updatesPlacedTojosFile(@Mktmp final Path temp) throws IOException { + final FakeMaven maven = new FakeMaven(temp); + final Path file = UnplaceMojoTest.placed(temp, maven, "bat"); MatcherAssert.assertThat( - String.format("JAR file %s should still be placed as it is in use", other), - tojos.stream() - .filter(tojo -> tojo.identifier().equals(other)) - .allMatch(TjPlaced::placed), + "Tojo must be marked as unplaced", + maven.execute(UnplaceMojo.class).placed().find(file).get().unplaced(), Matchers.is(true) ); } - @ParameterizedTest - @MethodSource("testArgsProvider") - void unplacesWithKeepOrRemoveBinariesParam(final String[] params, @Mktmp final Path temp) - throws Exception { - final Path placed = UnplaceMojoTest.placeClass(temp, UnplaceMojoTest.clazz(temp)); - final FakeMaven maven = new FakeMaven(temp) - .with("placed", placed.toFile()); - for (final String param : params) { - maven.with(param, UnplaceMojoTest.GLOB_PATTERN); - } - final Map res = maven.execute(UnplaceMojo.class).result(); - if (params.length == 1 && "keepBinaries".equals(params[0])) { - MatcherAssert.assertThat( - "Class files must be kept, but they were removed", - res.values().stream().anyMatch(UnplaceMojoTest::isClass), - Matchers.is(true) - ); - MatcherAssert.assertThat( - "Output must contain false, but it doesn't", - new TextOf(res.get(placed.getFileName().toString())).asString(), - Matchers.allOf( - Matchers.containsString("false"), - Matchers.not(Matchers.containsString("true")) - ) - ); - } else { - MatcherAssert.assertThat( - "Class files must be removed, but some were kept", - res.values().stream().noneMatch(UnplaceMojoTest::isClass), - Matchers.is(true) - ); - MatcherAssert.assertThat( - "Output must contain false, but it doesn't", - new TextOf(res.get(placed.getFileName().toString())).asString(), - Matchers.allOf( - Matchers.not(Matchers.containsString("false")), - Matchers.containsString("true") - ) - ); - } - } - @Test - void unplacesWithRemoveBinaries(@Mktmp final Path temp) throws Exception { - final Path target = Paths.get("target"); - final Path source = target - .resolve("classes") - .resolve("EOorg") - .resolve("EOeolang") - .resolve("EOtxt") - .resolve("EOregexp.class"); - final Path test = target - .resolve("test-classes") - .resolve("EOorg") - .resolve("EOeolang") - .resolve("EOtxt") - .resolve("EOregexp.class"); - final Path remaining = target - .resolve("test-classes") - .resolve("EOorg") - .resolve("EOeolang") - .resolve("EOharmcrest") - .resolve("EOassert.class"); - new Saved(UUID.randomUUID().toString(), temp.resolve(source)).value(); - new Saved(UUID.randomUUID().toString(), temp.resolve(test)).value(); - new Saved(UUID.randomUUID().toString(), temp.resolve(remaining)).value(); - UnplaceMojoTest.placeClass(temp, temp.resolve(source)); - final Path placed = UnplaceMojoTest.placeClass(temp, temp.resolve(test)); - new FakeMaven(temp) - .with("placed", placed.toFile()) - .with("removeBinaries", Collections.singleton("EOorg/EOeolang/EOtxt/**")) - .execute(UnplaceMojo.class) - .result(); - MatcherAssert.assertThat( - String.format("Source class %s has not to be present", source), - temp.resolve(source).toFile(), - Matchers.not(FileMatchers.anExistingFile()) - ); + void deletesAllEmptyDirectories(@Mktmp final Path temp) throws IOException { + final FakeMaven maven = new FakeMaven(temp); + UnplaceMojoTest.placed(temp, maven, Paths.get("org/eolang/index.html")); + UnplaceMojoTest.placed(temp, maven, Paths.get("org/styles.css")); MatcherAssert.assertThat( - String.format("Test class %s has not to be present", test), - temp.resolve(test).toFile(), - Matchers.not(FileMatchers.anExistingFile()) - ); - MatcherAssert.assertThat( - String.format("Test class %s has to be present", remaining), - temp.resolve(remaining).toFile(), - FileMatchers.anExistingFile() + "UnplaceMojo must delete all empty directories", + maven.execute(UnplaceMojo.class).result(), + Matchers.allOf( + Matchers.not(Matchers.hasKey("target/classes/org/eolang")), + Matchers.not(Matchers.hasKey("target/classes/org")), + Matchers.hasKey("target/classes") + ) ); } /** - * Saves a class file into the placed tojos file. - * @param temp Temporary directory. - * @param clazz Class file. - * @return Path to the placed tojos file. + * Place file to the placed tojos file. + * @param temp Temporary directory + * @param maven Maven instance + * @param ext File extension + * @return Path to placed file */ - private static Path placeClass(final Path temp, final Path clazz) { - final Path placed = UnplaceMojoTest.placedFile(temp); - new TjsPlaced(placed).placeClass( - clazz, - temp.relativize(clazz).toString(), - UnplaceMojoTest.DEFAULT_JAR + private static Path placed( + final Path temp, final FakeMaven maven, final String ext + ) throws IOException { + return UnplaceMojoTest.placed( + temp, + maven, + Paths.get( + String.format("a/b/c/%d_foo.%s", new SecureRandom().nextInt(), ext) + ) ); - return placed; - } - - /** - * Saves a jar into the placed tojos file. - * @param temp Temporary directory. - * @param name Name of the jar. - * @return Path to the placed tojos file. - */ - private static void placeJar(final Path temp, final String name) { - new TjsPlaced(UnplaceMojoTest.placedFile(temp)).placeJar(name); - } - - /** - * Creates a path to the placed tojos file. - * @param temp Temporary directory. - * @return Path to the placed tojos file. - */ - private static Path placedFile(final Path temp) { - return temp.resolve("placed.csv"); } /** - * Creates and saves a class file. - * @param temp Where to save the file. - * @return The path to the file. - * @throws IOException If fails. + * Place file into the placed tojos file. + * @param temp Temporary directory + * @param maven Maven instance + * @param relative Relative path to file + * @return Path to placed file + * @throws IOException If Fails to place */ - private static Path clazz(final Path temp) throws IOException { - final Path path = - Paths.get(String.format("a/b/c/%d_foo.class", new SecureRandom().nextInt())); - return new Saved( - () -> UUID.randomUUID().toString(), - temp.resolve(path) + private static Path placed( + final Path temp, final FakeMaven maven, final Path relative + ) throws IOException { + final Path file = new Saved( + UUID.randomUUID().toString(), + maven.classesPath().resolve(relative) ).value(); - } - - /** - * Checks if the path is a class file. - * @param path The path to check. - * @return True if it is a class file. - */ - private static boolean isClass(final Path path) { - return path.toString().endsWith(".class"); - } - - /** - * Input arguments for unit tests. - * - * @return Stream of arguments. - */ - @SuppressWarnings("PMD.UnusedPrivateMethod") - private static Stream testArgsProvider() { - return Stream.of( - Arguments.of((Object) new String[]{"keepBinaries"}), - Arguments.of((Object) new String[]{"removeBinaries"}), - Arguments.of((Object) new String[]{"keepBinaries", "removeBinaries"}) + maven.placed().placeClass( + file, + temp.relativize(file).toString(), + "eo-lib" ); + return file; } } diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/UnspileMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/UnspileMojoTest.java index 4f4fbf8f71f..441f1f523cc 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/UnspileMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/UnspileMojoTest.java @@ -10,6 +10,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Set; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; @@ -24,24 +25,80 @@ final class UnspileMojoTest { @Test - void cleans(@Mktmp final Path temp) throws IOException { - final Path generated = Paths.get("generated"); - final Path classes = Paths.get("classes"); + void deletesClassIfCompiledFromGeneratedSources(@Mktmp final Path temp) throws IOException { final Path foo = Paths.get("a/b/c/foo.class"); final FakeMaven maven = new FakeMaven(temp); new Saved("abc", temp.resolve(foo)).value(); - new Saved("xxx", temp.resolve(generated).resolve("a/b/c/foo.java")).value(); - new Saved("cde", temp.resolve(classes).resolve("foo.txt")).value(); - maven.with("generatedDir", generated.toFile()) - .with("classesDir", classes.toFile()) - .execute(UnspileMojo.class); + new Saved("xxx", maven.generatedPath().resolve("a/b/c/foo.java")).value(); + maven.execute(UnspileMojo.class); MatcherAssert.assertThat( - String.format( - "UnspileMojo unable to remove %s class", - foo - ), + String.format("UnspileMojo unable to remove %s class", foo), Files.exists(foo), Matchers.is(false) ); } + + @Test + void keepsSpecifiedClasses(@Mktmp final Path temp) throws IOException { + final FakeMaven maven = new FakeMaven(temp) + .with("keepBinaries", Set.of("EOorg/package-info.class")); + new Saved("gen1", maven.generatedPath().resolve("EOorg/package-info.java")).value(); + new Saved( + "gen2", maven.generatedPath().resolve("EOorg/EOeolang/package-info.java") + ).value(); + final Path org = new Saved( + "clz", maven.classesPath().resolve("EOorg/package-info.class") + ).value(); + final Path eolang = new Saved( + "pkg", maven.classesPath().resolve("EOorg/EOeolang/package-info.class") + ).value(); + MatcherAssert.assertThat( + "UnspileMojo must keep files matching to keepBinaries globs", + maven.execute(UnspileMojo.class).result(), + Matchers.allOf( + Matchers.hasValue(org), + Matchers.not(Matchers.hasValue(eolang)) + ) + ); + } + + @Test + void deletesInnerGeneratedClasses(@Mktmp final Path temp) throws IOException { + final FakeMaven maven = new FakeMaven(temp); + new Saved("outer", maven.generatedPath().resolve("EOorg/EOnumber.java")).value(); + final Path clazz = new Saved( + "clz", maven.classesPath().resolve("EOorg/EOnumber.class") + ).value(); + final Path inner = new Saved( + "inner", maven.classesPath().resolve("EOorg/EOnumber$1$2$3.class") + ).value(); + final Path located = new Saved( + "clss", maven.classesPath().resolve("EOorg/EOnumber$EOΦorgeolanginner.class") + ).value(); + MatcherAssert.assertThat( + "UnspileMojo must delete inner auto generated classes", + maven.execute(UnspileMojo.class).result(), + Matchers.allOf( + Matchers.not(Matchers.hasValue(clazz)), + Matchers.not(Matchers.hasValue(inner)), + Matchers.not(Matchers.hasValue(located)) + ) + ); + } + + @Test + void deletesEmptyDirectories(@Mktmp final Path temp) throws IOException { + final FakeMaven maven = new FakeMaven(temp); + new Saved("src", maven.generatedPath().resolve("org/eolang/number.java")).value(); + new Saved("cnt", maven.classesPath().resolve("org/eolang/number.class")).value(); + MatcherAssert.assertThat( + "UnspileMojo must remove all empty directories recursively", + maven.execute(UnspileMojo.class).result(), + Matchers.allOf( + Matchers.not(Matchers.hasKey("target/classes/org/eolang")), + Matchers.not(Matchers.hasKey("target/classes/org")), + Matchers.hasKey("target/classes") + ) + ); + } } diff --git a/eo-runtime/pom.xml b/eo-runtime/pom.xml index 4007c34629a..1091b337f60 100644 --- a/eo-runtime/pom.xml +++ b/eo-runtime/pom.xml @@ -220,15 +220,20 @@ compile transpile xmir-to-phi - phi-to-xmir - copy unplace unspile true - true false + + EOorg/package-info.class + EOorg/EOeolang/package-info.class + EOorg/EOeolang/EOfs/package-info.class + EOorg/EOeolang/EOmath/package-info.class + EOorg/EOeolang/EOsys/package-info.class + EOorg/EOeolang/EOtxt/package-info.class + @@ -238,7 +243,6 @@ register compile xmir-to-phi - phi-to-xmir transpile @@ -247,14 +251,11 @@ ${project.build.directory}/eo-test ${project.build.directory}/eo-test/1-parse ${project.build.directory}/eo-test/phi - ${project.build.directory}/eo-test/phi - ${project.build.directory}/eo-test/unphi false true true ${project.build.directory}/generated-test-sources true - true diff --git a/eo-runtime/src/test/groovy/check-target-files.groovy b/eo-runtime/src/test/groovy/check-target-files.groovy index debba85e694..c21c9993c19 100644 --- a/eo-runtime/src/test/groovy/check-target-files.groovy +++ b/eo-runtime/src/test/groovy/check-target-files.groovy @@ -11,17 +11,20 @@ List expected = [ 'eo/5-lint/org/eolang/go.xmir', 'eo/8-transpile/org/eolang/malloc.xmir', 'eo/phi/org/eolang/number.phi', - 'eo/unphi/org/eolang/number.xmir', 'eo-test/1-parse/org/eolang/bool-tests.xmir', 'eo-test/2-shake/org/eolang/go-tests.xmir', 'eo-test/5-lint/org/eolang/dataized-tests.xmir', 'eo-test/8-transpile/org/eolang/runtime-tests.xmir', 'eo-test/phi/org/eolang/number-tests.phi', - 'eo-test/unphi/org/eolang/number-tests.xmir', 'generated-sources/EOorg/EOeolang/EOdataized.java', 'generated-sources/EOorg/EOeolang/EOnet/EOsocket.java', 'generated-test-sources/EOorg/EOeolang/EOtests_and_with_zeroTest.java', - 'classes/EO-SOURCES/org/eolang/false.eo', + 'classes/EOorg/package-info.class', + 'classes/EOorg/EOeolang/package-info.class', + 'classes/EOorg/EOeolang/EOsys/package-info.class', + 'classes/EOorg/EOeolang/EOmath/package-info.class', + 'classes/EOorg/EOeolang/EOfs/package-info.class', + 'classes/EOorg/EOeolang/EOtxt/package-info.class', ] for (path in expected) { diff --git a/eo-runtime/src/test/java/integration/JarIT.java b/eo-runtime/src/test/java/integration/JarIT.java index 8624aaca045..95c7be3b4f4 100644 --- a/eo-runtime/src/test/java/integration/JarIT.java +++ b/eo-runtime/src/test/java/integration/JarIT.java @@ -4,7 +4,6 @@ */ package integration; -import com.jcabi.manifests.Manifests; import com.yegor256.Jaxec; import com.yegor256.MayBeSlow; import com.yegor256.Mktmp; @@ -45,21 +44,13 @@ void runsProgramFromJar(final @Mktmp Path temp) throws IOException { .write( "QQ.io.stdout \"Hello, world!\" > simple\n".getBytes(StandardCharsets.UTF_8) ); - f.dependencies() - .append( - "org.eolang", - "eo-runtime", - System.getProperty( - "eo.version", - Manifests.read("EO-Version") - ) - ); new EoMavenPlugin(f) .appended() .execution("compile") - .phase("generate-sources") .goals("register", "compile", "transpile") .configuration() + .set("ignoreRuntime", Boolean.TRUE.toString()) + .set("offline", Boolean.TRUE.toString()) .set("failOnWarning", Boolean.FALSE.toString()) .set("skipLinting", Boolean.TRUE.toString()); f.exec("clean", "compile", "jar:jar"); diff --git a/eo-runtime/src/test/java/integration/PhiUnphiIT.java b/eo-runtime/src/test/java/integration/PhiUnphiIT.java index 3c4f0808624..689be7bd10a 100644 --- a/eo-runtime/src/test/java/integration/PhiUnphiIT.java +++ b/eo-runtime/src/test/java/integration/PhiUnphiIT.java @@ -111,31 +111,19 @@ void runsAfterPhiAndUnphi(final @Mktmp Path temp) throws IOException { ) ) .execution("compile") - .goals( - "register", - "compile", - "transpile", - "copy", - "unplace", - "unspile" - ) + .goals("register", "compile", "transpile") .configuration() .set("foreign", "${project.basedir}/target/eo-foreign.json") .set("foreignFormat", "csv") .set("failOnWarning", Boolean.FALSE.toString()) .set("offline", Boolean.TRUE.toString()) .set("skipLinting", Boolean.TRUE.toString()) - .set("ignoreRuntime", Boolean.TRUE.toString()) - .set("placeBinariesThatHaveSources", Boolean.TRUE.toString()); + .set("ignoreRuntime", Boolean.TRUE.toString()); new EoMavenPlugin(f) .appended() .execution("tests") .phase("generate-test-sources") - .goals( - "register", - "compile", - "transpile" - ) + .goals("register", "compile", "transpile") .configuration() .set("foreign", "${project.basedir}/target/eo-foreign.json") .set("foreignFormat", "csv") @@ -148,8 +136,7 @@ void runsAfterPhiAndUnphi(final @Mktmp Path temp) throws IOException { .set("addTestSourcesRoot", Boolean.TRUE.toString()) .set("failOnWarning", Boolean.FALSE.toString()) .set("generatedDir", "${project.basedir}/target/generated-test-sources") - .set("ignoreRuntime", Boolean.TRUE.toString()) - .set("placeBinariesThatHaveSources", Boolean.TRUE.toString()); + .set("ignoreRuntime", Boolean.TRUE.toString()); f.exec("clean", "test"); MatcherAssert.assertThat( "Some tests weren't passed after converting to phi and back",