From 1fb466d9bd1446a2fc652ad44fd977dfa81d61ba Mon Sep 17 00:00:00 2001 From: Marc O'Morain Date: Tue, 30 Nov 2021 12:10:56 +0000 Subject: [PATCH] Improve leiningen project search I have a problem when I use Calva's Jack In command - I have to run to open my project.clj file in the root of the repo before I Jack In. If I run the command when I have any source files open in the editor, the Jack In fails. The reason for this is that Calva will search from the directory containing the current file down to the workspace root. There are many projects named `project.clj` in the main CircleCI repo, since a project one of our core domain objects: ``` marc@blaster ~/dev/circleci/circle $ find . -name project.clj ./project.clj ./src/circle/project.clj ./src/circle/http/api/v1/v1_0/project.clj ./src/circle/http/api/v1/v1_1/project.clj ./src/circle/http/api/v1/shared/project.clj ./src/circle/http/api/v2/insights/project.clj ./src/circle/http/api/v2/project.clj ./src/circle/http/api/v2/entities/insights/project.clj ./src/circle/http/api/v2/entities/project.clj ./src/circle/model/project.clj ./src/circle/model/api/project.clj ``` If I have any file open in `src/circle`, (which is the location of all source files), Calva will find `src/circle/project.clj` before it considers the project.clj in the root. As far as I understand, this is a desirable search behaviour, since it allows folks to use Calva in projects that contain multiple leiningen projects. This change alters the search behaviour to only consider files that don't begin with the string `(ns ` when attempting the determine the project path. Fixes #871 --- src/state.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/state.ts b/src/state.ts index ec4a2cbd2..f1184c7ec 100644 --- a/src/state.ts +++ b/src/state.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import Analytics from './analytics'; import * as util from './utilities'; +import * as filesCache from './files-cache' import * as path from 'path'; import * as os from 'os'; import * as fs from 'fs'; @@ -140,14 +141,20 @@ export async function initProjectDir(uri?: vscode.Uri): Promise { } } -async function findLocalProjectRoot(projectFileNames, doc, workspaceFolder): Promise { +function isNamespace(path: string): boolean { + const content = filesCache.content(path); + const hasNsDecl = /^\(ns /.test(content); + return hasNsDecl; +} + +async function findLocalProjectRoot(projectFileNames: string[], doc: vscode.TextDocument, workspaceFolder: vscode.WorkspaceFolder): Promise { if (workspaceFolder) { let rootPath: string = path.resolve(workspaceFolder.uri.fsPath); setStateValue(PROJECT_DIR_KEY, rootPath); setStateValue(PROJECT_DIR_URI_KEY, workspaceFolder.uri); - let d = null; - let prev = null; + let d: string = null; + let prev: string = null; if (doc && path.dirname(doc.uri.fsPath) !== '.') { d = path.dirname(doc.uri.fsPath); } else { @@ -156,7 +163,7 @@ async function findLocalProjectRoot(projectFileNames, doc, workspaceFolder): Pro while (d !== prev) { for (let projectFile in projectFileNames) { const p = path.resolve(d, projectFileNames[projectFile]); - if (fs.existsSync(p)) { + if (fs.existsSync(p) && !isNamespace(p)) { rootPath = d; break; } @@ -192,8 +199,10 @@ async function findProjectRootUri(projectFileNames, doc, workspaceFolder): Promi const u = vscode.Uri.joinPath(searchUri, projectFileNames[projectFile]); try { await vscode.workspace.fs.stat(u); - setStateValue(PROJECT_DIR_URI_KEY, searchUri); - return; + if (!isNamespace(u.fsPath)) { + setStateValue(PROJECT_DIR_URI_KEY, searchUri); + return; + } } catch { } }