From 30aaac33d3b082c2feeb7cb01790dbdb1948c618 Mon Sep 17 00:00:00 2001 From: Ronen Amiel Date: Tue, 4 Feb 2025 13:26:29 +0200 Subject: [PATCH 1/4] initial implementation --- .../docs/rules/unified-signatures.mdx | 44 +++ .../src/rules/unified-signatures.ts | 67 +++- .../unified-signatures.shot | 39 ++ .../tests/rules/unified-signatures.test.ts | 364 ++++++++++++++++++ .../schema-snapshots/unified-signatures.shot | 6 + 5 files changed, 516 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/unified-signatures.mdx b/packages/eslint-plugin/docs/rules/unified-signatures.mdx index 6813957a5e80..593af8594126 100644 --- a/packages/eslint-plugin/docs/rules/unified-signatures.mdx +++ b/packages/eslint-plugin/docs/rules/unified-signatures.mdx @@ -78,6 +78,50 @@ function f(b: string): void; +### `ignoreOverloadsWithDifferentJSDoc` + +{/* insert option description */} + +Examples of code for this rule with `ignoreOverloadsWithDifferentJSDoc`: + + + + +```ts option='{ "ignoreOverloadsWithDifferentJSDoc": true }' +declare function f(x: string): void; +declare function f(x: boolean): void; +/** + * @deprecate + */ +declare function f(x: number): void; +/** + * @deprecate + */ +declare function f(x: null): void; +``` + + + + +```ts option='{ "ignoreOverloadsWithDifferentJSDoc": true }' +declare function f(x: string): void; +/** + * This signature does something else. + */ +declare function f(x: boolean): void; +/** + * @async + */ +declare function f(x: number): void; +/** + * @deprecate + */ +declare function f(x: null): void; +``` + + + + ## When Not To Use It This is purely a stylistic rule to help with readability of function signature overloads. diff --git a/packages/eslint-plugin/src/rules/unified-signatures.ts b/packages/eslint-plugin/src/rules/unified-signatures.ts index 9c255b6f9f50..23100c75d109 100644 --- a/packages/eslint-plugin/src/rules/unified-signatures.ts +++ b/packages/eslint-plugin/src/rules/unified-signatures.ts @@ -1,10 +1,15 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import { AST_NODE_TYPES } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import type { Equal } from '../util'; -import { arraysAreEqual, createRule, nullThrows } from '../util'; +import { + arraysAreEqual, + createRule, + LINEBREAK_MATCHER, + nullThrows, +} from '../util'; interface Failure { only2: boolean; @@ -61,6 +66,7 @@ export type MessageIds = export type Options = [ { ignoreDifferentlyNamedParameters?: boolean; + ignoreOverloadsWithDifferentJSDoc?: boolean; }, ]; @@ -91,6 +97,11 @@ export default createRule({ description: 'Whether two parameters with different names at the same index should be considered different even if their types are the same.', }, + ignoreOverloadsWithDifferentJSDoc: { + type: 'boolean', + description: + 'Whether two overloads with different JSDoc comments should be considered different even if their parameter and return types are the same.', + }, }, }, ], @@ -98,9 +109,13 @@ export default createRule({ defaultOptions: [ { ignoreDifferentlyNamedParameters: false, + ignoreOverloadsWithDifferentJSDoc: false, }, ], - create(context, [{ ignoreDifferentlyNamedParameters }]) { + create( + context, + [{ ignoreDifferentlyNamedParameters, ignoreOverloadsWithDifferentJSDoc }], + ) { //---------------------------------------------------------------------- // Helpers //---------------------------------------------------------------------- @@ -230,6 +245,15 @@ export default createRule({ } } + if (ignoreOverloadsWithDifferentJSDoc) { + const aComment = getJSDocCommentForNode(getExportingNode(a) ?? a); + const bComment = getJSDocCommentForNode(getExportingNode(b) ?? b); + + if (aComment?.value !== bComment?.value) { + return false; + } + } + return ( typesAreEqual(a.returnType, b.returnType) && // Must take the same type parameters. @@ -522,6 +546,18 @@ export default createRule({ currentScope = scopes.pop(); } + /** + * @returns the first valid JSDoc comment annotating `node` + */ + function getJSDocCommentForNode( + node: TSESTree.Node, + ): TSESTree.Comment | undefined { + return context.sourceCode + .getCommentsBefore(node) + .reverse() + .find(comment => isJSDocComment(comment)); + } + function addOverload( signature: OverloadNode, key?: string, @@ -586,7 +622,7 @@ export default createRule({ }); function getExportingNode( - node: TSESTree.TSDeclareFunction, + node: SignatureDefinition, ): | TSESTree.ExportDefaultDeclaration | TSESTree.ExportNamedDeclaration @@ -634,3 +670,26 @@ function getStaticParameterName(param: TSESTree.Node): string | undefined { function isIdentifier(node: TSESTree.Node): node is TSESTree.Identifier { return node.type === AST_NODE_TYPES.Identifier; } + +/** + * Checks if a comment is in JSDoc form. + * + * Based on https://github.com/eslint/eslint/blob/93c325a7a841d0fe4b5bf79efdec832e7c8f805f/lib/rules/multiline-comment-style.js#L104-L119 + */ +function isJSDocComment(comment: TSESTree.Comment) { + if (comment.type !== AST_TOKEN_TYPES.Block) { + return false; + } + + const lines = comment.value.split(LINEBREAK_MATCHER); + + if (lines.length === 1) { + return lines[0].startsWith('*'); + } + + return ( + /^\*\s*$/u.test(lines[0]) && + lines.slice(1, -1).every(line => /^\s* /u.test(line)) && + /^\s*$/u.test(lines[lines.length - 1]) + ); +} diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot index c35fb2cc7545..222058e486b1 100644 --- a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot @@ -60,3 +60,42 @@ function f(a: number): void; function f(b: string): void; " `; + +exports[`Validating rule docs unified-signatures.mdx code examples ESLint output 8`] = ` +"Incorrect +Options: { "ignoreOverloadsWithDifferentJSDoc": true } + +declare function f(x: string): void; +declare function f(x: boolean): void; + ~~~~~~~~~~ This overload and the one on line 1 can be combined into one signature taking \`string | boolean\`. +/** + * @deprecate + */ +declare function f(x: number): void; +/** + * @deprecate + */ +declare function f(x: null): void; + ~~~~~~~ This overload and the one on line 6 can be combined into one signature taking \`number | null\`. +" +`; + +exports[`Validating rule docs unified-signatures.mdx code examples ESLint output 9`] = ` +"Correct +Options: { "ignoreOverloadsWithDifferentJSDoc": true } + +declare function f(x: string): void; +/** + * This signature does something else. + */ +declare function f(x: boolean): void; +/** + * @async + */ +declare function f(x: number): void; +/** + * @deprecate + */ +declare function f(x: null): void; +" +`; diff --git a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts index 0e5ee9219ce7..7f8d4bb6bcb4 100644 --- a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts +++ b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts @@ -220,6 +220,145 @@ class C { `, options: [{ ignoreDifferentlyNamedParameters: true }], }, + { + code: ` +/** @deprecated */ +declare function f(x: number): unknown; +declare function f(x: boolean): unknown; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +declare function f(x: number): unknown; +/** @deprecated */ +declare function f(x: boolean): unknown; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +declare function f(x: number): unknown; +/** @deprecated */ declare function f(x: boolean): unknown; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +declare function f(x: string): void; +/** + * @async + */ +declare function f(x: boolean): void; +/** + * @deprecate + */ +declare function f(x: number): void; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * @deprecate + */ +declare function f(x: string): void; +/** + * @async + */ +declare function f(x: boolean): void; +declare function f(x: number): void; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * This signature does something. + */ +declare function f(x: number): void; + +/** + * This signature does something else. + */ +declare function f(x: string): void; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** @deprecated */ +export function f(x: number): unknown; +export function f(x: boolean): unknown; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +export function f(x: number): unknown; +/** @deprecated */ +export function f(x: boolean): unknown; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +export function f(x: string): void; +/** + * @async + */ +export function f(x: boolean): void; +/** + * @deprecate + */ +export function f(x: number): void; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * @deprecate + */ +export function f(x: string): void; +/** + * @async + */ +export function f(x: boolean): void; +export function f(x: number): void; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * This signature does something. + */ +export function f(x: number): void; + +/** + * This signature does something else. + */ +export function f(x: string): void; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * This signature does something. + */ + +// some other comment +export function f(x: number): void; + +/** + * This signature does something else. + */ +export function f(x: string): void; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, ], invalid: [ { @@ -771,5 +910,230 @@ export default function (foo: number, bar?: string): string[]; }, ], }, + { + code: ` +/** + * @deprecate + */ +declare function f(x: string): void; +declare function f(x: number): void; +declare function f(x: boolean): void; + `, + errors: [ + { + column: 20, + data: { + failureStringStart: + 'This overload and the one on line 6 can be combined into one signature', + type1: 'number', + type2: 'boolean', + }, + line: 7, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * @deprecate + */ +declare function f(x: string): void; +/** + * @deprecate + */ +declare function f(x: number): void; +declare function f(x: boolean): void; + `, + errors: [ + { + column: 20, + data: { + failureStringStart: + 'This overload and the one on line 5 can be combined into one signature', + type1: 'string', + type2: 'number', + }, + line: 9, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +declare function f(x: string): void; +/** + * @deprecate + */ +declare function f(x: number): void; +/** + * @deprecate + */ +declare function f(x: boolean): void; + `, + errors: [ + { + column: 20, + data: { + failureStringStart: + 'This overload and the one on line 6 can be combined into one signature', + type1: 'number', + type2: 'boolean', + }, + line: 10, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +export function f(x: string): void; +/** + * @deprecate + */ +export function f(x: number): void; +/** + * @deprecate + */ +export function f(x: boolean): void; + `, + errors: [ + { + column: 19, + data: { + failureStringStart: + 'This overload and the one on line 6 can be combined into one signature', + type1: 'number', + type2: 'boolean', + }, + line: 10, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * This signature does something. + */ + +/** + * This signature does something else. + */ +function f(x: number): void; + +/** + * This signature does something else. + */ +function f(x: string): void; + `, + errors: [ + { + column: 12, + data: { + failureStringStart: + 'These overloads can be combined into one signature', + type1: 'number', + type2: 'string', + }, + line: 14, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + // invalid jsdoc comments + { + code: ` +/* @deprecated */ +declare function f(x: number): unknown; +declare function f(x: boolean): unknown; + `, + errors: [ + { + column: 20, + data: { + failureStringStart: + 'These overloads can be combined into one signature', + type1: 'number', + type2: 'boolean', + }, + line: 4, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/* + * This signature does something. + */ +declare function f(x: number): unknown; +declare function f(x: boolean): unknown; + `, + errors: [ + { + column: 20, + data: { + failureStringStart: + 'These overloads can be combined into one signature', + type1: 'number', + type2: 'boolean', + }, + line: 6, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * This signature does something. + **/ +declare function f(x: number): unknown; +declare function f(x: boolean): unknown; + `, + errors: [ + { + column: 20, + data: { + failureStringStart: + 'These overloads can be combined into one signature', + type1: 'number', + type2: 'boolean', + }, + line: 6, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +// just a comment +declare function f(x: number): unknown; +declare function f(x: boolean): unknown; + `, + errors: [ + { + column: 20, + data: { + failureStringStart: + 'These overloads can be combined into one signature', + type1: 'number', + type2: 'boolean', + }, + line: 4, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, ], }); diff --git a/packages/eslint-plugin/tests/schema-snapshots/unified-signatures.shot b/packages/eslint-plugin/tests/schema-snapshots/unified-signatures.shot index 39b61b6dde7d..9f16f8aa1da6 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/unified-signatures.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/unified-signatures.shot @@ -11,6 +11,10 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "ignoreDifferentlyNamedParameters": { "description": "Whether two parameters with different names at the same index should be considered different even if their types are the same.", "type": "boolean" + }, + "ignoreOverloadsWithDifferentJSDoc": { + "description": "Whether two overloads with different JSDoc comments should be considered different even if their parameter and return types are the same.", + "type": "boolean" } }, "type": "object" @@ -24,6 +28,8 @@ type Options = [ { /** Whether two parameters with different names at the same index should be considered different even if their types are the same. */ ignoreDifferentlyNamedParameters?: boolean; + /** Whether two overloads with different JSDoc comments should be considered different even if their parameter and return types are the same. */ + ignoreOverloadsWithDifferentJSDoc?: boolean; }, ]; " From b9d0b2a536f917c60c92c6b05eaf2f0840a28b57 Mon Sep 17 00:00:00 2001 From: Ronen Amiel Date: Tue, 4 Feb 2025 13:39:53 +0200 Subject: [PATCH 2/4] add a test for interfaces --- .../tests/rules/unified-signatures.test.ts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts index 7f8d4bb6bcb4..54ea9cb7b6ae 100644 --- a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts +++ b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts @@ -359,6 +359,18 @@ export function f(x: string): void; `, options: [{ ignoreOverloadsWithDifferentJSDoc: true }], }, + { + code: ` +interface I { + /** + * This signature does something else. + */ + f(x: number): void; + f(x: string): void; +} + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, ], invalid: [ { @@ -1046,6 +1058,35 @@ function f(x: string): void; ], options: [{ ignoreOverloadsWithDifferentJSDoc: true }], }, + { + code: ` +interface I { + f(x: string): void; + /** + * @deprecate + */ + f(x: number): void; + /** + * @deprecate + */ + f(x: boolean): void; +} + `, + errors: [ + { + column: 5, + data: { + failureStringStart: + 'This overload and the one on line 7 can be combined into one signature', + type1: 'number', + type2: 'boolean', + }, + line: 11, + messageId: 'singleParameterDifference', + }, + ], + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, // invalid jsdoc comments { code: ` From cabc56c23f4622a1d4fb36104ce20b4d9518ea40 Mon Sep 17 00:00:00 2001 From: Ronen Amiel Date: Tue, 4 Feb 2025 17:19:55 +0200 Subject: [PATCH 3/4] remove some redundant 'export function ...' tests --- .../tests/rules/unified-signatures.test.ts | 50 ------------------- 1 file changed, 50 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts index 54ea9cb7b6ae..5a9e46e56e8d 100644 --- a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts +++ b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts @@ -295,56 +295,6 @@ export function f(x: boolean): unknown; }, { code: ` -export function f(x: number): unknown; -/** @deprecated */ -export function f(x: boolean): unknown; - `, - options: [{ ignoreOverloadsWithDifferentJSDoc: true }], - }, - { - code: ` -export function f(x: string): void; -/** - * @async - */ -export function f(x: boolean): void; -/** - * @deprecate - */ -export function f(x: number): void; - `, - options: [{ ignoreOverloadsWithDifferentJSDoc: true }], - }, - { - code: ` -/** - * @deprecate - */ -export function f(x: string): void; -/** - * @async - */ -export function f(x: boolean): void; -export function f(x: number): void; - `, - options: [{ ignoreOverloadsWithDifferentJSDoc: true }], - }, - { - code: ` -/** - * This signature does something. - */ -export function f(x: number): void; - -/** - * This signature does something else. - */ -export function f(x: string): void; - `, - options: [{ ignoreOverloadsWithDifferentJSDoc: true }], - }, - { - code: ` /** * This signature does something. */ From ec9a1eab07dc54606aeaab8fec30396f15b9d7c9 Mon Sep 17 00:00:00 2001 From: Ronen Amiel Date: Tue, 25 Feb 2025 23:49:59 +0200 Subject: [PATCH 4/4] check for block comments instead of a heuristic to check jsdoc comments --- .../src/rules/unified-signatures.ts | 38 +------ .../tests/rules/unified-signatures.test.ts | 99 ++++++------------- 2 files changed, 35 insertions(+), 102 deletions(-) diff --git a/packages/eslint-plugin/src/rules/unified-signatures.ts b/packages/eslint-plugin/src/rules/unified-signatures.ts index d05ca3bed73f..7c0ac6cd161d 100644 --- a/packages/eslint-plugin/src/rules/unified-signatures.ts +++ b/packages/eslint-plugin/src/rules/unified-signatures.ts @@ -4,12 +4,7 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import type { Equal } from '../util'; -import { - arraysAreEqual, - createRule, - LINEBREAK_MATCHER, - nullThrows, -} from '../util'; +import { arraysAreEqual, createRule, nullThrows } from '../util'; interface Failure { only2: boolean; @@ -246,8 +241,8 @@ export default createRule({ } if (ignoreOverloadsWithDifferentJSDoc) { - const aComment = getJSDocCommentForNode(getExportingNode(a) ?? a); - const bComment = getJSDocCommentForNode(getExportingNode(b) ?? b); + const aComment = getBlockCommentForNode(getExportingNode(a) ?? a); + const bComment = getBlockCommentForNode(getExportingNode(b) ?? b); if (aComment?.value !== bComment?.value) { return false; @@ -549,13 +544,13 @@ export default createRule({ /** * @returns the first valid JSDoc comment annotating `node` */ - function getJSDocCommentForNode( + function getBlockCommentForNode( node: TSESTree.Node, ): TSESTree.Comment | undefined { return context.sourceCode .getCommentsBefore(node) .reverse() - .find(comment => isJSDocComment(comment)); + .find(comment => comment.type === AST_TOKEN_TYPES.Block); } function addOverload( @@ -675,29 +670,6 @@ function isIdentifier(node: TSESTree.Node): node is TSESTree.Identifier { return node.type === AST_NODE_TYPES.Identifier; } -/** - * Checks if a comment is in JSDoc form. - * - * Based on https://github.com/eslint/eslint/blob/93c325a7a841d0fe4b5bf79efdec832e7c8f805f/lib/rules/multiline-comment-style.js#L104-L119 - */ -function isJSDocComment(comment: TSESTree.Comment) { - if (comment.type !== AST_TOKEN_TYPES.Block) { - return false; - } - - const lines = comment.value.split(LINEBREAK_MATCHER); - - if (lines.length === 1) { - return lines[0].startsWith('*'); - } - - return ( - /^\*\s*$/u.test(lines[0]) && - lines.slice(1, -1).every(line => /^\s* /u.test(line)) && - /^\s*$/u.test(lines[lines.length - 1]) - ); -} - function isGetterOrSetter( node: | TSESTree.MethodDefinition diff --git a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts index 8dd2ca68d280..16e48d02ca5d 100644 --- a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts +++ b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts @@ -339,6 +339,35 @@ interface I { `, options: [{ ignoreOverloadsWithDifferentJSDoc: true }], }, + // invalid jsdoc comments + { + code: ` +/* @deprecated */ +declare function f(x: number): unknown; +declare function f(x: boolean): unknown; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/* + * This signature does something. + */ +declare function f(x: number): unknown; +declare function f(x: boolean): unknown; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, + { + code: ` +/** + * This signature does something. + **/ +declare function f(x: number): unknown; +declare function f(x: boolean): unknown; + `, + options: [{ ignoreOverloadsWithDifferentJSDoc: true }], + }, ], invalid: [ { @@ -1055,77 +1084,9 @@ interface I { ], options: [{ ignoreOverloadsWithDifferentJSDoc: true }], }, - // invalid jsdoc comments - { - code: ` -/* @deprecated */ -declare function f(x: number): unknown; -declare function f(x: boolean): unknown; - `, - errors: [ - { - column: 20, - data: { - failureStringStart: - 'These overloads can be combined into one signature', - type1: 'number', - type2: 'boolean', - }, - line: 4, - messageId: 'singleParameterDifference', - }, - ], - options: [{ ignoreOverloadsWithDifferentJSDoc: true }], - }, - { - code: ` -/* - * This signature does something. - */ -declare function f(x: number): unknown; -declare function f(x: boolean): unknown; - `, - errors: [ - { - column: 20, - data: { - failureStringStart: - 'These overloads can be combined into one signature', - type1: 'number', - type2: 'boolean', - }, - line: 6, - messageId: 'singleParameterDifference', - }, - ], - options: [{ ignoreOverloadsWithDifferentJSDoc: true }], - }, - { - code: ` -/** - * This signature does something. - **/ -declare function f(x: number): unknown; -declare function f(x: boolean): unknown; - `, - errors: [ - { - column: 20, - data: { - failureStringStart: - 'These overloads can be combined into one signature', - type1: 'number', - type2: 'boolean', - }, - line: 6, - messageId: 'singleParameterDifference', - }, - ], - options: [{ ignoreOverloadsWithDifferentJSDoc: true }], - }, { code: ` -// just a comment +// a line comment declare function f(x: number): unknown; declare function f(x: boolean): unknown; `,