Fix occasional silent error emit for JSDoc declaration emit and overzealous node serialization of jsdoc optional parameters. (#60034)

This commit is contained in:
Wesley Wigham 2024-09-25 15:40:10 -07:00 коммит произвёл GitHub
Родитель 8496039426
Коммит 3ad0f75248
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
10 изменённых файлов: 257 добавлений и 21 удалений

Просмотреть файл

@ -8415,7 +8415,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (typeFromTypeNode === type) {
return true;
}
if (annotatedDeclaration && (isParameter(annotatedDeclaration) || isPropertySignature(annotatedDeclaration) || isPropertyDeclaration(annotatedDeclaration)) && annotatedDeclaration.questionToken) {
if (!annotatedDeclaration) {
return false;
}
if ((isPropertySignature(annotatedDeclaration) || isPropertyDeclaration(annotatedDeclaration)) && annotatedDeclaration.questionToken) {
return getTypeWithFacts(type, TypeFacts.NEUndefined) === typeFromTypeNode;
}
if (isParameter(annotatedDeclaration) && hasEffectiveQuestionToken(annotatedDeclaration)) {
return getTypeWithFacts(type, TypeFacts.NEUndefined) === typeFromTypeNode;
}
return false;
@ -9420,7 +9426,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const skipMembershipCheck = !isPrivate; // We only call this on exported symbols when we know they're in the correct scope
if (skipMembershipCheck || (!!length(symbol.declarations) && some(symbol.declarations, d => !!findAncestor(d, n => n === enclosingDeclaration)))) {
const scopeCleanup = cloneNodeBuilderContext(context);
context.tracker.pushErrorFallbackNode(find(symbol.declarations, d => getSourceFileOfNode(d) === context.enclosingFile));
serializeSymbolWorker(symbol, isPrivate, propertyAsAlias);
context.tracker.popErrorFallbackNode();
scopeCleanup();
}
}
@ -53022,4 +53030,12 @@ class SymbolTrackerImpl implements SymbolTracker {
this.inner.reportInferenceFallback(node);
}
}
pushErrorFallbackNode(node: Declaration | undefined): void {
return this.inner?.pushErrorFallbackNode?.(node);
}
popErrorFallbackNode(): void {
return this.inner?.popErrorFallbackNode?.();
}
}

Просмотреть файл

@ -270,6 +270,7 @@ export function transformDeclarations(context: TransformationContext): Transform
const { factory } = context;
const host = context.getEmitHost();
let restoreFallbackNode = () => void 0;
const symbolTracker: SymbolTracker = {
trackSymbol,
reportInaccessibleThisError,
@ -282,6 +283,18 @@ export function transformDeclarations(context: TransformationContext): Transform
reportNonlocalAugmentation,
reportNonSerializableProperty,
reportInferenceFallback,
pushErrorFallbackNode(node) {
const currentFallback = errorFallbackNode;
const currentRestore = restoreFallbackNode;
restoreFallbackNode = () => {
restoreFallbackNode = currentRestore;
errorFallbackNode = currentFallback;
};
errorFallbackNode = node;
},
popErrorFallbackNode() {
restoreFallbackNode();
},
};
let errorNameNode: DeclarationName | undefined;
let errorFallbackNode: Declaration | undefined;

Просмотреть файл

