Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5992,15 +5992,25 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
}
}

function shouldWriteComment(text: string, pos: number) {
function shouldWriteComment(text: string, pos: number, end?: number) {
if (printerOptions.onlyPrintJsDocStyle) {
return (isJSDocLikeText(text, pos) || isPinnedComment(text, pos));
if (!isJSDocLikeText(text, pos) && !isPinnedComment(text, pos)) {
return false;
}
// Skip @typedef and @callback comments - they're converted to type declarations
if (end !== undefined) {
const commentText = text.slice(pos, end);
if (commentText.includes("@typedef") || commentText.includes("@callback")) {
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The string matching for '@typedef' and '@callback' could produce false positives if these strings appear in comment content that isn't actually a typedef or callback declaration (e.g., in documentation text or code examples). Consider using a more precise pattern match that checks for these tags at word boundaries, such as matching /@typedef\b/ and /@callback\b/ to ensure they are actual JSDoc tags.

Suggested change
if (commentText.includes("@typedef") || commentText.includes("@callback")) {
if (/@typedef\b/.test(commentText) || /@callback\b/.test(commentText)) {

Copilot uses AI. Check for mistakes.
return false;
}
Comment on lines +6002 to +6005
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

Creating a substring via slice() for every comment during emit could impact performance when processing files with many comments. Consider checking for the presence of '@typedef' or '@callback' using indexOf() with boundary checks on the original string instead of creating a new substring.

Suggested change
const commentText = text.slice(pos, end);
if (commentText.includes("@typedef") || commentText.includes("@callback")) {
return false;
}
const typedefIndex = text.indexOf("@typedef", pos);
if (typedefIndex !== -1 && typedefIndex < end) {
return false;
}
const callbackIndex = text.indexOf("@callback", pos);
if (callbackIndex !== -1 && callbackIndex < end) {
return false;
}

Copilot uses AI. Check for mistakes.
}
return true;
}
return true;
}

function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) {
if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return;
if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos, commentEnd)) return;
if (!hasWrittenComment) {
emitNewLineBeforeLeadingCommentOfPosition(getCurrentLineMap(), writer, rangePos, commentPos);
hasWrittenComment = true;
Expand Down Expand Up @@ -6032,7 +6042,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
}

function emitTrailingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return;
if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos, commentEnd)) return;
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/
if (!writer.isAtStartOfLine()) {
writer.writeSpace(" ");
Expand Down Expand Up @@ -6135,7 +6145,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
}

