From 810320d0bfa0b61616109e230ea4a23f0d82d88b Mon Sep 17 00:00:00 2001 From: tcernicovad1 Date: Fri, 16 Oct 2026 10:32:42 +0100 Subject: [PATCH] Ensure `pathsBasePath` is correctly forwarded from the API --- .../api/session_createprogram_test.go | 46 +++++++++++++++++++ tsc/internal/tsoptions/rawcompileroptions.go | 2 + .../tsoptions/rawcompileroptions_test.go | 2 + 3 files changed, 50 insertions(+) diff --git a/tsc/internal/api/session_createprogram_test.go b/tsc/internal/api/session_createprogram_test.go index 54709aec92d6a..827ab46eb2961 100644 --- a/tsc/internal/api/session_createprogram_test.go +++ b/tsc/internal/api/session_createprogram_test.go @@ -316,3 +316,49 @@ func TestCreateProgramReportsNonCompositeProjectReference(t *testing.T) { } assert.DeepEqual(t, codes, []int32{6306}) } + +func TestCreateSnapshotResolvesPathsRelativeToParsedConfigDirectory(t *testing.T) { + t.Parallel() + + const ( + mainFile = "/project/main.ts" + libFile = "/project/types/lib.d.ts" + ) + init, _ := projecttestutil.GetSessionInitOptions(map[string]any{ + mainFile: `import { x } from "lib"; export const y: number = x;`, + libFile: `export declare const x: number;`, + }, nil, &projecttestutil.TypingsInstallerOptions{}) + init.Options.CurrentDirectory = "/somewhere-else" + session := NewStandaloneSession(init, nil) + defer session.Close() + + var parseParams ParseJsonConfigFileContentParams + assert.NilError(t, json.Unmarshal([]byte(`{ + "json": { + "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "noLib": true, + "types": [], + "paths": { "lib": ["./types/lib.d.ts"] } + } + }, + "configDirectory": "/project" + }`), &parseParams)) + parsed, err := session.handleParseJsonConfigFileContent(context.Background(), &parseParams) + assert.NilError(t, err) + + // Round-trip the parsed options through JSON as an API client would. + encodedOptions, err := json.Marshal(parsed.Options) + assert.NilError(t, err) + var createParams CreateSnapshotParams + assert.NilError(t, json.Unmarshal([]byte(`{"createPrograms":[{"rootFiles":["`+mainFile+`"],"compilerOptions":`+string(encodedOptions)+`}]}`), &createParams)) + + response, err := session.handleCreateSnapshot(context.Background(), &createParams) + assert.NilError(t, err) + snapshot, err := session.getSnapshotData(response.Snapshot) + assert.NilError(t, err) + program, err := snapshot.getProgram(response.Projects[0].Id) + assert.NilError(t, err) + assert.Assert(t, program.GetSourceFile(libFile) != nil, "expected 'lib' to resolve via paths relative to /project") +} diff --git a/tsc/internal/tsoptions/rawcompileroptions.go b/tsc/internal/tsoptions/rawcompileroptions.go index d437fa81fb394..1a570da9f19ae 100644 --- a/tsc/internal/tsoptions/rawcompileroptions.go +++ b/tsc/internal/tsoptions/rawcompileroptions.go @@ -85,6 +85,8 @@ func (o *RawCompilerOptions) Finalize(basePath tspath.RootedDirectoryPath) (*cor } } else if key == "configFilePath" { pathKind = CommandLineOptionPathKindFile + } else if key == "pathsBasePath" { + pathKind = CommandLineOptionPathKindDirectory } else if key != "allowNonTsExtensions" && key != "suppressOutputPathCheck" { continue } diff --git a/tsc/internal/tsoptions/rawcompileroptions_test.go b/tsc/internal/tsoptions/rawcompileroptions_test.go index f8f8f83e9ecb3..6ccb1c43b323c 100644 --- a/tsc/internal/tsoptions/rawcompileroptions_test.go +++ b/tsc/internal/tsoptions/rawcompileroptions_test.go @@ -27,6 +27,7 @@ func TestRawCompilerOptionsFinalizePaths(t *testing.T) { "allowNonTsExtensions": true, "suppressOutputPathCheck": true, "configFilePath": "", + "pathsBasePath": "config", "NoImplicitAny": true }`), &raw)) @@ -46,5 +47,6 @@ func TestRawCompilerOptionsFinalizePaths(t *testing.T) { assert.Equal(t, options.AllowNonTsExtensions, core.TSTrue) assert.Equal(t, options.SuppressOutputPathCheck, core.TSTrue) assert.Equal(t, options.ConfigFilePath, tspath.RootedFilePath("")) + assert.Equal(t, options.PathsBasePath, tspath.RootedDirectoryPath("/project/config")) assert.Equal(t, options.NoImplicitAny, core.TSUnknown) }