From 9e80ae70b934fff4ab72526c8e45db8caec511ad Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Thu, 23 Jan 2025 18:07:10 +0100 Subject: [PATCH] refactor: merge alias attributes When one alias refers to another we now merge the attributes of the two aliases (when dealing with lists and maps, in the case of simple values the "parent" alias overrides the "child" alias). See #1910 --- src/main/java/dev/jbang/catalog/Alias.java | 71 ++++++++++++++-------- src/test/java/dev/jbang/cli/TestAlias.java | 18 +++--- src/test/java/dev/jbang/cli/TestRun.java | 28 +++++++++ 3 files changed, 81 insertions(+), 36 deletions(-) diff --git a/src/main/java/dev/jbang/catalog/Alias.java b/src/main/java/dev/jbang/catalog/Alias.java index 6f761fdfc..fca7310e8 100644 --- a/src/main/java/dev/jbang/catalog/Alias.java +++ b/src/main/java/dev/jbang/catalog/Alias.java @@ -3,10 +3,7 @@ import static dev.jbang.cli.BaseCommand.EXIT_INVALID_INPUT; import java.nio.file.Path; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.function.Function; import javax.annotation.Nonnull; @@ -205,40 +202,30 @@ private static Alias merge(Alias a1, String name, Function findUn names.add(name); a2 = merge(a2, a2.scriptRef, findUnqualifiedAlias, names); String desc = a1.description != null ? a1.description : a2.description; - List args = a1.arguments != null && !a1.arguments.isEmpty() ? a1.arguments : a2.arguments; - List jopts = a1.runtimeOptions != null && !a1.runtimeOptions.isEmpty() ? a1.runtimeOptions - : a2.runtimeOptions; - List srcs = a1.sources != null && !a1.sources.isEmpty() ? a1.sources - : a2.sources; - List ress = a1.resources != null && !a1.resources.isEmpty() ? a1.resources - : a2.resources; - List deps = a1.dependencies != null && !a1.dependencies.isEmpty() ? a1.dependencies - : a2.dependencies; - List repos = a1.repositories != null && !a1.repositories.isEmpty() ? a1.repositories - : a2.repositories; - List cpaths = a1.classpaths != null && !a1.classpaths.isEmpty() ? a1.classpaths - : a2.classpaths; - Map props = a1.properties != null && !a1.properties.isEmpty() ? a1.properties - : a2.properties; + List args = join(a1.arguments, a2.arguments); + List jopts = join(a1.runtimeOptions, a2.runtimeOptions); + List srcs = join(a1.sources, a2.sources); + List ress = join(a1.resources, a2.resources); + List deps = join(a1.dependencies, a2.dependencies); + List repos = join(a1.repositories, a2.repositories); + List cpaths = join(a1.classpaths, a2.classpaths); + Map props = join(a1.properties, a2.properties); String javaVersion = a1.javaVersion != null ? a1.javaVersion : a2.javaVersion; String mainClass = a1.mainClass != null ? a1.mainClass : a2.mainClass; String moduleName = a1.moduleName != null ? a1.moduleName : a2.moduleName; - List copts = a1.compileOptions != null && !a1.compileOptions.isEmpty() ? a1.compileOptions - : a2.compileOptions; - List nopts = a1.nativeOptions != null && !a1.nativeOptions.isEmpty() ? a1.nativeOptions - : a2.nativeOptions; + List copts = join(a1.compileOptions, a2.compileOptions); + List nopts = join(a1.nativeOptions, a2.nativeOptions); Boolean nimg = a1.nativeImage != null ? a1.nativeImage : a2.nativeImage; Boolean ints = a1.integrations != null ? a1.integrations : a2.integrations; String jfr = a1.jfr != null ? a1.jfr : a2.jfr; - Map debug = a1.debug != null ? a1.debug : a2.debug; + Map debug = join(a1.debug, a2.debug); Boolean cds = a1.cds != null ? a1.cds : a2.cds; Boolean inter = a1.interactive != null ? a1.interactive : a2.interactive; Boolean ep = a1.enablePreview != null ? a1.enablePreview : a2.enablePreview; Boolean ea = a1.enableAssertions != null ? a1.enableAssertions : a2.enableAssertions; Boolean esa = a1.enableSystemAssertions != null ? a1.enableSystemAssertions : a2.enableSystemAssertions; - Map mopts = a1.manifestOptions != null && !a1.manifestOptions.isEmpty() ? a1.manifestOptions - : a2.manifestOptions; - List jags = a1.javaAgents != null && !a1.javaAgents.isEmpty() ? a1.javaAgents : a2.javaAgents; + Map mopts = join(a1.manifestOptions, a2.manifestOptions); + List jags = join(a1.javaAgents, a2.javaAgents); Catalog catalog = a2.catalog != null ? a2.catalog : a1.catalog; return new Alias(a2.scriptRef, desc, args, jopts, srcs, ress, deps, repos, cpaths, props, javaVersion, mainClass, moduleName, copts, nimg, nopts, ints, jfr, debug, cds, inter, ep, ea, esa, mopts, jags, @@ -248,6 +235,36 @@ private static Alias merge(Alias a1, String name, Function findUn } } + private static List join(List l1, List l2) { + if (l1 != null && !l1.isEmpty()) { + if (l2 != null && !l2.isEmpty()) { + List merged = new ArrayList<>(l1.size() + l2.size()); + merged.addAll(l2); + merged.addAll(l1); + return merged; + } else { + return l1; + } + } else { + return l2; + } + } + + private static Map join(Map m1, Map m2) { + if (m1 != null && !m1.isEmpty()) { + if (m2 != null && !m2.isEmpty()) { + Map merged = new HashMap<>(); + merged.putAll(m2); + merged.putAll(m1); + return merged; + } else { + return m1; + } + } else { + return m2; + } + } + /** * Returns the given Alias from the local file system * diff --git a/src/test/java/dev/jbang/cli/TestAlias.java b/src/test/java/dev/jbang/cli/TestAlias.java index b1fb37319..9cb14ed47 100644 --- a/src/test/java/dev/jbang/cli/TestAlias.java +++ b/src/test/java/dev/jbang/cli/TestAlias.java @@ -458,10 +458,10 @@ void testGetAliasFour() throws IOException { assertThat(alias.scriptRef, equalTo("http://dummy")); assertThat(alias.resolve(), equalTo("http://dummy")); assertThat(alias.description, equalTo("fourdesc")); - assertThat(alias.arguments, iterableWithSize(1)); - assertThat(alias.arguments, contains("4")); - assertThat(alias.runtimeOptions, iterableWithSize(1)); - assertThat(alias.runtimeOptions, contains("--four")); + assertThat(alias.arguments, iterableWithSize(2)); + assertThat(alias.arguments, contains("3", "4")); + assertThat(alias.runtimeOptions, iterableWithSize(2)); + assertThat(alias.runtimeOptions, contains("--three", "--four")); assertThat(alias.sources, iterableWithSize(1)); assertThat(alias.sources, contains("foursrc")); assertThat(alias.resources, iterableWithSize(1)); @@ -472,16 +472,16 @@ void testGetAliasFour() throws IOException { assertThat(alias.repositories, contains("fourrepo")); assertThat(alias.classpaths, iterableWithSize(1)); assertThat(alias.classpaths, contains("fourcp")); - assertThat(alias.properties, aMapWithSize(1)); + assertThat(alias.properties, aMapWithSize(2)); assertThat(alias.properties, hasEntry("four", "4")); assertThat(alias.javaVersion, equalTo("fourjava")); assertThat(alias.mainClass, equalTo("fourmain")); assertThat(alias.moduleName, equalTo("fourmodule")); - assertThat(alias.compileOptions, iterableWithSize(1)); - assertThat(alias.compileOptions, contains("--cfour")); + assertThat(alias.compileOptions, iterableWithSize(2)); + assertThat(alias.compileOptions, contains("--cthree", "--cfour")); assertThat(alias.nativeImage, is(Boolean.FALSE)); - assertThat(alias.nativeOptions, iterableWithSize(1)); - assertThat(alias.nativeOptions, contains("--nfour")); + assertThat(alias.nativeOptions, iterableWithSize(2)); + assertThat(alias.nativeOptions, contains("--nthree", "--nfour")); assertThat(alias.jfr, equalTo("fourjfr")); assertThat(alias.debug, aMapWithSize(1)); assertThat(alias.debug, hasEntry("fourd", "4")); diff --git a/src/test/java/dev/jbang/cli/TestRun.java b/src/test/java/dev/jbang/cli/TestRun.java index a10b05324..bce999bc8 100644 --- a/src/test/java/dev/jbang/cli/TestRun.java +++ b/src/test/java/dev/jbang/cli/TestRun.java @@ -2580,6 +2580,34 @@ void testAliasArguments() throws IOException { assertThat(cmdline, endsWith("echo foo bar baz")); } + @Test + void testAliasAliasArguments() throws IOException { + File f = examplesTestFolder.resolve("echo.java").toFile(); + List args = Arrays.asList("foo"); + Alias alias = new Alias(f.toString(), null, args, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null); + CatalogUtil.addNearestAlias("foo", alias); + + List args2 = Arrays.asList("bar"); + Alias alias2 = new Alias("foo", null, args2, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null); + CatalogUtil.addNearestAlias("bar", alias2); + + CommandLine.ParseResult pr = JBang .getCommandLine() + .parseArgs("run", "bar", "baz"); + Run run = (Run) pr.subcommand().commandSpec().userObject(); + + ProjectBuilder pb = run.createProjectBuilderForRun(); + Project prj = pb.build("bar"); + + BuildContext ctx = BuildContext.forProject(prj, null); + CmdGeneratorBuilder genb = Project.codeBuilder(ctx).build(); + + String cmdline = run.updateGeneratorForRun(genb).build().generate(); + + assertThat(cmdline, endsWith("echo foo bar baz")); + } + @Test void testCatalogAliasArguments() throws IOException { File f = examplesTestFolder.resolve("jbang-catalog.json").toFile();