IDEA-CR-36178 maven run anything - command line arguments completion

This commit is contained in:
Ivan Bessonov
2018-08-20 14:42:51 +03:00
parent 4db939e5bb
commit a5f4151611
4 changed files with 190 additions and 19 deletions
@@ -0,0 +1,89 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.execution;
import java.util.*;
/**
* @author ibessonov
*/
public class MavenCommandLineOptions {
private static final Map<String, Option> ourOptionsIndexMap;
private static final Set<Option> ourAllOptions;
static {
ourAllOptions = new HashSet<>();
ourAllOptions.add(new Option("-am", "--also-make", "If project list is specified, also build projects required by the list"));
ourAllOptions.add(new Option("-amd", "--also-make-dependents", "If project list is specified, also build projects that depend on projects on the list"));
ourAllOptions.add(new Option("-B", "--batch-mode", "Run in non-interactive (batch) mode (disables output color)"));
ourAllOptions.add(new Option("-b", "--builder", "The id of the build strategy to use"));
ourAllOptions.add(new Option("-C", "--strict-checksums", "Fail the build if checksums don't match"));
ourAllOptions.add(new Option("-c", "--lax-checksums", "Warn if checksums don't match"));
ourAllOptions.add(new Option("-cpu", "--check-plugin-updates", "Ineffective, only kept for backward compatibility"));
ourAllOptions.add(new Option("-D", "--define", "Define a system property"));
ourAllOptions.add(new Option("-e", "--errors", "Produce execution error messages"));
ourAllOptions.add(new Option("-emp", "--encrypt-master-password", "Encrypt master security password"));
ourAllOptions.add(new Option("-ep", "--encrypt-password", "Encrypt server password"));
ourAllOptions.add(new Option("-f", "--file", "Force the use of an alternate POM file (or directory with pom.xml)"));
ourAllOptions.add(new Option("-fae", "--fail-at-end", "Only fail the build afterwards; allow all non-impacted builds to continue"));
ourAllOptions.add(new Option("-ff", "--fail-fast", "Stop at first failure in reactorized builds"));
ourAllOptions.add(new Option("-fn", "--fail-never", "NEVER fail the build, regardless of project result"));
ourAllOptions.add(new Option("-gs", "--global-settings", "Alternate path for the global settings file"));
ourAllOptions.add(new Option("-gt", "--global-toolchains", "Alternate path for the global toolchains file"));
ourAllOptions.add(new Option("-h", "--help", "Display help information"));
ourAllOptions.add(new Option("-l", "--log-file", "Log file where all build output will go (disables output color)"));
ourAllOptions.add(new Option("-llr", "--legacy-local-repository", "Use Maven 2 Legacy Local Repository behaviour, ie no use of _remote.repositories. Can also be activated by using -Dmaven.legacyLocalRepo=true"));
ourAllOptions.add(new Option("-N", "--non-recursive", "Do not recurse into sub-projects"));
ourAllOptions.add(new Option("-npr", "--no-plugin-registry", "Ineffective, only kept for backward compatibility"));
ourAllOptions.add(new Option("-npu", "--no-plugin-updates", "Ineffective, only kept for backward compatibility"));
ourAllOptions.add(new Option("-nsu", "--no-snapshot-updates", "Suppress SNAPSHOT updates"));
ourAllOptions.add(new Option("-o", "--offline", "Work offline"));
ourAllOptions.add(new Option("-P", "--activate-profiles", "Comma-delimited list of profiles to activate"));
ourAllOptions.add(new Option("-pl", "--projects", "Comma-delimited list of specified reactor projects to build instead of all projects. A project can be specified by [groupId]:artifactId or by its relative path"));
ourAllOptions.add(new Option("-q", "--quiet", "Quiet output - only show errors"));
ourAllOptions.add(new Option("-rf", "--resume-from", "Resume reactor from specified project"));
ourAllOptions.add(new Option("-s", "--settings", "Alternate path for the user settings file"));
ourAllOptions.add(new Option("-t", "--toolchains", "Alternate path for the user toolchains file"));
ourAllOptions.add(new Option("-T", "--threads", "Thread count, for instance 2.0C where C is core multiplied"));
ourAllOptions.add(new Option("-U", "--update-snapshots", "Forces a check for missing releases and updated snapshots on remote repositories"));
ourAllOptions.add(new Option("-up", "--update-plugins", "Ineffective, only kept for backward compatibility"));
ourAllOptions.add(new Option("-v", "--version", "Display version information"));
ourAllOptions.add(new Option("-V", "--show-version", "Display version information WITHOUT stopping build"));
ourAllOptions.add(new Option("-X", "--debug", "Produce execution debug output"));
ourOptionsIndexMap = new HashMap<>();
for (Option option : ourAllOptions) {
ourOptionsIndexMap.put(option.getName(false), option);
ourOptionsIndexMap.put(option.getName(true), option);
}
}
public static class Option {
private final String myName;
private final String myLongName;
private final String myDescription;
public Option(String name, String longName, String description) {
myName = name;
myLongName = longName;
myDescription = description;
}
public String getName(boolean longName) {
return longName? myLongName : myName;
}
public String getDescription() {
return myDescription;
}
}
public static Collection<Option> getAllOptions() {
return Collections.unmodifiableSet(ourAllOptions);
}
public static Option findOption(String name) {
return ourOptionsIndexMap.get(name);
}
}
@@ -4,7 +4,6 @@ package org.jetbrains.idea.maven.execution;
import com.intellij.ide.actions.runAnything.activity.RunAnythingProviderBase;
import com.intellij.ide.actions.runAnything.items.RunAnythingHelpItem;
import com.intellij.ide.actions.runAnything.items.RunAnythingItem;
import com.intellij.ide.actions.runAnything.items.RunAnythingItemBase;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
@@ -22,10 +21,8 @@ import org.jetbrains.idea.maven.utils.MavenArtifactUtil;
import org.jetbrains.idea.maven.utils.MavenPluginInfo;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import static com.intellij.ide.actions.runAnything.RunAnythingUtil.fetchProject;
import static com.intellij.openapi.util.text.StringUtil.*;
@@ -40,7 +37,7 @@ public class MavenRunAnythingProvider extends RunAnythingProviderBase<String> {
@NotNull
@Override
public RunAnythingItem getMainListItem(@NotNull DataContext dataContext, @NotNull String value) {
return new RunAnythingItemBase(getCommand(value), getIcon(value));
return new RunAnythingMavenItem(getCommand(value), getIcon(value));
}
@NotNull
@@ -75,32 +72,50 @@ public class MavenRunAnythingProvider extends RunAnythingProviderBase<String> {
}
}
HashSet<String> goals = new HashSet<>(params.subList(onlyOneMavenProject ? 0 : 1, params.size()));
Module module = onlyOneMavenProject ? projectsManager.findModule(mavenProjects.get(0))
: ModuleManager.getInstance(project).findModuleByName(params.get(0));
if (module != null) {
MavenProject mavenProject = projectsManager.findProject(module);
MavenProject mavenProject = onlyOneMavenProject ? mavenProjects.get(0) : projectsManager.findProject(module);
if (mavenProject != null) {
String prefix = notNullize(substringBeforeLast(pattern, " "), getHelpCommand()).trim() + " ";
if (!onlyOneMavenProject && prefix.trim().equals(getHelpCommand())) {
prefix = prefix + module.getName() + " ";
}
// list basic phases
for (String phase : MavenConstants.BASIC_PHASES) {
if (!goals.contains(phase)) {
values.add(prefix + phase);
if (pattern.startsWith(prefix) && trimStart(pattern, prefix).startsWith("-")) {
boolean longName = trimStart(pattern, prefix).startsWith("--");
Set<MavenCommandLineOptions.Option> options = params.stream()
.skip(onlyOneMavenProject ? 0 : 1)
.map(MavenCommandLineOptions::findOption)
.filter(option -> option != null)
.collect(Collectors.toSet());
// list available cl options
for (MavenCommandLineOptions.Option option : MavenCommandLineOptions.getAllOptions()) {
if (!options.contains(option)) {
values.add(prefix + option.getName(longName));
}
}
}
else {
Set<String> goals = new HashSet<>(params.subList(onlyOneMavenProject ? 0 : 1, params.size()));
// list plugin-specific goals
for (MavenPlugin mavenPlugin : mavenProject.getDeclaredPlugins()) {
MavenPluginInfo pluginInfo = MavenArtifactUtil.readPluginInfo(projectsManager.getLocalRepository(), mavenPlugin.getMavenId());
if (pluginInfo == null) continue;
// list basic phases
for (String phase : MavenConstants.BASIC_PHASES) {
if (!goals.contains(phase)) {
values.add(prefix + phase);
}
}
for (MavenPluginInfo.Mojo mojo : pluginInfo.getMojos()) {
if (!goals.contains(mojo.getGoal())) {
values.add(prefix + mojo.getDisplayName());
// list plugin-specific goals
for (MavenPlugin mavenPlugin : mavenProject.getDeclaredPlugins()) {
MavenPluginInfo pluginInfo = MavenArtifactUtil.readPluginInfo(projectsManager.getLocalRepository(), mavenPlugin.getMavenId());
if (pluginInfo == null) continue;
for (MavenPluginInfo.Mojo mojo : pluginInfo.getMojos()) {
if (!goals.contains(mojo.getDisplayName())) {
values.add(prefix + mojo.getDisplayName());
}
}
}
}
@@ -0,0 +1,48 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.execution;
import com.intellij.ide.actions.runAnything.items.RunAnythingItemBase;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.execution.MavenCommandLineOptions.Option;
import javax.swing.*;
import java.awt.*;
import static com.intellij.openapi.util.text.StringUtil.*;
/**
* @author ibessonov
*/
public class RunAnythingMavenItem extends RunAnythingItemBase {
public RunAnythingMavenItem(@NotNull String command, @Nullable Icon icon) {
super(command, icon);
}
@NotNull
@Override
public Component createComponent(boolean isSelected) {
String command = getCommand();
String toComplete = notNullize(substringAfterLast(command, " "));
String description = null;
if (toComplete.startsWith("-")) {
Option option = MavenCommandLineOptions.findOption(toComplete);
if (option != null) {
description = option.getDescription();
}
}
SimpleColoredComponent component = new SimpleColoredComponent();
component.append(command);
component.appendTextPadding(20);
setupIcon(component, myIcon);
if (description != null) {
component.append(" " + shortenTextWithEllipsis(description, 200, 0), SimpleTextAttributes.GRAYED_ITALIC_ATTRIBUTES);
}
return component;
}
}
@@ -3,6 +3,7 @@ package org.jetbrains.idea.maven.execution;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.idea.maven.MavenImportingTestCase;
import org.jetbrains.idea.maven.model.MavenConstants;
@@ -103,5 +104,23 @@ public class MavenRunAnythingProviderTest extends MavenImportingTestCase {
assertContain((List<String>)moduleValues, "mvn m1 war:help", "mvn m1 war:inplace", "mvn m1 war:exploded", "mvn m1 war:war");
assertDoNotContain((List<String>)projectValues, "mvn m2 war:war");
projectValues = myProvider.getValues(myDataContext, "mvn m2 compiler:compile ");
assertContain((List<String>)projectValues, "mvn m2 compiler:compile compiler:help");
assertDoNotContain((List<String>)projectValues, "mvn m2 compiler:compile compiler:compile");
}
public void testOptions() {
importProject("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<version>1</version>");
Collection<String> values = myProvider.getValues(myDataContext, "mvn -");
assertEquals(37, values.size());
assertFalse(values.stream().map(value -> trimStart(value,"mvn ")).anyMatch(option -> option.startsWith("--")));
values = myProvider.getValues(myDataContext, "mvn --");
assertEquals(37, values.size());
assertTrue(values.stream().map(value -> trimStart(value,"mvn ")).allMatch(option -> option.startsWith("--")));
}
}