Skip to content

Commit 8d502ad

Browse files
authored
Use editor tooling distributed with compiler when supported (#1055)
* run analysis from compiler package if high enough version * run from appropriate bins also on the LS client * fix running reanalyze * changelog
1 parent 541b1e4 commit 8d502ad

File tree

8 files changed

+133
-40
lines changed

8 files changed

+133
-40
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#### :house: Internal
2020

2121
- Auto-format vendored OCaml sources like in compiler repo. https://github.com/rescript-lang/rescript-vscode/pull/1053
22+
- All OCaml sources in this repo is now considered "legacy", as the OCaml parts of the editor integration are now shipped with the compiler instead.
2223

2324
## 1.58.0
2425

client/src/commands/code_analysis.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
OutputChannel,
1515
StatusBarItem,
1616
} from "vscode";
17-
import { analysisProdPath, getAnalysisBinaryPath } from "../utils";
17+
import { findProjectRootOfFileInDir, getBinaryPath } from "../utils";
1818

1919
export let statusBarItem = {
2020
setToStopText: (codeAnalysisRunningStatusBarItem: StatusBarItem) => {
@@ -208,9 +208,19 @@ export const runCodeAnalysisWithReanalyze = (
208208
let currentDocument = window.activeTextEditor.document;
209209
let cwd = targetDir ?? path.dirname(currentDocument.uri.fsPath);
210210

211-
let binaryPath = getAnalysisBinaryPath();
211+
let projectRootPath: string | null = findProjectRootOfFileInDir(
212+
currentDocument.uri.fsPath
213+
);
214+
215+
// This little weird lookup is because in the legacy setup reanalyze needs to be
216+
// run from the analysis binary, whereas in the new setup it's run from the tools
217+
// binary.
218+
let binaryPath =
219+
getBinaryPath("rescript-tools.exe", projectRootPath) ??
220+
getBinaryPath("rescript-editor-analysis.exe");
221+
212222
if (binaryPath === null) {
213-
window.showErrorMessage("Binary executable not found.", analysisProdPath);
223+
window.showErrorMessage("Binary executable not found.");
214224
return;
215225
}
216226

client/src/commands/dump_debug.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import {
77
ViewColumn,
88
window,
99
} from "vscode";
10-
import { createFileInTempDir, getAnalysisBinaryPath } from "../utils";
10+
import {
11+
createFileInTempDir,
12+
findProjectRootOfFileInDir,
13+
getBinaryPath,
14+
} from "../utils";
1115
import * as path from "path";
1216

1317
// Maps to Cli.ml
@@ -132,7 +136,11 @@ export const dumpDebug = async (
132136
const { line: endLine, character: endChar } = editor.selection.end;
133137
const filePath = editor.document.uri.fsPath;
134138

135-
const binaryPath = getAnalysisBinaryPath();
139+
let projectRootPath: string | null = findProjectRootOfFileInDir(filePath);
140+
const binaryPath = getBinaryPath(
141+
"rescript-editor-analysis.exe",
142+
projectRootPath
143+
);
136144
if (binaryPath === null) {
137145
window.showErrorMessage("Binary executable not found.");
138146
return;

client/src/utils.ts

+59-21
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,50 @@
11
import * as path from "path";
22
import * as fs from "fs";
33
import * as os from "os";
4+
import { DocumentUri } from "vscode-languageclient";
5+
6+
/*
7+
* Much of the code in here is duplicated from the server code.
8+
* At some point we should move the functionality powered by this
9+
* to the server itself.
10+
*/
11+
12+
type binaryName = "rescript-editor-analysis.exe" | "rescript-tools.exe";
413

514
const platformDir =
615
process.arch === "arm64" ? process.platform + process.arch : process.platform;
716

8-
const analysisDevPath = path.join(
9-
path.dirname(__dirname),
10-
"..",
11-
"analysis",
12-
"rescript-editor-analysis.exe"
13-
);
14-
15-
export const analysisProdPath = path.join(
16-
path.dirname(__dirname),
17-
"..",
18-
"server",
19-
"analysis_binaries",
20-
platformDir,
21-
"rescript-editor-analysis.exe"
22-
);
23-
24-
export const getAnalysisBinaryPath = (): string | null => {
25-
if (fs.existsSync(analysisDevPath)) {
26-
return analysisDevPath;
27-
} else if (fs.existsSync(analysisProdPath)) {
28-
return analysisProdPath;
17+
const getLegacyBinaryDevPath = (b: binaryName) =>
18+
path.join(path.dirname(__dirname), "..", "analysis", b);
19+
20+
export const getLegacyBinaryProdPath = (b: binaryName) =>
21+
path.join(
22+
path.dirname(__dirname),
23+
"..",
24+
"server",
25+
"analysis_binaries",
26+
platformDir,
27+
b
28+
);
29+
30+
export const getBinaryPath = (
31+
binaryName: "rescript-editor-analysis.exe" | "rescript-tools.exe",
32+
projectRootPath: string | null = null
33+
): string | null => {
34+
const binaryFromCompilerPackage = path.join(
35+
projectRootPath ?? "",
36+
"node_modules",
37+
"rescript",
38+
platformDir,
39+
binaryName
40+
);
41+
42+
if (projectRootPath != null && fs.existsSync(binaryFromCompilerPackage)) {
43+
return binaryFromCompilerPackage;
44+
} else if (fs.existsSync(getLegacyBinaryDevPath(binaryName))) {
45+
return getLegacyBinaryDevPath(binaryName);
46+
} else if (fs.existsSync(getLegacyBinaryProdPath(binaryName))) {
47+
return getLegacyBinaryProdPath(binaryName);
2948
} else {
3049
return null;
3150
}
@@ -39,3 +58,22 @@ export const createFileInTempDir = (prefix = "", extension = "") => {
3958
tempFileId = tempFileId + 1;
4059
return path.join(os.tmpdir(), tempFileName);
4160
};
61+
62+
export let findProjectRootOfFileInDir = (
63+
source: DocumentUri
64+
): null | DocumentUri => {
65+
let dir = path.dirname(source);
66+
if (
67+
fs.existsSync(path.join(dir, "rescript.json")) ||
68+
fs.existsSync(path.join(dir, "bsconfig.json"))
69+
) {
70+
return dir;
71+
} else {
72+
if (dir === source) {
73+
// reached top
74+
return null;
75+
} else {
76+
return findProjectRootOfFileInDir(dir);
77+
}
78+
}
79+
};

server/src/constants.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,22 @@ export let jsonrpcVersion = "2.0";
1010
export let platformPath = path.join("rescript", platformDir);
1111
export let nodeModulesPlatformPath = path.join("node_modules", platformPath);
1212
export let bscExeName = "bsc.exe";
13+
export let editorAnalysisName = "rescript-editor-analysis.exe";
1314
export let bscNativeReScriptPartialPath = path.join(
1415
nodeModulesPlatformPath,
1516
bscExeName
1617
);
1718

18-
export let analysisDevPath = path.join(
19+
export let builtinAnalysisDevPath = path.join(
1920
path.dirname(__dirname),
2021
"..",
21-
"rescript-editor-analysis.exe"
22+
editorAnalysisName
2223
);
23-
export let analysisProdPath = path.join(
24+
export let builtinAnalysisProdPath = path.join(
2425
path.dirname(__dirname),
2526
"analysis_binaries",
2627
platformDir,
27-
"rescript-editor-analysis.exe"
28+
editorAnalysisName
2829
);
2930

3031
export let rescriptBinName = "rescript";

server/src/projectFiles.ts

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface projectFiles {
1111
filesDiagnostics: filesDiagnostics;
1212
rescriptVersion: string | undefined;
1313
bscBinaryLocation: string | null;
14+
editorAnalysisLocation: string | null;
1415
namespaceName: string | null;
1516

1617
bsbWatcherByEditor: null | cp.ChildProcess;

server/src/server.ts

+1
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ let openedFile = (fileUri: string, fileContent: string) => {
272272
rescriptVersion: utils.findReScriptVersion(projectRootPath),
273273
bsbWatcherByEditor: null,
274274
bscBinaryLocation: utils.findBscExeBinary(projectRootPath),
275+
editorAnalysisLocation: utils.findEditorAnalysisBinary(projectRootPath),
275276
hasPromptedToStartBuild: /(\/|\\)node_modules(\/|\\)/.test(
276277
projectRootPath
277278
)

server/src/utils.ts

+43-10
Original file line numberDiff line numberDiff line change
@@ -192,23 +192,19 @@ export let findReScriptVersion = (
192192
}
193193
};
194194

195-
let binaryPath: string | null = null;
196-
if (fs.existsSync(c.analysisDevPath)) {
197-
binaryPath = c.analysisDevPath;
198-
} else if (fs.existsSync(c.analysisProdPath)) {
199-
binaryPath = c.analysisProdPath;
200-
} else {
195+
// This is the path for the _builtin_ legacy analysis, that works for versions 11 and below.
196+
let builtinBinaryPath: string | null = null;
197+
if (fs.existsSync(c.builtinAnalysisDevPath)) {
198+
builtinBinaryPath = c.builtinAnalysisDevPath;
199+
} else if (fs.existsSync(c.builtinAnalysisProdPath)) {
200+
builtinBinaryPath = c.builtinAnalysisProdPath;
201201
}
202202

203203
export let runAnalysisAfterSanityCheck = (
204204
filePath: p.DocumentUri,
205205
args: Array<any>,
206206
projectRequired = false
207207
) => {
208-
if (binaryPath == null) {
209-
return null;
210-
}
211-
212208
let projectRootPath = findProjectRootOfFile(filePath);
213209
if (projectRootPath == null && projectRequired) {
214210
return null;
@@ -217,6 +213,35 @@ export let runAnalysisAfterSanityCheck = (
217213
projectsFiles.get(projectRootPath ?? "")?.rescriptVersion ??
218214
findReScriptVersion(filePath);
219215

216+
let binaryPath = builtinBinaryPath;
217+
218+
let project = projectRootPath ? projectsFiles.get(projectRootPath) : null;
219+
220+
/**
221+
* All versions including 12.0.0-alpha.5 and above should use the analysis binary
222+
* that now ships with the compiler. Previous versions use the legacy one we ship
223+
* with the extension itself.
224+
*/
225+
let shouldUseBuiltinAnalysis =
226+
rescriptVersion?.startsWith("9.") ||
227+
rescriptVersion?.startsWith("10.") ||
228+
rescriptVersion?.startsWith("11.") ||
229+
[
230+
"12.0.0-alpha.1",
231+
"12.0.0-alpha.2",
232+
"12.0.0-alpha.3",
233+
"12.0.0-alpha.4",
234+
].includes(rescriptVersion ?? "");
235+
236+
if (!shouldUseBuiltinAnalysis && project != null) {
237+
binaryPath = project.editorAnalysisLocation;
238+
} else if (!shouldUseBuiltinAnalysis && project == null) {
239+
// TODO: Warn user about broken state?
240+
return null;
241+
} else {
242+
binaryPath = builtinBinaryPath;
243+
}
244+
220245
let options: childProcess.ExecFileSyncOptions = {
221246
cwd: projectRootPath || undefined,
222247
maxBuffer: Infinity,
@@ -233,6 +258,11 @@ export let runAnalysisAfterSanityCheck = (
233258
: undefined,
234259
},
235260
};
261+
262+
if (binaryPath == null) {
263+
return null;
264+
}
265+
236266
let stdout = "";
237267
try {
238268
stdout = childProcess.execFileSync(binaryPath, args, options).toString();
@@ -737,3 +767,6 @@ let findPlatformPath = (projectRootPath: p.DocumentUri | null) => {
737767

738768
export let findBscExeBinary = (projectRootPath: p.DocumentUri | null) =>
739769
findBinary(findPlatformPath(projectRootPath), c.bscExeName);
770+
771+
export let findEditorAnalysisBinary = (projectRootPath: p.DocumentUri | null) =>
772+
findBinary(findPlatformPath(projectRootPath), c.editorAnalysisName);

0 commit comments

Comments
 (0)