From 3b57c41faf8eb3715d7f0d72699d3dd3fa0a59b5 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 11 Nov 2024 19:04:41 +0100 Subject: [PATCH 1/4] run analysis from compiler package if high enough version --- server/src/constants.ts | 9 ++++--- server/src/projectFiles.ts | 1 + server/src/server.ts | 1 + server/src/utils.ts | 53 +++++++++++++++++++++++++++++++------- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/server/src/constants.ts b/server/src/constants.ts index a08525523..fe569b1cd 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -10,21 +10,22 @@ export let jsonrpcVersion = "2.0"; export let platformPath = path.join("rescript", platformDir); export let nodeModulesPlatformPath = path.join("node_modules", platformPath); export let bscExeName = "bsc.exe"; +export let editorAnalysisName = "rescript-editor-analysis.exe"; export let bscNativeReScriptPartialPath = path.join( nodeModulesPlatformPath, bscExeName ); -export let analysisDevPath = path.join( +export let builtinAnalysisDevPath = path.join( path.dirname(__dirname), "..", - "rescript-editor-analysis.exe" + editorAnalysisName ); -export let analysisProdPath = path.join( +export let builtinAnalysisProdPath = path.join( path.dirname(__dirname), "analysis_binaries", platformDir, - "rescript-editor-analysis.exe" + editorAnalysisName ); export let rescriptBinName = "rescript"; diff --git a/server/src/projectFiles.ts b/server/src/projectFiles.ts index 5520a479b..4a1787a0c 100644 --- a/server/src/projectFiles.ts +++ b/server/src/projectFiles.ts @@ -11,6 +11,7 @@ interface projectFiles { filesDiagnostics: filesDiagnostics; rescriptVersion: string | undefined; bscBinaryLocation: string | null; + editorAnalysisLocation: string | null; namespaceName: string | null; bsbWatcherByEditor: null | cp.ChildProcess; diff --git a/server/src/server.ts b/server/src/server.ts index c7e0cf2c0..f41c13219 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -272,6 +272,7 @@ let openedFile = (fileUri: string, fileContent: string) => { rescriptVersion: utils.findReScriptVersion(projectRootPath), bsbWatcherByEditor: null, bscBinaryLocation: utils.findBscExeBinary(projectRootPath), + editorAnalysisLocation: utils.findEditorAnalysisBinary(projectRootPath), hasPromptedToStartBuild: /(\/|\\)node_modules(\/|\\)/.test( projectRootPath ) diff --git a/server/src/utils.ts b/server/src/utils.ts index 0b8d3ef3d..6f386cc83 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -192,12 +192,12 @@ export let findReScriptVersion = ( } }; -let binaryPath: string | null = null; -if (fs.existsSync(c.analysisDevPath)) { - binaryPath = c.analysisDevPath; -} else if (fs.existsSync(c.analysisProdPath)) { - binaryPath = c.analysisProdPath; -} else { +// This is the path for the _builtin_ legacy analysis, that works for versions 11 and below. +let builtinBinaryPath: string | null = null; +if (fs.existsSync(c.builtinAnalysisDevPath)) { + builtinBinaryPath = c.builtinAnalysisDevPath; +} else if (fs.existsSync(c.builtinAnalysisProdPath)) { + builtinBinaryPath = c.builtinAnalysisProdPath; } export let runAnalysisAfterSanityCheck = ( @@ -205,10 +205,6 @@ export let runAnalysisAfterSanityCheck = ( args: Array, projectRequired = false ) => { - if (binaryPath == null) { - return null; - } - let projectRootPath = findProjectRootOfFile(filePath); if (projectRootPath == null && projectRequired) { return null; @@ -217,6 +213,35 @@ export let runAnalysisAfterSanityCheck = ( projectsFiles.get(projectRootPath ?? "")?.rescriptVersion ?? findReScriptVersion(filePath); + let binaryPath = builtinBinaryPath; + + let project = projectRootPath ? projectsFiles.get(projectRootPath) : null; + + /** + * All versions including 12.0.0-alpha.5 and above should use the analysis binary + * that now ships with the compiler. Previous versions use the legacy one we ship + * with the extension itself. + */ + let shouldUseBuiltinAnalysis = + rescriptVersion?.startsWith("9.") || + rescriptVersion?.startsWith("10.") || + rescriptVersion?.startsWith("11.") || + [ + "12.0.0-alpha.1", + "12.0.0-alpha.2", + "12.0.0-alpha.3", + "12.0.0-alpha.4", + ].includes(rescriptVersion ?? ""); + + if (!shouldUseBuiltinAnalysis && project != null) { + binaryPath = project.editorAnalysisLocation; + } else if (!shouldUseBuiltinAnalysis && project == null) { + // TODO: Warn user about broken state? + return null; + } else { + binaryPath = builtinBinaryPath; + } + let options: childProcess.ExecFileSyncOptions = { cwd: projectRootPath || undefined, maxBuffer: Infinity, @@ -233,6 +258,11 @@ export let runAnalysisAfterSanityCheck = ( : undefined, }, }; + + if (binaryPath == null) { + return null; + } + let stdout = ""; try { stdout = childProcess.execFileSync(binaryPath, args, options).toString(); @@ -737,3 +767,6 @@ let findPlatformPath = (projectRootPath: p.DocumentUri | null) => { export let findBscExeBinary = (projectRootPath: p.DocumentUri | null) => findBinary(findPlatformPath(projectRootPath), c.bscExeName); + +export let findEditorAnalysisBinary = (projectRootPath: p.DocumentUri | null) => + findBinary(findPlatformPath(projectRootPath), c.editorAnalysisName); From 0131b59abb5ea79dc8afc15b8d33a07c6774b931 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 11 Nov 2024 19:43:51 +0100 Subject: [PATCH 2/4] run from appropriate bins also on the LS client --- client/src/commands/code_analysis.ts | 9 ++-- client/src/commands/dump_debug.ts | 12 ++++- client/src/utils.ts | 80 ++++++++++++++++++++-------- 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/client/src/commands/code_analysis.ts b/client/src/commands/code_analysis.ts index 322844d33..7a8c1f7eb 100644 --- a/client/src/commands/code_analysis.ts +++ b/client/src/commands/code_analysis.ts @@ -14,7 +14,7 @@ import { OutputChannel, StatusBarItem, } from "vscode"; -import { analysisProdPath, getAnalysisBinaryPath } from "../utils"; +import { findProjectRootOfFileInDir, getBinaryPath } from "../utils"; export let statusBarItem = { setToStopText: (codeAnalysisRunningStatusBarItem: StatusBarItem) => { @@ -208,9 +208,12 @@ export const runCodeAnalysisWithReanalyze = ( let currentDocument = window.activeTextEditor.document; let cwd = targetDir ?? path.dirname(currentDocument.uri.fsPath); - let binaryPath = getAnalysisBinaryPath(); + let projectRootPath: string | null = findProjectRootOfFileInDir( + currentDocument.uri.fsPath + ); + let binaryPath = getBinaryPath("rescript-tools.exe", projectRootPath); if (binaryPath === null) { - window.showErrorMessage("Binary executable not found.", analysisProdPath); + window.showErrorMessage("Binary executable not found."); return; } diff --git a/client/src/commands/dump_debug.ts b/client/src/commands/dump_debug.ts index ff1e3cbd0..168d87a22 100644 --- a/client/src/commands/dump_debug.ts +++ b/client/src/commands/dump_debug.ts @@ -7,7 +7,11 @@ import { ViewColumn, window, } from "vscode"; -import { createFileInTempDir, getAnalysisBinaryPath } from "../utils"; +import { + createFileInTempDir, + findProjectRootOfFileInDir, + getBinaryPath, +} from "../utils"; import * as path from "path"; // Maps to Cli.ml @@ -132,7 +136,11 @@ export const dumpDebug = async ( const { line: endLine, character: endChar } = editor.selection.end; const filePath = editor.document.uri.fsPath; - const binaryPath = getAnalysisBinaryPath(); + let projectRootPath: string | null = findProjectRootOfFileInDir(filePath); + const binaryPath = getBinaryPath( + "rescript-editor-analysis.exe", + projectRootPath + ); if (binaryPath === null) { window.showErrorMessage("Binary executable not found."); return; diff --git a/client/src/utils.ts b/client/src/utils.ts index 0c6ba3ea7..4857045e4 100644 --- a/client/src/utils.ts +++ b/client/src/utils.ts @@ -1,31 +1,50 @@ import * as path from "path"; import * as fs from "fs"; import * as os from "os"; +import { DocumentUri } from "vscode-languageclient"; + +/* + * Much of the code in here is duplicated from the server code. + * At some point we should move the functionality powered by this + * to the server itself. + */ + +type binaryName = "rescript-editor-analysis.exe" | "rescript-tools.exe"; const platformDir = process.arch === "arm64" ? process.platform + process.arch : process.platform; -const analysisDevPath = path.join( - path.dirname(__dirname), - "..", - "analysis", - "rescript-editor-analysis.exe" -); - -export const analysisProdPath = path.join( - path.dirname(__dirname), - "..", - "server", - "analysis_binaries", - platformDir, - "rescript-editor-analysis.exe" -); - -export const getAnalysisBinaryPath = (): string | null => { - if (fs.existsSync(analysisDevPath)) { - return analysisDevPath; - } else if (fs.existsSync(analysisProdPath)) { - return analysisProdPath; +const getLegacyBinaryDevPath = (b: binaryName) => + path.join(path.dirname(__dirname), "..", "analysis", b); + +export const getLegacyBinaryProdPath = (b: binaryName) => + path.join( + path.dirname(__dirname), + "..", + "server", + "analysis_binaries", + platformDir, + b + ); + +export const getBinaryPath = ( + binaryName: "rescript-editor-analysis.exe" | "rescript-tools.exe", + projectRootPath: string +): string | null => { + const binaryFromCompilerPackage = path.join( + projectRootPath, + "node_modules", + "rescript", + platformDir, + binaryName + ); + + if (fs.existsSync(binaryFromCompilerPackage)) { + return binaryFromCompilerPackage; + } else if (fs.existsSync(getLegacyBinaryDevPath(binaryName))) { + return getLegacyBinaryDevPath(binaryName); + } else if (fs.existsSync(getLegacyBinaryProdPath(binaryName))) { + return getLegacyBinaryProdPath(binaryName); } else { return null; } @@ -39,3 +58,22 @@ export const createFileInTempDir = (prefix = "", extension = "") => { tempFileId = tempFileId + 1; return path.join(os.tmpdir(), tempFileName); }; + +export let findProjectRootOfFileInDir = ( + source: DocumentUri +): null | DocumentUri => { + let dir = path.dirname(source); + if ( + fs.existsSync(path.join(dir, "rescript.json")) || + fs.existsSync(path.join(dir, "bsconfig.json")) + ) { + return dir; + } else { + if (dir === source) { + // reached top + return null; + } else { + return findProjectRootOfFileInDir(dir); + } + } +}; From 6938b339ab7cd39ba6202c69a9add3c7db27679f Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 11 Nov 2024 20:15:53 +0100 Subject: [PATCH 3/4] fix running reanalyze --- client/src/commands/code_analysis.ts | 9 ++++++++- client/src/utils.ts | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/client/src/commands/code_analysis.ts b/client/src/commands/code_analysis.ts index 7a8c1f7eb..d8eeaec20 100644 --- a/client/src/commands/code_analysis.ts +++ b/client/src/commands/code_analysis.ts @@ -211,7 +211,14 @@ export const runCodeAnalysisWithReanalyze = ( let projectRootPath: string | null = findProjectRootOfFileInDir( currentDocument.uri.fsPath ); - let binaryPath = getBinaryPath("rescript-tools.exe", projectRootPath); + + // This little weird lookup is because in the legacy setup reanalyze needs to be + // run from the analysis binary, whereas in the new setup it's run from the tools + // binary. + let binaryPath = + getBinaryPath("rescript-tools.exe", projectRootPath) ?? + getBinaryPath("rescript-editor-analysis.exe"); + if (binaryPath === null) { window.showErrorMessage("Binary executable not found."); return; diff --git a/client/src/utils.ts b/client/src/utils.ts index 4857045e4..397c1a593 100644 --- a/client/src/utils.ts +++ b/client/src/utils.ts @@ -29,17 +29,17 @@ export const getLegacyBinaryProdPath = (b: binaryName) => export const getBinaryPath = ( binaryName: "rescript-editor-analysis.exe" | "rescript-tools.exe", - projectRootPath: string + projectRootPath: string | null = null ): string | null => { const binaryFromCompilerPackage = path.join( - projectRootPath, + projectRootPath ?? "", "node_modules", "rescript", platformDir, binaryName ); - if (fs.existsSync(binaryFromCompilerPackage)) { + if (projectRootPath != null && fs.existsSync(binaryFromCompilerPackage)) { return binaryFromCompilerPackage; } else if (fs.existsSync(getLegacyBinaryDevPath(binaryName))) { return getLegacyBinaryDevPath(binaryName); From a47ca672858eab82b35e5ef71eab2e583f5d5db4 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 12 Nov 2024 15:23:41 +0100 Subject: [PATCH 4/4] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f528e2f0..84b2353f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ #### :house: Internal - Auto-format vendored OCaml sources like in compiler repo. https://github.com/rescript-lang/rescript-vscode/pull/1053 +- 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. ## 1.58.0