function emitComment(text: string, lineMap: readonly number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) {
if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return;
if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos, commentEnd)) return;
emitPos(commentPos);
writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);
Expand Down
7 changes: 0 additions & 7 deletions tests/baselines/reference/callbackTagNestedParameter.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,6 @@ function eachPerson(callback) {


//// [cb_nested.d.ts]
/**
* @callback WorksWithPeopleCallback
* @param {Object} person
* @param {string} person.name
* @param {number} [person.age]
* @returns {void}
*/
/**
* For each person, calls your callback.
* @param {WorksWithPeopleCallback} callback
Expand Down
5 changes: 0 additions & 5 deletions tests/baselines/reference/callbackTagVariadicType.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ var res = (0, exports.x)('a', 'b');


//// [callbackTagVariadicType.d.ts]
/**
* @callback Foo
* @param {...string} args
* @returns {number}
*/
/** @type {Foo} */
export const x: Foo;
export type Foo = (...args: string[]) => number;
1 change: 0 additions & 1 deletion tests/baselines/reference/checkJsdocSatisfiesTag15.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ function fn7(uuid) { }
/** @satisfies {(uuid: string) => void} */
export function fn7(uuid: any): void;
export function fn1(uuid: string): void;
/** @typedef {Parameters<typeof fn1>} Foo */
/** @type Foo */
export const v1: Foo;
/** @type Foo */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ export default X;
export type Options = {
test?: typeof import("./Test.js").default | undefined;
};
/**
* @typedef {Object} Options
* @property {typeof import("./Test.js").default} [test]
*/
declare class X extends Test {
/**
* @param {Options} options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,27 +153,6 @@ declare class Timer {
}
//// [context.d.ts]
export = Context;
/**
* Imports
*
* @typedef {import("./timer")} Timer
* @typedef {import("./hook")} Hook
* @typedef {import("./hook").HookHandler} HookHandler
*/
/**
* Input type definition
*
* @typedef {Object} Input
* @prop {Timer} timer
* @prop {Hook} hook
*/
/**
* State type definition
*
* @typedef {Object} State
* @prop {Timer} timer
* @prop {Hook} hook
*/
/**
* New `Context`
*
Expand All @@ -182,27 +161,6 @@ export = Context;
*/
declare function Context(input: Input): Context;
declare class Context {
/**
* Imports
*
* @typedef {import("./timer")} Timer
* @typedef {import("./hook")} Hook
* @typedef {import("./hook").HookHandler} HookHandler
*/
/**
* Input type definition
*
* @typedef {Object} Input
* @prop {Timer} timer
* @prop {Hook} hook
*/
/**
* State type definition
*
* @typedef {Object} State
* @prop {Timer} timer
* @prop {Hook} hook
*/
/**
* New `Context`
*
Expand Down Expand Up @@ -249,17 +207,11 @@ type State = {
};
//// [hook.d.ts]
export = Hook;
/**
* @typedef {(arg: import("./context")) => void} HookHandler
*/
/**
* @param {HookHandler} handle
*/
declare function Hook(handle: HookHandler): void;
declare class Hook {
/**
* @typedef {(arg: import("./context")) => void} HookHandler
*/
/**
* @param {HookHandler} handle
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ export const myTypes: {
export namespace testFnTypes {
type input = boolean | myTypes.typeC;
}
/** @typedef {boolean|myTypes.typeC} testFnTypes.input */
/**
* @function testFn
* @description A test function.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ export namespace myTypes {
type typeC = myTypes.typeB | Function;
}
//// [file2.d.ts]
/** @typedef {boolean|myTypes.typeC} testFnTypes.input */
/**
* @function testFn
* @description A test function.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export var dummy = 1


//// [mod1.d.ts]
/** @typedef {number} Dotted.Name */
export const dummy: number;
export namespace Dotted {
type Name = number;
Expand Down
3 changes: 0 additions & 3 deletions tests/baselines/reference/jsDeclarationsImportTypeBundled.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ module.exports = items;
//// [out.d.ts]
declare module "folder/mod1" {
export = x;
/**
* @typedef {{x: number}} Item
*/
/**
* @type {Item};
*/
Expand Down
8 changes: 0 additions & 8 deletions tests/baselines/reference/jsDeclarationsInheritedTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,6 @@ class C3 extends C1 {


//// [a.d.ts]
/**
* @typedef A
* @property {string} a
*/
/**
* @typedef B
* @property {number} b
*/
declare class C1 {
/**
* @type {A}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,6 @@ type couldntThinkOfAny = {
new (): {};
};
};
/** @typedef {import('./base')} BaseFactory */
/**
* @callback BaseFactoryFactory
* @param {import('./base')} factory
*/
/** @enum {import('./base')} */
declare const couldntThinkOfAny: {};
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ declare namespace BaseFactory {
declare class Base {
}
//// [file.d.ts]
/** @typedef {typeof import('./base')} BaseFactory */
/**
*
* @param {InstanceType<BaseFactory["Base"]>} base
Expand Down
3 changes: 0 additions & 3 deletions tests/baselines/reference/jsDeclarationsTypeAliases.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,6 @@ export type Identity<T> = (x: T) => T;
export type SomeType = {
x: string;
} | number | LocalThing | ExportedThing;
/**
* @typedef {{x: string} | number | LocalThing | ExportedThing} SomeType
*/
/**
* @param {number} x
* @returns {SomeType}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ module.exports = {

//// [conn.d.ts]
export = Conn;
/**
* @typedef {string | number} Whatever
*/
declare class Conn {
item: number;
method(): void;
Expand All @@ -81,9 +78,6 @@ declare namespace Conn {
type Whatever = string | number;
//// [usage.d.ts]
export type Conn = import("./conn");
/**
* @typedef {import("./conn")} Conn
*/
export class Wrap {
/**
* @param {Conn} c
Expand Down
5 changes: 0 additions & 5 deletions tests/baselines/reference/jsDeclarationsTypedefFunction.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ const send = handlers => new Promise((resolve, reject) => {


//// [foo.d.ts]
/**
* @typedef {{
* [id: string]: [Function, Function];
* }} ResolveRejectMap
*/
declare let id: number;
/**
* @param {ResolveRejectMap} handlers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,6 @@ export type TaskGroup = {
label: string;
traceEventNames: string[];
};
/** @typedef {'parseHTML'|'styleLayout'} TaskGroupIds */
/**
* @typedef TaskGroup
* @property {TaskGroupIds} id
* @property {string} label
* @property {string[]} traceEventNames
*/
/**
* @type {{[P in TaskGroupIds]: {id: P, label: string}}}
*/
Expand All @@ -130,14 +123,6 @@ export const taskNameToGroup: {
};
//// [index.d.ts]
export = MainThreadTasks;
/** @typedef {import('./module.js').TaskGroup} TaskGroup */
/**
* @typedef TaskNode
* @prop {TaskNode[]} children
* @prop {TaskNode|undefined} parent
* @prop {TaskGroup} group
*/
/** @typedef {{timers: Map<string, TaskNode>}} PriorTaskData */
declare class MainThreadTasks {
/**
* @param {TaskGroup} x
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ NewAjax.prototype.case6_unexpectedlyResolvesPathToNodeModules;


//// [index.d.ts]
/**
* @typedef {import('@lion/ajax').LionRequestInit} LionRequestInit
*/
export class NewAjax {
/**
* @param {LionRequestInit} [init]
Expand Down
27 changes: 0 additions & 27 deletions tests/baselines/reference/jsdocTemplateTagDefault.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,29 +128,6 @@ function f3(a, b) { }


//// [file.d.ts]
/**
* @template T
* @template [U=T] - ok: default can reference earlier type parameter
* @typedef {[T, U]} B
*/
/**
* @template {string | number} [T] - error: default requires an `=type`
* @typedef {[T]} C
*/
/**
* @template {string | number} [T=] - error: default requires a `type`
* @typedef {[T]} D
*/
/**
* @template {string | number} [T=string]
* @template U - error: Required type parameters cannot follow optional type parameters
* @typedef {[T, U]} E
*/
/**
* @template [T=U] - error: Type parameter defaults can only reference previously declared type parameters.
* @template [U=T]
* @typedef {[T, U]} G
*/
/**
* @template T
* @template [U=T] - ok: default can reference earlier type parameter
Expand All @@ -172,10 +149,6 @@ declare function f2<T extends string | number = string, U>(a: T, b: U): void;
* @param {U} b
*/
declare function f3<T = U, U = T>(a: T, b: U): void;
/**
* @template {string | number} [T=string] - ok: defaults are permitted
* @typedef {[T]} A
*/
/** @type {A} */ declare const aDefault1: A;
/** @type {A} */ declare const aDefault2: A;
/** @type {A<string>} */ declare const aString: A<string>;
Expand Down
7 changes: 0 additions & 7 deletions tests/baselines/reference/linkTagEmit1.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@ var see3 = true;


//// [linkTagEmit1.d.ts]
/** @typedef {number} N */
/**
* @typedef {Object} D1
* @property {1} e Just link to {@link NS.R} this time
* @property {1} m Wyatt Earp loved {@link N integers} I bet.
*/
/** @typedef {number} Z @see N {@link N} */
/**
* @param {number} integer {@link Z}
*/
Expand Down
21 changes: 0 additions & 21 deletions tests/baselines/reference/recursiveTypeReferences2.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,27 +55,6 @@ var p = {};


//// [bug39372.d.ts]
/** @typedef {ReadonlyArray<Json>} JsonArray */
/** @typedef {{ readonly [key: string]: Json }} JsonRecord */
/** @typedef {boolean | number | string | null | JsonRecord | JsonArray | readonly []} Json */
/**
* @template T
* @typedef {{
$A: {
[K in keyof T]?: XMLObject<T[K]>[]
},
$O: {
[K in keyof T]?: {
$$?: Record<string, string>
} & (T[K] extends string ? {$:string} : XMLObject<T[K]>)
},
$$?: Record<string, string>,
} & {
[K in keyof T]?: (
T[K] extends string ? string
: XMLObject<T[K]>
)
}} XMLObject<T> */
/** @type {XMLObject<{foo:string}>} */
declare const p: XMLObject<{
foo: string;
Expand Down
Loading
Loading