From a2307ad75429ce20cdc20becd2016f8f8e5c1180 Mon Sep 17 00:00:00 2001 From: Christian Kohler Date: Fri, 11 Feb 2022 17:20:18 +0100 Subject: [PATCH] feat(baseUrl): add extended support - reads subfolder of baseurl and adds them as mappings Fixes #196 --- README.md | 13 +- src/configuration/configuration.interface.ts | 6 +- src/configuration/configuration.service.ts | 8 +- src/configuration/tsconfig.service.ts | 188 +++++++++++++++--- src/extension.ts | 2 +- .../javascript/javascript.provider.ts | 22 +- src/test/demo-workspace/demo.code-workspace | 8 +- src/test/demo-workspace/project-one/index.js | 2 +- .../otherfolder/fileInOtherFolder.js | 0 .../otherfolder/othersubfolder/.gitkeep | 0 .../demo-workspace/project-one/tsconfig.json | 4 +- .../project-two/folderInTwo/.gitkeep | 0 .../demo-workspace/project-two/tsconfig.json | 2 +- .../project-withBaseUrlRoot/index.js | 1 + .../myfolder/fileInFolder.js | 2 + .../myfolder/otherfile.js | 0 .../project-withBaseUrlRoot/myservice.js | 0 .../otherfolder/fileInOtherFolder.js | 0 .../project-withBaseUrlRoot/tsconfig.json | 5 + .../project-withBaseUrlRoot2/src/bar/index.js | 2 + .../src/foo/foo-a/foo-a1/.gitkeep | 0 .../src/foo/foo-a/foo-a2/.gitkeep | 0 .../src/foo/foo-b/.gitkeep | 0 .../project-withBaseUrlRoot2/tsconfig.json | 5 + src/test/suite/baseUrl.test.ts | 63 ++++++ src/test/suite/configuration.service.test.ts | 28 ++- src/utils/file-utills.ts | 54 +++-- 27 files changed, 342 insertions(+), 73 deletions(-) create mode 100644 src/test/demo-workspace/project-one/otherfolder/fileInOtherFolder.js create mode 100644 src/test/demo-workspace/project-one/otherfolder/othersubfolder/.gitkeep create mode 100644 src/test/demo-workspace/project-two/folderInTwo/.gitkeep create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot/index.js create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot/myfolder/fileInFolder.js create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot/myfolder/otherfile.js create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot/myservice.js create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot/otherfolder/fileInOtherFolder.js create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot/tsconfig.json create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot2/src/bar/index.js create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-a/foo-a1/.gitkeep create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-a/foo-a2/.gitkeep create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-b/.gitkeep create mode 100644 src/test/demo-workspace/project-withBaseUrlRoot2/tsconfig.json create mode 100644 src/test/suite/baseUrl.test.ts diff --git a/README.md b/README.md index 86f23f7..f9c4bef 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,18 @@ Pathintellisense uses the ts.config.compilerOptions.baseUrl as a mapping. So no For example: +```markdown +# Folderstructure + +src/ +module-a +foo.ts +module-b +``` + ```javascript +// tsconfig + { "baseUrl": "src", } @@ -71,7 +82,7 @@ would allow to type: ```javascript { - import {} from "src/mymodule"; + import {} from "module-a/foo.ts"; } ``` diff --git a/src/configuration/configuration.interface.ts b/src/configuration/configuration.interface.ts index 3937510..baf698c 100644 --- a/src/configuration/configuration.interface.ts +++ b/src/configuration/configuration.interface.ts @@ -7,7 +7,11 @@ export interface Config { absolutePathToWorkspace: boolean; absolutePathTo: string | null; showOnAbsoluteSlash: boolean; - filesExclude: { [key: string]: string }; + filesExclude: FilesExclude; +} + +export interface FilesExclude { + [key: string]: string; } export interface Mapping { diff --git a/src/configuration/configuration.service.ts b/src/configuration/configuration.service.ts index 50739b6..36fec33 100644 --- a/src/configuration/configuration.service.ts +++ b/src/configuration/configuration.service.ts @@ -38,9 +38,15 @@ async function getMappings( ): Promise { const mappings = parseMappings(configuration["mappings"]); const ignoreTsConfigBaseUrl = configuration["ignoreTsConfigBaseUrl"]; + const showHiddenFiles = configuration["showHiddenFiles"]; + const filesExclude = configuration["exclude"]; const tsConfigMappings = await (ignoreTsConfigBaseUrl ? [] - : getWorkfolderTsConfigConfiguration(workfolder)); + : getWorkfolderTsConfigConfiguration( + workfolder, + showHiddenFiles, + filesExclude + )); const allMappings = [...mappings, ...tsConfigMappings]; return replaceWorkspaceFolder(allMappings, workfolder); } diff --git a/src/configuration/tsconfig.service.ts b/src/configuration/tsconfig.service.ts index ff9e64b..463e35b 100644 --- a/src/configuration/tsconfig.service.ts +++ b/src/configuration/tsconfig.service.ts @@ -1,22 +1,26 @@ import * as vscode from "vscode"; import * as JSON5 from "json5"; -import { Mapping } from "./configuration.interface"; +import { FilesExclude, Mapping } from "./configuration.interface"; +import { join } from "path"; +import { getChildrenOfPath } from "../utils/file-utills"; export const getWorkfolderTsConfigConfiguration = memoize(async function ( - workfolder: vscode.WorkspaceFolder + workfolder: vscode.WorkspaceFolder, + showHiddenFiles: boolean, + filesExclude: FilesExclude ): Promise { - const include = new vscode.RelativePattern(workfolder, "[tj]sconfig.json"); - const exclude = new vscode.RelativePattern(workfolder, "**/node_modules/**"); - const files = await vscode.workspace.findFiles(include, exclude); + const parsedFiles = await findTsConfigFiles(workfolder); let mappings: Mapping[] = []; - for (const file of files) { + for (const parsedFile of parsedFiles) { try { - const fileUri = vscode.Uri.file(file.fsPath); - const fileContents = await vscode.workspace.fs.readFile(fileUri); - const parsedFile = JSON5.parse(fileContents.toString()); - const newMappings = createMappingsFromWorkspaceConfig(parsedFile); + const newMappings = await createMappingsFromWorkspaceConfig( + parsedFile, + workfolder, + showHiddenFiles, + filesExclude + ); mappings.push(...newMappings); } catch {} } @@ -24,45 +28,169 @@ export const getWorkfolderTsConfigConfiguration = memoize(async function ( return mappings; }); -export function subscribeToTsConfigChanges(): vscode.Disposable[] { - const disposables: vscode.Disposable[] = []; +export async function subscribeToTsConfigChanges( + context: vscode.ExtensionContext +) { for (const workfolder of vscode.workspace.workspaceFolders || []) { + /** + * Invalidate Cache when tsconfig changes + */ + let baseUrlWatchers = await subscribeToBaseUrlFolderChanges(workfolder); + context.subscriptions.push(...baseUrlWatchers); + + /** + * Invalidate Cache when tsconfig changes + */ const pattern = new vscode.RelativePattern(workfolder, "[tj]sconfig.json"); const fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); - fileWatcher.onDidChange(() => invalidateCache(workfolder)); - disposables.push(fileWatcher); + fileWatcher.onDidChange(async () => { + invalidateCache(workfolder); + + // Throw away old base url subscriptions... + for (const disposable of baseUrlWatchers) { + disposable.dispose(); + } + + // .. and create new subscriptions + baseUrlWatchers = await subscribeToBaseUrlFolderChanges(workfolder); + context.subscriptions.push(...baseUrlWatchers); + }); + + context.subscriptions.push(fileWatcher); } +} + +/** + * Invalidate Cache when tsconfig changes + */ +async function subscribeToBaseUrlFolderChanges( + workfolder: vscode.WorkspaceFolder +): Promise { + const disposables = []; + + const tsConfigs = await findTsConfigFiles(workfolder); + + for (const tsconfig of tsConfigs) { + const baseUrl = tsconfig?.compilerOptions?.baseUrl; + + if (!baseUrl) { + continue; + } + + const patternBaseUrl = new vscode.RelativePattern( + join(workfolder.uri.fsPath, baseUrl), + "*" + ); + const fileWatcherBaseUrl = vscode.workspace.createFileSystemWatcher( + patternBaseUrl, + false, + true, + false + ); + + fileWatcherBaseUrl.onDidCreate((file) => + invalidateCacheIfDirectory(file, workfolder) + ); + fileWatcherBaseUrl.onDidDelete((file) => + invalidateCacheIfDirectory(file, workfolder) + ); + disposables.push(fileWatcherBaseUrl); + } + return disposables; } -function createMappingsFromWorkspaceConfig(tsconfig: { - compilerOptions: { baseUrl: string }; -}): Mapping[] { +async function invalidateCacheIfDirectory( + file: vscode.Uri, + workdfolder: vscode.WorkspaceFolder +) { + const fileStat = await vscode.workspace.fs.stat(file); + if (fileStat.type === vscode.FileType.Directory) { + invalidateCache(workdfolder); + } +} + +async function findTsConfigFiles(workfolder: vscode.WorkspaceFolder) { + const include = new vscode.RelativePattern(workfolder, "[tj]sconfig.json"); + const exclude = new vscode.RelativePattern(workfolder, "**/node_modules/**"); + const files = await vscode.workspace.findFiles(include, exclude); + + const parsedFiles = []; + + for (const file of files) { + try { + const fileUri = vscode.Uri.file(file.fsPath); + const fileContents = await vscode.workspace.fs.readFile(fileUri); + const parsedFile = JSON5.parse(fileContents.toString()); + parsedFiles.push(parsedFile); + } catch {} + } + + return parsedFiles; +} + +async function createMappingsFromWorkspaceConfig( + tsconfig: { + compilerOptions: { baseUrl: string }; + }, + workfolder: vscode.WorkspaceFolder, + showHiddenFiles: boolean, + filesExclude: FilesExclude +): Promise { const mappings: Mapping[] = []; const baseUrl = tsconfig?.compilerOptions?.baseUrl; - if (baseUrl) { - mappings.push({ - key: baseUrl, - // value: `${workfolder.uri.path}/${baseUrl}` - value: "${workspaceFolder}/" + baseUrl, - }); + if (baseUrl && workfolder) { + const foldersInBaseUrl = await getFoldersInBaseUrl( + workfolder, + baseUrl, + showHiddenFiles, + filesExclude + ); + + for (const folderInBaseUrl of foldersInBaseUrl) { + mappings.push({ + key: folderInBaseUrl, + // value: `${workfolder.uri.path}/${baseUrl}` + value: "${workspaceFolder}/" + baseUrl + "/" + folderInBaseUrl, + }); + } } - // Todo: paths property - return mappings; } +async function getFoldersInBaseUrl( + workfolder: vscode.WorkspaceFolder, + baseUrl: string, + showHiddenFiles: boolean, + filesExclude: FilesExclude +) { + const allFiles = await getChildrenOfPath( + join(workfolder.uri.fsPath, baseUrl), + showHiddenFiles, + filesExclude + ); + + const folders = allFiles.filter((file) => !file.isFile); + return folders.map((folder) => folder.file); +} + /** Caching */ let cachedMappings = new Map(); function memoize( - fn: (workfolder: vscode.WorkspaceFolder) => Promise + fn: ( + workfolder: vscode.WorkspaceFolder, + showHiddenFiles: boolean, + filesExclude: FilesExclude + ) => Promise ) { async function cachedFunction( - workfolder?: vscode.WorkspaceFolder + workfolder?: vscode.WorkspaceFolder, + showHiddenFiles?: boolean, + filesExclude?: FilesExclude ): Promise { if (!workfolder) { return Promise.resolve([]); @@ -74,7 +202,11 @@ function memoize( if (cachedMapping) { return cachedMapping; } else { - let result = await fn(workfolder); + let result = await fn( + workfolder, + showHiddenFiles || false, + filesExclude || {} + ); cachedMappings.set(key, result); return result; } diff --git a/src/extension.ts b/src/extension.ts index fe8465e..e56ba70 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -10,7 +10,7 @@ export function activate(context: ExtensionContext) { /** * Subscribe to the ts config changes */ - context.subscriptions.push(...subscribeToTsConfigChanges()); + subscribeToTsConfigChanges(context); /** * Register Providers diff --git a/src/providers/javascript/javascript.provider.ts b/src/providers/javascript/javascript.provider.ts index 2d9c39c..bb74f12 100644 --- a/src/providers/javascript/javascript.provider.ts +++ b/src/providers/javascript/javascript.provider.ts @@ -55,10 +55,11 @@ function shouldProvide(context: Context, config: Config): boolean { fromString.startsWith(key) ); - return isImport && ( - startsWithDot - || startsWithMapping - || (startsWithSlash && config.showOnAbsoluteSlash) + return ( + isImport && + (startsWithDot || + startsWithMapping || + (startsWithSlash && config.showOnAbsoluteSlash)) ); } @@ -71,10 +72,9 @@ async function provide( ): Promise { const workspace = vscode.workspace.getWorkspaceFolder(context.document.uri); - - const rootPath = config.absolutePathTo||(config.absolutePathToWorkspace - ? workspace?.uri.fsPath - : undefined); + const rootPath = + config.absolutePathTo || + (config.absolutePathToWorkspace ? workspace?.uri.fsPath : undefined); const path = getPathOfFolderToLookupFiles( context.document.uri.fsPath, @@ -83,7 +83,11 @@ async function provide( config.mappings ); - const childrenOfPath = await getChildrenOfPath(path, config); + const childrenOfPath = await getChildrenOfPath( + path, + config.showHiddenFiles, + config.filesExclude + ); return [ ...childrenOfPath.map((child) => diff --git a/src/test/demo-workspace/demo.code-workspace b/src/test/demo-workspace/demo.code-workspace index 0e9a2d7..ef448d7 100644 --- a/src/test/demo-workspace/demo.code-workspace +++ b/src/test/demo-workspace/demo.code-workspace @@ -12,9 +12,15 @@ { "path": "project-three-absolute-changes" }, + { + "path": "project-withBaseUrlRoot" + }, + { + "path": "project-withBaseUrlRoot2" + } ], "settings": { "typescript.suggest.paths": false, - "javascript.suggest.paths": false, + "javascript.suggest.paths": false } } diff --git a/src/test/demo-workspace/project-one/index.js b/src/test/demo-workspace/project-one/index.js index 7aa67d7..a0b9958 100644 --- a/src/test/demo-workspace/project-one/index.js +++ b/src/test/demo-workspace/project-one/index.js @@ -1 +1 @@ -import {} from "./"; +import {} from "./"; \ No newline at end of file diff --git a/src/test/demo-workspace/project-one/otherfolder/fileInOtherFolder.js b/src/test/demo-workspace/project-one/otherfolder/fileInOtherFolder.js new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-one/otherfolder/othersubfolder/.gitkeep b/src/test/demo-workspace/project-one/otherfolder/othersubfolder/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-one/tsconfig.json b/src/test/demo-workspace/project-one/tsconfig.json index 70fc856..e4463e4 100644 --- a/src/test/demo-workspace/project-one/tsconfig.json +++ b/src/test/demo-workspace/project-one/tsconfig.json @@ -1,5 +1,5 @@ { "compilerOptions": { - "baseUrl": "baseurl-one" + "baseUrl": "myfolder" } -} \ No newline at end of file +} diff --git a/src/test/demo-workspace/project-two/folderInTwo/.gitkeep b/src/test/demo-workspace/project-two/folderInTwo/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-two/tsconfig.json b/src/test/demo-workspace/project-two/tsconfig.json index 619e551..187548b 100644 --- a/src/test/demo-workspace/project-two/tsconfig.json +++ b/src/test/demo-workspace/project-two/tsconfig.json @@ -1,5 +1,5 @@ { "compilerOptions": { - "baseUrl": "baseurl-two" + "baseUrl": "./" } } diff --git a/src/test/demo-workspace/project-withBaseUrlRoot/index.js b/src/test/demo-workspace/project-withBaseUrlRoot/index.js new file mode 100644 index 0000000..a0b9958 --- /dev/null +++ b/src/test/demo-workspace/project-withBaseUrlRoot/index.js @@ -0,0 +1 @@ +import {} from "./"; \ No newline at end of file diff --git a/src/test/demo-workspace/project-withBaseUrlRoot/myfolder/fileInFolder.js b/src/test/demo-workspace/project-withBaseUrlRoot/myfolder/fileInFolder.js new file mode 100644 index 0000000..a83cad2 --- /dev/null +++ b/src/test/demo-workspace/project-withBaseUrlRoot/myfolder/fileInFolder.js @@ -0,0 +1,2 @@ +import { } from "./"; +import { } from "otherfolder/"; \ No newline at end of file diff --git a/src/test/demo-workspace/project-withBaseUrlRoot/myfolder/otherfile.js b/src/test/demo-workspace/project-withBaseUrlRoot/myfolder/otherfile.js new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-withBaseUrlRoot/myservice.js b/src/test/demo-workspace/project-withBaseUrlRoot/myservice.js new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-withBaseUrlRoot/otherfolder/fileInOtherFolder.js b/src/test/demo-workspace/project-withBaseUrlRoot/otherfolder/fileInOtherFolder.js new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-withBaseUrlRoot/tsconfig.json b/src/test/demo-workspace/project-withBaseUrlRoot/tsconfig.json new file mode 100644 index 0000000..3b2c1a3 --- /dev/null +++ b/src/test/demo-workspace/project-withBaseUrlRoot/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "baseUrl": "./" + } +} \ No newline at end of file diff --git a/src/test/demo-workspace/project-withBaseUrlRoot2/src/bar/index.js b/src/test/demo-workspace/project-withBaseUrlRoot2/src/bar/index.js new file mode 100644 index 0000000..7e68e7d --- /dev/null +++ b/src/test/demo-workspace/project-withBaseUrlRoot2/src/bar/index.js @@ -0,0 +1,2 @@ +import { } from "foo/"; +import { } from "foo/foo-a/"; \ No newline at end of file diff --git a/src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-a/foo-a1/.gitkeep b/src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-a/foo-a1/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-a/foo-a2/.gitkeep b/src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-a/foo-a2/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-b/.gitkeep b/src/test/demo-workspace/project-withBaseUrlRoot2/src/foo/foo-b/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/test/demo-workspace/project-withBaseUrlRoot2/tsconfig.json b/src/test/demo-workspace/project-withBaseUrlRoot2/tsconfig.json new file mode 100644 index 0000000..ec2332e --- /dev/null +++ b/src/test/demo-workspace/project-withBaseUrlRoot2/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "baseUrl": "src" + } +} diff --git a/src/test/suite/baseUrl.test.ts b/src/test/suite/baseUrl.test.ts new file mode 100644 index 0000000..0e144e0 --- /dev/null +++ b/src/test/suite/baseUrl.test.ts @@ -0,0 +1,63 @@ +import * as assert from "assert"; +import * as vscode from "vscode"; +import { beforeEach, afterEach } from "mocha"; +import { getFileUri } from "../utils/open-document"; +import { setConfig, setDefaults } from "../utils/set-config"; + +suite("BaseUrl", () => { + beforeEach(async () => { + await setDefaults(); + }); + + afterEach(async () => { + await setDefaults(); + }); + + suite("with baseUrl ./", () => { + const project = "demo-workspace/project-withBaseUrlRoot"; + const fileInFolder = `${project}/myfolder/fileInFolder.js`; + + test("Get correct file when not using baseUrl", async () => { + await setConfig("ignoreTsConfigBaseUrl", false); + const result = await triggerCompletion(fileInFolder, 0, 20); + assert.ok(hasItem(result, "otherfile.js")); + }); + + test("Get correct file when using baseUrl", async () => { + await setConfig("ignoreTsConfigBaseUrl", false); + const result = await triggerCompletion(fileInFolder, 1, 30); + assert.ok(hasItem(result, "fileInOtherFolder.js")); + }); + }); + + suite("with baseUrl src", () => { + const project = "demo-workspace/project-withBaseUrlRoot2"; + const fileInBar = `${project}/src/bar/index.js`; + + test("Get correct file when using baseUrl", async () => { + await setConfig("ignoreTsConfigBaseUrl", false); + const result = await triggerCompletion(fileInBar, 0, 22); + assert.ok(hasItem(result, "foo-a")); + assert.ok(hasItem(result, "foo-b")); + }); + + test("Get correct file when using baseUrl in subfolders", async () => { + await setConfig("ignoreTsConfigBaseUrl", false); + const result = await triggerCompletion(fileInBar, 1, 28); + assert.ok(hasItem(result, "foo-a1")); + assert.ok(hasItem(result, "foo-a2")); + }); + }); +}); + +async function triggerCompletion(uri: string, line: number, column: number) { + return (await vscode.commands.executeCommand( + "vscode.executeCompletionItemProvider", + getFileUri(uri), + new vscode.Position(line, column) + )) as vscode.CompletionList; +} + +function hasItem(list: vscode.CompletionList, label: string) { + return list.items.some((item) => item.label === label); +} diff --git a/src/test/suite/configuration.service.test.ts b/src/test/suite/configuration.service.test.ts index 0145d0a..d3a9bda 100644 --- a/src/test/suite/configuration.service.test.ts +++ b/src/test/suite/configuration.service.test.ts @@ -17,7 +17,9 @@ suite("Configuration Service", () => { }); test("has different configuration for the workspaceFolders", async () => { - await subscribeToTsConfigChanges(); + await subscribeToTsConfigChanges({ + subscriptions: [], + } as unknown as vscode.ExtensionContext); await setConfig("absolutePathToWorkspace", true); await setConfig("extensionOnImport", true); @@ -49,7 +51,7 @@ suite("Configuration Service", () => { ); assertEndsWith( configurationProjectOne?.mappings[1].value, - "/demo-workspace/project-one/baseurl-one", + "/project-one/myfolder/mysubfolder", "1:mappings[1]" ); @@ -70,19 +72,23 @@ suite("Configuration Service", () => { ); assertEndsWith( configurationProjectTwo?.mappings[1].value, - "/demo-workspace/project-two/baseurl-two", + "/project-two/.//folderInTwo", "1:mappings[1]" ); }); test("still can load the config with a wrong ts config", async () => { assert.doesNotThrow(async () => { - await subscribeToTsConfigChanges(); + await subscribeToTsConfigChanges({ + subscriptions: [], + } as unknown as vscode.ExtensionContext); }); }); test("has default configuration for non project folder files", async () => { - await subscribeToTsConfigChanges(); + await subscribeToTsConfigChanges({ + subscriptions: [], + } as unknown as vscode.ExtensionContext); await setConfig("absolutePathToWorkspace", true); await setConfig("extensionOnImport", true); @@ -117,7 +123,9 @@ suite("Configuration Service", () => { }); test("updates configuration on tsconfig change", async () => { - await subscribeToTsConfigChanges(); + await subscribeToTsConfigChanges({ + subscriptions: [], + } as unknown as vscode.ExtensionContext); await setConfig("absolutePathToWorkspace", true); await setConfig("ignoreTsConfigBaseUrl", false); @@ -139,7 +147,7 @@ suite("Configuration Service", () => { const document = await vscode.workspace.openTextDocument(absoluteUrl); await vscode.window.showTextDocument(document); await vscode.window.activeTextEditor?.edit((editbuilder) => { - editbuilder.replace(new vscode.Range(2, 24, 2, 27), "bla"); + editbuilder.replace(new vscode.Range(2, 16, 2, 24), "otherfolder"); }); await document.save(); @@ -155,20 +163,20 @@ suite("Configuration Service", () => { // Clean up await vscode.window.showTextDocument(document); await vscode.window.activeTextEditor?.edit((editbuilder) => { - editbuilder.replace(new vscode.Range(2, 24, 2, 27), "one"); + editbuilder.replace(new vscode.Range(2, 16, 2, 27), "myfolder"); }); await document.save(); assert.strictEqual( configuration?.mappings[1].value.endsWith( - "/demo-workspace/project-one/baseurl-one" + "/demo-workspace/project-one/myfolder/mysubfolder" ), true ); assert.strictEqual( newConfiguration?.mappings[1].value.endsWith( - "/demo-workspace/project-one/baseurl-bla" + "/demo-workspace/project-one/otherfolder/othersubfolder" ), true ); diff --git a/src/utils/file-utills.ts b/src/utils/file-utills.ts index 069332e..11c7092 100644 --- a/src/utils/file-utills.ts +++ b/src/utils/file-utills.ts @@ -1,8 +1,11 @@ -import * as path from "path"; -import * as vscode from "vscode"; -import { Mapping, Config } from "../configuration/configuration.interface"; import * as minimatch from "minimatch"; +import * as path from "path"; import { join } from "path"; +import * as vscode from "vscode"; +import { + FilesExclude, + Mapping, +} from "../configuration/configuration.interface"; export interface FileInfo { file: string; @@ -30,7 +33,9 @@ export function getPathOfFolderToLookupFiles( const mapping = mappings && mappings.reduce((prev: any, curr: any) => { - return prev || (normalizedText.startsWith(path.normalize(curr.key)) && curr); + return ( + prev || (normalizedText.startsWith(path.normalize(curr.key)) && curr) + ); }, undefined); let rootFolder, pathEntered; @@ -45,14 +50,18 @@ export function getPathOfFolderToLookupFiles( } else { // We only care about whether the path specified was absolute if it's unmapped (e.g. // we allow user-specified maps to "override" (skip) this root folder determination.) - rootFolder = isPathAbsolute ? (rootPath || "") : path.dirname(fileName); + rootFolder = isPathAbsolute ? rootPath || "" : path.dirname(fileName); pathEntered = normalizedText; } return path.join(rootFolder, pathEntered); } -export async function getChildrenOfPath(path: string, config: Config) { +export async function getChildrenOfPath( + path: string, + showHiddenFiles: boolean, + filesExclude: FilesExclude +) { try { const filesTubles = await vscode.workspace.fs.readDirectory( vscode.Uri.file(path) @@ -60,7 +69,9 @@ export async function getChildrenOfPath(path: string, config: Config) { const files = filesTubles .map((fileTuble) => fileTuble[0]) - .filter((filename) => filterHiddenFiles(filename, config)); + .filter((filename) => + filterHiddenFiles(filename, showHiddenFiles, filesExclude) + ); const fileInfoList: FileInfo[] = []; @@ -90,15 +101,21 @@ function getDocumentExtension(file: string, fileStat: vscode.FileStat) { return fragments[fragments.length - 1]; } -function filterHiddenFiles(filename: string, config: Config) { - if (config.showHiddenFiles) { +function filterHiddenFiles( + filename: string, + showHiddenFiles: boolean, + filesExclude: FilesExclude +) { + if (showHiddenFiles) { return true; } - return isFileHidden(filename, config) ? false : true; + return isFileHidden(filename, filesExclude) ? false : true; } -function isFileHidden(filename: string, config: Config) { - return filename.startsWith(".") || isFileHiddenByVsCode(filename, config); +function isFileHidden(filename: string, filesExclude: FilesExclude) { + return ( + filename.startsWith(".") || isFileHiddenByVsCode(filename, filesExclude) + ); } // files.exclude has the following form. key is the glob @@ -106,11 +123,11 @@ function isFileHidden(filename: string, config: Config) { // "**//*.js": true // "**//*.js": true "*.git": true // } -function isFileHiddenByVsCode(filename: string, config: Config) { +function isFileHiddenByVsCode(filename: string, filesExclude: FilesExclude) { return ( - config.filesExclude && - Object.keys(config.filesExclude).some( - (key) => config.filesExclude[key] && minimatch(filename, key) + filesExclude && + Object.keys(filesExclude).some( + (key) => filesExclude[key] && minimatch(filename, key) ) ); } @@ -122,7 +139,10 @@ function isFileHiddenByVsCode(filename: string, config: Config) { * @param value * @param rootPath */ -export function replaceWorkspaceFolderWithRootPath(value: string, rootPath: string) { +export function replaceWorkspaceFolderWithRootPath( + value: string, + rootPath: string +) { return value .replace("${workspaceRoot}", rootPath) .replace("${workspaceFolder}", rootPath);