@ -9958,6 +9958,8 @@ export interface SymbolTracker {
reportNonlocalAugmentation?(containingFile: SourceFile, parentSymbol: Symbol, augmentingSymbol: Symbol): void;
reportNonSerializableProperty?(propertyName: string): void;
reportInferenceFallback?(node: Node): void;
pushErrorFallbackNode?(node: Declaration | undefined): void;
popErrorFallbackNode?(): void;
}
export interface TextSpan {

Просмотреть файл

@ -70,10 +70,10 @@ const fn2 =
* @param {number} [b]
*/
function self(a, b) {
>function self(a, b) { acceptNum(b); // error self(""); self("", undefined); } : (a: string, b?: number | undefined) => void
> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>self : (a: string, b?: number | undefined) => void
> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function self(a, b) { acceptNum(b); // error self(""); self("", undefined); } : (a: string, b?: number) => void
> : ^ ^^^^^^^^^^ ^^^ ^^^^^^^^^
>self : (a: string, b?: number) => void
> : ^ ^^^^^^^^^^ ^^^ ^^^^^^^^^
>a : string
> : ^^^^^^
>b : number | undefined
@ -90,16 +90,16 @@ const fn2 =
self("");
>self("") : void
> : ^^^^
>self : (a: string, b?: number | undefined) => void
> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>self : (a: string, b?: number) => void
> : ^ ^^^^^^^^^^ ^^^ ^^^^^^^^^
>"" : ""
> : ^^
self("", undefined);
>self("", undefined) : void
> : ^^^^
>self : (a: string, b?: number | undefined) => void
> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>self : (a: string, b?: number) => void
> : ^ ^^^^^^^^^^ ^^^ ^^^^^^^^^
>"" : ""
> : ^^
>undefined : undefined

Просмотреть файл

@ -28,8 +28,8 @@ const a = filter(
* @param {number} [pose]
*/
(pose) => true
>(pose) => true : (pose?: number | undefined) => true
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(pose) => true : (pose?: number) => true
> : ^ ^^^ ^^^^^^^^^
>pose : number | undefined
> : ^^^^^^^^^^^^^^^^^^
>true : true
@ -50,8 +50,8 @@ const b = filter(
* @param {number} [_]
*/
(pose, _) => true
>(pose, _) => true : (pose?: number | undefined, _?: number | undefined) => true
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(pose, _) => true : (pose?: number, _?: number) => true
> : ^ ^^^ ^^ ^^^ ^^^^^^^^^
>pose : number | undefined
> : ^^^^^^^^^^^^^^^^^^
>_ : number | undefined

Просмотреть файл

@ -0,0 +1,63 @@
//// [tests/cases/compiler/jsDocDeclarationEmitDoesNotUseNodeModulesPathWithoutError.ts] ////
//// [package.json]
{
"name": "typescript-issue",
"private": true,
"version": "0.0.0",
"type": "module"
}
//// [package.json]
{
"name": "@lion/ajax",
"version": "2.0.2",
"type": "module",
"exports": {
".": {
"types": "./dist-types/src/index.d.ts",
"default": "./src/index.js"
},
"./docs/*": "./docs/*"
}
}
//// [index.d.ts]
export type LionRequestInit = import('../types/types.js').LionRequestInit;
//// [types.d.ts]
export interface LionRequestInit {
body?: null | Object;
}
//// [index.js]
/**
* @typedef {import('@lion/ajax').LionRequestInit} LionRequestInit
*/
export class NewAjax {
/**
* @param {LionRequestInit} [init]
*/
case5_unexpectedlyResolvesPathToNodeModules(init) {}
}
/**
* @type {(init?: LionRequestInit) => void}
*/
// @ts-expect-error
NewAjax.prototype.case6_unexpectedlyResolvesPathToNodeModules;
//// [index.d.ts]
/**
* @typedef {import('@lion/ajax').LionRequestInit} LionRequestInit
*/
export class NewAjax {
/**
* @param {LionRequestInit} [init]
*/
case5_unexpectedlyResolvesPathToNodeModules(init?: LionRequestInit): void;
/**
* @type {(init?: LionRequestInit) => void}
*/
case6_unexpectedlyResolvesPathToNodeModules: (init?: LionRequestInit) => void;
}
export type LionRequestInit = import("@lion/ajax").LionRequestInit;

Просмотреть файл

@ -0,0 +1,42 @@
//// [tests/cases/compiler/jsDocDeclarationEmitDoesNotUseNodeModulesPathWithoutError.ts] ////
=== node_modules/@lion/ajax/dist-types/src/index.d.ts ===
export type LionRequestInit = import('../types/types.js').LionRequestInit;
>LionRequestInit : Symbol(LionRequestInit, Decl(index.d.ts, 0, 0))
>LionRequestInit : Symbol(LionRequestInit, Decl(types.d.ts, 0, 0))
=== node_modules/@lion/ajax/dist-types/types/types.d.ts ===
export interface LionRequestInit {
>LionRequestInit : Symbol(LionRequestInit, Decl(types.d.ts, 0, 0))
body?: null | Object;
>body : Symbol(LionRequestInit.body, Decl(types.d.ts, 0, 34))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
=== index.js ===
/**
* @typedef {import('@lion/ajax').LionRequestInit} LionRequestInit
*/
export class NewAjax {
>NewAjax : Symbol(NewAjax, Decl(index.js, 0, 0))
/**
* @param {LionRequestInit} [init]
*/
case5_unexpectedlyResolvesPathToNodeModules(init) {}
>case5_unexpectedlyResolvesPathToNodeModules : Symbol(NewAjax.case5_unexpectedlyResolvesPathToNodeModules, Decl(index.js, 4, 22))
>init : Symbol(init, Decl(index.js, 8, 48))
}
/**
* @type {(init?: LionRequestInit) => void}
*/
// @ts-expect-error
NewAjax.prototype.case6_unexpectedlyResolvesPathToNodeModules;
>NewAjax.prototype.case6_unexpectedlyResolvesPathToNodeModules : Symbol(NewAjax.case6_unexpectedlyResolvesPathToNodeModules, Decl(index.js, 9, 1))
>NewAjax.prototype : Symbol(NewAjax.prototype)
>NewAjax : Symbol(NewAjax, Decl(index.js, 0, 0))
>prototype : Symbol(NewAjax.prototype)
>case6_unexpectedlyResolvesPathToNodeModules : Symbol(NewAjax.case6_unexpectedlyResolvesPathToNodeModules, Decl(index.js, 9, 1))

Просмотреть файл

@ -0,0 +1,48 @@
//// [tests/cases/compiler/jsDocDeclarationEmitDoesNotUseNodeModulesPathWithoutError.ts] ////
=== node_modules/@lion/ajax/dist-types/src/index.d.ts ===
export type LionRequestInit = import('../types/types.js').LionRequestInit;
>LionRequestInit : import("node_modules/@lion/ajax/dist-types/types/types").LionRequestInit
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
=== node_modules/@lion/ajax/dist-types/types/types.d.ts ===
export interface LionRequestInit {
body?: null | Object;
>body : Object | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
}
=== index.js ===
/**
* @typedef {import('@lion/ajax').LionRequestInit} LionRequestInit
*/
export class NewAjax {
>NewAjax : NewAjax
> : ^^^^^^^
/**
* @param {LionRequestInit} [init]
*/
case5_unexpectedlyResolvesPathToNodeModules(init) {}
>case5_unexpectedlyResolvesPathToNodeModules : (init?: LionRequestInit) => void
> : ^ ^^^ ^^^^^^^^^
>init : import("node_modules/@lion/ajax/dist-types/types/types").LionRequestInit | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
/**
* @type {(init?: LionRequestInit) => void}
*/
// @ts-expect-error
NewAjax.prototype.case6_unexpectedlyResolvesPathToNodeModules;
>NewAjax.prototype.case6_unexpectedlyResolvesPathToNodeModules : (init?: LionRequestInit) => void
> : ^ ^^^ ^^^^^
>NewAjax.prototype : NewAjax
> : ^^^^^^^
>NewAjax : typeof NewAjax
> : ^^^^^^^^^^^^^^
>prototype : NewAjax
> : ^^^^^^^
>case6_unexpectedlyResolvesPathToNodeModules : (init?: LionRequestInit) => void
> : ^ ^^^ ^^^^^

Просмотреть файл

@ -7,8 +7,8 @@
* @param {number} [r=101]
*/
function f(p, q, r) {
>f : (p?: number | undefined, q?: number | undefined, r?: number | undefined) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f : (p?: number, q?: number | undefined, r?: number) => void
> : ^ ^^^ ^^ ^^^ ^^^^^^^^^^^ ^^^ ^^^^^^^^^
>p : number | undefined
> : ^^^^^^^^^^^^^^^^^^
>q : number | undefined
@ -45,14 +45,14 @@ function f(p, q, r) {
f()
>f() : void
> : ^^^^
>f : (p?: number | undefined, q?: number | undefined, r?: number | undefined) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f : (p?: number, q?: number | undefined, r?: number) => void
> : ^ ^^^ ^^ ^^^ ^^^^^^^^^^^ ^^^ ^^^^^^^^^
f(undefined, undefined, undefined)
>f(undefined, undefined, undefined) : void
> : ^^^^
>f : (p?: number | undefined, q?: number | undefined, r?: number | undefined) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f : (p?: number, q?: number | undefined, r?: number) => void
> : ^ ^^^ ^^ ^^^ ^^^^^^^^^^^ ^^^ ^^^^^^^^^
>undefined : undefined
> : ^^^^^^^^^
>undefined : undefined
@ -63,8 +63,8 @@ f(undefined, undefined, undefined)
f(1, 2, 3)
>f(1, 2, 3) : void
> : ^^^^
>f : (p?: number | undefined, q?: number | undefined, r?: number | undefined) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f : (p?: number, q?: number | undefined, r?: number) => void
> : ^ ^^^ ^^ ^^^ ^^^^^^^^^^^ ^^^ ^^^^^^^^^
>1 : 1
> : ^
>2 : 2

Просмотреть файл

@ -0,0 +1,52 @@
// @allowJs: true
// @checkJs: true
// @strict: true
// @target: esnext
// @module: nodenext
// @moduleResolution: nodenext
// @declaration: true
// @emitDeclarationOnly: true
// @outDir: ./dist-types
// @filename: package.json
{
"name": "typescript-issue",
"private": true,
"version": "0.0.0",
"type": "module"
}
// @filename: node_modules/@lion/ajax/package.json
{
"name": "@lion/ajax",
"version": "2.0.2",
"type": "module",
"exports": {
".": {
"types": "./dist-types/src/index.d.ts",
"default": "./src/index.js"
},
"./docs/*": "./docs/*"
}
}
// @filename: node_modules/@lion/ajax/dist-types/src/index.d.ts
export type LionRequestInit = import('../types/types.js').LionRequestInit;
// @filename: node_modules/@lion/ajax/dist-types/types/types.d.ts
export interface LionRequestInit {
body?: null | Object;
}
// @filename: index.js
/**
* @typedef {import('@lion/ajax').LionRequestInit} LionRequestInit
*/
export class NewAjax {
/**
* @param {LionRequestInit} [init]
*/
case5_unexpectedlyResolvesPathToNodeModules(init) {}
}
/**
* @type {(init?: LionRequestInit) => void}
*/
// @ts-expect-error
NewAjax.prototype.case6_unexpectedlyResolvesPathToNodeModules;