Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing recursive vistor on copied import type nodes #58165

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 9 additions & 17 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ import {
createEvaluator,
createFileDiagnostic,
createFlowNode,
createGetCanonicalFileName,
createGetSymbolWalker,
createModeAwareCacheKey,
createModuleNotFoundChain,
Expand Down Expand Up @@ -347,7 +346,6 @@ import {
getPropertyNameFromType,
getResolutionDiagnostic,
getResolutionModeOverride,
getResolvedExternalModuleName,
getResolveJsonModule,
getRestParameterElementType,
getRootDeclaration,
Expand Down Expand Up @@ -7668,14 +7666,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1);
}
}
if (!context.enclosingDeclaration || !context.tracker.moduleResolverHost) {
if (!context.enclosingFile || !context.tracker.moduleResolverHost) {
// If there's no context declaration, we can't lookup a non-ambient specifier, so we just use the symbol name
if (ambientModuleSymbolRegex.test(symbol.escapedName as string)) {
return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1);
}
return getSourceFileOfNode(getNonAugmentationDeclaration(symbol)!).fileName; // A resolver may not be provided for baselines and errors - in those cases we use the fileName in full
}
const contextFile = getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration));
const contextFile = context.enclosingFile;
const resolutionMode = overrideImportMode || contextFile?.impliedNodeFormat;
const cacheKey = createModeAwareCacheKey(contextFile.path, resolutionMode);
const links = getSymbolLinks(symbol);
Expand Down Expand Up @@ -8479,22 +8477,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

