From 7dacb4992c8d1ca81db2d73b8c95e78a18a4815b Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Wed, 15 Feb 2023 20:32:45 +0100 Subject: [PATCH 1/3] (fix) use closest config file Not any tsconfig over a closer jsconfig. This aligns with TS VS Code behavior --- .../src/plugins/typescript/utils.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/language-server/src/plugins/typescript/utils.ts b/packages/language-server/src/plugins/typescript/utils.ts index ac42209aa..d8803baff 100644 --- a/packages/language-server/src/plugins/typescript/utils.ts +++ b/packages/language-server/src/plugins/typescript/utils.ts @@ -132,13 +132,14 @@ export function findTsConfigPath( ) { const searchDir = dirname(fileName); - const path = - ts.findConfigFile(searchDir, fileExists, 'tsconfig.json') || - ts.findConfigFile(searchDir, fileExists, 'jsconfig.json') || - ''; - // Don't return config files that exceed the current workspace context. - return !!path && rootUris.some((rootUri) => isSubPath(rootUri, path, getCanonicalFileName)) - ? path + const tsconfig = ts.findConfigFile(searchDir, fileExists, 'tsconfig.json') || ''; + const jsconfig = ts.findConfigFile(searchDir, fileExists, 'jsconfig.json') || ''; + // Prefer closest config file + const config = tsconfig.length >= jsconfig.length ? tsconfig : jsconfig; + + // Don't return config files that exceed the current workspace context + return !!config && rootUris.some((rootUri) => isSubPath(rootUri, config, getCanonicalFileName)) + ? config : ''; } From d3c83f731470bee1beeb49af74da901a58008a78 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Thu, 16 Feb 2023 11:13:07 +0100 Subject: [PATCH 2/3] node_modules check, perf by caching the config path --- .../src/plugins/typescript/service.ts | 14 ++++++++------ .../src/plugins/typescript/utils.ts | 9 +++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/language-server/src/plugins/typescript/service.ts b/packages/language-server/src/plugins/typescript/service.ts index c24b84b52..13b0578e6 100644 --- a/packages/language-server/src/plugins/typescript/service.ts +++ b/packages/language-server/src/plugins/typescript/service.ts @@ -48,6 +48,7 @@ const serviceSizeMap = new FileMap(); const configWatchers = new FileMap(); const extendedConfigWatchers = new FileMap(); const extendedConfigToTsConfigPath = new FileMap(); +const configFileForOpenFiles = new FileMap(); const pendingReloads = new FileSet(); /** @@ -81,14 +82,12 @@ export async function getService( docContext.tsSystem.useCaseSensitiveFileNames ); - const tsconfigPath = findTsConfigPath( - path, - workspaceUris, - docContext.tsSystem.fileExists, - getCanonicalFileName - ); + const tsconfigPath = + configFileForOpenFiles.get(path) ?? + findTsConfigPath(path, workspaceUris, docContext.tsSystem.fileExists, getCanonicalFileName); if (tsconfigPath) { + configFileForOpenFiles.set(path, tsconfigPath); return getServiceForTsconfig(tsconfigPath, dirname(tsconfigPath), docContext); } @@ -243,6 +242,7 @@ async function createLanguageService( function deleteSnapshot(filePath: string): void { svelteModuleLoader.deleteFromModuleCache(filePath); snapshotManager.delete(filePath); + configFileForOpenFiles.delete(filePath); } function updateSnapshot(documentOrFilePath: Document | string): DocumentSnapshot { @@ -517,6 +517,7 @@ async function createLanguageService( snapshotManager.dispose(); configWatchers.get(tsconfigPath)?.close(); configWatchers.delete(tsconfigPath); + configFileForOpenFiles.clear(); docContext.globalSnapshotsManager.removeChangeListener(onSnapshotChange); } @@ -565,6 +566,7 @@ async function createLanguageService( scheduleReload(fileName); } else if (kind === ts.FileWatcherEventKind.Deleted) { services.delete(fileName); + configFileForOpenFiles.clear(); } docContext.onProjectReloaded?.(); diff --git a/packages/language-server/src/plugins/typescript/utils.ts b/packages/language-server/src/plugins/typescript/utils.ts index d8803baff..f67acc6cf 100644 --- a/packages/language-server/src/plugins/typescript/utils.ts +++ b/packages/language-server/src/plugins/typescript/utils.ts @@ -137,8 +137,13 @@ export function findTsConfigPath( // Prefer closest config file const config = tsconfig.length >= jsconfig.length ? tsconfig : jsconfig; - // Don't return config files that exceed the current workspace context - return !!config && rootUris.some((rootUri) => isSubPath(rootUri, config, getCanonicalFileName)) + // Don't return config files that exceed the current workspace context or cross a node_modules folder + return !!config && + rootUris.some((rootUri) => isSubPath(rootUri, config, getCanonicalFileName)) && + !fileName + .substring(config.length - 13) + .split('/') + .includes('node_modules') ? config : ''; } From a842104db2be01bdf1aa34ad880598556d868f1b Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Thu, 16 Feb 2023 11:43:57 +0100 Subject: [PATCH 3/3] node_modules boundary --- .../src/plugins/typescript/service.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/language-server/src/plugins/typescript/service.ts b/packages/language-server/src/plugins/typescript/service.ts index 13b0578e6..ec26770b8 100644 --- a/packages/language-server/src/plugins/typescript/service.ts +++ b/packages/language-server/src/plugins/typescript/service.ts @@ -91,13 +91,23 @@ export async function getService( return getServiceForTsconfig(tsconfigPath, dirname(tsconfigPath), docContext); } + // Find closer boundary: workspace uri or node_modules const nearestWorkspaceUri = workspaceUris.find((workspaceUri) => isSubPath(workspaceUri, path, getCanonicalFileName) ); + const lastNodeModulesIdx = path.split('/').lastIndexOf('node_modules') + 2; + const nearestNodeModulesBoundary = + lastNodeModulesIdx === 1 + ? undefined + : path.split('/').slice(0, lastNodeModulesIdx).join('/'); + const nearestBoundary = + (nearestNodeModulesBoundary?.length ?? 0) > (nearestWorkspaceUri?.length ?? 0) + ? nearestNodeModulesBoundary + : nearestWorkspaceUri; return getServiceForTsconfig( tsconfigPath, - (nearestWorkspaceUri && urlToPath(nearestWorkspaceUri)) ?? + (nearestBoundary && urlToPath(nearestBoundary)) ?? docContext.tsSystem.getCurrentDirectory(), docContext );