Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<extension point="org.eclipse.jdt.ls.core.delegateCommandHandler">
<delegateCommandHandler class="com.microsoft.gradle.bs.importer.handler.GradleDelegateCommandHandler">
<command id="java.gradle.delegateTest" />
<command id="java.gradle.getBuildTargetInfo" />
</delegateCommandHandler>
Comment thread
wenytang-ms marked this conversation as resolved.
</extension>
</plugin>
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.microsoft.gradle.bs.importer.handler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Collections;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
Expand All @@ -22,7 +26,13 @@
import ch.epfl.scala.bsp4j.BuildTargetTag;
import ch.epfl.scala.bsp4j.ScalaTestSuiteSelection;
import ch.epfl.scala.bsp4j.ScalaTestSuites;
import ch.epfl.scala.bsp4j.SourceItem;
import ch.epfl.scala.bsp4j.SourceItemKind;
import ch.epfl.scala.bsp4j.SourcesItem;
import ch.epfl.scala.bsp4j.SourcesParams;
import ch.epfl.scala.bsp4j.SourcesResult;
import ch.epfl.scala.bsp4j.TestParams;
import ch.epfl.scala.bsp4j.extended.JvmBuildTargetEx;

public class GradleDelegateCommandHandler implements IDelegateCommandHandler {

Expand Down Expand Up @@ -78,6 +88,65 @@ public Object executeCommand(String commandId, List<Object> arguments, IProgress
testParams.setData(scalaTestSuites);
buildServerConnection.buildTargetTest(testParams);
return null;
case "java.gradle.getBuildTargetInfo": {
String sourcesProjectName = (String) arguments.get(0);
IProject sourcesProject = ProjectUtils.getProject(sourcesProjectName);
if (sourcesProject == null) {
throw new IllegalArgumentException("Project not found: " + sourcesProjectName);
}
if (!Utils.isGradleBuildServerProject(sourcesProject)) {
throw new IllegalArgumentException(
"Project is not a Gradle build server project: " + sourcesProjectName);
}
IPath sourcesRootPath = ProjectUtils.findBelongedWorkspaceRoot(sourcesProject.getLocation());
BuildServerConnection sourcesConnection = ImporterPlugin.getBuildServerConnection(sourcesRootPath, false);
if (sourcesConnection == null) {
throw new IllegalStateException(
"Build server connection not found for project: " + sourcesProjectName);
}
List<BuildTarget> sourceTargets = Utils
.getBuildTargetsByProjectUri(sourcesConnection, sourcesProject.getLocationURI());
List<BuildTargetIdentifier> sourcesBtIds = sourceTargets.stream()
.map(BuildTarget::getId).collect(Collectors.toList());
if (sourcesBtIds.isEmpty()) {
return Collections.emptyMap();
}
SourcesResult sourcesResult = sourcesConnection
.buildTargetSources(new SourcesParams(sourcesBtIds)).get(5, TimeUnit.SECONDS);

Map<String, BuildTarget> targetsById = sourceTargets.stream().collect(
Collectors.toMap(target -> target.getId().getUri(), target -> target));
String gradleVersion = null;
for (BuildTarget target : sourceTargets) {
if ("jvm".equals(target.getDataKind())) {
JvmBuildTargetEx jvmTarget = JSONUtility.toModel(target.getData(), JvmBuildTargetEx.class);
if (jvmTarget.getGradleVersion() != null && !jvmTarget.getGradleVersion().isBlank()) {
gradleVersion = jvmTarget.getGradleVersion();
break;
}
}
}

List<Map<String, Object>> sourceRoots = new ArrayList<>();
for (SourcesItem item : sourcesResult.getItems()) {
BuildTarget target = targetsById.get(item.getTarget().getUri());
boolean isTest = target != null && (target.getTags().contains(BuildTargetTag.TEST)
|| target.getTags().contains(BuildTargetTag.INTEGRATION_TEST));
for (SourceItem source : item.getSources()) {
if (source.getKind() == SourceItemKind.DIRECTORY) {
Map<String, Object> sourceRoot = new HashMap<>();
sourceRoot.put("uri", source.getUri());
sourceRoot.put("isTest", isTest);
sourceRoot.put("generated", Boolean.TRUE.equals(source.getGenerated()));
sourceRoots.add(sourceRoot);
}
}
}
Map<String, Object> result = new LinkedHashMap<>();
result.put("gradleVersion", gradleVersion);
result.put("sourceRoots", sourceRoots);
return result;
}
default:
break;
}
Expand Down
4 changes: 2 additions & 2 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
"license": "SEE LICENSE IN LICENSE.md",
"engines": {
"vscode": "^1.76.0",
"vscode": "^1.88.0",
"node": ">=20.0.0",
"npm": "^10.7.0"
},
Expand Down Expand Up @@ -989,7 +989,7 @@
"@types/mocha": "^10.0.1",
"@types/node": "^16.11.7",
"@types/sinon": "^10.0.13",
"@types/vscode": "^1.76.0",
"@types/vscode": "^1.88.0",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"@vscode/test-electron": "^2.3.8",
Expand Down
12 changes: 12 additions & 0 deletions extension/src/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper";
import { GradleBuildContentProvider } from "./client/GradleBuildContentProvider";
import { BuildServerController } from "./bs/BuildServerController";
import { supportsDelegatedTestCoverage } from "./bs/coverage";

export class Extension {
private readonly taskServerClient: TaskServerClient;
Expand Down Expand Up @@ -421,6 +422,17 @@ export class Extension {
vscode.TestRunProfileKind.Debug,
testRunner
);
// Delegated coverage needs the Test Runner for Java extension to
// supply an output directory and to analyze the `.exec` files the
// Gradle test JVM writes there. Without that half of the feature
// the profile could only fail, so it stays hidden.
if (supportsDelegatedTestCoverage(testRunnerApi)) {
testRunnerApi.registerTestProfile(
"Delegate Test to Gradle (Coverage)",
vscode.TestRunProfileKind.Coverage,
testRunner
);
}
}
}
}
Expand Down
Loading
Loading