From 2f9db4777dc054e4ee2f2514087faf8c78887dce Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 12 Mar 2024 17:48:25 +0100 Subject: [PATCH] Do not return on exact match when searching extensions When looking for "rest", we want all the extensions matching "rest" returned and not quarkus-rest only. Fixes #39312 --- .../ListExtensionsCommandHandler.java | 2 +- .../handlers/QuarkusCommandHandlers.java | 28 +++++++++--- .../handlers/QuarkusCommandHandlersTest.java | 44 ++++++++++++++----- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ListExtensionsCommandHandler.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ListExtensionsCommandHandler.java index 8efdbd1e04068..ca7154bc9f64c 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ListExtensionsCommandHandler.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ListExtensionsCommandHandler.java @@ -57,7 +57,7 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws invocation.getQuarkusProject().getExtensionManager()); final Collection extensions = search == null ? invocation.getExtensionsCatalog().getExtensions() - : QuarkusCommandHandlers.select(search, invocation.getExtensionsCatalog().getExtensions(), true) + : QuarkusCommandHandlers.listExtensions(search, invocation.getExtensionsCatalog().getExtensions(), true) .getExtensions(); if (extensions.isEmpty()) { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlers.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlers.java index 6b2a3c04935ff..6f4da36ee8772 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlers.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlers.java @@ -61,7 +61,7 @@ static List computeExtensionsFromQuery(ExtensionCatalog catalog, result = new SelectionResult(List.of(), false); } } else { - result = select(query, extensionCatalog, false); + result = selectExtensions(query, extensionCatalog, false); } if (result.matches()) { builder.addAll(result.getExtensions()); @@ -96,6 +96,22 @@ static List computeCoordsFromQuery(final QuarkusCommandInvocatio : extensions.stream().map(e -> Extensions.stripVersion(e.getArtifact())).collect(Collectors.toList()); } + /** + * Select extensions and return only one if exact match on the name or short name. + */ + static SelectionResult selectExtensions(final String query, final Collection allExtensions, + boolean labelLookup) { + return listExtensions(query, allExtensions, true, labelLookup); + } + + /** + * List extensions. Returns all matching extensions. + */ + static SelectionResult listExtensions(final String query, final Collection allExtensions, + boolean labelLookup) { + return listExtensions(query, allExtensions, false, labelLookup); + } + /** * Selection algorithm. * @@ -105,8 +121,8 @@ static List computeCoordsFromQuery(final QuarkusCommandInvocatio * be {@code false} by default. * @return the list of matching candidates and whether or not a match has been found. */ - static SelectionResult select(final String query, final Collection allExtensions, - final boolean labelLookup) { + private static SelectionResult listExtensions(final String query, final Collection allExtensions, + boolean returnOnExactMatch, boolean labelLookup) { String q = query.trim().toLowerCase(); final Map matches = new LinkedHashMap<>(); @@ -117,7 +133,7 @@ static SelectionResult select(final String query, final Collection al .filter(extension -> extension.getName().equalsIgnoreCase(q) || matchesArtifactId(extension.getArtifact().getArtifactId(), q)) .forEach(e -> matches.putIfAbsent(e.getArtifact().getKey(), e)); - if (matches.size() == 1) { + if (matches.size() == 1 && returnOnExactMatch) { return new SelectionResult(matches.values(), true); } @@ -126,7 +142,7 @@ static SelectionResult select(final String query, final Collection al // Try short names listedExtensions.stream().filter(extension -> matchesShortName(extension, q)) .forEach(e -> matches.putIfAbsent(e.getArtifact().getKey(), e)); - if (matches.size() == 1) { + if (matches.size() == 1 && returnOnExactMatch) { return new SelectionResult(matches.values(), true); } @@ -138,7 +154,7 @@ static SelectionResult select(final String query, final Collection al .forEach(e -> matches.putIfAbsent(e.getArtifact().getKey(), e)); // Even if we have a single partial match, if the name, artifactId and short names are ambiguous, so not // consider it as a match. - if (matches.size() == 1) { + if (matches.size() == 1 && returnOnExactMatch) { return new SelectionResult(matches.values(), true); } diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java index 4c7734978343f..4b32cd41ba3b6 100644 --- a/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/commands/handlers/QuarkusCommandHandlersTest.java @@ -1,6 +1,7 @@ package io.quarkus.devtools.commands.handlers; -import static io.quarkus.devtools.commands.handlers.QuarkusCommandHandlers.select; +import static io.quarkus.devtools.commands.handlers.QuarkusCommandHandlers.listExtensions; +import static io.quarkus.devtools.commands.handlers.QuarkusCommandHandlers.selectExtensions; import static java.util.Arrays.asList; import java.util.Arrays; @@ -35,11 +36,11 @@ void testMultiMatchByLabels() { List extensions = asList(e1, e2, e3); Collections.shuffle(extensions); - SelectionResult matches = select("foo", extensions, true); + SelectionResult matches = selectExtensions("foo", extensions, true); Assertions.assertFalse(matches.matches()); Assertions.assertEquals(2, matches.getExtensions().size()); - matches = select("foo", extensions, false); + matches = selectExtensions("foo", extensions, false); Assertions.assertFalse(matches.matches()); Assertions.assertEquals(0, matches.getExtensions().size()); } @@ -58,7 +59,7 @@ void testThatSingleLabelMatchIsNotAMatch() { List extensions = asList(e1, e2); Collections.shuffle(extensions); - SelectionResult matches = select("foo", extensions, true); + SelectionResult matches = selectExtensions("foo", extensions, true); Assertions.assertFalse(matches.matches()); Assertions.assertEquals(1, matches.getExtensions().size()); } @@ -80,11 +81,11 @@ void testMultiMatchByArtifactIdsAndNames() { List extensions = asList(e1, e2, e3); Collections.shuffle(extensions); - SelectionResult matches = select("foo", extensions, false); + SelectionResult matches = selectExtensions("foo", extensions, false); Assertions.assertFalse(matches.matches(), " " + matches.getExtensions().size()); Assertions.assertEquals(2, matches.getExtensions().size()); - matches = select("foo", extensions, true); + matches = selectExtensions("foo", extensions, true); Assertions.assertFalse(matches.matches()); Assertions.assertEquals(3, matches.getExtensions().size()); @@ -108,7 +109,7 @@ void testShortNameSelection() { List extensions = asList(e1, e2, e3); Collections.shuffle(extensions); - SelectionResult matches = select("foo", extensions, false); + SelectionResult matches = selectExtensions("foo", extensions, false); Assertions.assertTrue(matches.matches()); Assertions.assertEquals(1, matches.getExtensions().size()); Assertions.assertTrue(matches.iterator().hasNext()); @@ -135,12 +136,35 @@ void testArtifactIdSelectionWithQuarkusPrefix() { List extensions = asList(e1, e2, e3); Collections.shuffle(extensions); - SelectionResult matches = select("foo", extensions, false); + SelectionResult matches = selectExtensions("foo", extensions, false); Assertions.assertEquals(1, matches.getExtensions().size()); Assertions.assertTrue(matches.iterator().hasNext()); Assertions.assertTrue(matches.iterator().next().getArtifact().getArtifactId().equalsIgnoreCase("quarkus-foo")); } + @Test + void testList() { + Extension e1 = Extension.builder() + .setArtifact(ArtifactCoords.jar("org.acme", "quarkus-rest", "1.0")) + .setName("Quarkus REST"); + + Extension e2 = Extension.builder() + .setArtifact(ArtifactCoords.jar("org.acme", "quarkus-rest-jackson", "1.0")) + .setName("Quarkus REST Jackson"); + + Extension e3 = Extension.builder() + .setArtifact(ArtifactCoords.jar("org.acme", "quarkus-kafka", "1.0")) + .setName("unrelated"); + + List extensions = asList(e1, e2, e3); + Collections.shuffle(extensions); + SelectionResult matches = selectExtensions("rest", extensions, true); + Assertions.assertEquals(1, matches.getExtensions().size()); + + matches = listExtensions("rest", extensions, true); + Assertions.assertEquals(2, matches.getExtensions().size()); + } + @Test void testListedVsUnlisted() { Extension e1 = Extension.builder() @@ -163,10 +187,10 @@ void testListedVsUnlisted() { List extensions = asList(e1, e2, e3); Collections.shuffle(extensions); - SelectionResult matches = select("quarkus-foo", extensions, true); + SelectionResult matches = selectExtensions("quarkus-foo", extensions, true); Assertions.assertEquals(2, matches.getExtensions().size()); - matches = select("quarkus-foo-unlisted", extensions, true); + matches = selectExtensions("quarkus-foo-unlisted", extensions, true); Assertions.assertEquals(1, matches.getExtensions().size()); }