Skip to content

Commit 7d972cd

Browse files
mildagleWixBuildServer
authored andcommitted
Add Bsp Fast compile support for intellij 2023
1 parent 1e1d1c8 commit 7d972cd

File tree

2 files changed

+185
-1
lines changed

2 files changed

+185
-1
lines changed

scala/BUILD

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,16 @@ licenses(["notice"])
1919

2020
java_library(
2121
name = "scala",
22-
srcs = glob(["src/**/*.java"]),
22+
srcs = select({
23+
"//intellij_platform_sdk:intellij-2022.3": glob(
24+
["src/**/*.java"],
25+
exclude = ["src/com/google/idea/blaze/scala/fastbuild/v23/BspFastCompile.java"],
26+
),
27+
"//conditions:default": glob(
28+
["src/**/*.java"],
29+
exclude = ["src/com/google/idea/blaze/scala/fastbuild/BspFastCompile.java"],
30+
),
31+
}),
2332
deps = [
2433
"//base",
2534
"//common/experiments",
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
package com.google.idea.blaze.scala.fastbuild;
2+
3+
import ch.epfl.scala.bsp4j.BuildTargetIdentifier;
4+
import ch.epfl.scala.bsp4j.CompileParams;
5+
import ch.epfl.scala.bsp4j.CompileResult;
6+
import ch.epfl.scala.bsp4j.DiagnosticSeverity;
7+
import ch.epfl.scala.bsp4j.Position;
8+
import ch.epfl.scala.bsp4j.PublishDiagnosticsParams;
9+
import ch.epfl.scala.bsp4j.StatusCode;
10+
import ch.epfl.scala.bsp4j.TaskFinishParams;
11+
import com.google.gson.JsonObject;
12+
import com.google.idea.blaze.base.io.VfsUtils;
13+
import com.google.idea.blaze.base.scope.BlazeContext;
14+
import com.google.idea.blaze.base.scope.output.StatusOutput;
15+
import com.google.idea.blaze.scala.fastbuild.BloopProject;
16+
import com.google.idea.blaze.scala.fastbuild.FileUtils;
17+
import com.intellij.openapi.diagnostic.Logger;
18+
import com.intellij.openapi.editor.Document;
19+
import com.intellij.openapi.fileEditor.FileDocumentManager;
20+
import com.intellij.openapi.vfs.VirtualFile;
21+
import com.intellij.util.DocumentUtil;
22+
import java.io.File;
23+
import java.io.IOException;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
26+
import java.util.Arrays;
27+
import java.util.Collections;
28+
import java.util.Objects;
29+
import java.util.concurrent.BlockingQueue;
30+
import java.util.concurrent.CompletableFuture;
31+
import java.util.concurrent.LinkedBlockingQueue;
32+
import java.util.concurrent.TimeUnit;
33+
import org.jetbrains.bsp.protocol.BspCommunication;
34+
import org.jetbrains.bsp.protocol.BspNotifications.BspNotification;
35+
import org.jetbrains.bsp.protocol.BspNotifications.PublishDiagnostics;
36+
import org.jetbrains.bsp.protocol.BspNotifications.TaskFinish;
37+
import org.jetbrains.bsp.protocol.session.BspSession.BspServer;
38+
import org.jetbrains.bsp.protocol.session.BspSession.BuildServerInfo;
39+
import org.jetbrains.bsp.settings.BspProjectSettings.BloopConfig$;
40+
import org.jetbrains.plugins.scala.build.BuildReporter;
41+
import org.jetbrains.plugins.scala.build.ConsoleReporter;
42+
import scala.Function1;
43+
import scala.Function2;
44+
import scala.runtime.BoxedUnit;
45+
46+
public class BspFastCompile {
47+
48+
private static final String FILE_PROTOCOL_PREFIX = "file://";
49+
private static final String CLIENT_DIR_FILE_PROTOCOL_PREFIX = "file://";
50+
private final File destination;
51+
private final BloopProject bloopProject;
52+
private final BlockingQueue<TaskFinishParams> finishParams;
53+
private static final Logger logger = Logger.getInstance(BspFastCompile.class);
54+
private final BspCompileRunner bspCompileRunner;
55+
private final BspNotificationsHandler bspNotificationsHandler;
56+
private final BuildReporter reporter;
57+
58+
public BspFastCompile(File destination, BloopProject bloopProject,
59+
BlazeContext context) {
60+
this.destination = destination;
61+
this.bloopProject = bloopProject;
62+
finishParams = new LinkedBlockingQueue<>();
63+
bspCompileRunner = new BspCompileRunner(bloopProject);
64+
bspNotificationsHandler = new BspNotificationsHandler(finishParams, context);
65+
reporter = new ConsoleReporter("Fast test");
66+
67+
}
68+
69+
void compileWithBsp() throws IOException, InterruptedException {
70+
final BspCommunication bspCommunication =
71+
BspCommunication.forWorkspace(bloopProject.getWorkspaceDir().toFile(),
72+
BloopConfig$.MODULE$);
73+
// for some reason the BspJop<CompileResult> doesn't return the actual data
74+
// so we're using a queue to communicate back the results
75+
bspCommunication.run(bspCompileRunner, bspNotificationsHandler, BspFastCompile::log, reporter);
76+
77+
TaskFinishParams taskFinishParams = finishParams.poll(3, TimeUnit.MINUTES);
78+
if (taskFinishParams.getStatus() == StatusCode.OK) {
79+
copyCompilationOutputs(taskFinishParams);
80+
} else {
81+
throw new RuntimeException("Bsp fast scala compilation");
82+
}
83+
84+
}
85+
86+
private void copyCompilationOutputs(TaskFinishParams taskFinishParams) throws IOException {
87+
JsonObject jsonObject = (JsonObject) taskFinishParams.getData();
88+
String clientDir = jsonObject.get("clientDir").getAsString();
89+
//clientDir starts with file protocol prefix which needs to be removed
90+
Path clientDirPath = Paths.get(clientDir.substring(CLIENT_DIR_FILE_PROTOCOL_PREFIX.length()));
91+
FileUtils.copyFolderRecursively(clientDirPath, destination.toPath());
92+
}
93+
94+
private static class BspCompileRunner implements
95+
Function2<BspServer, BuildServerInfo, CompletableFuture<CompileResult>> {
96+
97+
private final BloopProject bloopProject;
98+
99+
private BspCompileRunner(BloopProject bloopProject) {
100+
this.bloopProject = bloopProject;
101+
}
102+
103+
@Override
104+
public CompletableFuture<CompileResult> apply(BspServer bspServer,
105+
BuildServerInfo v2) {
106+
return bspServer.buildTargetCompile(new CompileParams(
107+
Collections.singletonList(new BuildTargetIdentifier(FILE_PROTOCOL_PREFIX + bloopProject
108+
.getWorkspaceDir() + "?id=" + bloopProject.getName())))
109+
);
110+
}
111+
}
112+
113+
private static class BspNotificationsHandler implements Function1<BspNotification, BoxedUnit> {
114+
115+
private final BlockingQueue<TaskFinishParams> finishParams;
116+
private final BlazeContext context;
117+
118+
private BspNotificationsHandler(BlockingQueue<TaskFinishParams> finishParams,
119+
BlazeContext context) {
120+
this.finishParams = finishParams;
121+
this.context = context;
122+
}
123+
124+
@Override
125+
public BoxedUnit apply(BspNotification bspNotification) {
126+
switch (bspNotification.getClass().getSimpleName()) {
127+
case "PublishDiagnostics": {
128+
PublishDiagnosticsParams params = ((PublishDiagnostics) bspNotification).params();
129+
130+
final String fileLocationWithoutFileProtocolPrefix = params.getTextDocument().getUri()
131+
.substring(FILE_PROTOCOL_PREFIX.length());
132+
final File file = Paths.get(fileLocationWithoutFileProtocolPrefix).toFile();
133+
final VirtualFile virtualFile = VfsUtils.resolveVirtualFile(file, false);
134+
params.getDiagnostics().stream()
135+
.filter(diagnostic -> diagnostic.getSeverity() == DiagnosticSeverity.ERROR)
136+
.map(diagnostic -> {
137+
final Position start = diagnostic.getRange().getStart();
138+
final Document document = FileDocumentManager.getInstance().getDocument(
139+
Objects.requireNonNull(virtualFile));
140+
final String lineWithError = Objects.requireNonNull(document)
141+
.getText(DocumentUtil.getLineTextRange(document, start.getLine()));
142+
final StatusOutput lineWithErrorStatusOutput = new StatusOutput(lineWithError);
143+
final StatusOutput locationStatusOutput = new StatusOutput(
144+
fileLocationWithoutFileProtocolPrefix + ":" + (start.getLine() + 1) + ":" + (
145+
start.getCharacter() + 1) + System.lineSeparator());
146+
final StatusOutput messageStatusOutput = new StatusOutput(diagnostic.getMessage());
147+
return Arrays.asList(lineWithErrorStatusOutput, locationStatusOutput, messageStatusOutput);
148+
}).forEach(statusOutputs -> statusOutputs.forEach(context::output));
149+
break;
150+
}
151+
case "TaskFinish": {
152+
TaskFinishParams params = ((TaskFinish) bspNotification).params();
153+
finishParams.add(params);
154+
break;
155+
}
156+
default: {
157+
/*
158+
LogMessage
159+
ShowMessage
160+
TaskStart
161+
TaskProgress
162+
DidChangeBuildTarget
163+
*/
164+
}
165+
}
166+
return BoxedUnit.UNIT;
167+
}
168+
169+
}
170+
171+
private static BoxedUnit log(String message) {
172+
logger.debug(message);
173+
return BoxedUnit.UNIT;
174+
}
175+
}

0 commit comments

Comments
 (0)