diff --git a/_extension/package.json b/_extension/package.json index 8aca1f4c3d..be929cd77d 100644 --- a/_extension/package.json +++ b/_extension/package.json @@ -31,6 +31,11 @@ { "title": "TypeScript Native Preview", "properties": { + "typescript.native-preview.customConfigFileName": { + "type": "string", + "description": "Custom config file name to use, before defaulting to tsconfig.json/jsconfig.json.", + "tags": ["experimental"] + }, "typescript.native-preview.trace.server": { "type": "string", "enum": [ diff --git a/_extension/src/client.ts b/_extension/src/client.ts index 46fd90ebb0..be4ee4571e 100644 --- a/_extension/src/client.ts +++ b/_extension/src/client.ts @@ -94,6 +94,7 @@ export class Client { const config = vscode.workspace.getConfiguration("typescript.native-preview"); const pprofDir = config.get("pprofDir"); const pprofArgs = pprofDir ? ["--pprofDir", pprofDir] : []; + const customConfigFileName = config.get("customConfigFileName") ?? ""; const serverOptions: ServerOptions = { run: { @@ -112,7 +113,12 @@ export class Client { "typescript.native-preview", "typescript.native-preview-lsp", serverOptions, - this.clientOptions, + { + ...this.clientOptions, + initializationOptions: { + customConfigFileName, + }, + }, ); this.outputChannel.appendLine(`Starting language server...`); diff --git a/_extension/src/extension.ts b/_extension/src/extension.ts index 784ebee7fc..cdd54916be 100644 --- a/_extension/src/extension.ts +++ b/_extension/src/extension.ts @@ -14,11 +14,12 @@ export async function activate(context: vscode.ExtensionContext) { registerCommands(context, client, output, traceOutput); context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(event => { - if (event.affectsConfiguration("typescript.experimental.useTsgo")) { + if (event.affectsConfiguration("typescript.experimental.useTsgo") || + event.affectsConfiguration("typescript.native-preview.customConfigFileName")) { // Delay because the command to change the config setting will restart // the extension host, so no need to show a message setTimeout(async () => { - const selected = await vscode.window.showInformationMessage("TypeScript Native Preview setting has changed. Restart extensions to apply changes.", "Restart Extensions"); + const selected = await vscode.window.showInformationMessage("TypeScript Native Preview settings have changed. Restart extensions to apply changes.", "Restart Extensions"); if (selected) { vscode.commands.executeCommand("workbench.action.restartExtensionHost"); } diff --git a/internal/lsp/server.go b/internal/lsp/server.go index ed1a15ddb6..1dc60391fb 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -628,15 +628,26 @@ func (s *Server) handleInitialized(ctx context.Context, params *lsproto.Initiali s.watchEnabled = true } + // Read customConfigFileName from initializationOptions if provided + var customConfigFileName string + if init := s.initializeParams; init != nil && init.InitializationOptions != nil { + if m, ok := (*init.InitializationOptions).(map[string]any); ok { + if v, ok := m["customConfigFileName"].(string); ok { + customConfigFileName = v + } + } + } + s.session = project.NewSession(&project.SessionInit{ Options: &project.SessionOptions{ - CurrentDirectory: s.cwd, - DefaultLibraryPath: s.defaultLibraryPath, - TypingsLocation: s.typingsLocation, - PositionEncoding: s.positionEncoding, - WatchEnabled: s.watchEnabled, - LoggingEnabled: true, - DebounceDelay: 500 * time.Millisecond, + CurrentDirectory: s.cwd, + DefaultLibraryPath: s.defaultLibraryPath, + TypingsLocation: s.typingsLocation, + PositionEncoding: s.positionEncoding, + WatchEnabled: s.watchEnabled, + LoggingEnabled: true, + DebounceDelay: 500 * time.Millisecond, + CustomConfigFileName: customConfigFileName, }, FS: s.fs, Logger: s.logger, diff --git a/internal/project/configfileregistrybuilder.go b/internal/project/configfileregistrybuilder.go index 725bc343a8..bd3dc8f83c 100644 --- a/internal/project/configfileregistrybuilder.go +++ b/internal/project/configfileregistrybuilder.go @@ -409,7 +409,27 @@ func (c *configFileRegistryBuilder) handleConfigChange(entry *dirty.SyncMapEntry func (c *configFileRegistryBuilder) computeConfigFileName(fileName string, skipSearchInDirectoryOfFile bool, logger *logging.LogTree) string { searchPath := tspath.GetDirectoryPath(fileName) - result, _ := tspath.ForEachAncestorDirectory(searchPath, func(directory string) (result string, stop bool) { + skipSearchInDirectoryOfFileForCustomConfig := skipSearchInDirectoryOfFile + var result string + // If custom config file is provided, search for it in directory of file and its ancestors first. + // If a custom config file is provided and not found, default to tsconfig.json/jsconfig.json. + if c.sessionOptions.CustomConfigFileName != "" { + result, _ = tspath.ForEachAncestorDirectory(searchPath, func(directory string) (result string, stop bool) { + customConfigFilePath := tspath.CombinePaths(directory, c.sessionOptions.CustomConfigFileName) + if !skipSearchInDirectoryOfFileForCustomConfig && c.FS().FileExists(customConfigFilePath) { + return customConfigFilePath, true + } + skipSearchInDirectoryOfFileForCustomConfig = false + return "", false + }) + } + + if result != "" { + logger.Logf("computeConfigFileName:: File: %s:: Result: %s", fileName, result) + return result + } + + result, _ = tspath.ForEachAncestorDirectory(searchPath, func(directory string) (result string, stop bool) { tsconfigPath := tspath.CombinePaths(directory, "tsconfig.json") if !skipSearchInDirectoryOfFile && c.FS().FileExists(tsconfigPath) { return tsconfigPath, true diff --git a/internal/project/session.go b/internal/project/session.go index fabaf9a3c0..c0cda57fec 100644 --- a/internal/project/session.go +++ b/internal/project/session.go @@ -31,6 +31,7 @@ type SessionOptions struct { WatchEnabled bool LoggingEnabled bool DebounceDelay time.Duration + CustomConfigFileName string } type SessionInit struct {