From 5c69a5550de43d7ff62daf7989c93b670ade44cc Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 11 Sep 2026 10:10:39 -0700 Subject: [PATCH 1/3] [api] Add Program module resolution methods Expose cached module and type reference directive resolutions through the async and sync APIs, with optional on-demand lookup location collection and precise result overloads. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- packages/typescript/src/api/async/api.ts | 144 +++++++++++ .../typescript/src/api/proto.generated.ts | 87 +++++++ packages/typescript/src/api/sync/api.ts | 177 +++++++++++++ packages/typescript/test/async/api.test.ts | 63 +++++ .../test/sync/api-generators.test.ts | 10 + packages/typescript/test/sync/api.test.ts | 63 +++++ tsc/internal/api/proto.go | 244 ++++++++++++------ tsc/internal/api/session.go | 144 +++++++++++ tsc/internal/compiler/program.go | 26 +- tsc/internal/module/resolver.go | 57 +++- tsc/internal/module/types.go | 7 + 11 files changed, 940 insertions(+), 82 deletions(-) diff --git a/packages/typescript/src/api/async/api.ts b/packages/typescript/src/api/async/api.ts index ef9a22be49a5e..b373509ef22c8 100644 --- a/packages/typescript/src/api/async/api.ts +++ b/packages/typescript/src/api/async/api.ts @@ -19,6 +19,7 @@ import { type __String, type Declaration, type Expression, + type FileReference, type Identifier, type IndexSignatureDeclaration, ModifierFlags, @@ -27,6 +28,7 @@ import { type ParameterDeclaration, type Path, type SourceFile, + type StringLiteralLikeNode, type SyntaxKind, type TypeNode, unescapeLeadingUnderscores, @@ -65,10 +67,15 @@ import type { ImportAdderAction, IntrinsicTypeMethod, LSPUpdateSnapshotParams, + PackageId, ParsedCommandLine, ProjectReference, ProjectResponse, ReadConfigFileResponse, + ResolvedModule, + ResolvedModuleWithFailedLookupLocations, + ResolvedTypeReferenceDirective, + ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SignaturePropertyMethod, SignatureResponse, SourceFileMetadata, @@ -184,10 +191,15 @@ export type { LSPConnectionOptions, NumberLiteralType, ObjectType, + PackageId, ParsedCommandLine, ProjectReference, ReadConfigFileResponse, RequestTiming, + ResolvedModule, + ResolvedModuleWithFailedLookupLocations, + ResolvedTypeReferenceDirective, + ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SourceFileMetadata, StringLiteralType, StringMappingType, @@ -216,6 +228,29 @@ export interface TranspileOptions { reportDiagnostics?: boolean; } +export interface ResolutionOptions { + /** Include failed and resolution-affecting file lookup locations in the result. */ + includeLookupLocations?: boolean | undefined; +} + +export interface ResolutionOptionsWithLookupLocations { + includeLookupLocations: true; +} + +export type ResolvedModuleWithLookupLocations = + & Omit + & { + failedLookupLocations: string[]; + affectingLocations: string[]; + }; + +export type ResolvedTypeReferenceDirectiveWithLookupLocations = + & Omit + & { + failedLookupLocations: string[]; + affectingLocations: string[]; + }; + export interface TranspileOutput { outputText: string; diagnostics?: readonly Diagnostic[] | undefined; @@ -1223,6 +1258,115 @@ export class Program implements FormatDiagnosticsHost { return this.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, this.snapshotId, this.project.id); } + getResolvedModule( + file: DocumentIdentifier, + moduleName: string, + mode: ModuleKind, + options: ResolutionOptionsWithLookupLocations, + ): Promise; + getResolvedModule( + file: DocumentIdentifier, + moduleName: string, + mode: ModuleKind, + options?: ResolutionOptions, + ): Promise; + async getResolvedModule( + file: DocumentIdentifier, + moduleName: string, + mode: ModuleKind, + options?: ResolutionOptions, + ): Promise { + const result = await this.client.apiRequest("getResolvedModule", { + snapshot: this.snapshotId, + project: this.project.id, + file, + moduleName, + mode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + + getResolvedModuleFromModuleSpecifier( + moduleSpecifier: StringLiteralLikeNode, + sourceFile: DocumentIdentifier | undefined, + options: ResolutionOptionsWithLookupLocations, + ): Promise; + getResolvedModuleFromModuleSpecifier( + moduleSpecifier: StringLiteralLikeNode, + sourceFile?: DocumentIdentifier, + options?: ResolutionOptions, + ): Promise; + async getResolvedModuleFromModuleSpecifier( + moduleSpecifier: StringLiteralLikeNode, + sourceFile?: DocumentIdentifier, + options?: ResolutionOptions, + ): Promise { + const result = await this.client.apiRequest("getResolvedModuleFromModuleSpecifier", { + snapshot: this.snapshotId, + project: this.project.id, + moduleSpecifier: getNodeId(moduleSpecifier), + sourceFile, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + + getResolvedTypeReferenceDirective( + file: DocumentIdentifier, + typeDirectiveName: string, + mode: ModuleKind, + options: ResolutionOptionsWithLookupLocations, + ): Promise; + getResolvedTypeReferenceDirective( + file: DocumentIdentifier, + typeDirectiveName: string, + mode: ModuleKind, + options?: ResolutionOptions, + ): Promise; + async getResolvedTypeReferenceDirective( + file: DocumentIdentifier, + typeDirectiveName: string, + mode: ModuleKind, + options?: ResolutionOptions, + ): Promise { + const result = await this.client.apiRequest("getResolvedTypeReferenceDirective", { + snapshot: this.snapshotId, + project: this.project.id, + file, + typeDirectiveName, + mode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + + getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( + typeReferenceDirective: FileReference, + sourceFile: DocumentIdentifier, + options: ResolutionOptionsWithLookupLocations, + ): Promise; + getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( + typeReferenceDirective: FileReference, + sourceFile: DocumentIdentifier, + options?: ResolutionOptions, + ): Promise; + async getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( + typeReferenceDirective: FileReference, + sourceFile: DocumentIdentifier, + options?: ResolutionOptions, + ): Promise { + const result = await this.client.apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { + snapshot: this.snapshotId, + project: this.project.id, + sourceFile, + typeDirectiveName: typeReferenceDirective.fileName, + resolutionMode: typeReferenceDirective.resolutionMode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + async getSourceFileNames(): Promise { const data = await this.client.apiRequest("getSourceFileNames", { snapshot: this.snapshotId, diff --git a/packages/typescript/src/api/proto.generated.ts b/packages/typescript/src/api/proto.generated.ts index 0f6a952a42758..3599f24f08da5 100644 --- a/packages/typescript/src/api/proto.generated.ts +++ b/packages/typescript/src/api/proto.generated.ts @@ -45,6 +45,10 @@ export interface APIMethodInfo { getSourceFile: APIMethod; getSourceFileNames: APIMethod; getSourceFileMetadata: APIMethod; + getResolvedModule: APIMethod; + getResolvedModuleFromModuleSpecifier: APIMethod; + getResolvedTypeReferenceDirective: APIMethod; + getResolvedTypeReferenceDirectiveFromTypeReferenceDirective: APIMethod; getConfigFileNames: APIMethod; getConfigSourceFile: APIMethod; resolveName: APIMethod; @@ -475,6 +479,55 @@ export interface SourceFileMetadata { impliedNodeFormat: ModuleKind; } +export interface GetResolvedModuleParams { + snapshot: number; + project: string; + file: DocumentIdentifier; + moduleName: string; + mode: ModuleKind; + includeLookupLocations?: boolean | undefined; +} + +export interface ResolvedModuleWithFailedLookupLocations { + resolvedModule?: ResolvedModule | undefined; + failedLookupLocations?: string[] | undefined; + affectingLocations?: string[] | undefined; + resolutionDiagnostics?: DiagnosticResponse[] | undefined; +} + +export interface GetResolvedModuleFromModuleSpecifierParams { + snapshot: number; + project: string; + moduleSpecifier: string; + sourceFile?: DocumentIdentifier | undefined; + includeLookupLocations?: boolean | undefined; +} + +export interface GetResolvedTypeReferenceDirectiveParams { + snapshot: number; + project: string; + file: DocumentIdentifier; + typeDirectiveName: string; + mode: ModuleKind; + includeLookupLocations?: boolean | undefined; +} + +export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { + resolvedTypeReferenceDirective?: ResolvedTypeReferenceDirective | undefined; + failedLookupLocations?: string[] | undefined; + affectingLocations?: string[] | undefined; + resolutionDiagnostics?: DiagnosticResponse[] | undefined; +} + +export interface GetResolvedTypeReferenceDirectiveFromReferenceParams { + snapshot: number; + project: string; + sourceFile: DocumentIdentifier; + typeDirectiveName: string; + resolutionMode: ModuleKind; + includeLookupLocations?: boolean | undefined; +} + /** GetProjectDiagnosticsParams are parameters for project-wide diagnostic methods. */ export interface GetProjectDiagnosticsParams { snapshot: number; @@ -991,7 +1044,11 @@ export interface BatchRequest { | "getReferencedSymbolsForNode" | "getReferencesToSymbolInFile" | "getRegularTypeOfType" + | "getResolvedModule" + | "getResolvedModuleFromModuleSpecifier" | "getResolvedSignature" + | "getResolvedTypeReferenceDirective" + | "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective" | "getRestTypeOfSignature" | "getReturnTypeOfSignature" | "getSemanticDiagnostics" @@ -1138,7 +1195,11 @@ export interface BatchResponse { | "getReferencedSymbolsForNode" | "getReferencesToSymbolInFile" | "getRegularTypeOfType" + | "getResolvedModule" + | "getResolvedModuleFromModuleSpecifier" | "getResolvedSignature" + | "getResolvedTypeReferenceDirective" + | "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective" | "getRestTypeOfSignature" | "getReturnTypeOfSignature" | "getSemanticDiagnostics" @@ -1402,6 +1463,25 @@ export interface TranspileOptions { reportDiagnostics?: boolean | undefined; } +export interface ResolvedModule { + resolvedFileName: string; + originalPath?: string | undefined; + extension: string; + resolvedUsingTsExtension?: boolean | undefined; + resolvedUsingExtraExtensions?: boolean | undefined; + packageId?: PackageId | undefined; + isExternalLibraryImport?: boolean | undefined; + alternateResult?: string | undefined; +} + +export interface ResolvedTypeReferenceDirective { + primary: boolean; + resolvedFileName: string; + originalPath?: string | undefined; + packageId?: PackageId | undefined; + isExternalLibraryImport?: boolean | undefined; +} + export interface ImportAdderAction { kind: "importSymbol"; symbol?: number | undefined; @@ -1467,6 +1547,13 @@ export interface ProjectFileChanges { deletedFiles?: string[] | undefined; } +export interface PackageId { + name: string; + subModuleName: string; + version: string; + peerDependencies: string; +} + /** CompletionEntryLabelDetailsResponse holds additional label display text for a completion entry. */ export interface CompletionEntryLabelDetailsResponse { detail?: string | undefined; diff --git a/packages/typescript/src/api/sync/api.ts b/packages/typescript/src/api/sync/api.ts index c85780498bfe5..ebcae75fc2319 100644 --- a/packages/typescript/src/api/sync/api.ts +++ b/packages/typescript/src/api/sync/api.ts @@ -36,6 +36,7 @@ import { type __String, type Declaration, type Expression, + type FileReference, type Identifier, type IndexSignatureDeclaration, ModifierFlags, @@ -44,6 +45,7 @@ import { type ParameterDeclaration, type Path, type SourceFile, + type StringLiteralLikeNode, type SyntaxKind, type TypeNode, unescapeLeadingUnderscores, @@ -82,10 +84,15 @@ import type { ImportAdderAction, IntrinsicTypeMethod, LSPUpdateSnapshotParams, + PackageId, ParsedCommandLine, ProjectReference, ProjectResponse, ReadConfigFileResponse, + ResolvedModule, + ResolvedModuleWithFailedLookupLocations, + ResolvedTypeReferenceDirective, + ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SignaturePropertyMethod, SignatureResponse, SourceFileMetadata, @@ -201,10 +208,15 @@ export type { LSPConnectionOptions, NumberLiteralType, ObjectType, + PackageId, ParsedCommandLine, ProjectReference, ReadConfigFileResponse, RequestTiming, + ResolvedModule, + ResolvedModuleWithFailedLookupLocations, + ResolvedTypeReferenceDirective, + ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SourceFileMetadata, StringLiteralType, StringMappingType, @@ -233,6 +245,29 @@ export interface TranspileOptions { reportDiagnostics?: boolean; } +export interface ResolutionOptions { + /** Include failed and resolution-affecting file lookup locations in the result. */ + includeLookupLocations?: boolean | undefined; +} + +export interface ResolutionOptionsWithLookupLocations { + includeLookupLocations: true; +} + +export type ResolvedModuleWithLookupLocations = + & Omit + & { + failedLookupLocations: string[]; + affectingLocations: string[]; + }; + +export type ResolvedTypeReferenceDirectiveWithLookupLocations = + & Omit + & { + failedLookupLocations: string[]; + affectingLocations: string[]; + }; + export interface TranspileOutput { outputText: string; diagnostics?: readonly Diagnostic[] | undefined; @@ -2281,6 +2316,148 @@ export class Program implements FormatDiagnosticsHost { ); } + get getResolvedModule(): { + (file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): ResolvedModuleWithLookupLocations | undefined; + (file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined; + gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): Generator; + gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): Generator; + } { + const owner = this; + function getResolvedModule(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): ResolvedModuleWithLookupLocations | undefined; + function getResolvedModule(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined; + function getResolvedModule(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined { + const result = owner.client.apiRequest("getResolvedModule", { + snapshot: owner.snapshotId, + project: owner.project.id, + file, + moduleName, + mode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + function gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): Generator; + function gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): Generator; + function* gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): Generator { + const result = yield* apiRequest("getResolvedModule", { + snapshot: owner.snapshotId, + project: owner.project.id, + file, + moduleName, + mode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + return cacheGeneratorMethod(owner, "getResolvedModule", getResolvedModule, gen); + } + + get getResolvedModuleFromModuleSpecifier(): { + (moduleSpecifier: StringLiteralLikeNode, sourceFile: DocumentIdentifier | undefined, options: ResolutionOptionsWithLookupLocations): ResolvedModuleWithLookupLocations | undefined; + (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined; + gen(moduleSpecifier: StringLiteralLikeNode, sourceFile: DocumentIdentifier | undefined, options: ResolutionOptionsWithLookupLocations): Generator; + gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): Generator; + } { + const owner = this; + function getResolvedModuleFromModuleSpecifier(moduleSpecifier: StringLiteralLikeNode, sourceFile: DocumentIdentifier | undefined, options: ResolutionOptionsWithLookupLocations): ResolvedModuleWithLookupLocations | undefined; + function getResolvedModuleFromModuleSpecifier(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined; + function getResolvedModuleFromModuleSpecifier(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined { + const result = owner.client.apiRequest("getResolvedModuleFromModuleSpecifier", { + snapshot: owner.snapshotId, + project: owner.project.id, + moduleSpecifier: getNodeId(moduleSpecifier), + sourceFile, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + function gen(moduleSpecifier: StringLiteralLikeNode, sourceFile: DocumentIdentifier | undefined, options: ResolutionOptionsWithLookupLocations): Generator; + function gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): Generator; + function* gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): Generator { + const result = yield* apiRequest("getResolvedModuleFromModuleSpecifier", { + snapshot: owner.snapshotId, + project: owner.project.id, + moduleSpecifier: getNodeId(moduleSpecifier), + sourceFile, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + return cacheGeneratorMethod(owner, "getResolvedModuleFromModuleSpecifier", getResolvedModuleFromModuleSpecifier, gen); + } + + get getResolvedTypeReferenceDirective(): { + (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): ResolvedTypeReferenceDirectiveWithLookupLocations | undefined; + (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; + gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): Generator; + gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): Generator; + } { + const owner = this; + function getResolvedTypeReferenceDirective(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): ResolvedTypeReferenceDirectiveWithLookupLocations | undefined; + function getResolvedTypeReferenceDirective(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; + function getResolvedTypeReferenceDirective(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined { + const result = owner.client.apiRequest("getResolvedTypeReferenceDirective", { + snapshot: owner.snapshotId, + project: owner.project.id, + file, + typeDirectiveName, + mode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + function gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): Generator; + function gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): Generator; + function* gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): Generator { + const result = yield* apiRequest("getResolvedTypeReferenceDirective", { + snapshot: owner.snapshotId, + project: owner.project.id, + file, + typeDirectiveName, + mode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + return cacheGeneratorMethod(owner, "getResolvedTypeReferenceDirective", getResolvedTypeReferenceDirective, gen); + } + + get getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(): { + (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options: ResolutionOptionsWithLookupLocations): ResolvedTypeReferenceDirectiveWithLookupLocations | undefined; + (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; + gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options: ResolutionOptionsWithLookupLocations): Generator; + gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): Generator; + } { + const owner = this; + function getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options: ResolutionOptionsWithLookupLocations): ResolvedTypeReferenceDirectiveWithLookupLocations | undefined; + function getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; + function getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined { + const result = owner.client.apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { + snapshot: owner.snapshotId, + project: owner.project.id, + sourceFile, + typeDirectiveName: typeReferenceDirective.fileName, + resolutionMode: typeReferenceDirective.resolutionMode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + function gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options: ResolutionOptionsWithLookupLocations): Generator; + function gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): Generator; + function* gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): Generator { + const result = yield* apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { + snapshot: owner.snapshotId, + project: owner.project.id, + sourceFile, + typeDirectiveName: typeReferenceDirective.fileName, + resolutionMode: typeReferenceDirective.resolutionMode, + includeLookupLocations: options?.includeLookupLocations, + }); + return result ?? undefined; + } + return cacheGeneratorMethod(owner, "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", getResolvedTypeReferenceDirectiveFromTypeReferenceDirective, gen); + } + get getSourceFileNames(): { (): readonly string[]; gen(): Generator; diff --git a/packages/typescript/test/async/api.test.ts b/packages/typescript/test/async/api.test.ts index 9d0d352061ea2..8cf82ad141f33 100644 --- a/packages/typescript/test/async/api.test.ts +++ b/packages/typescript/test/async/api.test.ts @@ -66,6 +66,7 @@ import { type LiteralType, ModifierFlags, ModuleKind, + ModuleResolutionKind, ObjectFlags, type Signature, SignatureKind, @@ -327,6 +328,68 @@ describe("API", () => { await assert.rejects(program.getSourceFileNames(), /snapshot .* not found/); // @sync: assert.throws(() => program.getSourceFileNames(), /snapshot .* not found/); }); + test("Program resolved modules and type reference directives", async () => { + await using api = spawnAPI({ + "/src/index.ts": `/// +import "pkg"; +import "missing";`, + "/node_modules/pkg/package.json": JSON.stringify({ name: "pkg", version: "1.0.0", types: "index.d.ts" }), + "/node_modules/pkg/index.d.ts": `export {};`, + "/node_modules/@types/pkg-types/package.json": JSON.stringify({ name: "@types/pkg-types", version: "1.0.0", types: "index.d.ts" }), + "/node_modules/@types/pkg-types/index.d.ts": `export {};`, + }); + + const program = await api.createProgram(["/src/index.ts"], { + compilerOptions: { module: ModuleKind.ESNext, moduleResolution: ModuleResolutionKind.Bundler, noLib: true }, + }); + const sourceFile = await program.getSourceFile("/src/index.ts"); + assert.ok(sourceFile); + const pkgSpecifier = cast(cast(sourceFile.statements[0], isImportDeclaration).moduleSpecifier, isStringLiteral); + + const resolvedModule = await program.getResolvedModule("/src/index.ts", "pkg", ModuleKind.ESNext); + assert.equal(resolvedModule?.resolvedModule?.resolvedFileName, "/node_modules/pkg/index.d.ts"); + assert.equal(resolvedModule?.failedLookupLocations, undefined); + assert.equal(resolvedModule?.affectingLocations, undefined); + + const resolvedModuleWithLocations = await program.getResolvedModuleFromModuleSpecifier( + pkgSpecifier, + undefined, + { includeLookupLocations: true }, + ); + assert.ok(resolvedModuleWithLocations); + assert.equal(resolvedModuleWithLocations.resolvedModule?.packageId?.name, "pkg"); + assert.ok(resolvedModuleWithLocations.affectingLocations.includes("/node_modules/pkg/package.json")); + + const missingModule = await program.getResolvedModule( + "/src/index.ts", + "missing", + ModuleKind.ESNext, + { includeLookupLocations: true }, + ); + assert.ok(missingModule); + assert.equal(missingModule.resolvedModule, undefined); + assert.ok(missingModule.failedLookupLocations.length); + + const typeReference = sourceFile.typeReferenceDirectives[0]; + const resolvedTypeReference = await program.getResolvedTypeReferenceDirective( + "/src/index.ts", + "pkg-types", + ModuleKind.None, + ); + assert.equal(resolvedTypeReference?.resolvedTypeReferenceDirective?.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); + assert.equal(resolvedTypeReference?.failedLookupLocations, undefined); + + const resolvedTypeReferenceWithLocations = await program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( + typeReference, + "/src/index.ts", + { includeLookupLocations: true }, + ); + assert.ok(resolvedTypeReferenceWithLocations); + assert.ok(resolvedTypeReferenceWithLocations.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); + + await program.dispose(); + }); + test("createProgram ignores an on-disk tsconfig", async () => { await using api = spawnAPI({ "/tsconfig.json": JSON.stringify({ diff --git a/packages/typescript/test/sync/api-generators.test.ts b/packages/typescript/test/sync/api-generators.test.ts index 73adc15b31486..0a978202a118b 100644 --- a/packages/typescript/test/sync/api-generators.test.ts +++ b/packages/typescript/test/sync/api-generators.test.ts @@ -13,6 +13,7 @@ import { isNamedImports, isObjectLiteralExpression, isShorthandPropertyAssignment, + isStringLiteral, isTypeAliasDeclaration, isVariableDeclaration, isVariableStatement, @@ -36,6 +37,7 @@ import { type IndexInfo, type InterfaceType, type LiteralType, + ModuleKind, type NodeHandle, type Program, type Project, @@ -102,6 +104,7 @@ export enum Choice { First = 1, Second = "second" } export class Unimported { value = "extra"; } `, "/src/index.ts": ` +/// import { Base, Box, Choice, Derived } from "./models.js"; export { Derived as RenamedDerived } from "./models.js"; @@ -122,6 +125,7 @@ export function getArguments() { return arguments; } import { absent } from "./absent.js"; export const missingValue = absent; `, + "/node_modules/@types/parity/index.d.ts": `export {};`, "/src/syntax.ts": `export const broken: = 1;`, "/src/bind.ts": `let duplicate = 1; let duplicate = 2;`, "/src/suggestions.ts": `export function suggestion() { const unused = 1; return 1; }`, @@ -1363,6 +1367,8 @@ describe("API - generator batching", () => { const modelsFile = program.getSourceFile("/src/models.ts")!; const importDeclaration = cast(indexFile.statements[0], isImportDeclaration); + const importSpecifier = cast(importDeclaration.moduleSpecifier, isStringLiteral); + const typeReferenceDirective = indexFile.typeReferenceDirectives[0]; const importedNames = cast(importDeclaration.importClause?.namedBindings, isNamedImports); const importedDerived = importedNames.elements.find(element => element.name.text === "Derived")!.name; const exportDeclaration = cast(indexFile.statements[1], isExportDeclaration); @@ -1516,6 +1522,10 @@ describe("API - generator batching", () => { parityCase("LanguageService", "getCompletionsAtPosition", languageService.getCompletionsAtPosition, assertDeepEquivalent, "/src/index.ts", completionPosition, { includeSymbol: true }), parityCase("Program", "getSourceFile", program.getSourceFile, assertOptionalSourceFilesEquivalent, "/src/index.ts"), + parityCase("Program", "getResolvedModule", program.getResolvedModule, assertDeepEquivalent, "/src/index.ts", "./models.js", ModuleKind.CommonJS, { includeLookupLocations: true }), + parityCase("Program", "getResolvedModuleFromModuleSpecifier", program.getResolvedModuleFromModuleSpecifier, assertDeepEquivalent, importSpecifier), + parityCase("Program", "getResolvedTypeReferenceDirective", program.getResolvedTypeReferenceDirective, assertDeepEquivalent, "/src/index.ts", "parity", ModuleKind.CommonJS), + parityCase("Program", "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective, assertDeepEquivalent, typeReferenceDirective, "/src/index.ts", { includeLookupLocations: true }), parityCase("Program", "getSourceFileNames", program.getSourceFileNames, assertDeepEquivalent), parityCase("Program", "getSourceFileMetadata", program.getSourceFileMetadata, assertDeepEquivalent, "/src/index.ts"), parityCase("Program", "getSourceFileMetadataByPath", program.getSourceFileMetadataByPath, assertDeepEquivalent, indexFile.path), diff --git a/packages/typescript/test/sync/api.test.ts b/packages/typescript/test/sync/api.test.ts index b8c648a5ec343..5a09977e92c38 100644 --- a/packages/typescript/test/sync/api.test.ts +++ b/packages/typescript/test/sync/api.test.ts @@ -81,6 +81,7 @@ import { type LiteralType, ModifierFlags, ModuleKind, + ModuleResolutionKind, ObjectFlags, type Signature, SignatureKind, @@ -316,6 +317,68 @@ describe("API", () => { assert.throws(() => program.getSourceFileNames(), /snapshot .* not found/); }); + test("Program resolved modules and type reference directives", () => { + using api = spawnAPI({ + "/src/index.ts": `/// +import "pkg"; +import "missing";`, + "/node_modules/pkg/package.json": JSON.stringify({ name: "pkg", version: "1.0.0", types: "index.d.ts" }), + "/node_modules/pkg/index.d.ts": `export {};`, + "/node_modules/@types/pkg-types/package.json": JSON.stringify({ name: "@types/pkg-types", version: "1.0.0", types: "index.d.ts" }), + "/node_modules/@types/pkg-types/index.d.ts": `export {};`, + }); + + const program = api.createProgram(["/src/index.ts"], { + compilerOptions: { module: ModuleKind.ESNext, moduleResolution: ModuleResolutionKind.Bundler, noLib: true }, + }); + const sourceFile = program.getSourceFile("/src/index.ts"); + assert.ok(sourceFile); + const pkgSpecifier = cast(cast(sourceFile.statements[0], isImportDeclaration).moduleSpecifier, isStringLiteral); + + const resolvedModule = program.getResolvedModule("/src/index.ts", "pkg", ModuleKind.ESNext); + assert.equal(resolvedModule?.resolvedModule?.resolvedFileName, "/node_modules/pkg/index.d.ts"); + assert.equal(resolvedModule?.failedLookupLocations, undefined); + assert.equal(resolvedModule?.affectingLocations, undefined); + + const resolvedModuleWithLocations = program.getResolvedModuleFromModuleSpecifier( + pkgSpecifier, + undefined, + { includeLookupLocations: true }, + ); + assert.ok(resolvedModuleWithLocations); + assert.equal(resolvedModuleWithLocations.resolvedModule?.packageId?.name, "pkg"); + assert.ok(resolvedModuleWithLocations.affectingLocations.includes("/node_modules/pkg/package.json")); + + const missingModule = program.getResolvedModule( + "/src/index.ts", + "missing", + ModuleKind.ESNext, + { includeLookupLocations: true }, + ); + assert.ok(missingModule); + assert.equal(missingModule.resolvedModule, undefined); + assert.ok(missingModule.failedLookupLocations.length); + + const typeReference = sourceFile.typeReferenceDirectives[0]; + const resolvedTypeReference = program.getResolvedTypeReferenceDirective( + "/src/index.ts", + "pkg-types", + ModuleKind.None, + ); + assert.equal(resolvedTypeReference?.resolvedTypeReferenceDirective?.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); + assert.equal(resolvedTypeReference?.failedLookupLocations, undefined); + + const resolvedTypeReferenceWithLocations = program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( + typeReference, + "/src/index.ts", + { includeLookupLocations: true }, + ); + assert.ok(resolvedTypeReferenceWithLocations); + assert.ok(resolvedTypeReferenceWithLocations.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); + + program.dispose(); + }); + test("createProgram ignores an on-disk tsconfig", () => { using api = spawnAPI({ "/tsconfig.json": JSON.stringify({ diff --git a/tsc/internal/api/proto.go b/tsc/internal/api/proto.go index 107fbc580057e..807cb19bbf09b 100644 --- a/tsc/internal/api/proto.go +++ b/tsc/internal/api/proto.go @@ -18,6 +18,7 @@ import ( "github.com/microsoft/TypeScript/tsc/internal/locale" "github.com/microsoft/TypeScript/tsc/internal/ls/lsconv" "github.com/microsoft/TypeScript/tsc/internal/lsp/lsproto" + "github.com/microsoft/TypeScript/tsc/internal/module" "github.com/microsoft/TypeScript/tsc/internal/packagejson" "github.com/microsoft/TypeScript/tsc/internal/project" "github.com/microsoft/TypeScript/tsc/internal/scanner" @@ -66,42 +67,46 @@ const ( MethodBatchRequests Method = "batchRequests" - MethodInitialize Method = "initialize" - MethodUpdateSnapshot Method = "updateSnapshot" - MethodUpdateTemporarySnapshot Method = "updateTemporarySnapshot" - MethodCreateProgram Method = "createProgram" - MethodParseCommandLine Method = "parseCommandLine" - MethodReadConfigFile Method = "readConfigFile" - MethodParseJsonConfigFile Method = "parseJsonConfigFileContent" - MethodParseConfigFile Method = "parseConfigFile" - MethodTranspileModule Method = "transpileModule" - MethodTranspileModuleFromFile Method = "transpileModuleFromFile" - MethodTranspileDeclaration Method = "transpileDeclaration" - MethodTranspileDeclarationFromFile Method = "transpileDeclarationFromFile" - MethodGetDefaultProjectForFile Method = "getDefaultProjectForFile" - MethodGetSymbolAtPosition Method = "getSymbolAtPosition" - MethodGetSymbolsAtPositions Method = "getSymbolsAtPositions" - MethodGetSymbolAtLocation Method = "getSymbolAtLocation" - MethodGetSymbolsAtLocations Method = "getSymbolsAtLocations" - MethodGetSymbolOfSourceFile Method = "getSymbolOfSourceFile" - MethodGetSymbolsOfSourceFiles Method = "getSymbolsOfSourceFiles" - MethodGetTypeOfSymbol Method = "getTypeOfSymbol" - MethodGetTypesOfSymbols Method = "getTypesOfSymbols" - MethodGetDeclaredTypeOfSymbol Method = "getDeclaredTypeOfSymbol" - MethodGetNonMissingTypeOfSymbol Method = "getNonMissingTypeOfSymbol" - MethodGetSourceFile Method = "getSourceFile" - MethodGetSourceFileNames Method = "getSourceFileNames" - MethodGetSourceFileMetadata Method = "getSourceFileMetadata" - MethodGetConfigFileNames Method = "getConfigFileNames" - MethodGetConfigSourceFile Method = "getConfigSourceFile" - MethodResolveName Method = "resolveName" - MethodGetSymbolsInScope Method = "getSymbolsInScope" - MethodGetSignaturesOfType Method = "getSignaturesOfType" - MethodGetResolvedSignature Method = "getResolvedSignature" - MethodGetTypeAtLocation Method = "getTypeAtLocation" - MethodGetTypeAtLocations Method = "getTypeAtLocations" - MethodGetTypeAtPosition Method = "getTypeAtPosition" - MethodGetTypesAtPositions Method = "getTypesAtPositions" + MethodInitialize Method = "initialize" + MethodUpdateSnapshot Method = "updateSnapshot" + MethodUpdateTemporarySnapshot Method = "updateTemporarySnapshot" + MethodCreateProgram Method = "createProgram" + MethodParseCommandLine Method = "parseCommandLine" + MethodReadConfigFile Method = "readConfigFile" + MethodParseJsonConfigFile Method = "parseJsonConfigFileContent" + MethodParseConfigFile Method = "parseConfigFile" + MethodTranspileModule Method = "transpileModule" + MethodTranspileModuleFromFile Method = "transpileModuleFromFile" + MethodTranspileDeclaration Method = "transpileDeclaration" + MethodTranspileDeclarationFromFile Method = "transpileDeclarationFromFile" + MethodGetDefaultProjectForFile Method = "getDefaultProjectForFile" + MethodGetSymbolAtPosition Method = "getSymbolAtPosition" + MethodGetSymbolsAtPositions Method = "getSymbolsAtPositions" + MethodGetSymbolAtLocation Method = "getSymbolAtLocation" + MethodGetSymbolsAtLocations Method = "getSymbolsAtLocations" + MethodGetSymbolOfSourceFile Method = "getSymbolOfSourceFile" + MethodGetSymbolsOfSourceFiles Method = "getSymbolsOfSourceFiles" + MethodGetTypeOfSymbol Method = "getTypeOfSymbol" + MethodGetTypesOfSymbols Method = "getTypesOfSymbols" + MethodGetDeclaredTypeOfSymbol Method = "getDeclaredTypeOfSymbol" + MethodGetNonMissingTypeOfSymbol Method = "getNonMissingTypeOfSymbol" + MethodGetSourceFile Method = "getSourceFile" + MethodGetSourceFileNames Method = "getSourceFileNames" + MethodGetSourceFileMetadata Method = "getSourceFileMetadata" + MethodGetResolvedModule Method = "getResolvedModule" + MethodGetResolvedModuleFromModuleSpecifier Method = "getResolvedModuleFromModuleSpecifier" + MethodGetResolvedTypeReferenceDirective Method = "getResolvedTypeReferenceDirective" + MethodGetResolvedTypeReferenceDirectiveFromReference Method = "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective" + MethodGetConfigFileNames Method = "getConfigFileNames" + MethodGetConfigSourceFile Method = "getConfigSourceFile" + MethodResolveName Method = "resolveName" + MethodGetSymbolsInScope Method = "getSymbolsInScope" + MethodGetSignaturesOfType Method = "getSignaturesOfType" + MethodGetResolvedSignature Method = "getResolvedSignature" + MethodGetTypeAtLocation Method = "getTypeAtLocation" + MethodGetTypeAtLocations Method = "getTypeAtLocations" + MethodGetTypeAtPosition Method = "getTypeAtPosition" + MethodGetTypesAtPositions Method = "getTypesAtPositions" // Symbol sub-property methods MethodGetParentOfSymbol Method = "getParentOfSymbol" @@ -438,44 +443,48 @@ type UpdateSnapshotResponse struct { } var unmarshalers = map[Method]func([]byte) (any, error){ - MethodBatchRequests: unmarshallerFor[BatchRequestsParams], - MethodRelease: unmarshallerFor[ReleaseParams], - MethodInitialize: noParams, - MethodUpdateSnapshot: unmarshallerFor[UpdateSnapshotParams], - MethodUpdateTemporarySnapshot: unmarshallerFor[UpdateTemporarySnapshotParams], - MethodCreateProgram: unmarshallerFor[CreateProgramParams], - MethodParseCommandLine: unmarshallerFor[ParseCommandLineParams], - MethodReadConfigFile: unmarshallerFor[ReadConfigFileParams], - MethodParseJsonConfigFile: unmarshallerFor[ParseJsonConfigFileContentParams], - MethodParseConfigFile: unmarshallerFor[ParseConfigFileParams], - MethodTranspileModule: unmarshallerFor[TranspileParams], - MethodTranspileModuleFromFile: unmarshallerFor[TranspileFromFileParams], - MethodTranspileDeclaration: unmarshallerFor[TranspileParams], - MethodTranspileDeclarationFromFile: unmarshallerFor[TranspileFromFileParams], - MethodGetDefaultProjectForFile: unmarshallerFor[GetDefaultProjectForFileParams], - MethodGetSourceFile: unmarshallerFor[GetSourceFileParams], - MethodGetSourceFileNames: unmarshallerFor[GetSourceFileNamesParams], - MethodGetSourceFileMetadata: unmarshallerFor[GetSourceFileParams], - MethodGetConfigFileNames: unmarshallerFor[GetProjectDiagnosticsParams], - MethodGetConfigSourceFile: unmarshallerFor[GetSourceFileParams], - MethodGetSymbolAtPosition: unmarshallerFor[GetSymbolAtPositionParams], - MethodGetSymbolsAtPositions: unmarshallerFor[GetSymbolsAtPositionsParams], - MethodGetSymbolAtLocation: unmarshallerFor[GetSymbolAtLocationParams], - MethodGetSymbolsAtLocations: unmarshallerFor[GetSymbolsAtLocationsParams], - MethodGetSymbolOfSourceFile: unmarshallerFor[GetSymbolOfSourceFileParams], - MethodGetSymbolsOfSourceFiles: unmarshallerFor[GetSymbolsOfSourceFilesParams], - MethodGetTypeOfSymbol: unmarshallerFor[GetTypeOfSymbolParams], - MethodGetTypesOfSymbols: unmarshallerFor[GetTypesOfSymbolsParams], - MethodGetDeclaredTypeOfSymbol: unmarshallerFor[GetTypeOfSymbolParams], - MethodGetNonMissingTypeOfSymbol: unmarshallerFor[GetTypeOfSymbolParams], - MethodResolveName: unmarshallerFor[ResolveNameParams], - MethodGetSymbolsInScope: unmarshallerFor[GetSymbolsInScopeParams], - MethodGetSignaturesOfType: unmarshallerFor[GetSignaturesOfTypeParams], - MethodGetResolvedSignature: unmarshallerFor[GetResolvedSignatureParams], - MethodGetTypeAtLocation: unmarshallerFor[GetTypeAtLocationParams], - MethodGetTypeAtLocations: unmarshallerFor[GetTypeAtLocationsParams], - MethodGetTypeAtPosition: unmarshallerFor[GetTypeAtPositionParams], - MethodGetTypesAtPositions: unmarshallerFor[GetTypesAtPositionsParams], + MethodBatchRequests: unmarshallerFor[BatchRequestsParams], + MethodRelease: unmarshallerFor[ReleaseParams], + MethodInitialize: noParams, + MethodUpdateSnapshot: unmarshallerFor[UpdateSnapshotParams], + MethodUpdateTemporarySnapshot: unmarshallerFor[UpdateTemporarySnapshotParams], + MethodCreateProgram: unmarshallerFor[CreateProgramParams], + MethodParseCommandLine: unmarshallerFor[ParseCommandLineParams], + MethodReadConfigFile: unmarshallerFor[ReadConfigFileParams], + MethodParseJsonConfigFile: unmarshallerFor[ParseJsonConfigFileContentParams], + MethodParseConfigFile: unmarshallerFor[ParseConfigFileParams], + MethodTranspileModule: unmarshallerFor[TranspileParams], + MethodTranspileModuleFromFile: unmarshallerFor[TranspileFromFileParams], + MethodTranspileDeclaration: unmarshallerFor[TranspileParams], + MethodTranspileDeclarationFromFile: unmarshallerFor[TranspileFromFileParams], + MethodGetDefaultProjectForFile: unmarshallerFor[GetDefaultProjectForFileParams], + MethodGetSourceFile: unmarshallerFor[GetSourceFileParams], + MethodGetSourceFileNames: unmarshallerFor[GetSourceFileNamesParams], + MethodGetSourceFileMetadata: unmarshallerFor[GetSourceFileParams], + MethodGetResolvedModule: unmarshallerFor[GetResolvedModuleParams], + MethodGetResolvedModuleFromModuleSpecifier: unmarshallerFor[GetResolvedModuleFromModuleSpecifierParams], + MethodGetResolvedTypeReferenceDirective: unmarshallerFor[GetResolvedTypeReferenceDirectiveParams], + MethodGetResolvedTypeReferenceDirectiveFromReference: unmarshallerFor[GetResolvedTypeReferenceDirectiveFromReferenceParams], + MethodGetConfigFileNames: unmarshallerFor[GetProjectDiagnosticsParams], + MethodGetConfigSourceFile: unmarshallerFor[GetSourceFileParams], + MethodGetSymbolAtPosition: unmarshallerFor[GetSymbolAtPositionParams], + MethodGetSymbolsAtPositions: unmarshallerFor[GetSymbolsAtPositionsParams], + MethodGetSymbolAtLocation: unmarshallerFor[GetSymbolAtLocationParams], + MethodGetSymbolsAtLocations: unmarshallerFor[GetSymbolsAtLocationsParams], + MethodGetSymbolOfSourceFile: unmarshallerFor[GetSymbolOfSourceFileParams], + MethodGetSymbolsOfSourceFiles: unmarshallerFor[GetSymbolsOfSourceFilesParams], + MethodGetTypeOfSymbol: unmarshallerFor[GetTypeOfSymbolParams], + MethodGetTypesOfSymbols: unmarshallerFor[GetTypesOfSymbolsParams], + MethodGetDeclaredTypeOfSymbol: unmarshallerFor[GetTypeOfSymbolParams], + MethodGetNonMissingTypeOfSymbol: unmarshallerFor[GetTypeOfSymbolParams], + MethodResolveName: unmarshallerFor[ResolveNameParams], + MethodGetSymbolsInScope: unmarshallerFor[GetSymbolsInScopeParams], + MethodGetSignaturesOfType: unmarshallerFor[GetSignaturesOfTypeParams], + MethodGetResolvedSignature: unmarshallerFor[GetResolvedSignatureParams], + MethodGetTypeAtLocation: unmarshallerFor[GetTypeAtLocationParams], + MethodGetTypeAtLocations: unmarshallerFor[GetTypeAtLocationsParams], + MethodGetTypeAtPosition: unmarshallerFor[GetTypeAtPositionParams], + MethodGetTypesAtPositions: unmarshallerFor[GetTypesAtPositionsParams], MethodGetParentOfSymbol: unmarshallerFor[GetSymbolPropertyParams], MethodGetMembersOfSymbol: unmarshallerFor[GetSymbolPropertyParams], @@ -1089,6 +1098,93 @@ type GetSourceFileNamesParams struct { Project ProjectID `json:"project"` } +type GetResolvedModuleParams struct { + Snapshot SnapshotID `json:"snapshot"` + Project ProjectID `json:"project"` + File DocumentIdentifier `json:"file"` + ModuleName string `json:"moduleName"` + Mode core.ResolutionMode `json:"mode"` + IncludeLookupLocations bool `json:"includeLookupLocations,omitempty"` +} + +type GetResolvedModuleFromModuleSpecifierParams struct { + Snapshot SnapshotID `json:"snapshot"` + Project ProjectID `json:"project"` + ModuleSpecifier NodeHandle `json:"moduleSpecifier"` + SourceFile *DocumentIdentifier `json:"sourceFile,omitempty"` + IncludeLookupLocations bool `json:"includeLookupLocations,omitempty"` +} + +type GetResolvedTypeReferenceDirectiveParams struct { + Snapshot SnapshotID `json:"snapshot"` + Project ProjectID `json:"project"` + File DocumentIdentifier `json:"file"` + TypeDirectiveName string `json:"typeDirectiveName"` + Mode core.ResolutionMode `json:"mode"` + IncludeLookupLocations bool `json:"includeLookupLocations,omitempty"` +} + +type GetResolvedTypeReferenceDirectiveFromReferenceParams struct { + Snapshot SnapshotID `json:"snapshot"` + Project ProjectID `json:"project"` + SourceFile DocumentIdentifier `json:"sourceFile"` + TypeDirectiveName string `json:"typeDirectiveName"` + ResolutionMode core.ResolutionMode `json:"resolutionMode"` + IncludeLookupLocations bool `json:"includeLookupLocations,omitempty"` +} + +type PackageId struct { + Name string `json:"name"` + SubModuleName string `json:"subModuleName"` + Version string `json:"version"` + PeerDependencies string `json:"peerDependencies"` +} + +func NewPackageId(packageID module.PackageId) *PackageId { + if packageID.Name == "" { + return nil + } + return &PackageId{ + Name: packageID.Name, + SubModuleName: packageID.SubModuleName, + Version: packageID.Version, + PeerDependencies: packageID.PeerDependencies, + } +} + +type ResolvedModule struct { + ResolvedFileName string `json:"resolvedFileName"` + OriginalPath string `json:"originalPath,omitempty"` + Extension string `json:"extension"` + ResolvedUsingTsExtension bool `json:"resolvedUsingTsExtension,omitempty"` + ResolvedUsingExtraExtensions bool `json:"resolvedUsingExtraExtensions,omitempty"` + PackageId *PackageId `json:"packageId,omitempty"` + IsExternalLibraryImport bool `json:"isExternalLibraryImport,omitempty"` + AlternateResult string `json:"alternateResult,omitempty"` +} + +type ResolvedModuleWithFailedLookupLocations struct { + ResolvedModule *ResolvedModule `json:"resolvedModule,omitempty"` + FailedLookupLocations *[]string `json:"failedLookupLocations,omitempty"` + AffectingLocations *[]string `json:"affectingLocations,omitempty"` + ResolutionDiagnostics []*DiagnosticResponse `json:"resolutionDiagnostics,omitempty"` +} + +type ResolvedTypeReferenceDirective struct { + Primary bool `json:"primary"` + ResolvedFileName string `json:"resolvedFileName"` + OriginalPath string `json:"originalPath,omitempty"` + PackageId *PackageId `json:"packageId,omitempty"` + IsExternalLibraryImport bool `json:"isExternalLibraryImport,omitempty"` +} + +type ResolvedTypeReferenceDirectiveWithFailedLookupLocations struct { + ResolvedTypeReferenceDirective *ResolvedTypeReferenceDirective `json:"resolvedTypeReferenceDirective,omitempty"` + FailedLookupLocations *[]string `json:"failedLookupLocations,omitempty"` + AffectingLocations *[]string `json:"affectingLocations,omitempty"` + ResolutionDiagnostics []*DiagnosticResponse `json:"resolutionDiagnostics,omitempty"` +} + // SourceFileMetadata carries program-stored metadata about a single source file. type SourceFileMetadata struct { IsDefaultLibrary bool `json:"isDefaultLibrary"` diff --git a/tsc/internal/api/session.go b/tsc/internal/api/session.go index de5b7c7d5ddd6..96a6a542ed2b4 100644 --- a/tsc/internal/api/session.go +++ b/tsc/internal/api/session.go @@ -28,6 +28,7 @@ import ( "github.com/microsoft/TypeScript/tsc/internal/ls/autoimport" "github.com/microsoft/TypeScript/tsc/internal/ls/lsconv" "github.com/microsoft/TypeScript/tsc/internal/lsp/lsproto" + "github.com/microsoft/TypeScript/tsc/internal/module" "github.com/microsoft/TypeScript/tsc/internal/nodebuilder" "github.com/microsoft/TypeScript/tsc/internal/pprof" "github.com/microsoft/TypeScript/tsc/internal/printer" @@ -771,6 +772,14 @@ func (s *Session) HandleRequest(ctx context.Context, method string, params json. return s.handleGetSourceFileNames(ctx, parsed.(*GetSourceFileNamesParams)) case string(MethodGetSourceFileMetadata): return s.handleGetSourceFileMetadata(ctx, parsed.(*GetSourceFileParams)) + case string(MethodGetResolvedModule): + return s.handleGetResolvedModule(ctx, parsed.(*GetResolvedModuleParams)) + case string(MethodGetResolvedModuleFromModuleSpecifier): + return s.handleGetResolvedModuleFromModuleSpecifier(ctx, parsed.(*GetResolvedModuleFromModuleSpecifierParams)) + case string(MethodGetResolvedTypeReferenceDirective): + return s.handleGetResolvedTypeReferenceDirective(ctx, parsed.(*GetResolvedTypeReferenceDirectiveParams)) + case string(MethodGetResolvedTypeReferenceDirectiveFromReference): + return s.handleGetResolvedTypeReferenceDirectiveFromReference(ctx, parsed.(*GetResolvedTypeReferenceDirectiveFromReferenceParams)) case string(MethodGetConfigFileNames): return s.handleGetConfigFileNames(ctx, parsed.(*GetProjectDiagnosticsParams)) case string(MethodGetConfigSourceFile): @@ -1742,6 +1751,141 @@ func (s *Session) handleGetSourceFileMetadata(ctx context.Context, params *GetSo }, nil } +func newResolvedModuleResponse(resolution *module.ResolvedModule, includeLookupLocations bool) *ResolvedModuleWithFailedLookupLocations { + if resolution == nil { + return nil + } + result := &ResolvedModuleWithFailedLookupLocations{ + ResolutionDiagnostics: NewDiagnosticResponses(resolution.ResolutionDiagnostics), + } + if includeLookupLocations { + result.FailedLookupLocations = &resolution.FailedLookupLocations + result.AffectingLocations = &resolution.AffectingLocations + } + if resolution.IsResolved() { + result.ResolvedModule = &ResolvedModule{ + ResolvedFileName: resolution.ResolvedFileName, + OriginalPath: resolution.OriginalPath, + Extension: resolution.Extension, + ResolvedUsingTsExtension: resolution.ResolvedUsingTsExtension, + ResolvedUsingExtraExtensions: resolution.ResolvedUsingExtraExtensions, + PackageId: NewPackageId(resolution.PackageId), + IsExternalLibraryImport: resolution.IsExternalLibraryImport, + AlternateResult: resolution.AlternateResult, + } + } + return result +} + +func newResolvedTypeReferenceDirectiveResponse(resolution *module.ResolvedTypeReferenceDirective, includeLookupLocations bool) *ResolvedTypeReferenceDirectiveWithFailedLookupLocations { + if resolution == nil { + return nil + } + result := &ResolvedTypeReferenceDirectiveWithFailedLookupLocations{ + ResolutionDiagnostics: NewDiagnosticResponses(resolution.ResolutionDiagnostics), + } + if includeLookupLocations { + result.FailedLookupLocations = &resolution.FailedLookupLocations + result.AffectingLocations = &resolution.AffectingLocations + } + if resolution.IsResolved() { + result.ResolvedTypeReferenceDirective = &ResolvedTypeReferenceDirective{ + Primary: resolution.Primary, + ResolvedFileName: resolution.ResolvedFileName, + OriginalPath: resolution.OriginalPath, + PackageId: NewPackageId(resolution.PackageId), + IsExternalLibraryImport: resolution.IsExternalLibraryImport, + } + } + return result +} + +// @gen-proto-nullable +func (s *Session) handleGetResolvedModule(ctx context.Context, params *GetResolvedModuleParams) (*ResolvedModuleWithFailedLookupLocations, error) { + sd, err := s.getSnapshotData(params.Snapshot) + if err != nil { + return nil, err + } + program, err := sd.getProgram(params.Project) + if err != nil { + return nil, err + } + sourceFile, err := s.resolveOptionalSourceFile(program, ¶ms.File) + if err != nil { + return nil, err + } + return newResolvedModuleResponse(program.GetResolvedModuleWithOptions(sourceFile, params.ModuleName, params.Mode, params.IncludeLookupLocations), params.IncludeLookupLocations), nil +} + +// @gen-proto-nullable +func (s *Session) handleGetResolvedModuleFromModuleSpecifier(ctx context.Context, params *GetResolvedModuleFromModuleSpecifierParams) (*ResolvedModuleWithFailedLookupLocations, error) { + sd, err := s.getSnapshotData(params.Snapshot) + if err != nil { + return nil, err + } + program, err := sd.getProgram(params.Project) + if err != nil { + return nil, err + } + node, err := sd.resolveNodeHandle(program, params.ModuleSpecifier) + if err != nil { + return nil, err + } + if !ast.IsStringLiteralLike(node) { + return nil, fmt.Errorf("%w: moduleSpecifier must be a StringLiteralLike node", ErrClientError) + } + sourceFile := ast.GetSourceFileOfNode(node) + if params.SourceFile != nil { + sourceFile, err = s.resolveOptionalSourceFile(program, params.SourceFile) + if err != nil { + return nil, err + } + } + if sourceFile == nil { + return nil, fmt.Errorf("%w: moduleSpecifier must have a SourceFile ancestor or sourceFile must be provided", ErrClientError) + } + mode := program.GetModeForUsageLocation(sourceFile, node) + return newResolvedModuleResponse(program.GetResolvedModuleWithOptions(sourceFile, node.Text(), mode, params.IncludeLookupLocations), params.IncludeLookupLocations), nil +} + +// @gen-proto-nullable +func (s *Session) handleGetResolvedTypeReferenceDirective(ctx context.Context, params *GetResolvedTypeReferenceDirectiveParams) (*ResolvedTypeReferenceDirectiveWithFailedLookupLocations, error) { + sd, err := s.getSnapshotData(params.Snapshot) + if err != nil { + return nil, err + } + program, err := sd.getProgram(params.Project) + if err != nil { + return nil, err + } + sourceFile, err := s.resolveOptionalSourceFile(program, ¶ms.File) + if err != nil { + return nil, err + } + return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirectiveWithOptions(sourceFile, params.TypeDirectiveName, params.Mode, params.IncludeLookupLocations), params.IncludeLookupLocations), nil +} + +// @gen-proto-nullable +func (s *Session) handleGetResolvedTypeReferenceDirectiveFromReference(ctx context.Context, params *GetResolvedTypeReferenceDirectiveFromReferenceParams) (*ResolvedTypeReferenceDirectiveWithFailedLookupLocations, error) { + sd, err := s.getSnapshotData(params.Snapshot) + if err != nil { + return nil, err + } + program, err := sd.getProgram(params.Project) + if err != nil { + return nil, err + } + sourceFile, err := s.resolveOptionalSourceFile(program, ¶ms.SourceFile) + if err != nil { + return nil, err + } + mode := params.ResolutionMode + if mode == core.ResolutionModeNone { + mode = program.GetDefaultResolutionModeForFile(sourceFile) + } + return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirectiveWithOptions(sourceFile, params.TypeDirectiveName, mode, params.IncludeLookupLocations), params.IncludeLookupLocations), nil +} + // handleGetSymbolAtPosition returns the symbol at a position in a file. // @gen-proto-nullable func (s *Session) handleGetSymbolAtPosition(ctx context.Context, params *GetSymbolAtPositionParams) (*SymbolResponse, error) { diff --git a/tsc/internal/compiler/program.go b/tsc/internal/compiler/program.go index 34f713918a6ad..8a2813be475c9 100644 --- a/tsc/internal/compiler/program.go +++ b/tsc/internal/compiler/program.go @@ -612,6 +612,15 @@ func (p *Program) GetResolvedModule(file ast.HasFileName, moduleReference string return nil } +func (p *Program) GetResolvedModuleWithOptions(file ast.HasFileName, moduleReference string, mode core.ResolutionMode, includeLookupLocations bool) *module.ResolvedModule { + if !includeLookupLocations { + return p.GetResolvedModule(file, moduleReference, mode) + } + redirect, fileName := p.projectReferenceFileMapper.getRedirectForResolution(file) + resolved, _ := p.resolver.ResolveModuleNameWithOptions(moduleReference, fileName, mode, redirect, true) + return resolved +} + func (p *Program) GetResolvedModuleFromModuleSpecifier(file ast.HasFileName, moduleSpecifier *ast.StringLiteralLike) *module.ResolvedModule { if !ast.IsStringLiteralLike(moduleSpecifier) { panic("moduleSpecifier must be a StringLiteralLike") @@ -2098,14 +2107,27 @@ func (p *Program) GetLibFileFromReference(ref *ast.FileReference) *ast.SourceFil } func (p *Program) GetResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeRef *ast.FileReference, sourceFile *ast.SourceFile) *module.ResolvedTypeReferenceDirective { - if resolutions, ok := p.typeResolutionsInFile[sourceFile.Path()]; ok { - if resolved, ok := resolutions[module.ModeAwareCacheKey{Name: typeRef.FileName, Mode: p.getModeForTypeReferenceDirectiveInFile(typeRef, sourceFile)}]; ok { + return p.GetResolvedTypeReferenceDirective(sourceFile, typeRef.FileName, p.getModeForTypeReferenceDirectiveInFile(typeRef, sourceFile)) +} + +func (p *Program) GetResolvedTypeReferenceDirective(file ast.HasFileName, typeDirectiveName string, mode core.ResolutionMode) *module.ResolvedTypeReferenceDirective { + if resolutions, ok := p.typeResolutionsInFile[file.Path()]; ok { + if resolved, ok := resolutions[module.ModeAwareCacheKey{Name: typeDirectiveName, Mode: mode}]; ok { return resolved } } return nil } +func (p *Program) GetResolvedTypeReferenceDirectiveWithOptions(file ast.HasFileName, typeDirectiveName string, mode core.ResolutionMode, includeLookupLocations bool) *module.ResolvedTypeReferenceDirective { + if !includeLookupLocations { + return p.GetResolvedTypeReferenceDirective(file, typeDirectiveName, mode) + } + redirect, fileName := p.projectReferenceFileMapper.getRedirectForResolution(file) + resolved, _ := p.resolver.ResolveTypeReferenceDirectiveWithOptions(typeDirectiveName, fileName, mode, redirect, true) + return resolved +} + func (p *Program) GetResolvedTypeReferenceDirectives() map[tspath.Path]module.ModeAwareCache[*module.ResolvedTypeReferenceDirective] { return p.typeResolutionsInFile } diff --git a/tsc/internal/module/resolver.go b/tsc/internal/module/resolver.go index 2363435bb2207..dfc0592843870 100644 --- a/tsc/internal/module/resolver.go +++ b/tsc/internal/module/resolver.go @@ -73,6 +73,7 @@ type resolutionState struct { name string containingDirectory string isConfigLookup bool + includeLookupLocations bool features NodeResolutionFeatures esmMode bool conditions []string @@ -87,6 +88,8 @@ type resolutionState struct { // is suppressed so the checker does not attempt to extract a TS extension from the original specifier. candidateEndingIsFromConfig bool resolvedPackageDirectory bool + failedLookupLocations []string + affectingLocations []string diagnostics []*ast.Diagnostic } @@ -224,6 +227,16 @@ func (r *Resolver) ResolveTypeReferenceDirective( containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference, +) (*ResolvedTypeReferenceDirective, []DiagAndArgs) { + return r.ResolveTypeReferenceDirectiveWithOptions(typeReferenceDirectiveName, containingFile, resolutionMode, redirectedReference, false) +} + +func (r *Resolver) ResolveTypeReferenceDirectiveWithOptions( + typeReferenceDirectiveName string, + containingFile string, + resolutionMode core.ResolutionMode, + redirectedReference ResolvedProjectReference, + includeLookupLocations bool, ) (*ResolvedTypeReferenceDirective, []DiagAndArgs) { containingDirectory := tspath.GetDirectoryPath(containingFile) traceBuilder := r.newTraceBuilder() @@ -238,7 +251,7 @@ func (r *Resolver) ResolveTypeReferenceDirective( fromInferredTypesContainingFile: fromInferredTypesContainingFile, } - if traceBuilder == nil { + if traceBuilder == nil && !includeLookupLocations { if cached, ok := r.typeRefDirectiveResolutionCache.Get(cacheKey); ok { return cached, nil } @@ -253,18 +266,25 @@ func (r *Resolver) ResolveTypeReferenceDirective( } state := newResolutionState(typeReferenceDirectiveName, containingDirectory, true /*isTypeReferenceDirective*/, resolutionMode, compilerOptions, redirectedReference, r, traceBuilder) + state.includeLookupLocations = includeLookupLocations result := state.resolveTypeReferenceDirective(typeRoots, fromConfig, fromInferredTypesContainingFile) if traceBuilder != nil { traceBuilder.traceTypeReferenceDirectiveResult(typeReferenceDirectiveName, result) } - r.typeRefDirectiveResolutionCache.Set(cacheKey, result) + if !includeLookupLocations { + r.typeRefDirectiveResolutionCache.Set(cacheKey, result) + } return result, traceBuilder.getTraces() } func (r *Resolver) ResolveModuleName(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference) (*ResolvedModule, []DiagAndArgs) { + return r.ResolveModuleNameWithOptions(moduleName, containingFile, resolutionMode, redirectedReference, false) +} + +func (r *Resolver) ResolveModuleNameWithOptions(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference, includeLookupLocations bool) (*ResolvedModule, []DiagAndArgs) { containingDirectory := tspath.GetDirectoryPath(containingFile) traceBuilder := r.newTraceBuilder() @@ -275,7 +295,7 @@ func (r *Resolver) ResolveModuleName(moduleName string, containingFile string, r redirectConfigName: getRedirectConfigName(redirectedReference), } - if traceBuilder == nil { + if traceBuilder == nil && !includeLookupLocations { if cached, ok := r.moduleResolutionCache.Get(cacheKey); ok { return cached, nil } @@ -302,6 +322,7 @@ func (r *Resolver) ResolveModuleName(moduleName string, containingFile string, r switch moduleResolution { case core.ModuleResolutionKindNode16, core.ModuleResolutionKindNodeNext, core.ModuleResolutionKindBundler: state := newResolutionState(moduleName, containingDirectory, false /*isTypeReferenceDirective*/, resolutionMode, compilerOptions, redirectedReference, r, traceBuilder) + state.includeLookupLocations = includeLookupLocations result = state.resolveNodeLike() default: panic(fmt.Sprintf("Unexpected moduleResolution: %d", moduleResolution)) @@ -319,8 +340,10 @@ func (r *Resolver) ResolveModuleName(moduleName string, containingFile string, r } } - finalResult := r.tryResolveFromTypingsLocation(moduleName, containingDirectory, result, traceBuilder) - r.moduleResolutionCache.Set(cacheKey, finalResult) + finalResult := r.tryResolveFromTypingsLocation(moduleName, containingDirectory, result, traceBuilder, includeLookupLocations) + if !includeLookupLocations { + r.moduleResolutionCache.Set(cacheKey, finalResult) + } return finalResult, traceBuilder.getTraces() } @@ -336,7 +359,7 @@ func (r *Resolver) ResolvePackageDirectory(moduleName string, containingFile str return nil } -func (r *Resolver) tryResolveFromTypingsLocation(moduleName string, containingDirectory string, originalResult *ResolvedModule, traceBuilder *tracer) *ResolvedModule { +func (r *Resolver) tryResolveFromTypingsLocation(moduleName string, containingDirectory string, originalResult *ResolvedModule, traceBuilder *tracer, includeLookupLocations bool) *ResolvedModule { if r.typingsLocation == "" || tspath.IsExternalModuleNameRelative(moduleName) || (originalResult.ResolvedFileName != "" && tspath.ExtensionIsOneOf(originalResult.Extension, tspath.SupportedTSExtensionsWithJsonFlat)) { @@ -353,6 +376,7 @@ func (r *Resolver) tryResolveFromTypingsLocation(moduleName string, containingDi r, traceBuilder, ) + state.includeLookupLocations = includeLookupLocations if traceBuilder != nil { traceBuilder.write(diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, r.projectName, moduleName, r.typingsLocation) } @@ -361,6 +385,8 @@ func (r *Resolver) tryResolveFromTypingsLocation(moduleName string, containingDi return originalResult } result := state.createResolvedModule(globalResolved, true) + result.FailedLookupLocations = append(originalResult.FailedLookupLocations, result.FailedLookupLocations...) + result.AffectingLocations = append(originalResult.AffectingLocations, result.AffectingLocations...) result.ResolutionDiagnostics = append(originalResult.ResolutionDiagnostics, result.ResolutionDiagnostics...) return result } @@ -1168,6 +1194,8 @@ func (r *resolutionState) createResolvedModuleHandlingSymlink(resolved *resolved func (r *resolutionState) createResolvedModule(resolved *resolved, isExternalLibraryImport bool) *ResolvedModule { var resolvedModule ResolvedModule + resolvedModule.FailedLookupLocations = r.failedLookupLocations + resolvedModule.AffectingLocations = r.affectingLocations resolvedModule.ResolutionDiagnostics = r.diagnostics if resolved != nil { @@ -1184,6 +1212,8 @@ func (r *resolutionState) createResolvedModule(resolved *resolved, isExternalLib func (r *resolutionState) createResolvedTypeReferenceDirective(resolved *resolved, primary bool) *ResolvedTypeReferenceDirective { var resolvedTypeReferenceDirective ResolvedTypeReferenceDirective + resolvedTypeReferenceDirective.FailedLookupLocations = r.failedLookupLocations + resolvedTypeReferenceDirective.AffectingLocations = r.affectingLocations resolvedTypeReferenceDirective.ResolutionDiagnostics = r.diagnostics if resolved.isResolved() { @@ -1607,6 +1637,9 @@ func (r *resolutionState) tryFileLookup(fileName string) bool { } else if r.tracer != nil { r.tracer.write(diagnostics.File_0_does_not_exist, fileName) } + if r.includeLookupLocations { + r.failedLookupLocations = append(r.failedLookupLocations, fileName) + } return false } @@ -1769,11 +1802,17 @@ func (r *resolutionState) getPackageJsonInfo(packageDirectory string) *packagejs if r.tracer != nil { r.tracer.write(diagnostics.File_0_exists_according_to_earlier_cached_lookups, packageJsonPath) } + if r.includeLookupLocations { + r.affectingLocations = append(r.affectingLocations, packageJsonPath) + } return existing.WithPackageDirectory(packageDirectory) } else { if existing.DirectoryExists && r.tracer != nil { r.tracer.write(diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, packageJsonPath) } + if r.includeLookupLocations { + r.failedLookupLocations = append(r.failedLookupLocations, packageJsonPath) + } return nil } } @@ -1795,6 +1834,9 @@ func (r *resolutionState) getPackageJsonInfo(packageDirectory string) *packagejs }, } result = r.resolver.packageJsonInfoCache.Set(packageJsonPath, result) + if r.includeLookupLocations { + r.affectingLocations = append(r.affectingLocations, packageJsonPath) + } return result.WithPackageDirectory(packageDirectory) } else { if directoryExists && r.tracer != nil { @@ -1804,6 +1846,9 @@ func (r *resolutionState) getPackageJsonInfo(packageDirectory string) *packagejs PackageDirectory: packageDirectory, DirectoryExists: directoryExists, }) + if r.includeLookupLocations { + r.failedLookupLocations = append(r.failedLookupLocations, packageJsonPath) + } } return nil } diff --git a/tsc/internal/module/types.go b/tsc/internal/module/types.go index 72e2573adf3fe..64d2b254ae528 100644 --- a/tsc/internal/module/types.go +++ b/tsc/internal/module/types.go @@ -62,7 +62,13 @@ func (p *PackageId) PackageName() string { return p.Name } +type LookupLocations struct { + FailedLookupLocations []string + AffectingLocations []string +} + type ResolvedModule struct { + LookupLocations ResolutionDiagnostics []*ast.Diagnostic ResolvedFileName string OriginalPath string @@ -79,6 +85,7 @@ func (r *ResolvedModule) IsResolved() bool { } type ResolvedTypeReferenceDirective struct { + LookupLocations ResolutionDiagnostics []*ast.Diagnostic Primary bool ResolvedFileName string From 3af543d76b1eb251d1732e7c4e4dc5fa7ae9efc4 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 11 Sep 2026 10:55:00 -0700 Subject: [PATCH 2/3] Remove includeLookupLocations option, always include them for now --- packages/typescript/src/api/async/api.ts | 75 ------ .../typescript/src/api/proto.generated.ts | 12 +- packages/typescript/src/api/sync/api.ts | 247 ++++++++---------- packages/typescript/test/async/api.test.ts | 16 +- .../test/sync/api-generators.test.ts | 4 +- packages/typescript/test/sync/api.test.ts | 16 +- tsc/internal/api/proto.go | 50 ++-- tsc/internal/api/session.go | 24 +- tsc/internal/compiler/program.go | 14 +- tsc/internal/module/resolver.go | 21 +- 10 files changed, 172 insertions(+), 307 deletions(-) diff --git a/packages/typescript/src/api/async/api.ts b/packages/typescript/src/api/async/api.ts index b373509ef22c8..4bfb540843f5c 100644 --- a/packages/typescript/src/api/async/api.ts +++ b/packages/typescript/src/api/async/api.ts @@ -228,29 +228,6 @@ export interface TranspileOptions { reportDiagnostics?: boolean; } -export interface ResolutionOptions { - /** Include failed and resolution-affecting file lookup locations in the result. */ - includeLookupLocations?: boolean | undefined; -} - -export interface ResolutionOptionsWithLookupLocations { - includeLookupLocations: true; -} - -export type ResolvedModuleWithLookupLocations = - & Omit - & { - failedLookupLocations: string[]; - affectingLocations: string[]; - }; - -export type ResolvedTypeReferenceDirectiveWithLookupLocations = - & Omit - & { - failedLookupLocations: string[]; - affectingLocations: string[]; - }; - export interface TranspileOutput { outputText: string; diagnostics?: readonly Diagnostic[] | undefined; @@ -1258,23 +1235,10 @@ export class Program implements FormatDiagnosticsHost { return this.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, this.snapshotId, this.project.id); } - getResolvedModule( - file: DocumentIdentifier, - moduleName: string, - mode: ModuleKind, - options: ResolutionOptionsWithLookupLocations, - ): Promise; - getResolvedModule( - file: DocumentIdentifier, - moduleName: string, - mode: ModuleKind, - options?: ResolutionOptions, - ): Promise; async getResolvedModule( file: DocumentIdentifier, moduleName: string, mode: ModuleKind, - options?: ResolutionOptions, ): Promise { const result = await this.client.apiRequest("getResolvedModule", { snapshot: this.snapshotId, @@ -1282,53 +1246,27 @@ export class Program implements FormatDiagnosticsHost { file, moduleName, mode, - includeLookupLocations: options?.includeLookupLocations, }); return result ?? undefined; } - getResolvedModuleFromModuleSpecifier( - moduleSpecifier: StringLiteralLikeNode, - sourceFile: DocumentIdentifier | undefined, - options: ResolutionOptionsWithLookupLocations, - ): Promise; - getResolvedModuleFromModuleSpecifier( - moduleSpecifier: StringLiteralLikeNode, - sourceFile?: DocumentIdentifier, - options?: ResolutionOptions, - ): Promise; async getResolvedModuleFromModuleSpecifier( moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, - options?: ResolutionOptions, ): Promise { const result = await this.client.apiRequest("getResolvedModuleFromModuleSpecifier", { snapshot: this.snapshotId, project: this.project.id, moduleSpecifier: getNodeId(moduleSpecifier), sourceFile, - includeLookupLocations: options?.includeLookupLocations, }); return result ?? undefined; } - getResolvedTypeReferenceDirective( - file: DocumentIdentifier, - typeDirectiveName: string, - mode: ModuleKind, - options: ResolutionOptionsWithLookupLocations, - ): Promise; - getResolvedTypeReferenceDirective( - file: DocumentIdentifier, - typeDirectiveName: string, - mode: ModuleKind, - options?: ResolutionOptions, - ): Promise; async getResolvedTypeReferenceDirective( file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, - options?: ResolutionOptions, ): Promise { const result = await this.client.apiRequest("getResolvedTypeReferenceDirective", { snapshot: this.snapshotId, @@ -1336,25 +1274,13 @@ export class Program implements FormatDiagnosticsHost { file, typeDirectiveName, mode, - includeLookupLocations: options?.includeLookupLocations, }); return result ?? undefined; } - getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( - typeReferenceDirective: FileReference, - sourceFile: DocumentIdentifier, - options: ResolutionOptionsWithLookupLocations, - ): Promise; - getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( - typeReferenceDirective: FileReference, - sourceFile: DocumentIdentifier, - options?: ResolutionOptions, - ): Promise; async getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, - options?: ResolutionOptions, ): Promise { const result = await this.client.apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { snapshot: this.snapshotId, @@ -1362,7 +1288,6 @@ export class Program implements FormatDiagnosticsHost { sourceFile, typeDirectiveName: typeReferenceDirective.fileName, resolutionMode: typeReferenceDirective.resolutionMode, - includeLookupLocations: options?.includeLookupLocations, }); return result ?? undefined; } diff --git a/packages/typescript/src/api/proto.generated.ts b/packages/typescript/src/api/proto.generated.ts index 3599f24f08da5..a93de58617af2 100644 --- a/packages/typescript/src/api/proto.generated.ts +++ b/packages/typescript/src/api/proto.generated.ts @@ -485,13 +485,12 @@ export interface GetResolvedModuleParams { file: DocumentIdentifier; moduleName: string; mode: ModuleKind; - includeLookupLocations?: boolean | undefined; } export interface ResolvedModuleWithFailedLookupLocations { resolvedModule?: ResolvedModule | undefined; - failedLookupLocations?: string[] | undefined; - affectingLocations?: string[] | undefined; + failedLookupLocations: string[]; + affectingLocations: string[]; resolutionDiagnostics?: DiagnosticResponse[] | undefined; } @@ -500,7 +499,6 @@ export interface GetResolvedModuleFromModuleSpecifierParams { project: string; moduleSpecifier: string; sourceFile?: DocumentIdentifier | undefined; - includeLookupLocations?: boolean | undefined; } export interface GetResolvedTypeReferenceDirectiveParams { @@ -509,13 +507,12 @@ export interface GetResolvedTypeReferenceDirectiveParams { file: DocumentIdentifier; typeDirectiveName: string; mode: ModuleKind; - includeLookupLocations?: boolean | undefined; } export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { resolvedTypeReferenceDirective?: ResolvedTypeReferenceDirective | undefined; - failedLookupLocations?: string[] | undefined; - affectingLocations?: string[] | undefined; + failedLookupLocations: string[]; + affectingLocations: string[]; resolutionDiagnostics?: DiagnosticResponse[] | undefined; } @@ -525,7 +522,6 @@ export interface GetResolvedTypeReferenceDirectiveFromReferenceParams { sourceFile: DocumentIdentifier; typeDirectiveName: string; resolutionMode: ModuleKind; - includeLookupLocations?: boolean | undefined; } /** GetProjectDiagnosticsParams are parameters for project-wide diagnostic methods. */ diff --git a/packages/typescript/src/api/sync/api.ts b/packages/typescript/src/api/sync/api.ts index ebcae75fc2319..8fb118cc8d4a9 100644 --- a/packages/typescript/src/api/sync/api.ts +++ b/packages/typescript/src/api/sync/api.ts @@ -245,29 +245,6 @@ export interface TranspileOptions { reportDiagnostics?: boolean; } -export interface ResolutionOptions { - /** Include failed and resolution-affecting file lookup locations in the result. */ - includeLookupLocations?: boolean | undefined; -} - -export interface ResolutionOptionsWithLookupLocations { - includeLookupLocations: true; -} - -export type ResolvedModuleWithLookupLocations = - & Omit - & { - failedLookupLocations: string[]; - affectingLocations: string[]; - }; - -export type ResolvedTypeReferenceDirectiveWithLookupLocations = - & Omit - & { - failedLookupLocations: string[]; - affectingLocations: string[]; - }; - export interface TranspileOutput { outputText: string; diagnostics?: readonly Diagnostic[] | undefined; @@ -2317,145 +2294,125 @@ export class Program implements FormatDiagnosticsHost { } get getResolvedModule(): { - (file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): ResolvedModuleWithLookupLocations | undefined; - (file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined; - gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): Generator; - gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): Generator; + (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): ResolvedModuleWithFailedLookupLocations | undefined; + gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind): Generator; } { const owner = this; - function getResolvedModule(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): ResolvedModuleWithLookupLocations | undefined; - function getResolvedModule(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined; - function getResolvedModule(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined { - const result = owner.client.apiRequest("getResolvedModule", { - snapshot: owner.snapshotId, - project: owner.project.id, - file, - moduleName, - mode, - includeLookupLocations: options?.includeLookupLocations, - }); - return result ?? undefined; - } - function gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): Generator; - function gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): Generator; - function* gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind, options?: ResolutionOptions): Generator { - const result = yield* apiRequest("getResolvedModule", { - snapshot: owner.snapshotId, - project: owner.project.id, - file, - moduleName, - mode, - includeLookupLocations: options?.includeLookupLocations, - }); - return result ?? undefined; - } - return cacheGeneratorMethod(owner, "getResolvedModule", getResolvedModule, gen); + return cacheGeneratorMethod( + owner, + "getResolvedModule", + function (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): ResolvedModuleWithFailedLookupLocations | undefined { + const result = owner.client.apiRequest("getResolvedModule", { + snapshot: owner.snapshotId, + project: owner.project.id, + file, + moduleName, + mode, + }); + return result ?? undefined; + }, + function* (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): Generator { + const result = yield* apiRequest("getResolvedModule", { + snapshot: owner.snapshotId, + project: owner.project.id, + file, + moduleName, + mode, + }); + return result ?? undefined; + }, + ); } get getResolvedModuleFromModuleSpecifier(): { - (moduleSpecifier: StringLiteralLikeNode, sourceFile: DocumentIdentifier | undefined, options: ResolutionOptionsWithLookupLocations): ResolvedModuleWithLookupLocations | undefined; - (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined; - gen(moduleSpecifier: StringLiteralLikeNode, sourceFile: DocumentIdentifier | undefined, options: ResolutionOptionsWithLookupLocations): Generator; - gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): Generator; + (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): ResolvedModuleWithFailedLookupLocations | undefined; + gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): Generator; } { const owner = this; - function getResolvedModuleFromModuleSpecifier(moduleSpecifier: StringLiteralLikeNode, sourceFile: DocumentIdentifier | undefined, options: ResolutionOptionsWithLookupLocations): ResolvedModuleWithLookupLocations | undefined; - function getResolvedModuleFromModuleSpecifier(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined; - function getResolvedModuleFromModuleSpecifier(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): ResolvedModuleWithFailedLookupLocations | undefined { - const result = owner.client.apiRequest("getResolvedModuleFromModuleSpecifier", { - snapshot: owner.snapshotId, - project: owner.project.id, - moduleSpecifier: getNodeId(moduleSpecifier), - sourceFile, - includeLookupLocations: options?.includeLookupLocations, - }); - return result ?? undefined; - } - function gen(moduleSpecifier: StringLiteralLikeNode, sourceFile: DocumentIdentifier | undefined, options: ResolutionOptionsWithLookupLocations): Generator; - function gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): Generator; - function* gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, options?: ResolutionOptions): Generator { - const result = yield* apiRequest("getResolvedModuleFromModuleSpecifier", { - snapshot: owner.snapshotId, - project: owner.project.id, - moduleSpecifier: getNodeId(moduleSpecifier), - sourceFile, - includeLookupLocations: options?.includeLookupLocations, - }); - return result ?? undefined; - } - return cacheGeneratorMethod(owner, "getResolvedModuleFromModuleSpecifier", getResolvedModuleFromModuleSpecifier, gen); + return cacheGeneratorMethod( + owner, + "getResolvedModuleFromModuleSpecifier", + function (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): ResolvedModuleWithFailedLookupLocations | undefined { + const result = owner.client.apiRequest("getResolvedModuleFromModuleSpecifier", { + snapshot: owner.snapshotId, + project: owner.project.id, + moduleSpecifier: getNodeId(moduleSpecifier), + sourceFile, + }); + return result ?? undefined; + }, + function* (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): Generator { + const result = yield* apiRequest("getResolvedModuleFromModuleSpecifier", { + snapshot: owner.snapshotId, + project: owner.project.id, + moduleSpecifier: getNodeId(moduleSpecifier), + sourceFile, + }); + return result ?? undefined; + }, + ); } get getResolvedTypeReferenceDirective(): { - (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): ResolvedTypeReferenceDirectiveWithLookupLocations | undefined; - (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; - gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): Generator; - gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): Generator; + (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; + gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): Generator; } { const owner = this; - function getResolvedTypeReferenceDirective(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): ResolvedTypeReferenceDirectiveWithLookupLocations | undefined; - function getResolvedTypeReferenceDirective(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; - function getResolvedTypeReferenceDirective(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined { - const result = owner.client.apiRequest("getResolvedTypeReferenceDirective", { - snapshot: owner.snapshotId, - project: owner.project.id, - file, - typeDirectiveName, - mode, - includeLookupLocations: options?.includeLookupLocations, - }); - return result ?? undefined; - } - function gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options: ResolutionOptionsWithLookupLocations): Generator; - function gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): Generator; - function* gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, options?: ResolutionOptions): Generator { - const result = yield* apiRequest("getResolvedTypeReferenceDirective", { - snapshot: owner.snapshotId, - project: owner.project.id, - file, - typeDirectiveName, - mode, - includeLookupLocations: options?.includeLookupLocations, - }); - return result ?? undefined; - } - return cacheGeneratorMethod(owner, "getResolvedTypeReferenceDirective", getResolvedTypeReferenceDirective, gen); + return cacheGeneratorMethod( + owner, + "getResolvedTypeReferenceDirective", + function (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined { + const result = owner.client.apiRequest("getResolvedTypeReferenceDirective", { + snapshot: owner.snapshotId, + project: owner.project.id, + file, + typeDirectiveName, + mode, + }); + return result ?? undefined; + }, + function* (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): Generator { + const result = yield* apiRequest("getResolvedTypeReferenceDirective", { + snapshot: owner.snapshotId, + project: owner.project.id, + file, + typeDirectiveName, + mode, + }); + return result ?? undefined; + }, + ); } get getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(): { - (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options: ResolutionOptionsWithLookupLocations): ResolvedTypeReferenceDirectiveWithLookupLocations | undefined; - (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; - gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options: ResolutionOptionsWithLookupLocations): Generator; - gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): Generator; + (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; + gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): Generator; } { const owner = this; - function getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options: ResolutionOptionsWithLookupLocations): ResolvedTypeReferenceDirectiveWithLookupLocations | undefined; - function getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; - function getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined { - const result = owner.client.apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { - snapshot: owner.snapshotId, - project: owner.project.id, - sourceFile, - typeDirectiveName: typeReferenceDirective.fileName, - resolutionMode: typeReferenceDirective.resolutionMode, - includeLookupLocations: options?.includeLookupLocations, - }); - return result ?? undefined; - } - function gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options: ResolutionOptionsWithLookupLocations): Generator; - function gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): Generator; - function* gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, options?: ResolutionOptions): Generator { - const result = yield* apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { - snapshot: owner.snapshotId, - project: owner.project.id, - sourceFile, - typeDirectiveName: typeReferenceDirective.fileName, - resolutionMode: typeReferenceDirective.resolutionMode, - includeLookupLocations: options?.includeLookupLocations, - }); - return result ?? undefined; - } - return cacheGeneratorMethod(owner, "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", getResolvedTypeReferenceDirectiveFromTypeReferenceDirective, gen); + return cacheGeneratorMethod( + owner, + "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", + function (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined { + const result = owner.client.apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { + snapshot: owner.snapshotId, + project: owner.project.id, + sourceFile, + typeDirectiveName: typeReferenceDirective.fileName, + resolutionMode: typeReferenceDirective.resolutionMode, + }); + return result ?? undefined; + }, + function* (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): Generator { + const result = yield* apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { + snapshot: owner.snapshotId, + project: owner.project.id, + sourceFile, + typeDirectiveName: typeReferenceDirective.fileName, + resolutionMode: typeReferenceDirective.resolutionMode, + }); + return result ?? undefined; + }, + ); } get getSourceFileNames(): { diff --git a/packages/typescript/test/async/api.test.ts b/packages/typescript/test/async/api.test.ts index 8cf82ad141f33..7fd5a4218058c 100644 --- a/packages/typescript/test/async/api.test.ts +++ b/packages/typescript/test/async/api.test.ts @@ -347,15 +347,11 @@ import "missing";`, const pkgSpecifier = cast(cast(sourceFile.statements[0], isImportDeclaration).moduleSpecifier, isStringLiteral); const resolvedModule = await program.getResolvedModule("/src/index.ts", "pkg", ModuleKind.ESNext); - assert.equal(resolvedModule?.resolvedModule?.resolvedFileName, "/node_modules/pkg/index.d.ts"); - assert.equal(resolvedModule?.failedLookupLocations, undefined); - assert.equal(resolvedModule?.affectingLocations, undefined); + assert.ok(resolvedModule); + assert.equal(resolvedModule.resolvedModule?.resolvedFileName, "/node_modules/pkg/index.d.ts"); + assert.ok(resolvedModule.affectingLocations.includes("/node_modules/pkg/package.json")); - const resolvedModuleWithLocations = await program.getResolvedModuleFromModuleSpecifier( - pkgSpecifier, - undefined, - { includeLookupLocations: true }, - ); + const resolvedModuleWithLocations = await program.getResolvedModuleFromModuleSpecifier(pkgSpecifier); assert.ok(resolvedModuleWithLocations); assert.equal(resolvedModuleWithLocations.resolvedModule?.packageId?.name, "pkg"); assert.ok(resolvedModuleWithLocations.affectingLocations.includes("/node_modules/pkg/package.json")); @@ -364,7 +360,6 @@ import "missing";`, "/src/index.ts", "missing", ModuleKind.ESNext, - { includeLookupLocations: true }, ); assert.ok(missingModule); assert.equal(missingModule.resolvedModule, undefined); @@ -377,12 +372,11 @@ import "missing";`, ModuleKind.None, ); assert.equal(resolvedTypeReference?.resolvedTypeReferenceDirective?.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); - assert.equal(resolvedTypeReference?.failedLookupLocations, undefined); + assert.ok(resolvedTypeReference?.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); const resolvedTypeReferenceWithLocations = await program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( typeReference, "/src/index.ts", - { includeLookupLocations: true }, ); assert.ok(resolvedTypeReferenceWithLocations); assert.ok(resolvedTypeReferenceWithLocations.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); diff --git a/packages/typescript/test/sync/api-generators.test.ts b/packages/typescript/test/sync/api-generators.test.ts index 0a978202a118b..52ee6e89080a3 100644 --- a/packages/typescript/test/sync/api-generators.test.ts +++ b/packages/typescript/test/sync/api-generators.test.ts @@ -1522,10 +1522,10 @@ describe("API - generator batching", () => { parityCase("LanguageService", "getCompletionsAtPosition", languageService.getCompletionsAtPosition, assertDeepEquivalent, "/src/index.ts", completionPosition, { includeSymbol: true }), parityCase("Program", "getSourceFile", program.getSourceFile, assertOptionalSourceFilesEquivalent, "/src/index.ts"), - parityCase("Program", "getResolvedModule", program.getResolvedModule, assertDeepEquivalent, "/src/index.ts", "./models.js", ModuleKind.CommonJS, { includeLookupLocations: true }), + parityCase("Program", "getResolvedModule", program.getResolvedModule, assertDeepEquivalent, "/src/index.ts", "./models.js", ModuleKind.CommonJS), parityCase("Program", "getResolvedModuleFromModuleSpecifier", program.getResolvedModuleFromModuleSpecifier, assertDeepEquivalent, importSpecifier), parityCase("Program", "getResolvedTypeReferenceDirective", program.getResolvedTypeReferenceDirective, assertDeepEquivalent, "/src/index.ts", "parity", ModuleKind.CommonJS), - parityCase("Program", "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective, assertDeepEquivalent, typeReferenceDirective, "/src/index.ts", { includeLookupLocations: true }), + parityCase("Program", "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective, assertDeepEquivalent, typeReferenceDirective, "/src/index.ts"), parityCase("Program", "getSourceFileNames", program.getSourceFileNames, assertDeepEquivalent), parityCase("Program", "getSourceFileMetadata", program.getSourceFileMetadata, assertDeepEquivalent, "/src/index.ts"), parityCase("Program", "getSourceFileMetadataByPath", program.getSourceFileMetadataByPath, assertDeepEquivalent, indexFile.path), diff --git a/packages/typescript/test/sync/api.test.ts b/packages/typescript/test/sync/api.test.ts index 5a09977e92c38..1ce0b989cc207 100644 --- a/packages/typescript/test/sync/api.test.ts +++ b/packages/typescript/test/sync/api.test.ts @@ -336,15 +336,11 @@ import "missing";`, const pkgSpecifier = cast(cast(sourceFile.statements[0], isImportDeclaration).moduleSpecifier, isStringLiteral); const resolvedModule = program.getResolvedModule("/src/index.ts", "pkg", ModuleKind.ESNext); - assert.equal(resolvedModule?.resolvedModule?.resolvedFileName, "/node_modules/pkg/index.d.ts"); - assert.equal(resolvedModule?.failedLookupLocations, undefined); - assert.equal(resolvedModule?.affectingLocations, undefined); + assert.ok(resolvedModule); + assert.equal(resolvedModule.resolvedModule?.resolvedFileName, "/node_modules/pkg/index.d.ts"); + assert.ok(resolvedModule.affectingLocations.includes("/node_modules/pkg/package.json")); - const resolvedModuleWithLocations = program.getResolvedModuleFromModuleSpecifier( - pkgSpecifier, - undefined, - { includeLookupLocations: true }, - ); + const resolvedModuleWithLocations = program.getResolvedModuleFromModuleSpecifier(pkgSpecifier); assert.ok(resolvedModuleWithLocations); assert.equal(resolvedModuleWithLocations.resolvedModule?.packageId?.name, "pkg"); assert.ok(resolvedModuleWithLocations.affectingLocations.includes("/node_modules/pkg/package.json")); @@ -353,7 +349,6 @@ import "missing";`, "/src/index.ts", "missing", ModuleKind.ESNext, - { includeLookupLocations: true }, ); assert.ok(missingModule); assert.equal(missingModule.resolvedModule, undefined); @@ -366,12 +361,11 @@ import "missing";`, ModuleKind.None, ); assert.equal(resolvedTypeReference?.resolvedTypeReferenceDirective?.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); - assert.equal(resolvedTypeReference?.failedLookupLocations, undefined); + assert.ok(resolvedTypeReference?.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); const resolvedTypeReferenceWithLocations = program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( typeReference, "/src/index.ts", - { includeLookupLocations: true }, ); assert.ok(resolvedTypeReferenceWithLocations); assert.ok(resolvedTypeReferenceWithLocations.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); diff --git a/tsc/internal/api/proto.go b/tsc/internal/api/proto.go index 807cb19bbf09b..4518dc120ac1a 100644 --- a/tsc/internal/api/proto.go +++ b/tsc/internal/api/proto.go @@ -1099,38 +1099,34 @@ type GetSourceFileNamesParams struct { } type GetResolvedModuleParams struct { - Snapshot SnapshotID `json:"snapshot"` - Project ProjectID `json:"project"` - File DocumentIdentifier `json:"file"` - ModuleName string `json:"moduleName"` - Mode core.ResolutionMode `json:"mode"` - IncludeLookupLocations bool `json:"includeLookupLocations,omitempty"` + Snapshot SnapshotID `json:"snapshot"` + Project ProjectID `json:"project"` + File DocumentIdentifier `json:"file"` + ModuleName string `json:"moduleName"` + Mode core.ResolutionMode `json:"mode"` } type GetResolvedModuleFromModuleSpecifierParams struct { - Snapshot SnapshotID `json:"snapshot"` - Project ProjectID `json:"project"` - ModuleSpecifier NodeHandle `json:"moduleSpecifier"` - SourceFile *DocumentIdentifier `json:"sourceFile,omitempty"` - IncludeLookupLocations bool `json:"includeLookupLocations,omitempty"` + Snapshot SnapshotID `json:"snapshot"` + Project ProjectID `json:"project"` + ModuleSpecifier NodeHandle `json:"moduleSpecifier"` + SourceFile *DocumentIdentifier `json:"sourceFile,omitempty"` } type GetResolvedTypeReferenceDirectiveParams struct { - Snapshot SnapshotID `json:"snapshot"` - Project ProjectID `json:"project"` - File DocumentIdentifier `json:"file"` - TypeDirectiveName string `json:"typeDirectiveName"` - Mode core.ResolutionMode `json:"mode"` - IncludeLookupLocations bool `json:"includeLookupLocations,omitempty"` + Snapshot SnapshotID `json:"snapshot"` + Project ProjectID `json:"project"` + File DocumentIdentifier `json:"file"` + TypeDirectiveName string `json:"typeDirectiveName"` + Mode core.ResolutionMode `json:"mode"` } type GetResolvedTypeReferenceDirectiveFromReferenceParams struct { - Snapshot SnapshotID `json:"snapshot"` - Project ProjectID `json:"project"` - SourceFile DocumentIdentifier `json:"sourceFile"` - TypeDirectiveName string `json:"typeDirectiveName"` - ResolutionMode core.ResolutionMode `json:"resolutionMode"` - IncludeLookupLocations bool `json:"includeLookupLocations,omitempty"` + Snapshot SnapshotID `json:"snapshot"` + Project ProjectID `json:"project"` + SourceFile DocumentIdentifier `json:"sourceFile"` + TypeDirectiveName string `json:"typeDirectiveName"` + ResolutionMode core.ResolutionMode `json:"resolutionMode"` } type PackageId struct { @@ -1165,8 +1161,8 @@ type ResolvedModule struct { type ResolvedModuleWithFailedLookupLocations struct { ResolvedModule *ResolvedModule `json:"resolvedModule,omitempty"` - FailedLookupLocations *[]string `json:"failedLookupLocations,omitempty"` - AffectingLocations *[]string `json:"affectingLocations,omitempty"` + FailedLookupLocations []string `json:"failedLookupLocations" nonnil:"true"` + AffectingLocations []string `json:"affectingLocations" nonnil:"true"` ResolutionDiagnostics []*DiagnosticResponse `json:"resolutionDiagnostics,omitempty"` } @@ -1180,8 +1176,8 @@ type ResolvedTypeReferenceDirective struct { type ResolvedTypeReferenceDirectiveWithFailedLookupLocations struct { ResolvedTypeReferenceDirective *ResolvedTypeReferenceDirective `json:"resolvedTypeReferenceDirective,omitempty"` - FailedLookupLocations *[]string `json:"failedLookupLocations,omitempty"` - AffectingLocations *[]string `json:"affectingLocations,omitempty"` + FailedLookupLocations []string `json:"failedLookupLocations" nonnil:"true"` + AffectingLocations []string `json:"affectingLocations" nonnil:"true"` ResolutionDiagnostics []*DiagnosticResponse `json:"resolutionDiagnostics,omitempty"` } diff --git a/tsc/internal/api/session.go b/tsc/internal/api/session.go index 96a6a542ed2b4..37f00bc1dd48f 100644 --- a/tsc/internal/api/session.go +++ b/tsc/internal/api/session.go @@ -1751,17 +1751,15 @@ func (s *Session) handleGetSourceFileMetadata(ctx context.Context, params *GetSo }, nil } -func newResolvedModuleResponse(resolution *module.ResolvedModule, includeLookupLocations bool) *ResolvedModuleWithFailedLookupLocations { +func newResolvedModuleResponse(resolution *module.ResolvedModule) *ResolvedModuleWithFailedLookupLocations { if resolution == nil { return nil } result := &ResolvedModuleWithFailedLookupLocations{ + FailedLookupLocations: append([]string{}, resolution.FailedLookupLocations...), + AffectingLocations: append([]string{}, resolution.AffectingLocations...), ResolutionDiagnostics: NewDiagnosticResponses(resolution.ResolutionDiagnostics), } - if includeLookupLocations { - result.FailedLookupLocations = &resolution.FailedLookupLocations - result.AffectingLocations = &resolution.AffectingLocations - } if resolution.IsResolved() { result.ResolvedModule = &ResolvedModule{ ResolvedFileName: resolution.ResolvedFileName, @@ -1777,17 +1775,15 @@ func newResolvedModuleResponse(resolution *module.ResolvedModule, includeLookupL return result } -func newResolvedTypeReferenceDirectiveResponse(resolution *module.ResolvedTypeReferenceDirective, includeLookupLocations bool) *ResolvedTypeReferenceDirectiveWithFailedLookupLocations { +func newResolvedTypeReferenceDirectiveResponse(resolution *module.ResolvedTypeReferenceDirective) *ResolvedTypeReferenceDirectiveWithFailedLookupLocations { if resolution == nil { return nil } result := &ResolvedTypeReferenceDirectiveWithFailedLookupLocations{ + FailedLookupLocations: append([]string{}, resolution.FailedLookupLocations...), + AffectingLocations: append([]string{}, resolution.AffectingLocations...), ResolutionDiagnostics: NewDiagnosticResponses(resolution.ResolutionDiagnostics), } - if includeLookupLocations { - result.FailedLookupLocations = &resolution.FailedLookupLocations - result.AffectingLocations = &resolution.AffectingLocations - } if resolution.IsResolved() { result.ResolvedTypeReferenceDirective = &ResolvedTypeReferenceDirective{ Primary: resolution.Primary, @@ -1814,7 +1810,7 @@ func (s *Session) handleGetResolvedModule(ctx context.Context, params *GetResolv if err != nil { return nil, err } - return newResolvedModuleResponse(program.GetResolvedModuleWithOptions(sourceFile, params.ModuleName, params.Mode, params.IncludeLookupLocations), params.IncludeLookupLocations), nil + return newResolvedModuleResponse(program.GetResolvedModuleWithLookupLocations(sourceFile, params.ModuleName, params.Mode)), nil } // @gen-proto-nullable @@ -1845,7 +1841,7 @@ func (s *Session) handleGetResolvedModuleFromModuleSpecifier(ctx context.Context return nil, fmt.Errorf("%w: moduleSpecifier must have a SourceFile ancestor or sourceFile must be provided", ErrClientError) } mode := program.GetModeForUsageLocation(sourceFile, node) - return newResolvedModuleResponse(program.GetResolvedModuleWithOptions(sourceFile, node.Text(), mode, params.IncludeLookupLocations), params.IncludeLookupLocations), nil + return newResolvedModuleResponse(program.GetResolvedModuleWithLookupLocations(sourceFile, node.Text(), mode)), nil } // @gen-proto-nullable @@ -1862,7 +1858,7 @@ func (s *Session) handleGetResolvedTypeReferenceDirective(ctx context.Context, p if err != nil { return nil, err } - return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirectiveWithOptions(sourceFile, params.TypeDirectiveName, params.Mode, params.IncludeLookupLocations), params.IncludeLookupLocations), nil + return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirectiveWithLookupLocations(sourceFile, params.TypeDirectiveName, params.Mode)), nil } // @gen-proto-nullable @@ -1883,7 +1879,7 @@ func (s *Session) handleGetResolvedTypeReferenceDirectiveFromReference(ctx conte if mode == core.ResolutionModeNone { mode = program.GetDefaultResolutionModeForFile(sourceFile) } - return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirectiveWithOptions(sourceFile, params.TypeDirectiveName, mode, params.IncludeLookupLocations), params.IncludeLookupLocations), nil + return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirectiveWithLookupLocations(sourceFile, params.TypeDirectiveName, mode)), nil } // handleGetSymbolAtPosition returns the symbol at a position in a file. diff --git a/tsc/internal/compiler/program.go b/tsc/internal/compiler/program.go index 8a2813be475c9..4e7e9d22107fd 100644 --- a/tsc/internal/compiler/program.go +++ b/tsc/internal/compiler/program.go @@ -612,12 +612,9 @@ func (p *Program) GetResolvedModule(file ast.HasFileName, moduleReference string return nil } -func (p *Program) GetResolvedModuleWithOptions(file ast.HasFileName, moduleReference string, mode core.ResolutionMode, includeLookupLocations bool) *module.ResolvedModule { - if !includeLookupLocations { - return p.GetResolvedModule(file, moduleReference, mode) - } +func (p *Program) GetResolvedModuleWithLookupLocations(file ast.HasFileName, moduleReference string, mode core.ResolutionMode) *module.ResolvedModule { redirect, fileName := p.projectReferenceFileMapper.getRedirectForResolution(file) - resolved, _ := p.resolver.ResolveModuleNameWithOptions(moduleReference, fileName, mode, redirect, true) + resolved, _ := p.resolver.ResolveModuleNameWithLookupLocations(moduleReference, fileName, mode, redirect) return resolved } @@ -2119,12 +2116,9 @@ func (p *Program) GetResolvedTypeReferenceDirective(file ast.HasFileName, typeDi return nil } -func (p *Program) GetResolvedTypeReferenceDirectiveWithOptions(file ast.HasFileName, typeDirectiveName string, mode core.ResolutionMode, includeLookupLocations bool) *module.ResolvedTypeReferenceDirective { - if !includeLookupLocations { - return p.GetResolvedTypeReferenceDirective(file, typeDirectiveName, mode) - } +func (p *Program) GetResolvedTypeReferenceDirectiveWithLookupLocations(file ast.HasFileName, typeDirectiveName string, mode core.ResolutionMode) *module.ResolvedTypeReferenceDirective { redirect, fileName := p.projectReferenceFileMapper.getRedirectForResolution(file) - resolved, _ := p.resolver.ResolveTypeReferenceDirectiveWithOptions(typeDirectiveName, fileName, mode, redirect, true) + resolved, _ := p.resolver.ResolveTypeReferenceDirectiveWithLookupLocations(typeDirectiveName, fileName, mode, redirect) return resolved } diff --git a/tsc/internal/module/resolver.go b/tsc/internal/module/resolver.go index dfc0592843870..ad7a8a3c4759a 100644 --- a/tsc/internal/module/resolver.go +++ b/tsc/internal/module/resolver.go @@ -228,10 +228,19 @@ func (r *Resolver) ResolveTypeReferenceDirective( resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference, ) (*ResolvedTypeReferenceDirective, []DiagAndArgs) { - return r.ResolveTypeReferenceDirectiveWithOptions(typeReferenceDirectiveName, containingFile, resolutionMode, redirectedReference, false) + return r.resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, resolutionMode, redirectedReference, false) } -func (r *Resolver) ResolveTypeReferenceDirectiveWithOptions( +func (r *Resolver) ResolveTypeReferenceDirectiveWithLookupLocations( + typeReferenceDirectiveName string, + containingFile string, + resolutionMode core.ResolutionMode, + redirectedReference ResolvedProjectReference, +) (*ResolvedTypeReferenceDirective, []DiagAndArgs) { + return r.resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, resolutionMode, redirectedReference, true) +} + +func (r *Resolver) resolveTypeReferenceDirective( typeReferenceDirectiveName string, containingFile string, resolutionMode core.ResolutionMode, @@ -281,10 +290,14 @@ func (r *Resolver) ResolveTypeReferenceDirectiveWithOptions( } func (r *Resolver) ResolveModuleName(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference) (*ResolvedModule, []DiagAndArgs) { - return r.ResolveModuleNameWithOptions(moduleName, containingFile, resolutionMode, redirectedReference, false) + return r.resolveModuleName(moduleName, containingFile, resolutionMode, redirectedReference, false) +} + +func (r *Resolver) ResolveModuleNameWithLookupLocations(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference) (*ResolvedModule, []DiagAndArgs) { + return r.resolveModuleName(moduleName, containingFile, resolutionMode, redirectedReference, true) } -func (r *Resolver) ResolveModuleNameWithOptions(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference, includeLookupLocations bool) (*ResolvedModule, []DiagAndArgs) { +func (r *Resolver) resolveModuleName(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference, includeLookupLocations bool) (*ResolvedModule, []DiagAndArgs) { containingDirectory := tspath.GetDirectoryPath(containingFile) traceBuilder := r.newTraceBuilder() From 6b80b1ae266a56f03173fabcea5dc124c5ca7c30 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 11 Sep 2026 11:09:13 -0700 Subject: [PATCH 3/3] =?UTF-8?q?Wait,=20we=20don=E2=80=99t=20have=20lookup?= =?UTF-8?q?=20locations=20anymore=20at=20all!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/typescript/src/api/async/api.ts | 12 ++-- .../typescript/src/api/proto.generated.ts | 62 +++++++--------- packages/typescript/src/api/sync/api.ts | 36 +++++----- packages/typescript/test/async/api.test.ts | 15 ++-- packages/typescript/test/sync/api.test.ts | 15 ++-- tsc/internal/api/proto.go | 14 ---- tsc/internal/api/session.go | 70 +++++++------------ tsc/internal/compiler/program.go | 12 ---- tsc/internal/module/resolver.go | 70 ++----------------- tsc/internal/module/types.go | 7 -- 10 files changed, 87 insertions(+), 226 deletions(-) diff --git a/packages/typescript/src/api/async/api.ts b/packages/typescript/src/api/async/api.ts index 4bfb540843f5c..35a9c99ad47b5 100644 --- a/packages/typescript/src/api/async/api.ts +++ b/packages/typescript/src/api/async/api.ts @@ -73,9 +73,7 @@ import type { ProjectResponse, ReadConfigFileResponse, ResolvedModule, - ResolvedModuleWithFailedLookupLocations, ResolvedTypeReferenceDirective, - ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SignaturePropertyMethod, SignatureResponse, SourceFileMetadata, @@ -197,9 +195,7 @@ export type { ReadConfigFileResponse, RequestTiming, ResolvedModule, - ResolvedModuleWithFailedLookupLocations, ResolvedTypeReferenceDirective, - ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SourceFileMetadata, StringLiteralType, StringMappingType, @@ -1239,7 +1235,7 @@ export class Program implements FormatDiagnosticsHost { file: DocumentIdentifier, moduleName: string, mode: ModuleKind, - ): Promise { + ): Promise { const result = await this.client.apiRequest("getResolvedModule", { snapshot: this.snapshotId, project: this.project.id, @@ -1253,7 +1249,7 @@ export class Program implements FormatDiagnosticsHost { async getResolvedModuleFromModuleSpecifier( moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier, - ): Promise { + ): Promise { const result = await this.client.apiRequest("getResolvedModuleFromModuleSpecifier", { snapshot: this.snapshotId, project: this.project.id, @@ -1267,7 +1263,7 @@ export class Program implements FormatDiagnosticsHost { file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind, - ): Promise { + ): Promise { const result = await this.client.apiRequest("getResolvedTypeReferenceDirective", { snapshot: this.snapshotId, project: this.project.id, @@ -1281,7 +1277,7 @@ export class Program implements FormatDiagnosticsHost { async getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier, - ): Promise { + ): Promise { const result = await this.client.apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { snapshot: this.snapshotId, project: this.project.id, diff --git a/packages/typescript/src/api/proto.generated.ts b/packages/typescript/src/api/proto.generated.ts index a93de58617af2..5b910f578913c 100644 --- a/packages/typescript/src/api/proto.generated.ts +++ b/packages/typescript/src/api/proto.generated.ts @@ -45,10 +45,10 @@ export interface APIMethodInfo { getSourceFile: APIMethod; getSourceFileNames: APIMethod; getSourceFileMetadata: APIMethod; - getResolvedModule: APIMethod; - getResolvedModuleFromModuleSpecifier: APIMethod; - getResolvedTypeReferenceDirective: APIMethod; - getResolvedTypeReferenceDirectiveFromTypeReferenceDirective: APIMethod; + getResolvedModule: APIMethod; + getResolvedModuleFromModuleSpecifier: APIMethod; + getResolvedTypeReferenceDirective: APIMethod; + getResolvedTypeReferenceDirectiveFromTypeReferenceDirective: APIMethod; getConfigFileNames: APIMethod; getConfigSourceFile: APIMethod; resolveName: APIMethod; @@ -487,11 +487,15 @@ export interface GetResolvedModuleParams { mode: ModuleKind; } -export interface ResolvedModuleWithFailedLookupLocations { - resolvedModule?: ResolvedModule | undefined; - failedLookupLocations: string[]; - affectingLocations: string[]; - resolutionDiagnostics?: DiagnosticResponse[] | undefined; +export interface ResolvedModule { + resolvedFileName: string; + originalPath?: string | undefined; + extension: string; + resolvedUsingTsExtension?: boolean | undefined; + resolvedUsingExtraExtensions?: boolean | undefined; + packageId?: PackageId | undefined; + isExternalLibraryImport?: boolean | undefined; + alternateResult?: string | undefined; } export interface GetResolvedModuleFromModuleSpecifierParams { @@ -509,11 +513,12 @@ export interface GetResolvedTypeReferenceDirectiveParams { mode: ModuleKind; } -export interface ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - resolvedTypeReferenceDirective?: ResolvedTypeReferenceDirective | undefined; - failedLookupLocations: string[]; - affectingLocations: string[]; - resolutionDiagnostics?: DiagnosticResponse[] | undefined; +export interface ResolvedTypeReferenceDirective { + primary: boolean; + resolvedFileName: string; + originalPath?: string | undefined; + packageId?: PackageId | undefined; + isExternalLibraryImport?: boolean | undefined; } export interface GetResolvedTypeReferenceDirectiveFromReferenceParams { @@ -1459,23 +1464,11 @@ export interface TranspileOptions { reportDiagnostics?: boolean | undefined; } -export interface ResolvedModule { - resolvedFileName: string; - originalPath?: string | undefined; - extension: string; - resolvedUsingTsExtension?: boolean | undefined; - resolvedUsingExtraExtensions?: boolean | undefined; - packageId?: PackageId | undefined; - isExternalLibraryImport?: boolean | undefined; - alternateResult?: string | undefined; -} - -export interface ResolvedTypeReferenceDirective { - primary: boolean; - resolvedFileName: string; - originalPath?: string | undefined; - packageId?: PackageId | undefined; - isExternalLibraryImport?: boolean | undefined; +export interface PackageId { + name: string; + subModuleName: string; + version: string; + peerDependencies: string; } export interface ImportAdderAction { @@ -1543,13 +1536,6 @@ export interface ProjectFileChanges { deletedFiles?: string[] | undefined; } -export interface PackageId { - name: string; - subModuleName: string; - version: string; - peerDependencies: string; -} - /** CompletionEntryLabelDetailsResponse holds additional label display text for a completion entry. */ export interface CompletionEntryLabelDetailsResponse { detail?: string | undefined; diff --git a/packages/typescript/src/api/sync/api.ts b/packages/typescript/src/api/sync/api.ts index 8fb118cc8d4a9..222c7dd95c0c7 100644 --- a/packages/typescript/src/api/sync/api.ts +++ b/packages/typescript/src/api/sync/api.ts @@ -90,9 +90,7 @@ import type { ProjectResponse, ReadConfigFileResponse, ResolvedModule, - ResolvedModuleWithFailedLookupLocations, ResolvedTypeReferenceDirective, - ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SignaturePropertyMethod, SignatureResponse, SourceFileMetadata, @@ -214,9 +212,7 @@ export type { ReadConfigFileResponse, RequestTiming, ResolvedModule, - ResolvedModuleWithFailedLookupLocations, ResolvedTypeReferenceDirective, - ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SourceFileMetadata, StringLiteralType, StringMappingType, @@ -2294,14 +2290,14 @@ export class Program implements FormatDiagnosticsHost { } get getResolvedModule(): { - (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): ResolvedModuleWithFailedLookupLocations | undefined; - gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind): Generator; + (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): ResolvedModule | undefined; + gen(file: DocumentIdentifier, moduleName: string, mode: ModuleKind): Generator; } { const owner = this; return cacheGeneratorMethod( owner, "getResolvedModule", - function (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): ResolvedModuleWithFailedLookupLocations | undefined { + function (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): ResolvedModule | undefined { const result = owner.client.apiRequest("getResolvedModule", { snapshot: owner.snapshotId, project: owner.project.id, @@ -2311,7 +2307,7 @@ export class Program implements FormatDiagnosticsHost { }); return result ?? undefined; }, - function* (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): Generator { + function* (file: DocumentIdentifier, moduleName: string, mode: ModuleKind): Generator { const result = yield* apiRequest("getResolvedModule", { snapshot: owner.snapshotId, project: owner.project.id, @@ -2325,14 +2321,14 @@ export class Program implements FormatDiagnosticsHost { } get getResolvedModuleFromModuleSpecifier(): { - (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): ResolvedModuleWithFailedLookupLocations | undefined; - gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): Generator; + (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): ResolvedModule | undefined; + gen(moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): Generator; } { const owner = this; return cacheGeneratorMethod( owner, "getResolvedModuleFromModuleSpecifier", - function (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): ResolvedModuleWithFailedLookupLocations | undefined { + function (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): ResolvedModule | undefined { const result = owner.client.apiRequest("getResolvedModuleFromModuleSpecifier", { snapshot: owner.snapshotId, project: owner.project.id, @@ -2341,7 +2337,7 @@ export class Program implements FormatDiagnosticsHost { }); return result ?? undefined; }, - function* (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): Generator { + function* (moduleSpecifier: StringLiteralLikeNode, sourceFile?: DocumentIdentifier): Generator { const result = yield* apiRequest("getResolvedModuleFromModuleSpecifier", { snapshot: owner.snapshotId, project: owner.project.id, @@ -2354,14 +2350,14 @@ export class Program implements FormatDiagnosticsHost { } get getResolvedTypeReferenceDirective(): { - (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; - gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): Generator; + (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): ResolvedTypeReferenceDirective | undefined; + gen(file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): Generator; } { const owner = this; return cacheGeneratorMethod( owner, "getResolvedTypeReferenceDirective", - function (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined { + function (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): ResolvedTypeReferenceDirective | undefined { const result = owner.client.apiRequest("getResolvedTypeReferenceDirective", { snapshot: owner.snapshotId, project: owner.project.id, @@ -2371,7 +2367,7 @@ export class Program implements FormatDiagnosticsHost { }); return result ?? undefined; }, - function* (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): Generator { + function* (file: DocumentIdentifier, typeDirectiveName: string, mode: ModuleKind): Generator { const result = yield* apiRequest("getResolvedTypeReferenceDirective", { snapshot: owner.snapshotId, project: owner.project.id, @@ -2385,14 +2381,14 @@ export class Program implements FormatDiagnosticsHost { } get getResolvedTypeReferenceDirectiveFromTypeReferenceDirective(): { - (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined; - gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): Generator; + (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): ResolvedTypeReferenceDirective | undefined; + gen(typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): Generator; } { const owner = this; return cacheGeneratorMethod( owner, "getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", - function (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): ResolvedTypeReferenceDirectiveWithFailedLookupLocations | undefined { + function (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): ResolvedTypeReferenceDirective | undefined { const result = owner.client.apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { snapshot: owner.snapshotId, project: owner.project.id, @@ -2402,7 +2398,7 @@ export class Program implements FormatDiagnosticsHost { }); return result ?? undefined; }, - function* (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): Generator { + function* (typeReferenceDirective: FileReference, sourceFile: DocumentIdentifier): Generator { const result = yield* apiRequest("getResolvedTypeReferenceDirectiveFromTypeReferenceDirective", { snapshot: owner.snapshotId, project: owner.project.id, diff --git a/packages/typescript/test/async/api.test.ts b/packages/typescript/test/async/api.test.ts index 7fd5a4218058c..0dacd55c1c1e7 100644 --- a/packages/typescript/test/async/api.test.ts +++ b/packages/typescript/test/async/api.test.ts @@ -348,22 +348,18 @@ import "missing";`, const resolvedModule = await program.getResolvedModule("/src/index.ts", "pkg", ModuleKind.ESNext); assert.ok(resolvedModule); - assert.equal(resolvedModule.resolvedModule?.resolvedFileName, "/node_modules/pkg/index.d.ts"); - assert.ok(resolvedModule.affectingLocations.includes("/node_modules/pkg/package.json")); + assert.equal(resolvedModule.resolvedFileName, "/node_modules/pkg/index.d.ts"); const resolvedModuleWithLocations = await program.getResolvedModuleFromModuleSpecifier(pkgSpecifier); assert.ok(resolvedModuleWithLocations); - assert.equal(resolvedModuleWithLocations.resolvedModule?.packageId?.name, "pkg"); - assert.ok(resolvedModuleWithLocations.affectingLocations.includes("/node_modules/pkg/package.json")); + assert.equal(resolvedModuleWithLocations.packageId?.name, "pkg"); const missingModule = await program.getResolvedModule( "/src/index.ts", "missing", ModuleKind.ESNext, ); - assert.ok(missingModule); - assert.equal(missingModule.resolvedModule, undefined); - assert.ok(missingModule.failedLookupLocations.length); + assert.equal(missingModule, undefined); const typeReference = sourceFile.typeReferenceDirectives[0]; const resolvedTypeReference = await program.getResolvedTypeReferenceDirective( @@ -371,15 +367,14 @@ import "missing";`, "pkg-types", ModuleKind.None, ); - assert.equal(resolvedTypeReference?.resolvedTypeReferenceDirective?.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); - assert.ok(resolvedTypeReference?.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); + assert.equal(resolvedTypeReference?.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); const resolvedTypeReferenceWithLocations = await program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( typeReference, "/src/index.ts", ); assert.ok(resolvedTypeReferenceWithLocations); - assert.ok(resolvedTypeReferenceWithLocations.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); + assert.equal(resolvedTypeReferenceWithLocations.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); await program.dispose(); }); diff --git a/packages/typescript/test/sync/api.test.ts b/packages/typescript/test/sync/api.test.ts index 1ce0b989cc207..92ae14b894b8c 100644 --- a/packages/typescript/test/sync/api.test.ts +++ b/packages/typescript/test/sync/api.test.ts @@ -337,22 +337,18 @@ import "missing";`, const resolvedModule = program.getResolvedModule("/src/index.ts", "pkg", ModuleKind.ESNext); assert.ok(resolvedModule); - assert.equal(resolvedModule.resolvedModule?.resolvedFileName, "/node_modules/pkg/index.d.ts"); - assert.ok(resolvedModule.affectingLocations.includes("/node_modules/pkg/package.json")); + assert.equal(resolvedModule.resolvedFileName, "/node_modules/pkg/index.d.ts"); const resolvedModuleWithLocations = program.getResolvedModuleFromModuleSpecifier(pkgSpecifier); assert.ok(resolvedModuleWithLocations); - assert.equal(resolvedModuleWithLocations.resolvedModule?.packageId?.name, "pkg"); - assert.ok(resolvedModuleWithLocations.affectingLocations.includes("/node_modules/pkg/package.json")); + assert.equal(resolvedModuleWithLocations.packageId?.name, "pkg"); const missingModule = program.getResolvedModule( "/src/index.ts", "missing", ModuleKind.ESNext, ); - assert.ok(missingModule); - assert.equal(missingModule.resolvedModule, undefined); - assert.ok(missingModule.failedLookupLocations.length); + assert.equal(missingModule, undefined); const typeReference = sourceFile.typeReferenceDirectives[0]; const resolvedTypeReference = program.getResolvedTypeReferenceDirective( @@ -360,15 +356,14 @@ import "missing";`, "pkg-types", ModuleKind.None, ); - assert.equal(resolvedTypeReference?.resolvedTypeReferenceDirective?.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); - assert.ok(resolvedTypeReference?.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); + assert.equal(resolvedTypeReference?.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); const resolvedTypeReferenceWithLocations = program.getResolvedTypeReferenceDirectiveFromTypeReferenceDirective( typeReference, "/src/index.ts", ); assert.ok(resolvedTypeReferenceWithLocations); - assert.ok(resolvedTypeReferenceWithLocations.affectingLocations.includes("/node_modules/@types/pkg-types/package.json")); + assert.equal(resolvedTypeReferenceWithLocations.resolvedFileName, "/node_modules/@types/pkg-types/index.d.ts"); program.dispose(); }); diff --git a/tsc/internal/api/proto.go b/tsc/internal/api/proto.go index 4518dc120ac1a..b67f21129e528 100644 --- a/tsc/internal/api/proto.go +++ b/tsc/internal/api/proto.go @@ -1159,13 +1159,6 @@ type ResolvedModule struct { AlternateResult string `json:"alternateResult,omitempty"` } -type ResolvedModuleWithFailedLookupLocations struct { - ResolvedModule *ResolvedModule `json:"resolvedModule,omitempty"` - FailedLookupLocations []string `json:"failedLookupLocations" nonnil:"true"` - AffectingLocations []string `json:"affectingLocations" nonnil:"true"` - ResolutionDiagnostics []*DiagnosticResponse `json:"resolutionDiagnostics,omitempty"` -} - type ResolvedTypeReferenceDirective struct { Primary bool `json:"primary"` ResolvedFileName string `json:"resolvedFileName"` @@ -1174,13 +1167,6 @@ type ResolvedTypeReferenceDirective struct { IsExternalLibraryImport bool `json:"isExternalLibraryImport,omitempty"` } -type ResolvedTypeReferenceDirectiveWithFailedLookupLocations struct { - ResolvedTypeReferenceDirective *ResolvedTypeReferenceDirective `json:"resolvedTypeReferenceDirective,omitempty"` - FailedLookupLocations []string `json:"failedLookupLocations" nonnil:"true"` - AffectingLocations []string `json:"affectingLocations" nonnil:"true"` - ResolutionDiagnostics []*DiagnosticResponse `json:"resolutionDiagnostics,omitempty"` -} - // SourceFileMetadata carries program-stored metadata about a single source file. type SourceFileMetadata struct { IsDefaultLibrary bool `json:"isDefaultLibrary"` diff --git a/tsc/internal/api/session.go b/tsc/internal/api/session.go index 37f00bc1dd48f..a276cc51ce59a 100644 --- a/tsc/internal/api/session.go +++ b/tsc/internal/api/session.go @@ -1751,53 +1751,37 @@ func (s *Session) handleGetSourceFileMetadata(ctx context.Context, params *GetSo }, nil } -func newResolvedModuleResponse(resolution *module.ResolvedModule) *ResolvedModuleWithFailedLookupLocations { - if resolution == nil { +func newResolvedModuleResponse(resolution *module.ResolvedModule) *ResolvedModule { + if !resolution.IsResolved() { return nil } - result := &ResolvedModuleWithFailedLookupLocations{ - FailedLookupLocations: append([]string{}, resolution.FailedLookupLocations...), - AffectingLocations: append([]string{}, resolution.AffectingLocations...), - ResolutionDiagnostics: NewDiagnosticResponses(resolution.ResolutionDiagnostics), - } - if resolution.IsResolved() { - result.ResolvedModule = &ResolvedModule{ - ResolvedFileName: resolution.ResolvedFileName, - OriginalPath: resolution.OriginalPath, - Extension: resolution.Extension, - ResolvedUsingTsExtension: resolution.ResolvedUsingTsExtension, - ResolvedUsingExtraExtensions: resolution.ResolvedUsingExtraExtensions, - PackageId: NewPackageId(resolution.PackageId), - IsExternalLibraryImport: resolution.IsExternalLibraryImport, - AlternateResult: resolution.AlternateResult, - } + return &ResolvedModule{ + ResolvedFileName: resolution.ResolvedFileName, + OriginalPath: resolution.OriginalPath, + Extension: resolution.Extension, + ResolvedUsingTsExtension: resolution.ResolvedUsingTsExtension, + ResolvedUsingExtraExtensions: resolution.ResolvedUsingExtraExtensions, + PackageId: NewPackageId(resolution.PackageId), + IsExternalLibraryImport: resolution.IsExternalLibraryImport, + AlternateResult: resolution.AlternateResult, } - return result } -func newResolvedTypeReferenceDirectiveResponse(resolution *module.ResolvedTypeReferenceDirective) *ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - if resolution == nil { +func newResolvedTypeReferenceDirectiveResponse(resolution *module.ResolvedTypeReferenceDirective) *ResolvedTypeReferenceDirective { + if resolution == nil || !resolution.IsResolved() { return nil } - result := &ResolvedTypeReferenceDirectiveWithFailedLookupLocations{ - FailedLookupLocations: append([]string{}, resolution.FailedLookupLocations...), - AffectingLocations: append([]string{}, resolution.AffectingLocations...), - ResolutionDiagnostics: NewDiagnosticResponses(resolution.ResolutionDiagnostics), - } - if resolution.IsResolved() { - result.ResolvedTypeReferenceDirective = &ResolvedTypeReferenceDirective{ - Primary: resolution.Primary, - ResolvedFileName: resolution.ResolvedFileName, - OriginalPath: resolution.OriginalPath, - PackageId: NewPackageId(resolution.PackageId), - IsExternalLibraryImport: resolution.IsExternalLibraryImport, - } + return &ResolvedTypeReferenceDirective{ + Primary: resolution.Primary, + ResolvedFileName: resolution.ResolvedFileName, + OriginalPath: resolution.OriginalPath, + PackageId: NewPackageId(resolution.PackageId), + IsExternalLibraryImport: resolution.IsExternalLibraryImport, } - return result } // @gen-proto-nullable -func (s *Session) handleGetResolvedModule(ctx context.Context, params *GetResolvedModuleParams) (*ResolvedModuleWithFailedLookupLocations, error) { +func (s *Session) handleGetResolvedModule(ctx context.Context, params *GetResolvedModuleParams) (*ResolvedModule, error) { sd, err := s.getSnapshotData(params.Snapshot) if err != nil { return nil, err @@ -1810,11 +1794,11 @@ func (s *Session) handleGetResolvedModule(ctx context.Context, params *GetResolv if err != nil { return nil, err } - return newResolvedModuleResponse(program.GetResolvedModuleWithLookupLocations(sourceFile, params.ModuleName, params.Mode)), nil + return newResolvedModuleResponse(program.GetResolvedModule(sourceFile, params.ModuleName, params.Mode)), nil } // @gen-proto-nullable -func (s *Session) handleGetResolvedModuleFromModuleSpecifier(ctx context.Context, params *GetResolvedModuleFromModuleSpecifierParams) (*ResolvedModuleWithFailedLookupLocations, error) { +func (s *Session) handleGetResolvedModuleFromModuleSpecifier(ctx context.Context, params *GetResolvedModuleFromModuleSpecifierParams) (*ResolvedModule, error) { sd, err := s.getSnapshotData(params.Snapshot) if err != nil { return nil, err @@ -1841,11 +1825,11 @@ func (s *Session) handleGetResolvedModuleFromModuleSpecifier(ctx context.Context return nil, fmt.Errorf("%w: moduleSpecifier must have a SourceFile ancestor or sourceFile must be provided", ErrClientError) } mode := program.GetModeForUsageLocation(sourceFile, node) - return newResolvedModuleResponse(program.GetResolvedModuleWithLookupLocations(sourceFile, node.Text(), mode)), nil + return newResolvedModuleResponse(program.GetResolvedModule(sourceFile, node.Text(), mode)), nil } // @gen-proto-nullable -func (s *Session) handleGetResolvedTypeReferenceDirective(ctx context.Context, params *GetResolvedTypeReferenceDirectiveParams) (*ResolvedTypeReferenceDirectiveWithFailedLookupLocations, error) { +func (s *Session) handleGetResolvedTypeReferenceDirective(ctx context.Context, params *GetResolvedTypeReferenceDirectiveParams) (*ResolvedTypeReferenceDirective, error) { sd, err := s.getSnapshotData(params.Snapshot) if err != nil { return nil, err @@ -1858,11 +1842,11 @@ func (s *Session) handleGetResolvedTypeReferenceDirective(ctx context.Context, p if err != nil { return nil, err } - return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirectiveWithLookupLocations(sourceFile, params.TypeDirectiveName, params.Mode)), nil + return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirective(sourceFile, params.TypeDirectiveName, params.Mode)), nil } // @gen-proto-nullable -func (s *Session) handleGetResolvedTypeReferenceDirectiveFromReference(ctx context.Context, params *GetResolvedTypeReferenceDirectiveFromReferenceParams) (*ResolvedTypeReferenceDirectiveWithFailedLookupLocations, error) { +func (s *Session) handleGetResolvedTypeReferenceDirectiveFromReference(ctx context.Context, params *GetResolvedTypeReferenceDirectiveFromReferenceParams) (*ResolvedTypeReferenceDirective, error) { sd, err := s.getSnapshotData(params.Snapshot) if err != nil { return nil, err @@ -1879,7 +1863,7 @@ func (s *Session) handleGetResolvedTypeReferenceDirectiveFromReference(ctx conte if mode == core.ResolutionModeNone { mode = program.GetDefaultResolutionModeForFile(sourceFile) } - return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirectiveWithLookupLocations(sourceFile, params.TypeDirectiveName, mode)), nil + return newResolvedTypeReferenceDirectiveResponse(program.GetResolvedTypeReferenceDirective(sourceFile, params.TypeDirectiveName, mode)), nil } // handleGetSymbolAtPosition returns the symbol at a position in a file. diff --git a/tsc/internal/compiler/program.go b/tsc/internal/compiler/program.go index 4e7e9d22107fd..2d0461124718c 100644 --- a/tsc/internal/compiler/program.go +++ b/tsc/internal/compiler/program.go @@ -612,12 +612,6 @@ func (p *Program) GetResolvedModule(file ast.HasFileName, moduleReference string return nil } -func (p *Program) GetResolvedModuleWithLookupLocations(file ast.HasFileName, moduleReference string, mode core.ResolutionMode) *module.ResolvedModule { - redirect, fileName := p.projectReferenceFileMapper.getRedirectForResolution(file) - resolved, _ := p.resolver.ResolveModuleNameWithLookupLocations(moduleReference, fileName, mode, redirect) - return resolved -} - func (p *Program) GetResolvedModuleFromModuleSpecifier(file ast.HasFileName, moduleSpecifier *ast.StringLiteralLike) *module.ResolvedModule { if !ast.IsStringLiteralLike(moduleSpecifier) { panic("moduleSpecifier must be a StringLiteralLike") @@ -2116,12 +2110,6 @@ func (p *Program) GetResolvedTypeReferenceDirective(file ast.HasFileName, typeDi return nil } -func (p *Program) GetResolvedTypeReferenceDirectiveWithLookupLocations(file ast.HasFileName, typeDirectiveName string, mode core.ResolutionMode) *module.ResolvedTypeReferenceDirective { - redirect, fileName := p.projectReferenceFileMapper.getRedirectForResolution(file) - resolved, _ := p.resolver.ResolveTypeReferenceDirectiveWithLookupLocations(typeDirectiveName, fileName, mode, redirect) - return resolved -} - func (p *Program) GetResolvedTypeReferenceDirectives() map[tspath.Path]module.ModeAwareCache[*module.ResolvedTypeReferenceDirective] { return p.typeResolutionsInFile } diff --git a/tsc/internal/module/resolver.go b/tsc/internal/module/resolver.go index ad7a8a3c4759a..2363435bb2207 100644 --- a/tsc/internal/module/resolver.go +++ b/tsc/internal/module/resolver.go @@ -73,7 +73,6 @@ type resolutionState struct { name string containingDirectory string isConfigLookup bool - includeLookupLocations bool features NodeResolutionFeatures esmMode bool conditions []string @@ -88,8 +87,6 @@ type resolutionState struct { // is suppressed so the checker does not attempt to extract a TS extension from the original specifier. candidateEndingIsFromConfig bool resolvedPackageDirectory bool - failedLookupLocations []string - affectingLocations []string diagnostics []*ast.Diagnostic } @@ -227,25 +224,6 @@ func (r *Resolver) ResolveTypeReferenceDirective( containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference, -) (*ResolvedTypeReferenceDirective, []DiagAndArgs) { - return r.resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, resolutionMode, redirectedReference, false) -} - -func (r *Resolver) ResolveTypeReferenceDirectiveWithLookupLocations( - typeReferenceDirectiveName string, - containingFile string, - resolutionMode core.ResolutionMode, - redirectedReference ResolvedProjectReference, -) (*ResolvedTypeReferenceDirective, []DiagAndArgs) { - return r.resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, resolutionMode, redirectedReference, true) -} - -func (r *Resolver) resolveTypeReferenceDirective( - typeReferenceDirectiveName string, - containingFile string, - resolutionMode core.ResolutionMode, - redirectedReference ResolvedProjectReference, - includeLookupLocations bool, ) (*ResolvedTypeReferenceDirective, []DiagAndArgs) { containingDirectory := tspath.GetDirectoryPath(containingFile) traceBuilder := r.newTraceBuilder() @@ -260,7 +238,7 @@ func (r *Resolver) resolveTypeReferenceDirective( fromInferredTypesContainingFile: fromInferredTypesContainingFile, } - if traceBuilder == nil && !includeLookupLocations { + if traceBuilder == nil { if cached, ok := r.typeRefDirectiveResolutionCache.Get(cacheKey); ok { return cached, nil } @@ -275,29 +253,18 @@ func (r *Resolver) resolveTypeReferenceDirective( } state := newResolutionState(typeReferenceDirectiveName, containingDirectory, true /*isTypeReferenceDirective*/, resolutionMode, compilerOptions, redirectedReference, r, traceBuilder) - state.includeLookupLocations = includeLookupLocations result := state.resolveTypeReferenceDirective(typeRoots, fromConfig, fromInferredTypesContainingFile) if traceBuilder != nil { traceBuilder.traceTypeReferenceDirectiveResult(typeReferenceDirectiveName, result) } - if !includeLookupLocations { - r.typeRefDirectiveResolutionCache.Set(cacheKey, result) - } + r.typeRefDirectiveResolutionCache.Set(cacheKey, result) return result, traceBuilder.getTraces() } func (r *Resolver) ResolveModuleName(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference) (*ResolvedModule, []DiagAndArgs) { - return r.resolveModuleName(moduleName, containingFile, resolutionMode, redirectedReference, false) -} - -func (r *Resolver) ResolveModuleNameWithLookupLocations(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference) (*ResolvedModule, []DiagAndArgs) { - return r.resolveModuleName(moduleName, containingFile, resolutionMode, redirectedReference, true) -} - -func (r *Resolver) resolveModuleName(moduleName string, containingFile string, resolutionMode core.ResolutionMode, redirectedReference ResolvedProjectReference, includeLookupLocations bool) (*ResolvedModule, []DiagAndArgs) { containingDirectory := tspath.GetDirectoryPath(containingFile) traceBuilder := r.newTraceBuilder() @@ -308,7 +275,7 @@ func (r *Resolver) resolveModuleName(moduleName string, containingFile string, r redirectConfigName: getRedirectConfigName(redirectedReference), } - if traceBuilder == nil && !includeLookupLocations { + if traceBuilder == nil { if cached, ok := r.moduleResolutionCache.Get(cacheKey); ok { return cached, nil } @@ -335,7 +302,6 @@ func (r *Resolver) resolveModuleName(moduleName string, containingFile string, r switch moduleResolution { case core.ModuleResolutionKindNode16, core.ModuleResolutionKindNodeNext, core.ModuleResolutionKindBundler: state := newResolutionState(moduleName, containingDirectory, false /*isTypeReferenceDirective*/, resolutionMode, compilerOptions, redirectedReference, r, traceBuilder) - state.includeLookupLocations = includeLookupLocations result = state.resolveNodeLike() default: panic(fmt.Sprintf("Unexpected moduleResolution: %d", moduleResolution)) @@ -353,10 +319,8 @@ func (r *Resolver) resolveModuleName(moduleName string, containingFile string, r } } - finalResult := r.tryResolveFromTypingsLocation(moduleName, containingDirectory, result, traceBuilder, includeLookupLocations) - if !includeLookupLocations { - r.moduleResolutionCache.Set(cacheKey, finalResult) - } + finalResult := r.tryResolveFromTypingsLocation(moduleName, containingDirectory, result, traceBuilder) + r.moduleResolutionCache.Set(cacheKey, finalResult) return finalResult, traceBuilder.getTraces() } @@ -372,7 +336,7 @@ func (r *Resolver) ResolvePackageDirectory(moduleName string, containingFile str return nil } -func (r *Resolver) tryResolveFromTypingsLocation(moduleName string, containingDirectory string, originalResult *ResolvedModule, traceBuilder *tracer, includeLookupLocations bool) *ResolvedModule { +func (r *Resolver) tryResolveFromTypingsLocation(moduleName string, containingDirectory string, originalResult *ResolvedModule, traceBuilder *tracer) *ResolvedModule { if r.typingsLocation == "" || tspath.IsExternalModuleNameRelative(moduleName) || (originalResult.ResolvedFileName != "" && tspath.ExtensionIsOneOf(originalResult.Extension, tspath.SupportedTSExtensionsWithJsonFlat)) { @@ -389,7 +353,6 @@ func (r *Resolver) tryResolveFromTypingsLocation(moduleName string, containingDi r, traceBuilder, ) - state.includeLookupLocations = includeLookupLocations if traceBuilder != nil { traceBuilder.write(diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, r.projectName, moduleName, r.typingsLocation) } @@ -398,8 +361,6 @@ func (r *Resolver) tryResolveFromTypingsLocation(moduleName string, containingDi return originalResult } result := state.createResolvedModule(globalResolved, true) - result.FailedLookupLocations = append(originalResult.FailedLookupLocations, result.FailedLookupLocations...) - result.AffectingLocations = append(originalResult.AffectingLocations, result.AffectingLocations...) result.ResolutionDiagnostics = append(originalResult.ResolutionDiagnostics, result.ResolutionDiagnostics...) return result } @@ -1207,8 +1168,6 @@ func (r *resolutionState) createResolvedModuleHandlingSymlink(resolved *resolved func (r *resolutionState) createResolvedModule(resolved *resolved, isExternalLibraryImport bool) *ResolvedModule { var resolvedModule ResolvedModule - resolvedModule.FailedLookupLocations = r.failedLookupLocations - resolvedModule.AffectingLocations = r.affectingLocations resolvedModule.ResolutionDiagnostics = r.diagnostics if resolved != nil { @@ -1225,8 +1184,6 @@ func (r *resolutionState) createResolvedModule(resolved *resolved, isExternalLib func (r *resolutionState) createResolvedTypeReferenceDirective(resolved *resolved, primary bool) *ResolvedTypeReferenceDirective { var resolvedTypeReferenceDirective ResolvedTypeReferenceDirective - resolvedTypeReferenceDirective.FailedLookupLocations = r.failedLookupLocations - resolvedTypeReferenceDirective.AffectingLocations = r.affectingLocations resolvedTypeReferenceDirective.ResolutionDiagnostics = r.diagnostics if resolved.isResolved() { @@ -1650,9 +1607,6 @@ func (r *resolutionState) tryFileLookup(fileName string) bool { } else if r.tracer != nil { r.tracer.write(diagnostics.File_0_does_not_exist, fileName) } - if r.includeLookupLocations { - r.failedLookupLocations = append(r.failedLookupLocations, fileName) - } return false } @@ -1815,17 +1769,11 @@ func (r *resolutionState) getPackageJsonInfo(packageDirectory string) *packagejs if r.tracer != nil { r.tracer.write(diagnostics.File_0_exists_according_to_earlier_cached_lookups, packageJsonPath) } - if r.includeLookupLocations { - r.affectingLocations = append(r.affectingLocations, packageJsonPath) - } return existing.WithPackageDirectory(packageDirectory) } else { if existing.DirectoryExists && r.tracer != nil { r.tracer.write(diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, packageJsonPath) } - if r.includeLookupLocations { - r.failedLookupLocations = append(r.failedLookupLocations, packageJsonPath) - } return nil } } @@ -1847,9 +1795,6 @@ func (r *resolutionState) getPackageJsonInfo(packageDirectory string) *packagejs }, } result = r.resolver.packageJsonInfoCache.Set(packageJsonPath, result) - if r.includeLookupLocations { - r.affectingLocations = append(r.affectingLocations, packageJsonPath) - } return result.WithPackageDirectory(packageDirectory) } else { if directoryExists && r.tracer != nil { @@ -1859,9 +1804,6 @@ func (r *resolutionState) getPackageJsonInfo(packageDirectory string) *packagejs PackageDirectory: packageDirectory, DirectoryExists: directoryExists, }) - if r.includeLookupLocations { - r.failedLookupLocations = append(r.failedLookupLocations, packageJsonPath) - } } return nil } diff --git a/tsc/internal/module/types.go b/tsc/internal/module/types.go index 64d2b254ae528..72e2573adf3fe 100644 --- a/tsc/internal/module/types.go +++ b/tsc/internal/module/types.go @@ -62,13 +62,7 @@ func (p *PackageId) PackageName() string { return p.Name } -type LookupLocations struct { - FailedLookupLocations []string - AffectingLocations []string -} - type ResolvedModule struct { - LookupLocations ResolutionDiagnostics []*ast.Diagnostic ResolvedFileName string OriginalPath string @@ -85,7 +79,6 @@ func (r *ResolvedModule) IsResolved() bool { } type ResolvedTypeReferenceDirective struct { - LookupLocations ResolutionDiagnostics []*ast.Diagnostic Primary bool ResolvedFileName string