From c04b704248987bb6728727df8f64d0e821f51efe Mon Sep 17 00:00:00 2001 From: Iwan Date: Thu, 19 Nov 2020 19:08:35 +0100 Subject: [PATCH 1/2] Tweak heuristics to find the project root. The project root means "this is a folder containing node_modules/bs-platform/{platform}/bsc.exe". This path needs to be correct because it drives the formatter. The previous heuristics seemed to fail in the case users where using yarn workspaces. Yarn workspaces seem to have the following layout: ``` /root /node_modules - package.json - yarn.lock /folder1 /node_modules - package.json - bsconfig.json ``` The compiler seems to be located in the `node_modules` under the root and not in the `node_modules` of `folder1`. By searching for `bscPartialPath` instead of the nearest `bsconfig.json`, we can correctly determine the root. --- server/src/server.ts | 2 +- server/src/utils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/server.ts b/server/src/server.ts index 8f1a09625..0cabc6e71 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -419,7 +419,7 @@ process.on("message", (msg: m.Message) => { if (projectRootPath == null) { let params: p.ShowMessageParams = { type: p.MessageType.Error, - message: `Cannot find a nearby ${c.bsconfigPartialPath}. It's needed for determining the project's root.`, + message: `Cannot find a nearby ${c.bscPartialPath}. It's needed for determining the project's root.`, }; let response: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, diff --git a/server/src/utils.ts b/server/src/utils.ts index e411abfe4..da6b4b30a 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -22,7 +22,7 @@ export let findProjectRootOfFile = ( source: p.DocumentUri ): null | p.DocumentUri => { let dir = path.dirname(source); - if (fs.existsSync(path.join(dir, c.bsconfigPartialPath))) { + if (fs.existsSync(path.join(dir, c.bscPartialPath))) { return dir; } else { if (dir === source) { From 57009e58644a662c0f938d665b18c101a7bfd98b Mon Sep 17 00:00:00 2001 From: Iwan Date: Thu, 19 Nov 2020 20:41:42 +0100 Subject: [PATCH 2/2] Split project from from build root. the "build root" represents the nearest directory containing a "bsconfig.json" file. "bsconfig.json" can be used to locate the nearest build artefacts and .compiler.log for diagnostics. --- server/src/server.ts | 28 ++++++++++++++-------------- server/src/utils.ts | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/server/src/server.ts b/server/src/server.ts index 0cabc6e71..708ec3270 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -126,33 +126,33 @@ let openedFile = (fileUri: string, fileContent: string) => { stupidFileContentCache.set(filePath, fileContent); - let projectRootPath = utils.findProjectRootOfFile(filePath); - if (projectRootPath != null) { - if (!projectsFiles.has(projectRootPath)) { - projectsFiles.set(projectRootPath, { + let buildRootPath = utils.findBuildRootOfFile(filePath); + if (buildRootPath != null) { + if (!projectsFiles.has(buildRootPath)) { + projectsFiles.set(buildRootPath, { openFiles: new Set(), filesWithDiagnostics: new Set(), bsbWatcherByEditor: null, }); compilerLogsWatcher.add( - path.join(projectRootPath, c.compilerLogPartialPath) + path.join(buildRootPath, c.compilerLogPartialPath) ); } - let root = projectsFiles.get(projectRootPath)!; + let root = projectsFiles.get(buildRootPath)!; root.openFiles.add(filePath); let firstOpenFileOfProject = root.openFiles.size === 1; // check if .bsb.lock is still there. If not, start a bsb -w ourselves // because otherwise the diagnostics info we'll display might be stale - let bsbLockPath = path.join(projectRootPath, c.bsbLock); + let bsbLockPath = path.join(buildRootPath, c.bsbLock); if (firstOpenFileOfProject && !fs.existsSync(bsbLockPath)) { - let bsbPath = path.join(projectRootPath, c.bsbPartialPath); + let bsbPath = path.join(buildRootPath, c.bsbPartialPath); // TODO: sometime stale .bsb.lock dangling. bsb -w knows .bsb.lock is // stale. Use that logic // TODO: close watcher when lang-server shuts down if (fs.existsSync(bsbPath)) { let payload: clientSentBuildAction = { title: c.startBuildAction, - projectRootPath: projectRootPath, + projectRootPath: buildRootPath, }; let params = { type: p.MessageType.Info, @@ -183,17 +183,17 @@ let closedFile = (fileUri: string) => { stupidFileContentCache.delete(filePath); - let projectRootPath = utils.findProjectRootOfFile(filePath); - if (projectRootPath != null) { - let root = projectsFiles.get(projectRootPath); + let buildRootPath = utils.findBuildRootOfFile(filePath); + if (buildRootPath != null) { + let root = projectsFiles.get(buildRootPath); if (root != null) { root.openFiles.delete(filePath); // clear diagnostics too if no open files open in said project if (root.openFiles.size === 0) { compilerLogsWatcher.unwatch( - path.join(projectRootPath, c.compilerLogPartialPath) + path.join(buildRootPath, c.compilerLogPartialPath) ); - deleteProjectDiagnostics(projectRootPath); + deleteProjectDiagnostics(buildRootPath); if (root.bsbWatcherByEditor !== null) { root.bsbWatcherByEditor.kill(); root.bsbWatcherByEditor = null; diff --git a/server/src/utils.ts b/server/src/utils.ts index da6b4b30a..7097a001d 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -34,6 +34,24 @@ export let findProjectRootOfFile = ( } }; +// the "build root" represents the nearest directory containing a "bsconfig.json" file. +// "bsconfig.json" can be used to locate the nearest build artefacts +export let findBuildRootOfFile = ( + source: p.DocumentUri +): null | p.DocumentUri => { + let dir = path.dirname(source); + if (fs.existsSync(path.join(dir, c.bsconfigPartialPath))) { + return dir; + } else { + if (dir === source) { + // reached top + return null; + } else { + return findBuildRootOfFile(dir); + } + } +}; + type execResult = | { kind: "success";