function rewriteModuleSpecifier(parent: ImportTypeNode, lit: StringLiteral) {
if (context.bundled) {
if (context.tracker && context.tracker.moduleResolverHost) {
const targetFile = getExternalModuleFileFromDeclaration(parent);
if (targetFile) {
const getCanonicalFileName = createGetCanonicalFileName(!!host.useCaseSensitiveFileNames);
const resolverHost = {
getCanonicalFileName,
getCurrentDirectory: () => context.tracker.moduleResolverHost!.getCurrentDirectory(),
getCommonSourceDirectory: () => context.tracker.moduleResolverHost!.getCommonSourceDirectory(),
};
const newName = getResolvedExternalModuleName(resolverHost, targetFile);
return factory.createStringLiteral(newName);
if (context.bundled || context.enclosingFile !== getSourceFileOfNode(lit)) {
const targetFile = getExternalModuleFileFromDeclaration(parent);
if (targetFile) {
const newName = getSpecifierForModuleSymbol(targetFile.symbol, context);
if (newName !== lit.text) {
return setOriginalNode(factory.createStringLiteral(newName), lit);
}
}
}
return lit;
return visitNode(lit, visitExistingNodeTreeSymbols) as StringLiteral;
jakebailey marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/callbackCrossModule.types
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function C() {
=== use.js ===
/** @param {import('./mod1').Con} k */
function f(k) {
>f : (k: import('./mod1').Con) => any
>f : (k: import("./mod1").Con) => any
> : ^ ^^ ^^^^^^^^
>k : import("mod1").Con
> : ^^^^^^^^^^^^^^^^^^
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//// [tests/cases/compiler/declarationEmitCrossFileCopiedGeneratedImportType.ts] ////

//// [index.d.ts]
export declare class Foo extends Number {
private _;
}
//// [index.d.ts]
import { Foo } from "../projA";
export declare const f: (foo: Foo) => boolean;
//// [index.d.ts]
export declare const e: {
f: (foo: import("../projA").Foo) => boolean;
};
//// [index.ts]
import {e} from "../projC";

export const d = {e};

//// [index.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.d = void 0;
var projC_1 = require("../projC");
exports.d = { e: projC_1.e };


//// [index.d.ts]
export declare const d: {
e: {
f: (foo: import("../projA").Foo) => boolean;
Copy link
Member Author

@weswigham weswigham Apr 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I didn't also swap to getSpecifierForModuleSymbol as part of this, this emits as "../projA/index" because, well, getResolvedExternalModuleName is not the robust specifier generation solution in the checker that calls into moduleSpecifiers.ts, while getSpecifierForModuleSymbol is. getResolvedExternalModuleName was probably sufficient for just handling the unbundled -> bundled specifier case (which is all the declarations.ts version of rewriteModuleSpecifier needs to handle and what this was originally based on), but doesn't handle rewriting specifiers copied from other files, which is an additional case the node builder needs to handle (and as of this week, happens waaaaaaay more often). getSpecifierForModuleSymbol, however, does (and caches the results).

};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//// [tests/cases/compiler/declarationEmitCrossFileCopiedGeneratedImportType.ts] ////

=== projA/index.d.ts ===
export declare class Foo extends Number {
>Foo : Symbol(Foo, Decl(index.d.ts, 0, 0))
>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))

private _;
>_ : Symbol(Foo._, Decl(index.d.ts, 0, 41))
}
=== projB/index.d.ts ===
import { Foo } from "../projA";
>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8))

export declare const f: (foo: Foo) => boolean;
>f : Symbol(f, Decl(index.d.ts, 1, 20))
>foo : Symbol(foo, Decl(index.d.ts, 1, 25))
>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8))

=== projC/index.d.ts ===
export declare const e: {
>e : Symbol(e, Decl(index.d.ts, 0, 20))

f: (foo: import("../projA").Foo) => boolean;
>f : Symbol(f, Decl(index.d.ts, 0, 25))
>foo : Symbol(foo, Decl(index.d.ts, 1, 8))
>Foo : Symbol(Foo, Decl(index.d.ts, 0, 0))

};
=== projD/index.ts ===
import {e} from "../projC";
>e : Symbol(e, Decl(index.ts, 0, 8))

export const d = {e};
>d : Symbol(d, Decl(index.ts, 2, 12))
>e : Symbol(e, Decl(index.ts, 2, 18))

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//// [tests/cases/compiler/declarationEmitCrossFileCopiedGeneratedImportType.ts] ////

=== projA/index.d.ts ===
export declare class Foo extends Number {
>Foo : Foo
> : ^^^
>Number : Number
> : ^^^^^^

private _;
>_ : any
}
=== projB/index.d.ts ===
import { Foo } from "../projA";
>Foo : typeof Foo
> : ^^^^^^^^^^

export declare const f: (foo: Foo) => boolean;
>f : (foo: Foo) => boolean
> : ^ ^^ ^^^^^
>foo : Foo
> : ^^^

=== projC/index.d.ts ===
export declare const e: {
>e : { f: (foo: import("../projA").Foo) => boolean; }
> : ^^^^^ ^^^

f: (foo: import("../projA").Foo) => boolean;
>f : (foo: import("../projA").Foo) => boolean
> : ^ ^^ ^^^^^
>foo : import("projA/index").Foo
> : ^^^^^^^^^^^^^^^^^^^^^^^^^

};
=== projD/index.ts ===
import {e} from "../projC";
>e : { f: (foo: import("projA/index").Foo) => boolean; }
> : ^^^^^^ ^^ ^^^^^^^^^^^^^^^

export const d = {e};
>d : { e: { f: (foo: import("projA/index").Foo) => boolean; }; }
> : ^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^
>{e} : { e: { f: (foo: import("projA/index").Foo) => boolean; }; }
> : ^^^^^ ^^^
>e : { f: (foo: import("projA/index").Foo) => boolean; }
> : ^^^^^^ ^^ ^^^^^^^^^^^^^^^

Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,4 @@ export class Encoder<T> implements IEncoder<T> {
*/
encode(value: T): Uint8Array;
}
export type IEncoder<T> = import('./interface').Encoder<T>;
export type IEncoder<T> = import("./interface").Encoder<T>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're doing the recursive visit on the specifier now, the quote-style-conformity change we just made is now also being applied here~

Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ declare class Base {
* @returns {InstanceType<BaseFactory["Base"]>}
*/
declare function test(base: InstanceType<BaseFactory["Base"]>): InstanceType<BaseFactory["Base"]>;
type BaseFactory = typeof import('./base');
type BaseFactory = typeof import("./base");
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ declare class MainThreadTasks {
declare namespace MainThreadTasks {
export { TaskGroup, TaskNode, PriorTaskData };
}
type TaskGroup = import('./module.js').TaskGroup;
type TaskGroup = import("./module.js").TaskGroup;
type TaskNode = {
children: TaskNode[];
parent: TaskNode | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ export type WithSymbol = {
* @returns {import('./a').WithSymbol}
* @param {import('./a').WithSymbol} value
*/
export function b(value: import('./a').WithSymbol): import('./a').WithSymbol;
export function b(value: import("./a").WithSymbol): import("./a").WithSymbol;
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const kSymbol = Symbol("my-symbol");
* @param {import('./a').WithSymbol} value
*/
export function b(value) {
>b : (value: import('./a').WithSymbol) => import('./a').WithSymbol
>b : (value: import("./a").WithSymbol) => import("./a").WithSymbol
> : ^ ^^ ^^^^^
>value : import("a").WithSymbol
> : ^^^^^^^^^^^^^^^^^^^^^^
Expand Down
12 changes: 6 additions & 6 deletions tests/baselines/reference/jsdocThisType.types
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ export function f2() {

/** @type {(this: import('./types').Foo) => void} */
export const f3 = function() {
>f3 : (this: import('./types').Foo) => void
>f3 : (this: import("./types").Foo) => void
> : ^ ^^ ^^^^^^^^^
>function() { this.test();} : (this: import('./types').Foo) => void
>function() { this.test();} : (this: import("./types").Foo) => void
> : ^ ^^ ^^^^^^^^^

this.test();
Expand All @@ -68,7 +68,7 @@ export const f3 = function() {

/** @type {(this: import('./types').Foo) => void} */
export function f4() {
>f4 : (this: import('./types').Foo) => void
>f4 : (this: import("./types").Foo) => void
> : ^ ^^ ^^^^^

this.test();
Expand All @@ -84,9 +84,9 @@ export function f4() {

/** @type {function(this: import('./types').Foo): void} */
export const f5 = function() {
>f5 : (this: import('./types').Foo) => void
>f5 : (this: import("./types").Foo) => void
> : ^ ^^ ^^^^^^^^^
>function() { this.test();} : (this: import('./types').Foo) => void
>function() { this.test();} : (this: import("./types").Foo) => void
> : ^ ^^ ^^^^^^^^^

this.test();
Expand All @@ -102,7 +102,7 @@ export const f5 = function() {

/** @type {function(this: import('./types').Foo): void} */
export function f6() {
>f6 : (this: import('./types').Foo) => void
>f6 : (this: import("./types").Foo) => void
> : ^ ^^ ^^^^^

this.test();
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/moduleExportAssignment7.types
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ function jsvalues(a, b, c, d, e, f, g) {

=== index.ts ===
function types(
>types : (a: any, b: any, c: any, d: any, e: any, f: import('./mod').buz, g: any) => any
>types : (a: any, b: any, c: any, d: any, e: any, f: import("./mod").buz, g: any) => any
> : ^ ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^

a: import('./mod').Thing,
Expand Down Expand Up @@ -309,7 +309,7 @@ function types(
}

function values(
>values : (a: typeof import('./mod').Thing, b: typeof import('./mod').AnotherThing, c: typeof import('./mod').foo, d: typeof import('./mod').qux, e: typeof import('./mod').baz, f: any, g: typeof import('./mod').literal) => any
>values : (a: typeof import("./mod").Thing, b: typeof import("./mod").AnotherThing, c: typeof import("./mod").foo, d: typeof import("./mod").qux, e: typeof import("./mod").baz, f: any, g: typeof import("./mod").literal) => any
> : ^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^^^ ^^ ^^^^^^^^

a: typeof import('./mod').Thing,
Expand Down
8 changes: 4 additions & 4 deletions tests/baselines/reference/privateNamesUnique-2.types
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ const b = new B();
a.copy(b); // error
>a.copy(b) : void
> : ^^^^
>a.copy : (other: import(} fro).Foo) => void
> : ^ ^^ ^^^^^^^^^
>a.copy : (other: import("b").Foo) => void
> : ^ ^^ ^^^^^^^^^
>a : A
> : ^
>copy : (other: import(} fro).Foo) => void
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That we already had a test demonstrating the issue is... yeah, reviewing big baseline diffs is hard - easy to miss the one test that's still off. And that's why we try and break it down where we can. 🤷‍♂️

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops!

> : ^ ^^ ^^^^^^^^^
>copy : (other: import("b").Foo) => void
> : ^ ^^ ^^^^^^^^^
>b : B
> : ^

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type SelectorMap<T extends Record<string, (...params: unknown[]) => unkno
};

export declare const value2: {
>value2 : { sliceSelectors: <FuncMap extends import('./types').SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]>; }; }
>value2 : { sliceSelectors: <FuncMap extends import("./types").SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]>; }; }
> : ^^^^^^^^^^^^^^^^^^ ^^^

sliceSelectors: <FuncMap extends import('./types').SelectorMap<FuncMap>>(selectorsBySlice: FuncMap) => { [P in keyof FuncMap]: Parameters<FuncMap[P]> };
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// @declaration: true
// @filename: projA/index.d.ts
export declare class Foo extends Number {
private _;
}
// @filename: projB/index.d.ts
import { Foo } from "../projA";
export declare const f: (foo: Foo) => boolean;
// @filename: projC/index.d.ts
export declare const e: {
f: (foo: import("../projA").Foo) => boolean;
};
// @filename: projD/index.ts
import {e} from "../projC";

export const d = {e};