Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 86b47e3

Browse files
author
Arthur McGibbon
committedMay 13, 2024·
Better progress reports
1 parent 59b80ec commit 86b47e3

File tree

12 files changed

+397
-244
lines changed

12 files changed

+397
-244
lines changed
 

‎model/src/main/java/com/microsoft/java/bs/gradle/model/GradleSourceSet.java

+10
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ public interface GradleSourceSet extends Serializable {
5454
*/
5555
public String getClassesTaskName();
5656

57+
/**
58+
* The name of the clean task.
59+
*/
60+
public String getCleanTaskName();
61+
62+
/**
63+
* All the tasks relevant to compiling this source set.
64+
*/
65+
public Set<String> getTaskNames();
66+
5767
/**
5868
* The source directories of this source set.
5969
*/

‎model/src/main/java/com/microsoft/java/bs/gradle/model/impl/DefaultGradleSourceSet.java

+25-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public class DefaultGradleSourceSet implements GradleSourceSet {
3737

3838
private String classesTaskName;
3939

40+
private String cleanTaskName;
41+
42+
private Set<String> taskNames;
43+
4044
private Set<File> sourceDirs;
4145

4246
private Set<File> generatedSourceDirs;
@@ -73,6 +77,8 @@ public DefaultGradleSourceSet(GradleSourceSet gradleSourceSet) {
7377
this.rootDir = gradleSourceSet.getRootDir();
7478
this.sourceSetName = gradleSourceSet.getSourceSetName();
7579
this.classesTaskName = gradleSourceSet.getClassesTaskName();
80+
this.cleanTaskName = gradleSourceSet.getCleanTaskName();
81+
this.taskNames = gradleSourceSet.getTaskNames();
7682
this.sourceDirs = gradleSourceSet.getSourceDirs();
7783
this.generatedSourceDirs = gradleSourceSet.getGeneratedSourceDirs();
7884
this.sourceOutputDir = gradleSourceSet.getSourceOutputDir();
@@ -165,7 +171,22 @@ public void setClassesTaskName(String classesTaskName) {
165171
this.classesTaskName = classesTaskName;
166172
}
167173

168-
@Override
174+
public String getCleanTaskName() {
175+
return cleanTaskName;
176+
}
177+
178+
public void setCleanTaskName(String cleanTaskName) {
179+
this.cleanTaskName = cleanTaskName;
180+
}
181+
182+
public void setTaskNames(Set<String> taskNames) {
183+
this.taskNames = taskNames;
184+
}
185+
186+
public Set<String> getTaskNames() {
187+
return taskNames;
188+
}
189+
169190
public Set<File> getSourceDirs() {
170191
return sourceDirs;
171192
}
@@ -258,7 +279,7 @@ public void setExtensions(Map<String, LanguageExtension> extensions) {
258279
@Override
259280
public int hashCode() {
260281
return Objects.hash(gradleVersion, displayName, projectName, projectPath,
261-
projectDir, rootDir, sourceSetName, classesTaskName, sourceDirs,
282+
projectDir, rootDir, sourceSetName, classesTaskName, cleanTaskName, taskNames, sourceDirs,
262283
generatedSourceDirs, sourceOutputDir, resourceDirs, resourceOutputDir,
263284
compileClasspath, moduleDependencies, buildTargetDependencies,
264285
hasTests, extensions);
@@ -284,6 +305,8 @@ public boolean equals(Object obj) {
284305
&& Objects.equals(rootDir, other.rootDir)
285306
&& Objects.equals(sourceSetName, other.sourceSetName)
286307
&& Objects.equals(classesTaskName, other.classesTaskName)
308+
&& Objects.equals(cleanTaskName, other.cleanTaskName)
309+
&& Objects.equals(taskNames, other.taskNames)
287310
&& Objects.equals(sourceDirs, other.sourceDirs)
288311
&& Objects.equals(generatedSourceDirs, other.generatedSourceDirs)
289312
&& Objects.equals(sourceOutputDir, other.sourceOutputDir)

‎plugin/build.gradle

+1-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ dependencies {
1212
transitive = false
1313
}
1414

15-
testImplementation 'org.gradle:gradle-tooling-api:8.1.1'
16-
testImplementation(platform('org.junit:junit-bom:5.9.2'))
17-
testImplementation 'org.junit.jupiter:junit-jupiter'
15+
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
1816
}
1917

2018
java {

‎plugin/src/main/java/com/microsoft/java/bs/gradle/plugin/SourceSetsModelBuilder.java

+35-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.Set;
1515

1616
import org.gradle.api.Project;
17+
import org.gradle.api.Task;
1718
import org.gradle.api.file.CopySpec;
1819
import org.gradle.api.file.Directory;
1920
import org.gradle.api.file.FileCollection;
@@ -64,11 +65,20 @@ public Object buildAll(String modelName, Project rootProject) {
6465
cache.addProject(sourceSet, project);
6566
gradleSourceSet.setGradleVersion(project.getGradle().getGradleVersion());
6667
gradleSourceSet.setProjectName(project.getName());
67-
gradleSourceSet.setProjectPath(project.getPath());
68+
String projectPath = project.getPath();
69+
gradleSourceSet.setProjectPath(projectPath);
6870
gradleSourceSet.setProjectDir(project.getProjectDir());
6971
gradleSourceSet.setRootDir(project.getRootDir());
7072
gradleSourceSet.setSourceSetName(sourceSet.getName());
71-
gradleSourceSet.setClassesTaskName(sourceSet.getClassesTaskName());
73+
String classesTaskName = getFullTaskName(projectPath, sourceSet.getClassesTaskName());
74+
gradleSourceSet.setClassesTaskName(classesTaskName);
75+
String cleanTaskName = getFullTaskName(projectPath, "clean");
76+
gradleSourceSet.setCleanTaskName(cleanTaskName);
77+
Set<String> taskNames = new HashSet<>();
78+
gradleSourceSet.setTaskNames(taskNames);
79+
taskNames.add(classesTaskName);
80+
taskNames.add(cleanTaskName);
81+
taskNames.add(getFullTaskName(projectPath, sourceSet.getProcessResourcesTaskName()));
7282
String projectName = stripPathPrefix(gradleSourceSet.getProjectPath());
7383
if (projectName == null || projectName.length() == 0) {
7484
projectName = gradleSourceSet.getProjectName();
@@ -82,6 +92,11 @@ public Object buildAll(String modelName, Project rootProject) {
8292
for (LanguageModelBuilder languageModelBuilder :
8393
GradleBuildServerPlugin.SUPPORTED_LANGUAGE_BUILDERS) {
8494
if (languageModelBuilder.appliesFor(project, sourceSet)) {
95+
Task compileTask = languageModelBuilder.getLanguageCompileTask(project, sourceSet);
96+
if (compileTask != null) {
97+
String compileTaskName = getFullTaskName(projectPath, compileTask.getName());
98+
taskNames.add(compileTaskName);
99+
}
85100
srcDirs.addAll(languageModelBuilder.getSourceFoldersFor(project, sourceSet));
86101
generatedSrcDirs.addAll(
87102
languageModelBuilder.getGeneratedSourceFoldersFor(project, sourceSet));
@@ -259,6 +274,24 @@ private SourceSetContainer getSourceSetContainer(Project project) {
259274
return null;
260275
}
261276

277+
/**
278+
* Return a project task name - [project path]:[task].
279+
*/
280+
private String getFullTaskName(String modulePath, String taskName) {
281+
if (taskName == null) {
282+
return null;
283+
}
284+
if (taskName.isEmpty()) {
285+
return taskName;
286+
}
287+
288+
if (modulePath == null || modulePath.equals(":")) {
289+
// must be prefixed with ":" as taskPaths are reported back like that in progress messages
290+
return ":" + taskName;
291+
}
292+
return modulePath + ":" + taskName;
293+
}
294+
262295
private String stripPathPrefix(String projectPath) {
263296
if (projectPath.startsWith(":")) {
264297
return projectPath.substring(1);

‎plugin/src/test/java/com/microsoft/java/bs/gradle/plugin/GradleBuildServerPluginTest.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ void testModelBuilder() throws IOException {
5757
assertEquals(projectDir, gradleSourceSet.getRootDir());
5858
assertTrue(gradleSourceSet.getSourceSetName().equals("main")
5959
|| gradleSourceSet.getSourceSetName().equals("test"));
60-
assertTrue(gradleSourceSet.getClassesTaskName().equals("classes")
61-
|| gradleSourceSet.getClassesTaskName().equals("testClasses"));
60+
assertTrue(gradleSourceSet.getClassesTaskName().equals(":classes")
61+
|| gradleSourceSet.getClassesTaskName().equals(":testClasses"));
6262
assertFalse(gradleSourceSet.getCompileClasspath().isEmpty());
6363
assertTrue(gradleSourceSet.getSourceDirs().size() > 0);
6464
assertTrue(gradleSourceSet.getGeneratedSourceDirs().size() > 0);
@@ -354,8 +354,8 @@ void testScala2ModelBuilder() throws IOException {
354354
assertEquals(projectDir, gradleSourceSet.getRootDir());
355355
assertTrue(gradleSourceSet.getSourceSetName().equals("main")
356356
|| gradleSourceSet.getSourceSetName().equals("test"));
357-
assertTrue(gradleSourceSet.getClassesTaskName().equals("classes")
358-
|| gradleSourceSet.getClassesTaskName().equals("testClasses"));
357+
assertTrue(gradleSourceSet.getClassesTaskName().equals(":classes")
358+
|| gradleSourceSet.getClassesTaskName().equals(":testClasses"));
359359
assertFalse(gradleSourceSet.getCompileClasspath().isEmpty());
360360
assertTrue(gradleSourceSet.getSourceDirs().size() > 0);
361361
assertTrue(gradleSourceSet.getGeneratedSourceDirs().size() > 0);
@@ -406,8 +406,8 @@ void testScala3ModelBuilder() throws IOException {
406406
assertEquals(projectDir, gradleSourceSet.getRootDir());
407407
assertTrue(gradleSourceSet.getSourceSetName().equals("main")
408408
|| gradleSourceSet.getSourceSetName().equals("test"));
409-
assertTrue(gradleSourceSet.getClassesTaskName().equals("classes")
410-
|| gradleSourceSet.getClassesTaskName().equals("testClasses"));
409+
assertTrue(gradleSourceSet.getClassesTaskName().equals(":classes")
410+
|| gradleSourceSet.getClassesTaskName().equals(":testClasses"));
411411
assertFalse(gradleSourceSet.getCompileClasspath().isEmpty());
412412
assertTrue(gradleSourceSet.getSourceDirs().size() > 0);
413413
assertTrue(gradleSourceSet.getGeneratedSourceDirs().size() > 0);

‎server/src/main/java/com/microsoft/java/bs/core/internal/gradle/GradleApiConnector.java

+19-28
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.HashMap;
1313
import java.util.Map;
1414
import java.util.Set;
15+
import java.util.function.Function;
1516

1617
import org.gradle.tooling.BuildException;
1718
import org.gradle.tooling.BuildLauncher;
@@ -23,14 +24,12 @@
2324
import org.gradle.tooling.model.build.BuildEnvironment;
2425

2526
import com.microsoft.java.bs.core.internal.managers.PreferenceManager;
26-
import com.microsoft.java.bs.core.internal.reporter.CompileProgressReporter;
2727
import com.microsoft.java.bs.core.internal.reporter.DefaultProgressReporter;
28-
import com.microsoft.java.bs.core.internal.reporter.TaskProgressReporter;
28+
import com.microsoft.java.bs.core.internal.reporter.ProgressReporter;
2929
import com.microsoft.java.bs.gradle.model.GradleSourceSets;
3030
import com.microsoft.java.bs.gradle.model.impl.DefaultGradleSourceSets;
3131

3232
import ch.epfl.scala.bsp4j.BuildClient;
33-
import ch.epfl.scala.bsp4j.BuildTargetIdentifier;
3433
import ch.epfl.scala.bsp4j.StatusCode;
3534

3635
/**
@@ -77,13 +76,10 @@ public GradleSourceSets getGradleSourceSets(URI projectUri) {
7776
if (!initScript.exists()) {
7877
throw new IllegalStateException("Failed to get init script file.");
7978
}
80-
TaskProgressReporter reporter = new TaskProgressReporter(new DefaultProgressReporter(client));
79+
ProgressReporter reporter = new DefaultProgressReporter(client);
8180
ByteArrayOutputStream errorOut = new ByteArrayOutputStream();
82-
String summary = "";
83-
StatusCode statusCode = StatusCode.OK;
8481
try (ProjectConnection connection = getGradleConnector(projectUri).connect();
8582
errorOut;) {
86-
reporter.taskStarted("Retrieve source sets");
8783
ModelBuilder<GradleSourceSets> customModelBuilder = Utils.getModelBuilder(
8884
connection,
8985
preferenceManager.getPreferences(),
@@ -103,51 +99,46 @@ public GradleSourceSets getGradleSourceSets(URI projectUri) {
10399
// via a copy constructor and return as a POJO.
104100
return new DefaultGradleSourceSets(customModelBuilder.get());
105101
} catch (GradleConnectionException | IllegalStateException | IOException e) {
106-
summary = e.getMessage();
102+
String summary = e.getMessage();
107103
if (errorOut.size() > 0) {
108-
summary += "\n" + errorOut.toString();
104+
summary += "\n" + errorOut;
109105
}
110-
statusCode = StatusCode.ERROR;
106+
reporter.sendError(summary);
111107
throw new IllegalStateException("Error retrieving sourcesets \n" + summary, e);
112-
} finally {
113-
reporter.taskFinished(summary, statusCode);
114108
}
115109
}
116110

117111
/**
118112
* Request Gradle daemon to run the tasks.
119113
*/
120-
public StatusCode runTasks(URI projectUri, Set<BuildTargetIdentifier> btIds, String... tasks) {
121-
// Note: this might be anti-sepc, because the spec limits that one compile task report
122-
// can only have one build target id. While we aggregate all compile related tasks into one
123-
// Gradle call for the perf consideration. So, the build target id passed into the reporter
124-
// is not accurate.
125-
TaskProgressReporter reporter = new TaskProgressReporter(
126-
new CompileProgressReporter(client, btIds.iterator().next()));
114+
public StatusCode runTasks(URI projectUri, Set<String> tasks,
115+
Function<BuildClient, ProgressReporter> reporterCreator) {
116+
// Don't issue a start progress update - the listener will pick that up automatically
117+
ProgressReporter reporter = reporterCreator.apply(client);
118+
127119
final ByteArrayOutputStream errorOut = new ByteArrayOutputStream();
128-
String summary = "BUILD SUCCESSFUL";
129120
StatusCode statusCode = StatusCode.OK;
130121
try (ProjectConnection connection = getGradleConnector(projectUri).connect();
131-
errorOut;
122+
errorOut
132123
) {
133-
reporter.taskStarted("Start to build: " + String.join(" ", tasks));
124+
String[] taskArr = tasks.toArray(String[]::new);
134125
BuildLauncher launcher = Utils.getBuildLauncher(connection,
135126
preferenceManager.getPreferences());
136127
// TODO: consider to use outputstream to capture the output.
137128
launcher.addProgressListener(reporter, OperationType.TASK)
138129
.setStandardError(errorOut)
139-
.forTasks(tasks)
130+
.forTasks(taskArr)
140131
.run();
141132
} catch (IOException e) {
142133
// caused by close the output stream, just simply log the error.
143134
LOGGER.severe(e.getMessage());
144135
} catch (BuildException e) {
145-
summary = errorOut.toString();
136+
String summary = e.getMessage();
137+
if (errorOut.size() > 0) {
138+
summary += "\n" + errorOut;
139+
}
140+
reporter.sendError(summary);
146141
statusCode = StatusCode.ERROR;
147-
} finally {
148-
// If a build/taskStart notification has been sent,
149-
// the server must send build/taskFinish on completion of the same task.
150-
reporter.taskFinished(summary, statusCode);
151142
}
152143

153144
return statusCode;

‎server/src/main/java/com/microsoft/java/bs/core/internal/reporter/CompileProgressReporter.java

+70-24
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
package com.microsoft.java.bs.core.internal.reporter;
55

6-
import java.util.UUID;
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
import java.util.Set;
79

810
import ch.epfl.scala.bsp4j.BuildClient;
911
import ch.epfl.scala.bsp4j.BuildTargetIdentifier;
@@ -16,57 +18,101 @@
1618
import ch.epfl.scala.bsp4j.TaskProgressParams;
1719
import ch.epfl.scala.bsp4j.TaskStartParams;
1820

21+
import org.gradle.tooling.events.FailureResult;
22+
import org.gradle.tooling.events.FinishEvent;
23+
import org.gradle.tooling.events.OperationResult;
24+
import org.gradle.tooling.events.ProgressEvent;
25+
import org.gradle.tooling.events.ProgressListener;
26+
import org.gradle.tooling.events.StartEvent;
27+
1928
/**
20-
* An implementation of {@link ProgressReporter} used for compilation tasks.
29+
* An implementation of {@link ProgressReporter}
30+
* and {@link ProgressListener} used for compilation tasks.
2131
*/
22-
public class CompileProgressReporter implements ProgressReporter {
32+
public class CompileProgressReporter extends ProgressReporter {
2333

24-
private final BuildTargetIdentifier btId;
25-
private final TaskId taskId;
26-
private final BuildClient client;
34+
private final String originId;
35+
private final Map<String, Set<BuildTargetIdentifier>> taskPathMap;
36+
private final Map<String, Long> startTimes;
2737

2838
/**
2939
* Instantiates a {@link CompileProgressReporter}.
3040
*
31-
* @param btId Build target identifier
41+
* @param client BSP client to report to.
42+
* @param originId id of the BSP client message.
43+
* @param taskPathMap all know task paths to their build targets.
3244
*/
33-
public CompileProgressReporter(BuildClient client, BuildTargetIdentifier btId) {
34-
this.btId = btId;
35-
this.taskId = new TaskId(UUID.randomUUID().toString());
36-
this.client = client;
45+
public CompileProgressReporter(BuildClient client, String originId,
46+
Map<String, Set<BuildTargetIdentifier>> taskPathMap) {
47+
super(client);
48+
this.originId = originId;
49+
this.taskPathMap = taskPathMap;
50+
startTimes = new HashMap<>();
3751
}
3852

3953
@Override
40-
public void taskStarted(String message) {
54+
public void statusChanged(ProgressEvent event) {
4155
if (client != null) {
56+
String taskPath = getTaskPath(event.getDescriptor());
57+
TaskId taskId = getTaskId(taskPath);
58+
Set<BuildTargetIdentifier> targets = taskPathMap.get(taskPath);
59+
if (targets != null) {
60+
if (event instanceof StartEvent) {
61+
startTimes.put(taskPath, event.getEventTime());
62+
taskStarted(taskId, targets, event.getDisplayName());
63+
} else if (event instanceof FinishEvent) {
64+
OperationResult result = ((FinishEvent) event).getResult();
65+
StatusCode status = result instanceof FailureResult ? StatusCode.ERROR : StatusCode.OK;
66+
Long compileStartTime = startTimes.get(taskPath);
67+
Long compileTimeDuration = compileStartTime == null ? null
68+
: event.getEventTime() - compileStartTime;
69+
taskFinished(taskId, targets, event.getDisplayName(), compileTimeDuration, status);
70+
} else {
71+
taskInProgress(taskId, targets, event.getDisplayName());
72+
}
73+
}
74+
}
75+
}
76+
77+
private void taskStarted(TaskId taskId, Set<BuildTargetIdentifier> targets, String message) {
78+
long eventTime = System.currentTimeMillis();
79+
targets.forEach(btId -> {
4280
TaskStartParams startParam = new TaskStartParams(taskId);
81+
startParam.setEventTime(eventTime);
4382
startParam.setMessage(message);
4483
startParam.setDataKind(TaskDataKind.COMPILE_TASK);
45-
startParam.setData(new CompileTask(this.btId));
84+
startParam.setData(new CompileTask(btId));
4685
client.onBuildTaskStart(startParam);
47-
}
86+
});
4887
}
4988

50-
@Override
51-
public void taskInProgress(String message) {
52-
if (client != null) {
89+
private void taskInProgress(TaskId taskId, Set<BuildTargetIdentifier> targets, String message) {
90+
long eventTime = System.currentTimeMillis();
91+
targets.forEach(btId -> {
5392
TaskProgressParams progressParam = new TaskProgressParams(taskId);
93+
progressParam.setEventTime(eventTime);
5494
progressParam.setMessage(message);
5595
progressParam.setDataKind(TaskDataKind.COMPILE_TASK);
56-
progressParam.setData(new CompileTask(this.btId));
96+
progressParam.setData(new CompileTask(btId));
5797
client.onBuildTaskProgress(progressParam);
58-
}
98+
});
5999
}
60100

61-
@Override
62-
public void taskFinished(String message, StatusCode statusCode) {
63-
if (client != null) {
101+
private void taskFinished(TaskId taskId, Set<BuildTargetIdentifier> targets, String message,
102+
Long compileTimeDuration, StatusCode statusCode) {
103+
long eventTime = System.currentTimeMillis();
104+
targets.forEach(btId -> {
64105
TaskFinishParams endParam = new TaskFinishParams(taskId, statusCode);
106+
endParam.setEventTime(eventTime);
65107
endParam.setMessage(message);
66108
endParam.setDataKind(TaskDataKind.COMPILE_REPORT);
67-
endParam.setData(new CompileReport(this.btId, 0, 0)); // TODO: parse the errors and warnings
109+
// TODO Gradle > 8.8 Problems API will allow errors/warnings to be reported on
110+
CompileReport compileReport = new CompileReport(btId, 0, 0);
111+
compileReport.setOriginId(originId);
112+
compileReport.setTime(compileTimeDuration);
113+
endParam.setData(compileReport);
68114
client.onBuildTaskFinish(endParam);
69-
}
115+
});
70116
}
71117
}
72118

‎server/src/main/java/com/microsoft/java/bs/core/internal/reporter/DefaultProgressReporter.java

+42-25
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33

44
package com.microsoft.java.bs.core.internal.reporter;
55

6-
import java.util.UUID;
6+
import org.gradle.tooling.events.FailureResult;
7+
import org.gradle.tooling.events.FinishEvent;
8+
import org.gradle.tooling.events.OperationResult;
9+
import org.gradle.tooling.events.ProgressEvent;
10+
import org.gradle.tooling.events.StartEvent;
711

812
import ch.epfl.scala.bsp4j.BuildClient;
913
import ch.epfl.scala.bsp4j.StatusCode;
@@ -15,40 +19,53 @@
1519
/**
1620
* A default implementation of {@link ProgressReporter}.
1721
*/
18-
public class DefaultProgressReporter implements ProgressReporter {
19-
20-
private final TaskId taskId;
21-
private final BuildClient client;
22+
public class DefaultProgressReporter extends ProgressReporter {
2223

24+
/**
25+
* Instantiates a {@link DefaultProgressReporter}.
26+
*
27+
* @param client BSP client to report to.
28+
*/
2329
public DefaultProgressReporter(BuildClient client) {
24-
this.taskId = new TaskId(UUID.randomUUID().toString());
25-
this.client = client;
30+
super(client);
2631
}
2732

2833
@Override
29-
public void taskStarted(String message) {
34+
public void statusChanged(ProgressEvent event) {
3035
if (client != null) {
31-
TaskStartParams startParam = new TaskStartParams(taskId);
32-
startParam.setMessage(message);
33-
client.onBuildTaskStart(startParam);
36+
String taskPath = getTaskPath(event.getDescriptor());
37+
TaskId taskId = getTaskId(taskPath);
38+
if (event instanceof StartEvent) {
39+
taskStarted(taskId, event.getDisplayName());
40+
} else if (event instanceof FinishEvent) {
41+
OperationResult result = ((FinishEvent) event).getResult();
42+
StatusCode status = result instanceof FailureResult ? StatusCode.ERROR : StatusCode.OK;
43+
taskFinished(taskId, event.getDisplayName(), status);
44+
} else {
45+
taskInProgress(taskId, event.getDisplayName());
46+
}
3447
}
3548
}
3649

37-
@Override
38-
public void taskInProgress(String message) {
39-
if (client != null) {
40-
TaskProgressParams progressParam = new TaskProgressParams(taskId);
41-
progressParam.setMessage(message);
42-
client.onBuildTaskProgress(progressParam);
43-
}
50+
private void taskStarted(TaskId taskId, String message) {
51+
TaskStartParams startParam = new TaskStartParams(taskId);
52+
startParam.setEventTime(System.currentTimeMillis());
53+
startParam.setMessage(message);
54+
client.onBuildTaskStart(startParam);
4455
}
4556

46-
@Override
47-
public void taskFinished(String message, StatusCode statusCode) {
48-
if (client != null) {
49-
TaskFinishParams endParam = new TaskFinishParams(taskId, statusCode);
50-
endParam.setMessage(message);
51-
client.onBuildTaskFinish(endParam);
52-
}
57+
private void taskInProgress(TaskId taskId, String message) {
58+
TaskProgressParams progressParam = new TaskProgressParams(taskId);
59+
progressParam.setEventTime(System.currentTimeMillis());
60+
progressParam.setMessage(message);
61+
client.onBuildTaskProgress(progressParam);
62+
}
63+
64+
private void taskFinished(TaskId taskId, String message,
65+
StatusCode statusCode) {
66+
TaskFinishParams endParam = new TaskFinishParams(taskId, statusCode);
67+
endParam.setEventTime(System.currentTimeMillis());
68+
endParam.setMessage(message);
69+
client.onBuildTaskFinish(endParam);
5370
}
5471
}

‎server/src/main/java/com/microsoft/java/bs/core/internal/reporter/ProgressReporter.java

+55-16
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,71 @@
33

44
package com.microsoft.java.bs.core.internal.reporter;
55

6-
import ch.epfl.scala.bsp4j.StatusCode;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.UUID;
9+
10+
import org.gradle.tooling.events.OperationDescriptor;
11+
import org.gradle.tooling.events.ProgressListener;
12+
import org.gradle.tooling.events.task.TaskOperationDescriptor;
13+
14+
import ch.epfl.scala.bsp4j.BuildClient;
15+
import ch.epfl.scala.bsp4j.LogMessageParams;
16+
import ch.epfl.scala.bsp4j.MessageType;
17+
import ch.epfl.scala.bsp4j.TaskId;
718

819
/**
9-
* A progress reporter that reports the progress of a task.
20+
* An extension of {@link ProgressListener} that allows sending errors.
1021
*/
11-
public interface ProgressReporter {
22+
public abstract class ProgressReporter implements ProgressListener {
1223

13-
/**
14-
* Notify the client that a task has been started.
15-
*
16-
* @param message the message to be displayed.
17-
*/
18-
void taskStarted(String message);
24+
protected final BuildClient client;
25+
protected final TaskId taskId;
26+
protected final List<String> taskIds;
1927

2028
/**
21-
* Notify the progress of the task.
29+
* Instantiates a {@link ProgressReporter}.
2230
*
23-
* @param message the message to be displayed.
31+
* @param client BSP client to report to.
2432
*/
25-
void taskInProgress(String message);
33+
public ProgressReporter(BuildClient client) {
34+
this.client = client;
35+
taskId = new TaskId(UUID.randomUUID().toString());
36+
taskIds = new ArrayList<>();
37+
taskIds.add(taskId.getId());
38+
}
2639

2740
/**
28-
* Notify the client that a task has been finished.
41+
* Notify the client of an error.
2942
*
30-
* @param message the message to be displayed.
31-
* @param statusCode the status code of the task.
43+
* @param error the error message.
3244
*/
33-
void taskFinished(String message, StatusCode statusCode);
45+
public void sendError(String error) {
46+
if (client != null) {
47+
LogMessageParams messageParam = new LogMessageParams(MessageType.ERROR, error);
48+
messageParam.setTask(taskId);
49+
client.onBuildLogMessage(messageParam);
50+
}
51+
}
52+
53+
protected TaskId getTaskId(String taskPath) {
54+
TaskId taskId = new TaskId(taskPath == null ? "null" : taskPath);
55+
taskId.setParents(taskIds);
56+
return taskId;
57+
}
58+
59+
protected String getTaskPath(OperationDescriptor operationDescriptor) {
60+
if (operationDescriptor == null) {
61+
return null;
62+
} else if (operationDescriptor instanceof TaskOperationDescriptor) {
63+
return ((TaskOperationDescriptor) operationDescriptor).getTaskPath();
64+
} else {
65+
OperationDescriptor parent = operationDescriptor.getParent();
66+
if (parent != operationDescriptor) {
67+
return getTaskPath(operationDescriptor.getParent());
68+
} else {
69+
return null;
70+
}
71+
}
72+
}
3473
}

‎server/src/main/java/com/microsoft/java/bs/core/internal/reporter/TaskProgressReporter.java

-39
This file was deleted.

‎server/src/main/java/com/microsoft/java/bs/core/internal/services/BuildTargetService.java

+71-43
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,20 @@
1818
import java.util.logging.Level;
1919
import java.util.stream.Collectors;
2020

21-
import ch.epfl.scala.bsp4j.DependencySourcesItem;
22-
import ch.epfl.scala.bsp4j.DependencySourcesParams;
23-
import ch.epfl.scala.bsp4j.DependencySourcesResult;
24-
import ch.epfl.scala.bsp4j.ScalacOptionsItem;
25-
import ch.epfl.scala.bsp4j.ScalacOptionsParams;
26-
import ch.epfl.scala.bsp4j.ScalacOptionsResult;
27-
import com.microsoft.java.bs.gradle.model.JavaExtension;
28-
import com.microsoft.java.bs.gradle.model.ScalaExtension;
29-
import org.apache.commons.lang3.StringUtils;
30-
3121
import com.microsoft.java.bs.core.internal.gradle.GradleApiConnector;
3222
import com.microsoft.java.bs.core.internal.managers.BuildTargetManager;
3323
import com.microsoft.java.bs.core.internal.managers.PreferenceManager;
3424
import com.microsoft.java.bs.core.internal.model.GradleBuildTarget;
25+
import com.microsoft.java.bs.core.internal.reporter.CompileProgressReporter;
26+
import com.microsoft.java.bs.core.internal.reporter.DefaultProgressReporter;
27+
import com.microsoft.java.bs.core.internal.reporter.ProgressReporter;
3528
import com.microsoft.java.bs.core.internal.utils.TelemetryUtils;
3629
import com.microsoft.java.bs.core.internal.utils.UriUtils;
3730
import com.microsoft.java.bs.gradle.model.GradleModuleDependency;
3831
import com.microsoft.java.bs.gradle.model.GradleSourceSet;
3932
import com.microsoft.java.bs.gradle.model.GradleSourceSets;
33+
import com.microsoft.java.bs.gradle.model.JavaExtension;
34+
import com.microsoft.java.bs.gradle.model.ScalaExtension;
4035
import com.microsoft.java.bs.gradle.model.SupportedLanguages;
4136

4237
import ch.epfl.scala.bsp4j.BuildClient;
@@ -51,6 +46,9 @@
5146
import ch.epfl.scala.bsp4j.DependencyModulesItem;
5247
import ch.epfl.scala.bsp4j.DependencyModulesParams;
5348
import ch.epfl.scala.bsp4j.DependencyModulesResult;
49+
import ch.epfl.scala.bsp4j.DependencySourcesItem;
50+
import ch.epfl.scala.bsp4j.DependencySourcesParams;
51+
import ch.epfl.scala.bsp4j.DependencySourcesResult;
5452
import ch.epfl.scala.bsp4j.JavacOptionsItem;
5553
import ch.epfl.scala.bsp4j.JavacOptionsParams;
5654
import ch.epfl.scala.bsp4j.JavacOptionsResult;
@@ -65,13 +63,17 @@
6563
import ch.epfl.scala.bsp4j.ResourcesItem;
6664
import ch.epfl.scala.bsp4j.ResourcesParams;
6765
import ch.epfl.scala.bsp4j.ResourcesResult;
66+
import ch.epfl.scala.bsp4j.ScalacOptionsItem;
67+
import ch.epfl.scala.bsp4j.ScalacOptionsParams;
68+
import ch.epfl.scala.bsp4j.ScalacOptionsResult;
6869
import ch.epfl.scala.bsp4j.SourceItem;
6970
import ch.epfl.scala.bsp4j.SourceItemKind;
7071
import ch.epfl.scala.bsp4j.SourcesItem;
7172
import ch.epfl.scala.bsp4j.SourcesParams;
7273
import ch.epfl.scala.bsp4j.SourcesResult;
7374
import ch.epfl.scala.bsp4j.StatusCode;
7475
import ch.epfl.scala.bsp4j.WorkspaceBuildTargetsResult;
76+
import org.apache.commons.lang3.StringUtils;
7577

7678
/**
7779
* Service to handle build target related BSP requests.
@@ -260,7 +262,7 @@ public OutputPathsResult getBuildTargetOutputPaths(OutputPathsParams params) {
260262
public DependencySourcesResult getBuildTargetDependencySources(DependencySourcesParams params) {
261263
List<DependencySourcesItem> items = new ArrayList<>();
262264
for (BuildTargetIdentifier btId : params.getTargets()) {
263-
GradleBuildTarget target = buildTargetManager.getGradleBuildTarget(btId);
265+
GradleBuildTarget target = getGradleBuildTarget(btId);
264266
if (target == null) {
265267
LOGGER.warning("Skip output collection for the build target: " + btId.getUri()
266268
+ ". Because it cannot be found in the cache.");
@@ -329,14 +331,20 @@ public CompileResult compile(CompileParams params) {
329331
if (params.getTargets().isEmpty()) {
330332
return new CompileResult(StatusCode.OK);
331333
} else {
332-
StatusCode code = runTasks(params.getTargets(), this::getBuildTaskName);
334+
Function<Map<String, Set<BuildTargetIdentifier>>,
335+
Function<BuildClient, ProgressReporter>> reporterCreator =
336+
fullTaskPathMap -> buildClient ->
337+
new CompileProgressReporter(client, params.getOriginId(), fullTaskPathMap);
338+
StatusCode code = runTasks(params.getTargets(), this::getBuildTaskName, reporterCreator);
333339
CompileResult result = new CompileResult(code);
334340
result.setOriginId(params.getOriginId());
335341

336342
// Schedule a task to refetch the build targets after compilation, this is to
337343
// auto detect the source roots changes for those code generation framework,
338344
// such as Protocol Buffer.
339-
CompletableFuture.runAsync(this::reloadWorkspace);
345+
if (!Boolean.getBoolean("bsp.plugin.reloadworkspace.disabled")) {
346+
CompletableFuture.runAsync(this::reloadWorkspace);
347+
}
340348
return result;
341349
}
342350
}
@@ -345,22 +353,52 @@ public CompileResult compile(CompileParams params) {
345353
* clean the build targets.
346354
*/
347355
public CleanCacheResult cleanCache(CleanCacheParams params) {
348-
StatusCode code = runTasks(params.getTargets(), this::getCleanTaskName);
356+
Function<Map<String, Set<BuildTargetIdentifier>>,
357+
Function<BuildClient, ProgressReporter>> reporterCreator =
358+
fullTaskPathMap -> buildClient ->
359+
new DefaultProgressReporter(client);
360+
StatusCode code = runTasks(params.getTargets(), this::getCleanTaskName, reporterCreator);
349361
return new CleanCacheResult(null, code == StatusCode.OK);
350362
}
351363

364+
/**
365+
* create a map of all known taskpaths to the build targets they affect.
366+
* used to associate progress events to the correct target.
367+
*/
368+
private Map<String, Set<BuildTargetIdentifier>> getFullTaskPathMap() {
369+
Map<String, Set<BuildTargetIdentifier>> fullTaskPathMap = new HashMap<>();
370+
for (GradleBuildTarget buildTarget : buildTargetManager.getAllGradleBuildTargets()) {
371+
Set<String> tasks = buildTarget.getSourceSet().getTaskNames();
372+
BuildTargetIdentifier btId = buildTarget.getBuildTarget().getId();
373+
for (String taskName : tasks) {
374+
fullTaskPathMap.computeIfAbsent(taskName, k -> new HashSet<>())
375+
.add(btId);
376+
}
377+
}
378+
return fullTaskPathMap;
379+
}
380+
352381
/**
353382
* group targets by project root and execute the supplied tasks.
354383
*/
355384
private StatusCode runTasks(List<BuildTargetIdentifier> targets,
356-
Function<BuildTargetIdentifier, String> taskNameCreator) {
385+
Function<BuildTargetIdentifier, String> taskNameCreator,
386+
Function<Map<String, Set<BuildTargetIdentifier>>,
387+
Function<BuildClient, ProgressReporter>> progressReporterCreator) {
388+
// create task name for all build targets to be able to monitor progress
389+
Map<String, Set<BuildTargetIdentifier>> fullTaskPathMap = getFullTaskPathMap();
390+
357391
Map<URI, Set<BuildTargetIdentifier>> groupedTargets = groupBuildTargetsByRootDir(targets);
358392
StatusCode code = StatusCode.OK;
359393
for (Map.Entry<URI, Set<BuildTargetIdentifier>> entry : groupedTargets.entrySet()) {
360-
Set<BuildTargetIdentifier> btIds = entry.getValue();
361-
// remove duplicates as some tasks will have the same name for each sourceset e.g. clean.
362-
String[] tasks = btIds.stream().map(taskNameCreator).distinct().toArray(String[]::new);
363-
code = connector.runTasks(entry.getKey(), btIds, tasks);
394+
// use Set to remove duplicates. Some tasks have the same name for each sourceset e.g. clean.
395+
Set<String> tasks = entry.getValue().stream()
396+
.map(taskNameCreator)
397+
.collect(Collectors.toSet());
398+
Function<BuildClient, ProgressReporter> reporterCreator =
399+
progressReporterCreator.apply(fullTaskPathMap);
400+
code = connector.runTasks(entry.getKey(), tasks, reporterCreator);
401+
364402
if (code == StatusCode.ERROR) {
365403
break;
366404
}
@@ -484,44 +522,34 @@ private URI getRootProjectUri(BuildTargetIdentifier btId) {
484522
}
485523

486524
/**
487-
* Return the build task name - [project path]:[task].
525+
* Return a source set task name.
488526
*/
489-
private String getBuildTaskName(BuildTargetIdentifier btId) {
527+
private String getProjectTaskName(BuildTargetIdentifier btId, String title,
528+
Function<GradleSourceSet, String> creator) {
490529
GradleBuildTarget gradleBuildTarget = getGradleBuildTarget(btId);
491530
if (gradleBuildTarget == null) {
492531
// TODO: https://github.com/microsoft/build-server-for-gradle/issues/50
493532
throw new IllegalArgumentException("The build target does not exist: " + btId.getUri());
494533
}
495-
GradleSourceSet sourceSet = gradleBuildTarget.getSourceSet();
496-
String classesTaskName = sourceSet.getClassesTaskName();
497-
if (StringUtils.isBlank(classesTaskName)) {
498-
throw new IllegalArgumentException("The build target does not have a classes task: "
534+
String taskName = creator.apply(gradleBuildTarget.getSourceSet());
535+
if (StringUtils.isBlank(taskName)) {
536+
throw new IllegalArgumentException("The build target does not have a " + title + " task: "
499537
+ btId.getUri());
500538
}
539+
return taskName;
540+
}
501541

502-
String modulePath = sourceSet.getProjectPath();
503-
if (modulePath == null || modulePath.equals(":")) {
504-
return classesTaskName;
505-
}
506-
return modulePath + ":" + classesTaskName;
542+
/**
543+
* Return the build task name - [project path]:[task].
544+
*/
545+
private String getBuildTaskName(BuildTargetIdentifier btId) {
546+
return getProjectTaskName(btId, "classes", GradleSourceSet::getClassesTaskName);
507547
}
508548

509549
/**
510550
* Return the clean task name - [project path]:[task].
511551
*/
512552
private String getCleanTaskName(BuildTargetIdentifier btId) {
513-
GradleBuildTarget gradleBuildTarget = getGradleBuildTarget(btId);
514-
if (gradleBuildTarget == null) {
515-
// TODO: https://github.com/microsoft/build-server-for-gradle/issues/50
516-
throw new IllegalArgumentException("The build target does not exist: " + btId.getUri());
517-
}
518-
GradleSourceSet sourceSet = gradleBuildTarget.getSourceSet();
519-
String classesTaskName = "clean";
520-
521-
String modulePath = sourceSet.getProjectPath();
522-
if (modulePath == null || modulePath.equals(":")) {
523-
return classesTaskName;
524-
}
525-
return modulePath + ":" + classesTaskName;
553+
return getProjectTaskName(btId, "clean", GradleSourceSet::getCleanTaskName);
526554
}
527555
}

‎server/src/test/java/com/microsoft/java/bs/core/internal/server/BuildTargetServerIntegrationTest.java

+63-56
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package com.microsoft.java.bs.core.internal.server;
55

66
import static org.junit.jupiter.api.Assertions.assertEquals;
7-
import static org.junit.jupiter.api.Assertions.assertFalse;
87
import static org.junit.jupiter.api.Assertions.assertNotNull;
98
import static org.junit.jupiter.api.Assertions.assertTrue;
109

@@ -14,33 +13,13 @@
1413
import java.io.PipedOutputStream;
1514
import java.nio.file.Paths;
1615
import java.util.ArrayList;
17-
import java.util.HashSet;
1816
import java.util.List;
19-
import java.util.Set;
2017
import java.util.concurrent.ExecutorService;
2118
import java.util.concurrent.Executors;
2219
import java.util.function.BiConsumer;
20+
import java.util.function.IntSupplier;
2321
import java.util.stream.Collectors;
2422

25-
import ch.epfl.scala.bsp4j.DependencyModulesParams;
26-
import ch.epfl.scala.bsp4j.DependencyModulesResult;
27-
import ch.epfl.scala.bsp4j.DependencySourcesParams;
28-
import ch.epfl.scala.bsp4j.DependencySourcesResult;
29-
import ch.epfl.scala.bsp4j.MavenDependencyModule;
30-
import ch.epfl.scala.bsp4j.MavenDependencyModuleArtifact;
31-
import org.junit.jupiter.api.AfterAll;
32-
import org.junit.jupiter.api.BeforeAll;
33-
import org.junit.jupiter.api.Test;
34-
35-
import com.microsoft.java.bs.core.Launcher;
36-
import com.microsoft.java.bs.core.internal.gradle.GradleApiConnector;
37-
import com.microsoft.java.bs.core.internal.managers.BuildTargetManager;
38-
import com.microsoft.java.bs.core.internal.managers.PreferenceManager;
39-
import com.microsoft.java.bs.core.internal.services.BuildTargetService;
40-
import com.microsoft.java.bs.core.internal.services.LifecycleService;
41-
import com.microsoft.java.bs.core.internal.utils.JsonUtils;
42-
import com.microsoft.java.bs.gradle.model.SupportedLanguages;
43-
4423
import ch.epfl.scala.bsp4j.BuildClient;
4524
import ch.epfl.scala.bsp4j.BuildClientCapabilities;
4625
import ch.epfl.scala.bsp4j.BuildServer;
@@ -51,18 +30,36 @@
5130
import ch.epfl.scala.bsp4j.CompileParams;
5231
import ch.epfl.scala.bsp4j.CompileReport;
5332
import ch.epfl.scala.bsp4j.CompileResult;
33+
import ch.epfl.scala.bsp4j.DependencyModulesParams;
34+
import ch.epfl.scala.bsp4j.DependencyModulesResult;
35+
import ch.epfl.scala.bsp4j.DependencySourcesParams;
36+
import ch.epfl.scala.bsp4j.DependencySourcesResult;
5437
import ch.epfl.scala.bsp4j.DidChangeBuildTarget;
5538
import ch.epfl.scala.bsp4j.InitializeBuildParams;
5639
import ch.epfl.scala.bsp4j.JavaBuildServer;
5740
import ch.epfl.scala.bsp4j.JvmBuildServer;
5841
import ch.epfl.scala.bsp4j.LogMessageParams;
42+
import ch.epfl.scala.bsp4j.MavenDependencyModule;
43+
import ch.epfl.scala.bsp4j.MavenDependencyModuleArtifact;
5944
import ch.epfl.scala.bsp4j.PublishDiagnosticsParams;
6045
import ch.epfl.scala.bsp4j.ShowMessageParams;
6146
import ch.epfl.scala.bsp4j.StatusCode;
6247
import ch.epfl.scala.bsp4j.TaskFinishParams;
6348
import ch.epfl.scala.bsp4j.TaskProgressParams;
6449
import ch.epfl.scala.bsp4j.TaskStartParams;
6550
import ch.epfl.scala.bsp4j.WorkspaceBuildTargetsResult;
51+
import org.junit.jupiter.api.AfterAll;
52+
import org.junit.jupiter.api.BeforeAll;
53+
import org.junit.jupiter.api.Test;
54+
55+
import com.microsoft.java.bs.core.Launcher;
56+
import com.microsoft.java.bs.core.internal.gradle.GradleApiConnector;
57+
import com.microsoft.java.bs.core.internal.managers.BuildTargetManager;
58+
import com.microsoft.java.bs.core.internal.managers.PreferenceManager;
59+
import com.microsoft.java.bs.core.internal.services.BuildTargetService;
60+
import com.microsoft.java.bs.core.internal.services.LifecycleService;
61+
import com.microsoft.java.bs.core.internal.utils.JsonUtils;
62+
import com.microsoft.java.bs.gradle.model.SupportedLanguages;
6663

6764
// TODO: Move to a dedicated source set for integration tests
6865
class BuildTargetServerIntegrationTest {
@@ -73,24 +70,38 @@ private interface TestServer extends BuildServer, JavaBuildServer, JvmBuildServe
7370
private static class TestClient implements BuildClient {
7471

7572
private final List<TaskStartParams> startReports = new ArrayList<>();
76-
private final List<TaskFinishParams> finishReports = new ArrayList<>();
77-
private final Set<CompileReport> compileReports = new HashSet<>();
73+
private final List<String> finishReports = new ArrayList<>();
74+
private final List<CompileReport> compileReports = new ArrayList<>();
75+
private final List<CompileResult> compileResults = new ArrayList<>();
7876

7977
void clearMessages() {
8078
startReports.clear();
8179
finishReports.clear();
8280
compileReports.clear();
81+
compileResults.clear();
82+
}
83+
84+
void waitOnStartReports(int size) {
85+
waitOnMessages("Start Reports", size, startReports::size);
86+
}
87+
88+
void waitOnFinishReports(int size) {
89+
waitOnMessages("Finish Reports", size, finishReports::size);
90+
}
91+
92+
void waitOnCompileReports(int size) {
93+
waitOnMessages("Compile Reports", size, compileReports::size);
94+
}
95+
96+
void waitOnCompileResults(int size) {
97+
waitOnMessages("Compile Results", size, compileResults::size);
8398
}
8499

85-
void waitOnMessages(int startMessagesSize,
86-
int finishMessagesSize,
87-
int compileReportsSize) {
100+
private void waitOnMessages(String message, int size, IntSupplier sizeSupplier) {
88101
// set to 5000ms because it seems reasonable
89102
long timeoutMs = 5000;
90103
long endTime = System.currentTimeMillis() + timeoutMs;
91-
while ((startReports.size() < startMessagesSize
92-
|| finishReports.size() < finishMessagesSize
93-
|| compileReports.size() < compileReportsSize)
104+
while (sizeSupplier.getAsInt() < size
94105
&& System.currentTimeMillis() < endTime) {
95106
synchronized (this) {
96107
long waitTime = endTime - System.currentTimeMillis();
@@ -103,9 +114,7 @@ void waitOnMessages(int startMessagesSize,
103114
}
104115
}
105116
}
106-
assertEquals(startMessagesSize, startReports.size(), "Start Report count error");
107-
assertEquals(finishMessagesSize, finishReports.size(), "Finish Reports count error");
108-
assertEquals(compileReportsSize, compileReports.size(), "Compile Reports count error");
117+
assertEquals(size, sizeSupplier.getAsInt(), message + " count error");
109118
}
110119

111120
private CompileReport findCompileReport(BuildTargetIdentifier btId) {
@@ -150,9 +159,11 @@ public void onBuildTaskFinish(TaskFinishParams params) {
150159
if (params.getDataKind() != null) {
151160
if (params.getDataKind().equals("compile-report")) {
152161
compileReports.add(JsonUtils.toModel(params.getData(), CompileReport.class));
162+
} else if (params.getDataKind().equals("compile-result")) {
163+
compileResults.add(JsonUtils.toModel(params.getData(), CompileResult.class));
153164
}
154165
}
155-
finishReports.add(params);
166+
finishReports.add(params.getMessage());
156167
synchronized (this) {
157168
notify();
158169
}
@@ -174,11 +185,13 @@ static void beforeClass() {
174185
String pluginDir = Paths.get(System.getProperty("user.dir"),
175186
"build", "libs", "plugins").toString();
176187
System.setProperty(Launcher.PROP_PLUGIN_DIR, pluginDir);
188+
System.setProperty("bsp.plugin.reloadworkspace.disabled", "true");
177189
}
178190

179191
@AfterAll
180192
static void afterClass() {
181193
System.clearProperty(Launcher.PROP_PLUGIN_DIR);
194+
System.clearProperty("bsp.plugin.reloadworkspace.disabled");
182195
}
183196

184197
private InitializeBuildParams getInitializeBuildParams(String projectDir) {
@@ -257,22 +270,6 @@ private void withNewTestServer(String project, BiConsumer<TestServer, TestClient
257270
}
258271
}
259272

260-
private BuildTargetIdentifier getBt(List<BuildTargetIdentifier> btIds,
261-
String projectPathSection, String sourceSetName) {
262-
String sourceSet = "?sourceset=" + sourceSetName;
263-
List<BuildTargetIdentifier> matching = btIds.stream()
264-
.filter(id -> id.getUri().contains(projectPathSection))
265-
.filter(id -> id.getUri().endsWith(sourceSet))
266-
.collect(Collectors.toList());
267-
assertFalse(matching.isEmpty(), () -> "Build Target " + projectPathSection
268-
+ " with source set " + sourceSetName + " not found in "
269-
+ btIds.stream().map(Object::toString).collect(Collectors.joining(", ")));
270-
assertEquals(1, matching.size(), () -> "Too many Build Targets like " + projectPathSection
271-
+ " with source set " + sourceSetName + " found in "
272-
+ btIds.stream().map(Object::toString).collect(Collectors.joining(", ")));
273-
return matching.get(0);
274-
}
275-
276273
@Test
277274
void testCompilingSingleProjectServer() {
278275
withNewTestServer("junit5-jupiter-starter-gradle", (gradleBuildServer, client) -> {
@@ -314,18 +311,28 @@ void testCompilingSingleProjectServer() {
314311
CleanCacheResult cleanResult = gradleBuildServer
315312
.buildTargetCleanCache(cleanCacheParams).join();
316313
assertTrue(cleanResult.getCleaned());
317-
client.waitOnMessages(2, 2, 1);
314+
client.waitOnStartReports(2);
315+
client.waitOnFinishReports(2);
316+
client.waitOnCompileReports(0);
317+
client.waitOnCompileResults(0);
318318
client.clearMessages();
319319

320320
// compile targets
321321
CompileParams compileParams = new CompileParams(btIds);
322+
compileParams.setOriginId("originId");
322323
CompileResult compileResult = gradleBuildServer.buildTargetCompile(compileParams).join();
323324
assertEquals(StatusCode.OK, compileResult.getStatusCode());
324-
client.waitOnMessages(2, 2, 1);
325-
BuildTargetIdentifier testBt = getBt(btIds, "/junit5-jupiter-starter-gradle/", "test");
326-
CompileReport compileReportTest = client.findCompileReport(testBt);
327-
assertEquals(0, compileReportTest.getWarnings());
328-
assertEquals(0, compileReportTest.getErrors());
325+
client.waitOnStartReports(6);
326+
client.waitOnFinishReports(6);
327+
client.waitOnCompileReports(6);
328+
client.waitOnCompileResults(0);
329+
for (BuildTargetIdentifier btId : btIds) {
330+
CompileReport compileReport = client.findCompileReport(btId);
331+
assertEquals("originId", compileReport.getOriginId());
332+
// TODO compile results are not yet implemented so always zero for now.
333+
assertEquals(0, compileReport.getWarnings());
334+
assertEquals(0, compileReport.getErrors());
335+
}
329336
client.clearMessages();
330337
});
331338
}

0 commit comments

Comments
 (0)
Please sign in to comment.