IDEA-196697 Support starting Gradle tasks via 'Run Anything' action

This commit is contained in:
Vladislav.Soroka
2018-08-09 15:48:01 +03:00
parent ec056665b7
commit a217e22325
5 changed files with 263 additions and 0 deletions
@@ -111,6 +111,8 @@
<copyPastePreProcessor implementation="org.jetbrains.plugins.gradle.action.PasteMvnDependencyPreProcessor"/>
<runAnything.executionProvider implementation="org.jetbrains.plugins.gradle.execution.GradleRunAnythingProvider" order="first"/>
<runAnything.helpGroup implementation="org.jetbrains.plugins.gradle.execution.GradleRunAnythingHelpGroup"/>
</extensions>
<actions>
@@ -111,6 +111,10 @@ public class GradleExecuteTaskAction extends ExternalSystemAction {
historyService.addCommand(fullCommandLine, workDirectory);
runGradle(project, workDirectory, fullCommandLine);
}
public static void runGradle(@NotNull Project project, @NotNull String workDirectory, @NotNull String fullCommandLine) {
final ExternalTaskExecutionInfo taskExecutionInfo;
try {
taskExecutionInfo = buildTaskInfo(workDirectory, fullCommandLine);
@@ -0,0 +1,26 @@
// 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.plugins.gradle.execution;
import com.intellij.ide.actions.runAnything.activity.RunAnythingProvider;
import com.intellij.ide.actions.runAnything.groups.RunAnythingHelpGroup;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* @author Vladislav.Soroka
*/
public class GradleRunAnythingHelpGroup extends RunAnythingHelpGroup {
@NotNull
@Override
public String getTitle() {
return "Gradle";
}
@NotNull
@Override
public Collection<RunAnythingProvider> getProviders() {
return ContainerUtil.immutableSingletonList(RunAnythingProvider.EP_NAME.findExtension(GradleRunAnythingProvider.class));
}
}
@@ -0,0 +1,179 @@
// 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.plugins.gradle.execution;
import com.intellij.ide.actions.runAnything.activity.RunAnythingProviderBase;
import com.intellij.ide.actions.runAnything.items.RunAnythingItem;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalProjectInfo;
import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import groovyjarjarcommonscli.Option;
import icons.GradleIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.action.GradleExecuteTaskAction;
import org.jetbrains.plugins.gradle.service.execution.cmd.GradleCommandLineOptionsProvider;
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
import org.jetbrains.plugins.gradle.settings.GradleSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static com.intellij.ide.actions.runAnything.RunAnythingUtil.fetchProject;
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.getChildren;
/**
* @author Vladislav.Soroka
*/
public class GradleRunAnythingProvider extends RunAnythingProviderBase<String> {
@NotNull
@Override
public RunAnythingItem getMainListItem(@NotNull DataContext dataContext, @NotNull String value) {
return new RunAnythingGradleItem(getCommand(value), getIcon(value));
}
@Nullable
@Override
public String findMatchingValue(@NotNull DataContext dataContext, @NotNull String pattern) {
return pattern.startsWith(getHelpCommand()) ? getCommand(pattern) : null;
}
@NotNull
@Override
public Collection<String> getValues(@NotNull DataContext dataContext, @NotNull String pattern) {
if (!pattern.startsWith(getHelpCommand())) {
return Collections.emptyList();
}
List<String> result = ContainerUtil.newSmartList();
int spaceIndex = StringUtil.lastIndexOf(pattern, ' ', getHelpCommand().length(), pattern.length());
String prefix = StringUtil.trim(spaceIndex < 0 ? getHelpCommand() : pattern.substring(0, spaceIndex + 1)) + ' ';
String toComplete = spaceIndex < 0 ? "" : pattern.substring(spaceIndex + 1);
appendArgumentsVariants(result, prefix, toComplete);
if (!result.isEmpty()) return result;
appendTasksVariants(result, prefix, dataContext);
return result;
}
private static void appendTasksVariants(@NotNull List<String> result, @NotNull String prefix, @NotNull DataContext dataContext) {
MultiMap<String, String> tasks = fetchTasks(dataContext);
for (Map.Entry<String, Collection<String>> entry : tasks.entrySet()) {
for (String taskName : entry.getValue()) {
String taskFqn = entry.getKey() + taskName;
result.add(prefix + taskFqn);
}
}
}
private static void appendArgumentsVariants(@NotNull List<String> result, @NotNull String prefix, @NotNull String toComplete) {
if (!toComplete.startsWith("-")) return;
boolean isLongOpt = toComplete.startsWith("--");
prefix += (isLongOpt ? "--" : "-");
for (Object option : GradleCommandLineOptionsProvider.getSupportedOptions().getOptions()) {
if (option instanceof Option) {
String opt = isLongOpt ? ((Option)option).getLongOpt() : ((Option)option).getOpt();
if (StringUtil.isNotEmpty(opt)) {
result.add(prefix + opt);
}
}
}
}
@Override
public void execute(@NotNull DataContext dataContext, @NotNull String value) {
Project project = fetchProject(dataContext);
String commandLine = StringUtil.trimStart(value, getHelpCommand());
for (GradleProjectSettings setting : GradleSettings.getInstance(project).getLinkedProjectsSettings()) {
GradleExecuteTaskAction.runGradle(project, setting.getExternalProjectPath(), commandLine);
}
}
@NotNull
@Override
public String getCommand(@NotNull String value) {
return value;
}
@Nullable
@Override
public Icon getIcon(@NotNull String value) {
return GradleIcons.Gradle;
}
@NotNull
public String getCompletionGroupTitle() {
return "Gradle tasks";
}
@NotNull
@Override
public String getHelpCommandPlaceholder() {
return "gradle <taskName...> <--option-name...>";
}
@NotNull
@Override
public String getHelpCommand() {
return "gradle";
}
@Override
public Icon getHelpIcon() {
return GradleIcons.Gradle;
}
private static MultiMap<String, String> fetchTasks(@NotNull DataContext dataContext) {
Project project = fetchProject(dataContext);
return CachedValuesManager.getManager(project).getCachedValue(
project, () -> CachedValueProvider.Result.create(getTasksMap(project), ProjectRootManager.getInstance(project)));
}
@NotNull
private static MultiMap<String, String> getTasksMap(Project project) {
MultiMap<String, String> tasks = MultiMap.createOrderedSet();
for (GradleProjectSettings setting : GradleSettings.getInstance(project).getLinkedProjectsSettings()) {
final ExternalProjectInfo projectData =
ProjectDataManager.getInstance().getExternalProjectData(project, GradleConstants.SYSTEM_ID, setting.getExternalProjectPath());
if (projectData == null || projectData.getExternalProjectStructure() == null) continue;
for (DataNode<ModuleData> moduleDataNode : getChildren(projectData.getExternalProjectStructure(), ProjectKeys.MODULE)) {
String gradlePath;
String moduleId = moduleDataNode.getData().getId();
if (moduleId.charAt(0) != ':') {
int colonIndex = moduleId.indexOf(':');
gradlePath = colonIndex > 0 ? moduleId.substring(colonIndex) : ":";
}
else {
gradlePath = moduleId;
}
for (DataNode<TaskData> node : getChildren(moduleDataNode, ProjectKeys.TASK)) {
TaskData taskData = node.getData();
String taskName = taskData.getName();
if (StringUtil.isNotEmpty(taskName)) {
String taskPathPrefix = ":".equals(gradlePath) || taskName.startsWith(gradlePath) ? "" : (gradlePath + ':');
tasks.putValue(taskPathPrefix, taskName);
}
}
}
}
return tasks;
}
}
@@ -0,0 +1,52 @@
// 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.plugins.gradle.execution;
import com.intellij.ide.actions.runAnything.items.RunAnythingItemBase;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import groovyjarjarcommonscli.Option;
import groovyjarjarcommonscli.Options;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.service.execution.cmd.GradleCommandLineOptionsProvider;
import javax.swing.*;
import java.awt.*;
/**
* @author Vladislav.Soroka
*/
public class RunAnythingGradleItem extends RunAnythingItemBase {
public RunAnythingGradleItem(@NotNull String command, @Nullable Icon icon) {
super(command, icon);
}
@NotNull
@Override
public Component createComponent(boolean isSelected) {
String command = getCommand();
int spaceIndex = StringUtil.lastIndexOf(command, ' ', 0, command.length());
String toComplete = spaceIndex < 0 ? "" : command.substring(spaceIndex + 1);
String description = null;
if (toComplete.startsWith("-")) {
boolean isLongOpt = toComplete.startsWith("--");
Options options = GradleCommandLineOptionsProvider.getSupportedOptions();
Option option = options.getOption(toComplete.substring(isLongOpt ? 2 : 1));
if (option != null) {
description = option.getDescription();
}
}
SimpleColoredComponent component = new SimpleColoredComponent();
component.append(command);
component.appendTextPadding(20);
setupIcon(component, myIcon);
if (description != null) {
component.append(" " + StringUtil.shortenTextWithEllipsis(description, 200, 0), SimpleTextAttributes.GRAYED_ITALIC_ATTRIBUTES);
}
return component;
}
}