From 3a8259459e9e0fa9eabd3ebaf7222822ef56d93a Mon Sep 17 00:00:00 2001 From: Victor Rubezhny Date: Tue, 9 Aug 2022 15:39:07 +0200 Subject: [PATCH] Autocompletion for directory/file based properties #292 Auto completioin is added for mojo parameters (with type=File or name ending with Directory). JUnit test cases are added/updated for the issue. Signed-off-by: Victor Rubezhny --- .../MavenCompletionParticipant.java | 42 ++++++++++++- .../completion/PathWebResourcesTest.java | 61 +++++++++++++++---- .../pom-pluginManagement-configuration.xml | 26 ++++++++ .../resources/local-path/pom-webresource.xml | 3 +- 4 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 lemminx-maven/src/test/resources/local-path/pom-pluginManagement-configuration.xml diff --git a/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/participants/completion/MavenCompletionParticipant.java b/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/participants/completion/MavenCompletionParticipant.java index 0a17606a..4a512fff 100644 --- a/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/participants/completion/MavenCompletionParticipant.java +++ b/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/participants/completion/MavenCompletionParticipant.java @@ -114,6 +114,10 @@ public class MavenCompletionParticipant extends CompletionParticipantAdapter { private static final Logger LOGGER = Logger.getLogger(MavenCompletionParticipant.class.getName()); private static final Pattern ARTIFACT_ID_PATTERN = Pattern.compile("[-.a-zA-Z0-9]+"); + private static final String FILE_TYPE = "File"; + private static final String STRING_TYPE = "File"; + private static final String DIRECTORY_STRING_LC = "directory"; + static interface GAVInsertionStrategy { /** * set current element value and add siblings as addition textEdits @@ -357,7 +361,25 @@ public void onXMLContent(ICompletionRequest request, ICompletionResponse respons case GOAL_ELT: collectGoals(request).forEach(response::addCompletionItem); break; - } + default: + Set parameters = MavenPluginUtils.collectPluginConfigurationMojoParameters(request, plugin) + .stream().filter(p -> p.name.equals(parent.getLocalName())) + .filter(p -> (p.type.startsWith(FILE_TYPE)) || + (p.type.startsWith(STRING_TYPE) && p.name.toLowerCase().endsWith(DIRECTORY_STRING_LC))) + .collect(Collectors.toSet()); + if (parameters != null && parameters.size() > 0) { + collectMojoParametersDefaultCompletion(request, parameters) + .forEach(response::addCompletionItem); + if (parameters.stream() + .anyMatch(p -> !p.name.toLowerCase().endsWith(DIRECTORY_STRING_LC))) { + // Show all files + collectRelativeAnyPathCompletion(request).forEach(response::addCompletionItem); + } else { + // Show only directories + collectRelativeDirectoryPathCompletion(request).forEach(response::addCompletionItem); + } + } + } if (!allArtifactInfos.isEmpty()) { Comparator artifactInfoComparator = Comparator .comparing(artifact -> new DefaultArtifactVersion(artifact.artifact.getVersion())); @@ -376,7 +398,7 @@ public void onXMLContent(ICompletionRequest request, ICompletionResponse respons completeProperties(request).forEach(response::addCompletionAttribute); } } - + private CompletionItem toTextCompletionItem(ICompletionRequest request, String text) throws BadLocationException { CompletionItem res = new CompletionItem(text); res.setFilterText(text); @@ -731,6 +753,22 @@ private Collection collectSubModuleCompletion(ICompletionRequest return files.stream().map(file -> toFileCompletionItem(file, docFolder, request)).collect(Collectors.toList()); } + private Collection collectMojoParametersDefaultCompletion(ICompletionRequest request, Set parameters) { + String prefix = request.getNode().getNodeValue() != null ? request.getNode().getNodeValue() : ""; + List defaultValues = parameters.stream().filter(p -> (p.getDefaultValue() != null)) + .map(p -> p.getDefaultValue()) + .collect(Collectors.toList()); + + if (!prefix.isEmpty()) { + defaultValues = defaultValues.stream().filter(v -> v.startsWith(prefix)) + .collect(Collectors.toList()); + } + return defaultValues.stream() + .sorted(String.CASE_INSENSITIVE_ORDER) + .map(defaultValue -> toCompletionItem(defaultValue.toString(), null, request.getReplaceRange())) + .collect(Collectors.toList()); + } + private Collection collectRelativePathCompletion(ICompletionRequest request) { DOMDocument doc = request.getXMLDocument(); File docFile = new File(URI.create(doc.getTextDocument().getUri())); diff --git a/lemminx-maven/src/test/java/org/eclipse/lemminx/extensions/maven/participants/completion/PathWebResourcesTest.java b/lemminx-maven/src/test/java/org/eclipse/lemminx/extensions/maven/participants/completion/PathWebResourcesTest.java index f2965d40..01f0a98b 100644 --- a/lemminx-maven/src/test/java/org/eclipse/lemminx/extensions/maven/participants/completion/PathWebResourcesTest.java +++ b/lemminx-maven/src/test/java/org/eclipse/lemminx/extensions/maven/participants/completion/PathWebResourcesTest.java @@ -59,7 +59,7 @@ public void testWebResourcesDirectory() throws Exception { @Test public void testWebResourcesTargetPath() throws Exception { DOMDocument document = createDOMDocument("/local-path/pom-webresource.xml", languageService); - List doComplete = languageService.doComplete(document, new Position(0, 11), new SharedSettings()).getItems(); + List doComplete = languageService.doComplete(document, new Position(9, 12), new SharedSettings()).getItems(); // parent folder, then direct children assertEquals("..", doComplete.get(0).getLabel()); @@ -156,14 +156,15 @@ public void testWebResourcesFileExists() throws Exception { // files assertEquals("filter.properties", doComplete.get(0).getLabel()); - assertEquals("pom-webresource.xml", doComplete.get(1).getLabel()); - assertEquals("pom.xml", doComplete.get(2).getLabel()); + assertEquals("pom-pluginManagement-configuration.xml", doComplete.get(1).getLabel()); + assertEquals("pom-webresource.xml", doComplete.get(2).getLabel()); + assertEquals("pom.xml", doComplete.get(3).getLabel()); // parent folder, then direct children - assertEquals("..", doComplete.get(3).getLabel()); - assertEquals("child-parent", doComplete.get(4).getLabel()); - assertEquals("folder1", doComplete.get(5).getLabel()); - assertEquals("folder2", doComplete.get(6).getLabel()); + assertEquals("..", doComplete.get(4).getLabel()); + assertEquals("child-parent", doComplete.get(5).getLabel()); + assertEquals("folder1", doComplete.get(6).getLabel()); + assertEquals("folder2", doComplete.get(7).getLabel()); } // public static final String FILE_ELT = "file"; @@ -175,14 +176,48 @@ public void testWebResourcesFileMissing() throws Exception { // files assertEquals("filter.properties", doComplete.get(0).getLabel()); - assertEquals("pom-webresource.xml", doComplete.get(1).getLabel()); - assertEquals("pom.xml", doComplete.get(2).getLabel()); + assertEquals("pom-pluginManagement-configuration.xml", doComplete.get(1).getLabel()); + assertEquals("pom-webresource.xml", doComplete.get(2).getLabel()); + assertEquals("pom.xml", doComplete.get(3).getLabel()); + + // parent folder, then direct children + assertEquals("..", doComplete.get(4).getLabel()); + assertEquals("child-parent", doComplete.get(5).getLabel()); + assertEquals("folder1", doComplete.get(6).getLabel()); + assertEquals("folder2", doComplete.get(7).getLabel()); + } + + @Test + public void testMojoParametersDirectories() throws Exception { + DOMDocument document = createDOMDocument("/local-path/pom-pluginManagement-configuration.xml", languageService); + List doComplete = languageService.doComplete(document, new Position(18, 42), new SharedSettings()).getItems(); + + // Some typical conventions for directories + // Default values + assertEquals("${project.build.outputDirectory}", doComplete.get(0).getLabel()); + // parent + assertEquals("..", doComplete.get(1).getLabel()); + // then child folders + assertEquals("child-parent", doComplete.get(2).getLabel()); + assertEquals("folder1", doComplete.get(3).getLabel()); + assertEquals("folder2", doComplete.get(4).getLabel()); + } + @Test + public void testMojoParametersFiles() throws Exception { + DOMDocument document = createDOMDocument("/local-path/pom-pluginManagement-configuration.xml", languageService); + List doComplete = languageService.doComplete(document, new Position(19, 39), new SharedSettings()).getItems(); + + // Some typical conventions + assertEquals("filter.properties", doComplete.get(0).getLabel()); + assertEquals("pom-pluginManagement-configuration.xml", doComplete.get(1).getLabel()); + assertEquals("pom-webresource.xml", doComplete.get(2).getLabel()); + assertEquals("pom.xml", doComplete.get(3).getLabel()); // parent folder, then direct children - assertEquals("..", doComplete.get(3).getLabel()); - assertEquals("child-parent", doComplete.get(4).getLabel()); - assertEquals("folder1", doComplete.get(5).getLabel()); - assertEquals("folder2", doComplete.get(6).getLabel()); + assertEquals("..", doComplete.get(4).getLabel()); + assertEquals("child-parent", doComplete.get(5).getLabel()); + assertEquals("folder1", doComplete.get(6).getLabel()); + assertEquals("folder2", doComplete.get(7).getLabel()); } } \ No newline at end of file diff --git a/lemminx-maven/src/test/resources/local-path/pom-pluginManagement-configuration.xml b/lemminx-maven/src/test/resources/local-path/pom-pluginManagement-configuration.xml new file mode 100644 index 00000000..fce8c3a5 --- /dev/null +++ b/lemminx-maven/src/test/resources/local-path/pom-pluginManagement-configuration.xml @@ -0,0 +1,26 @@ + + 4.0.0 + + pluginManagement + parent + 0.0.1-SNAPSHOT + pom + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + + + + + + \ No newline at end of file diff --git a/lemminx-maven/src/test/resources/local-path/pom-webresource.xml b/lemminx-maven/src/test/resources/local-path/pom-webresource.xml index b1170abf..c0de7b6d 100644 --- a/lemminx-maven/src/test/resources/local-path/pom-webresource.xml +++ b/lemminx-maven/src/test/resources/local-path/pom-webresource.xml @@ -6,4 +6,5 @@ - \ No newline at end of file + + \ No newline at end of file