feat: Get tasks from custom tapi model (#1148)
This commit is contained in:
Родитель
846d52e349
Коммит
339166ecb3
|
@ -36,7 +36,7 @@ jobs:
|
|||
- name: Build & Analyse Gradle Server
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: gradle-server:build -x :test -x extension:test -x npm-package:test
|
||||
arguments: build -x test
|
||||
env:
|
||||
JAVA_HOME: ""
|
||||
- name: Upload lib
|
||||
|
|
|
@ -7,6 +7,10 @@ import java.util.List;
|
|||
import org.gradle.tooling.model.Model;
|
||||
|
||||
public interface GradleProjectModel extends Model {
|
||||
boolean getIsRoot();
|
||||
String getProjectPath();
|
||||
List<GradleProjectModel> getSubProjects();
|
||||
List<GradleTask> getTasks();
|
||||
GradleDependencyNode getDependencyNode();
|
||||
List<String> getPlugins();
|
||||
List<GradleClosure> getClosures();
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.microsoft.gradle.api;
|
||||
|
||||
public interface GradleTask {
|
||||
String getName();
|
||||
String getGroup();
|
||||
String getPath();
|
||||
String getProject();
|
||||
String getBuildFile();
|
||||
String getRootProject();
|
||||
String getDescription();
|
||||
}
|
|
@ -6,23 +6,49 @@ package com.microsoft.gradle;
|
|||
import com.microsoft.gradle.api.GradleClosure;
|
||||
import com.microsoft.gradle.api.GradleDependencyNode;
|
||||
import com.microsoft.gradle.api.GradleProjectModel;
|
||||
import com.microsoft.gradle.api.GradleTask;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultGradleProjectModel implements Serializable, GradleProjectModel {
|
||||
private boolean isRoot;
|
||||
private String projectPath;
|
||||
private List<GradleProjectModel> subProjects;
|
||||
private List<GradleTask> tasks;
|
||||
private GradleDependencyNode node;
|
||||
private List<String> plugins;
|
||||
private List<GradleClosure> closures;
|
||||
private List<String> scriptClasspaths;
|
||||
|
||||
public DefaultGradleProjectModel(GradleDependencyNode node, List<String> plugins, List<GradleClosure> closures,
|
||||
public DefaultGradleProjectModel(boolean isRoot, String projectPath, List<GradleProjectModel> subProjects,
|
||||
List<GradleTask> tasks, GradleDependencyNode node, List<String> plugins, List<GradleClosure> closures,
|
||||
List<String> scriptClasspaths) {
|
||||
this.isRoot = isRoot;
|
||||
this.projectPath = projectPath;
|
||||
this.subProjects = subProjects;
|
||||
this.tasks = tasks;
|
||||
this.node = node;
|
||||
this.plugins = plugins;
|
||||
this.closures = closures;
|
||||
this.scriptClasspaths = scriptClasspaths;
|
||||
}
|
||||
|
||||
public boolean getIsRoot() {
|
||||
return this.isRoot;
|
||||
}
|
||||
|
||||
public String getProjectPath() {
|
||||
return this.projectPath;
|
||||
}
|
||||
|
||||
public List<GradleProjectModel> getSubProjects() {
|
||||
return this.subProjects;
|
||||
}
|
||||
|
||||
public List<GradleTask> getTasks() {
|
||||
return this.tasks;
|
||||
}
|
||||
|
||||
public GradleDependencyNode getDependencyNode() {
|
||||
return this.node;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.microsoft.gradle;
|
||||
|
||||
import com.microsoft.gradle.api.GradleTask;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class DefaultGradleTask implements Serializable, GradleTask {
|
||||
private String name;
|
||||
private String group;
|
||||
private String path;
|
||||
private String project;
|
||||
private String buildFile;
|
||||
private String rootProject;
|
||||
private String description;
|
||||
|
||||
public DefaultGradleTask(String name, String group, String path, String project, String buildFile,
|
||||
String rootProject, String description) {
|
||||
this.name = name;
|
||||
this.group = group;
|
||||
this.path = path;
|
||||
this.project = project;
|
||||
this.buildFile = buildFile;
|
||||
this.rootProject = rootProject;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public String getBuildFile() {
|
||||
return buildFile;
|
||||
}
|
||||
|
||||
public String getRootProject() {
|
||||
return rootProject;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.microsoft.gradle.api.GradleDependencyType;
|
|||
import com.microsoft.gradle.api.GradleField;
|
||||
import com.microsoft.gradle.api.GradleMethod;
|
||||
import com.microsoft.gradle.api.GradleProjectModel;
|
||||
import com.microsoft.gradle.api.GradleTask;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -32,15 +33,42 @@ import org.gradle.api.plugins.Convention;
|
|||
import org.gradle.api.plugins.ExtensionsSchema;
|
||||
import org.gradle.api.plugins.ExtensionsSchema.ExtensionSchema;
|
||||
import org.gradle.api.reflect.TypeOf;
|
||||
import org.gradle.api.tasks.TaskContainer;
|
||||
import org.gradle.internal.classpath.ClassPath;
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilder;
|
||||
|
||||
public class GradleProjectModelBuilder implements ToolingModelBuilder {
|
||||
|
||||
private Set<GradleTask> cachedTasks = new HashSet<>();
|
||||
|
||||
public boolean canBuild(String modelName) {
|
||||
return modelName.equals(GradleProjectModel.class.getName());
|
||||
}
|
||||
|
||||
public Object buildAll(String modelName, Project project) {
|
||||
cachedTasks.clear();
|
||||
GradleProjectModel rootModel = buildModel(project, project);
|
||||
// add task selectors for root project
|
||||
Set<String> taskNames = new HashSet<>();
|
||||
for (GradleTask existingTask : rootModel.getTasks()) {
|
||||
taskNames.add(existingTask.getName());
|
||||
}
|
||||
for (GradleTask task : cachedTasks) {
|
||||
if (!taskNames.contains(task.getName())) {
|
||||
taskNames.add(task.getName());
|
||||
GradleTask newTask = new DefaultGradleTask(task.getName(), task.getGroup(), task.getPath(),
|
||||
project.getName(), project.getBuildscript().getSourceFile().getAbsolutePath(),
|
||||
task.getRootProject(), task.getDescription());
|
||||
rootModel.getTasks().add(newTask);
|
||||
}
|
||||
}
|
||||
return rootModel;
|
||||
}
|
||||
|
||||
private GradleProjectModel buildModel(Project rootProject, Project project) {
|
||||
if (rootProject == null || project == null) {
|
||||
return null;
|
||||
}
|
||||
ScriptHandler buildScript = project.getBuildscript();
|
||||
ClassPath classpath = ((DefaultScriptHandler) buildScript).getScriptClassPath();
|
||||
List<String> scriptClasspaths = new ArrayList<>();
|
||||
|
@ -50,7 +78,17 @@ public class GradleProjectModelBuilder implements ToolingModelBuilder {
|
|||
GradleDependencyNode node = generateDefaultGradleDependencyNode(project);
|
||||
List<String> plugins = getPlugins(project);
|
||||
List<GradleClosure> closures = getPluginClosures(project);
|
||||
return new DefaultGradleProjectModel(node, plugins, closures, scriptClasspaths);
|
||||
List<GradleProjectModel> subModels = new ArrayList<>();
|
||||
Set<Project> subProjects = project.getSubprojects();
|
||||
for (Project subProject : subProjects) {
|
||||
GradleProjectModel subModel = buildModel(rootProject, subProject);
|
||||
if (subModel != null) {
|
||||
subModels.add(subModel);
|
||||
}
|
||||
}
|
||||
List<GradleTask> tasks = getGradleTasks(rootProject, project);
|
||||
return new DefaultGradleProjectModel(project.getParent() == null, project.getProjectDir().getAbsolutePath(),
|
||||
subModels, tasks, node, plugins, closures, scriptClasspaths);
|
||||
}
|
||||
|
||||
private GradleDependencyNode generateDefaultGradleDependencyNode(Project project) {
|
||||
|
@ -142,6 +180,25 @@ public class GradleProjectModelBuilder implements ToolingModelBuilder {
|
|||
return closures;
|
||||
}
|
||||
|
||||
private List<GradleTask> getGradleTasks(Project rootProject, Project project) {
|
||||
List<GradleTask> tasks = new ArrayList<>();
|
||||
TaskContainer taskContainer = project.getTasks();
|
||||
taskContainer.forEach(task -> {
|
||||
String name = task.getName();
|
||||
String group = task.getGroup() == null ? null : task.getGroup();
|
||||
String path = task.getPath();
|
||||
String projectName = task.getProject().getName();
|
||||
String buildFile = task.getProject().getBuildscript().getSourceFile().getAbsolutePath();
|
||||
String rootProjectName = rootProject.getName();
|
||||
String description = task.getDescription() == null ? null : task.getDescription();
|
||||
GradleTask newTask = new DefaultGradleTask(name, group, path, projectName, buildFile, rootProjectName,
|
||||
description);
|
||||
tasks.add(newTask);
|
||||
cachedTasks.add(newTask);
|
||||
});
|
||||
return tasks;
|
||||
}
|
||||
|
||||
private boolean isDeprecated(AccessibleObject object) {
|
||||
for (Annotation annotation : object.getDeclaredAnnotations()) {
|
||||
if (annotation.toString().contains("Deprecated")) {
|
||||
|
|
|
@ -17,16 +17,24 @@ import com.github.badsyntax.gradle.JavaEnvironment;
|
|||
import com.github.badsyntax.gradle.Output;
|
||||
import com.github.badsyntax.gradle.Progress;
|
||||
import com.github.badsyntax.gradle.exceptions.GradleConnectionException;
|
||||
import com.github.badsyntax.gradle.utils.PluginUtils;
|
||||
import com.github.badsyntax.gradle.utils.Utils;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.microsoft.gradle.api.GradleModelAction;
|
||||
import com.microsoft.gradle.api.GradleProjectModel;
|
||||
import io.github.g00fy2.versioncompare.Version;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.gradle.internal.service.ServiceCreationException;
|
||||
import org.gradle.tooling.BuildActionExecuter;
|
||||
import org.gradle.tooling.BuildCancelledException;
|
||||
import org.gradle.tooling.CancellationToken;
|
||||
import org.gradle.tooling.GradleConnector;
|
||||
|
@ -88,8 +96,28 @@ public class GetBuildHandler {
|
|||
try (ProjectConnection connection = gradleConnector.connect()) {
|
||||
this.environment = buildEnvironment(connection);
|
||||
replyWithBuildEnvironment(this.environment);
|
||||
org.gradle.tooling.model.GradleProject gradleProject = getGradleProject(connection);
|
||||
replyWithProject(getProjectData(gradleProject, gradleProject, new HashSet<>()));
|
||||
BuildActionExecuter<GradleProjectModel> action = connection.action(new GradleModelAction());
|
||||
if (action == null) {
|
||||
responseObserver.onCompleted();
|
||||
return;
|
||||
}
|
||||
File initScript = PluginUtils.createInitScript();
|
||||
List<String> arguments = Arrays.asList("--init-script", initScript.getAbsolutePath());
|
||||
String jvmArguments = req.getGradleConfig().getJvmArguments();
|
||||
if (!Strings.isNullOrEmpty(jvmArguments)) {
|
||||
arguments.addAll(Arrays.stream(jvmArguments.split(" ")).filter(e -> e != null && !e.isEmpty())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
action.withArguments(arguments);
|
||||
CancellationToken cancellationToken = GradleBuildCancellation.buildToken(req.getCancellationKey());
|
||||
Set<OperationType> progressEvents = new HashSet<>();
|
||||
progressEvents.add(OperationType.PROJECT_CONFIGURATION);
|
||||
action.withCancellationToken(cancellationToken).addProgressListener(progressListener, progressEvents)
|
||||
.setStandardOutput(standardOutputListener).setStandardError(standardErrorListener)
|
||||
.setColorOutput(req.getShowOutputColors());
|
||||
GradleProjectModel gradleModel = action.run();
|
||||
GradleProject project = getProjectData(gradleModel);
|
||||
replyWithProject(project);
|
||||
} catch (BuildCancelledException e) {
|
||||
replyWithCancelled(e);
|
||||
} catch (ServiceCreationException | IOException | IllegalStateException
|
||||
|
@ -112,6 +140,8 @@ public class GetBuildHandler {
|
|||
}
|
||||
logger.error(e.getMessage());
|
||||
replyWithError(e);
|
||||
} catch (Exception e) {
|
||||
replyWithError(e);
|
||||
} finally {
|
||||
GradleBuildCancellation.clearToken(req.getCancellationKey());
|
||||
}
|
||||
|
@ -138,7 +168,8 @@ public class GetBuildHandler {
|
|||
CancellationToken cancellationToken = GradleBuildCancellation.buildToken(req.getCancellationKey());
|
||||
|
||||
buildEnvironment.withCancellationToken(cancellationToken).addProgressListener(progressListener, progressEvents)
|
||||
.setStandardOutput(standardOutputListener).setStandardError(standardErrorListener);
|
||||
.setStandardOutput(standardOutputListener).setStandardError(standardErrorListener)
|
||||
.setColorOutput(req.getShowOutputColors());
|
||||
String jvmArguments = req.getGradleConfig().getJvmArguments();
|
||||
if (!Strings.isNullOrEmpty(jvmArguments)) {
|
||||
buildEnvironment.setJvmArguments(Arrays.stream(jvmArguments.split(" "))
|
||||
|
@ -162,75 +193,35 @@ public class GetBuildHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private org.gradle.tooling.model.GradleProject getGradleProject(ProjectConnection connection) throws IOException {
|
||||
|
||||
ModelBuilder<org.gradle.tooling.model.GradleProject> projectBuilder = connection
|
||||
.model(org.gradle.tooling.model.GradleProject.class);
|
||||
|
||||
Set<OperationType> progressEvents = new HashSet<>();
|
||||
progressEvents.add(OperationType.PROJECT_CONFIGURATION);
|
||||
|
||||
CancellationToken cancellationToken = GradleBuildCancellation.buildToken(req.getCancellationKey());
|
||||
|
||||
projectBuilder.withCancellationToken(cancellationToken).addProgressListener(progressListener, progressEvents)
|
||||
.setStandardOutput(standardOutputListener).setStandardError(standardErrorListener)
|
||||
.setColorOutput(req.getShowOutputColors());
|
||||
String jvmArguments = req.getGradleConfig().getJvmArguments();
|
||||
if (!Strings.isNullOrEmpty(jvmArguments)) {
|
||||
projectBuilder.setJvmArguments(Arrays.stream(jvmArguments.split(" ")).filter(e -> e != null && !e.isEmpty())
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
|
||||
try {
|
||||
return projectBuilder.get();
|
||||
} finally {
|
||||
GradleBuildCancellation.clearToken(req.getCancellationKey());
|
||||
private GradleProject getProjectData(GradleProjectModel gradleModel) {
|
||||
GradleProject.Builder project = GradleProject.newBuilder();
|
||||
project.setIsRoot(gradleModel.getIsRoot());
|
||||
project.addAllTasks(getGradleTasks(gradleModel));
|
||||
List<GradleProject> subProjects = new ArrayList<>();
|
||||
for (GradleProjectModel subProjectModel : gradleModel.getSubProjects()) {
|
||||
subProjects.add(getProjectData(subProjectModel));
|
||||
}
|
||||
project.addAllProjects(subProjects);
|
||||
return project.build();
|
||||
}
|
||||
|
||||
private GradleProject getProjectData(org.gradle.tooling.model.GradleProject gradleProject,
|
||||
org.gradle.tooling.model.GradleProject rootGradleProject, Set<GradleTask> taskSelectors) {
|
||||
boolean isRoot = gradleProject.getParent() == null;
|
||||
GradleProject.Builder project = GradleProject.newBuilder().setIsRoot(isRoot);
|
||||
gradleProject.getChildren().stream().forEach(childGradleProject -> project
|
||||
.addProjects(getProjectData(childGradleProject, rootGradleProject, taskSelectors)));
|
||||
gradleProject.getTasks().stream().forEach(task -> {
|
||||
GradleTask.Builder gradleTask = GradleTask.newBuilder().setProject(task.getProject().getName())
|
||||
.setName(task.getName()).setPath(task.getPath())
|
||||
.setBuildFile(task.getProject().getBuildScript().getSourceFile().getAbsolutePath())
|
||||
.setRootProject(rootGradleProject.getName());
|
||||
if (task.getDescription() != null) {
|
||||
gradleTask.setDescription(task.getDescription());
|
||||
private List<GradleTask> getGradleTasks(GradleProjectModel model) {
|
||||
List<GradleTask> tasks = new ArrayList<>();
|
||||
model.getTasks().forEach(task -> {
|
||||
GradleTask.Builder builder = GradleTask.newBuilder();
|
||||
builder.setName(task.getName()).setPath(task.getPath()).setProject(task.getProject())
|
||||
.setBuildFile(task.getBuildFile()).setRootProject(task.getRootProject());
|
||||
String group = task.getGroup();
|
||||
if (group != null) {
|
||||
builder.setGroup(group);
|
||||
}
|
||||
if (task.getGroup() != null) {
|
||||
gradleTask.setGroup(task.getGroup());
|
||||
String description = task.getDescription();
|
||||
if (description != null) {
|
||||
builder.setDescription(description);
|
||||
}
|
||||
project.addTasks(gradleTask.build());
|
||||
taskSelectors.add(gradleTask.build());
|
||||
tasks.add(builder.build());
|
||||
});
|
||||
if (isRoot) {
|
||||
Set<String> taskNames = new HashSet<>();
|
||||
for (GradleTask existingTask : project.getTasksList()) {
|
||||
taskNames.add(existingTask.getName());
|
||||
}
|
||||
for (GradleTask task : taskSelectors) {
|
||||
if (!taskNames.contains(task.getName())) {
|
||||
taskNames.add(task.getName());
|
||||
GradleTask.Builder taskSelector = GradleTask.newBuilder().setProject(gradleProject.getName())
|
||||
.setName(task.getName()).setPath(task.getName())
|
||||
.setBuildFile(gradleProject.getBuildScript().getSourceFile().getAbsolutePath())
|
||||
.setRootProject(task.getRootProject());
|
||||
if (task.getDescription() != null) {
|
||||
taskSelector.setDescription(task.getDescription());
|
||||
}
|
||||
if (task.getGroup() != null) {
|
||||
taskSelector.setGroup(task.getGroup());
|
||||
}
|
||||
project.addTasks(taskSelector.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
return project.build();
|
||||
return tasks;
|
||||
}
|
||||
|
||||
private void replyWithProject(GradleProject gradleProject) {
|
||||
|
|
|
@ -220,7 +220,7 @@ public class GradleServerTest {
|
|||
|
||||
stub.getBuild(req, mockResponseObserver);
|
||||
verify(mockResponseObserver, never()).onError(any());
|
||||
verify(mockGradleProjectBuilder).setJvmArguments(jvmArgs.split(" "));
|
||||
verify(mockBuildEnvironmentBuilder).setJvmArguments(jvmArgs.split(" "));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -232,13 +232,13 @@ public class GradleServerTest {
|
|||
|
||||
stub.getBuild(req1, mockResponseObserver);
|
||||
verify(mockResponseObserver, never()).onError(any());
|
||||
verify(mockGradleProjectBuilder).setColorOutput(false);
|
||||
verify(mockBuildEnvironmentBuilder).setColorOutput(false);
|
||||
|
||||
GetBuildRequest req2 = GetBuildRequest.newBuilder().setProjectDir(mockProjectDir.getAbsolutePath().toString())
|
||||
.setGradleConfig(GradleConfig.newBuilder().setWrapperEnabled(true)).setShowOutputColors(true).build();
|
||||
stub.getBuild(req2, mockResponseObserver);
|
||||
verify(mockResponseObserver, never()).onError(any());
|
||||
verify(mockGradleProjectBuilder).setColorOutput(true);
|
||||
verify(mockBuildEnvironmentBuilder).setColorOutput(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -253,11 +253,11 @@ public class GradleServerTest {
|
|||
stub.getBuild(req, mockResponseObserver);
|
||||
verify(mockResponseObserver, never()).onError(any());
|
||||
|
||||
verify(mockGradleProjectBuilder).addProgressListener(any(org.gradle.tooling.events.ProgressListener.class),
|
||||
verify(mockBuildEnvironmentBuilder).addProgressListener(any(org.gradle.tooling.events.ProgressListener.class),
|
||||
onAddProgressListener.capture());
|
||||
|
||||
assertEquals(1, onAddProgressListener.getValue().size());
|
||||
assertTrue(onAddProgressListener.getValue().contains(OperationType.PROJECT_CONFIGURATION));
|
||||
assertTrue(onAddProgressListener.getValue().contains(OperationType.GENERIC));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Загрузка…
Ссылка в новой задаче