From 84f4f3c827e41be029b7e3f05db6b96a9cdd11be Mon Sep 17 00:00:00 2001 From: Sysix <3897725+Sysix@users.noreply.github.com> Date: Sun, 11 Jan 2026 15:29:46 +0000 Subject: [PATCH] fix(linter): add doc url for tsgolint diagnostics (#17879) closes https://github.com/oxc-project/oxc/issues/17647 --- ...golint@no-floating-promises__index.ts.snap | 10 +- ...nt_unused_disabled_directives@test.ts.snap | 4 +- ...type-aware -c config-test.json@oxlint.snap | 4 +- ...ixtures__tsgolint_--type-aware@oxlint.snap | 103 +++++++++--------- ...d-disable-directives unused.ts@oxlint.snap | 2 +- ...irectives_--type-aware test.ts@oxlint.snap | 4 +- ...lint_rule_options_--type-aware@oxlint.snap | 8 +- crates/oxc_linter/src/context/mod.rs | 8 +- crates/oxc_linter/src/lib.rs | 3 + crates/oxc_linter/src/tsgolint.rs | 3 +- 10 files changed, 75 insertions(+), 74 deletions(-) diff --git a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_tsgolint@no-floating-promises__index.ts.snap b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_tsgolint@no-floating-promises__index.ts.snap index a9181b0b35f9c..f164d424b762d 100644 --- a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_tsgolint@no-floating-promises__index.ts.snap +++ b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_tsgolint@no-floating-promises__index.ts.snap @@ -19,7 +19,7 @@ source: Some("oxc") tags: None code: "typescript-eslint(no-floating-promises)" -code_description.href: "None" +code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html" message: "Promises must be awaited.\nhelp: The promise must end with a call to .catch, or end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator." range: Range { start: Position { line: 1, character: 0 }, end: Position { line: 1, character: 8 } } related_information[0].message: "" @@ -30,7 +30,7 @@ source: Some("oxc") tags: None code: "typescript-eslint(no-floating-promises)" -code_description.href: "None" +code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html" message: "Promises must be awaited.\nhelp: The promise must end with a call to .catch, or end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator." range: Range { start: Position { line: 7, character: 0 }, end: Position { line: 7, character: 32 } } related_information[0].message: "" @@ -41,7 +41,7 @@ source: Some("oxc") tags: None code: "typescript-eslint(no-floating-promises)" -code_description.href: "None" +code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html" message: "Promises must be awaited.\nhelp: The promise must end with a call to .catch, or end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator." range: Range { start: Position { line: 9, character: 0 }, end: Position { line: 9, character: 32 } } related_information[0].message: "" @@ -52,7 +52,7 @@ source: Some("oxc") tags: None code: "typescript-eslint(no-floating-promises)" -code_description.href: "None" +code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html" message: "Promises must be awaited.\nhelp: The promise must end with a call to .catch, or end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator." range: Range { start: Position { line: 11, character: 0 }, end: Position { line: 11, character: 34 } } related_information[0].message: "" @@ -63,7 +63,7 @@ source: Some("oxc") tags: None code: "typescript-eslint(no-floating-promises)" -code_description.href: "None" +code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html" message: "An array of Promises may be unintentional.\nhelp: Consider handling the promises' fulfillment or rejection with Promise.all or similar, or explicitly marking the expression as ignored with the `void` operator." range: Range { start: Position { line: 13, character: 0 }, end: Position { line: 13, character: 34 } } related_information[0].message: "" diff --git a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_tsgolint_unused_disabled_directives@test.ts.snap b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_tsgolint_unused_disabled_directives@test.ts.snap index 2751a1245fc92..9d5b0de61fe25 100644 --- a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_tsgolint_unused_disabled_directives@test.ts.snap +++ b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_tsgolint_unused_disabled_directives@test.ts.snap @@ -8,7 +8,7 @@ Linted file: fixtures/lsp/tsgolint/unused_disabled_directives/test.ts File URI: file:///fixtures/lsp/tsgolint/unused_disabled_directives/test.ts code: "typescript-eslint(no-floating-promises)" -code_description.href: "None" +code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html" message: "Promises must be awaited.\nhelp: The promise must end with a call to .catch, or end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator." range: Range { start: Position { line: 18, character: 0 }, end: Position { line: 18, character: 9 } } related_information[0].message: "" @@ -19,7 +19,7 @@ source: Some("oxc") tags: None code: "typescript-eslint(no-floating-promises)" -code_description.href: "None" +code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html" message: "Promises must be awaited.\nhelp: The promise must end with a call to .catch, or end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator." range: Range { start: Position { line: 38, character: 0 }, end: Position { line: 38, character: 18 } } related_information[0].message: "" diff --git a/apps/oxlint/src/snapshots/fixtures__tsgolint_--type-aware -c config-test.json@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__tsgolint_--type-aware -c config-test.json@oxlint.snap index 861793d43c305..c5455c356e008 100644 --- a/apps/oxlint/src/snapshots/fixtures__tsgolint_--type-aware -c config-test.json@oxlint.snap +++ b/apps/oxlint/src/snapshots/fixtures__tsgolint_--type-aware -c config-test.json@oxlint.snap @@ -6,7 +6,7 @@ arguments: --type-aware -c config-test.json working directory: fixtures/tsgolint ---------- - ! typescript-eslint(no-floating-promises): Promises must be awaited. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html\typescript-eslint(no-floating-promises)]8;;\: Promises must be awaited. ,-[no-floating-promises.ts:2:1] 1 | const promise = new Promise((resolve, _reject) => resolve("value")); 2 | promise; @@ -23,7 +23,7 @@ working directory: fixtures/tsgolint `---- help: Remove the debugger statement - ! typescript-eslint(no-floating-promises): Promises must be awaited. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html\typescript-eslint(no-floating-promises)]8;;\: Promises must be awaited. ,-[prefer-promise-reject-errors.ts:1:1] 1 | Promise.reject('error'); : ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/apps/oxlint/src/snapshots/fixtures__tsgolint_--type-aware@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__tsgolint_--type-aware@oxlint.snap index 9c432716ffb6c..b67b1567d7436 100644 --- a/apps/oxlint/src/snapshots/fixtures__tsgolint_--type-aware@oxlint.snap +++ b/apps/oxlint/src/snapshots/fixtures__tsgolint_--type-aware@oxlint.snap @@ -6,27 +6,27 @@ arguments: --type-aware working directory: fixtures/tsgolint ---------- - x typescript-eslint(await-thenable): Unexpected `await` of a non-Promise (non-"Thenable") value. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/await-thenable.html\typescript-eslint(await-thenable)]8;;\: Unexpected `await` of a non-Promise (non-"Thenable") value. ,-[await-thenable.ts:1:1] 1 | await 12; : ^^^^^^^^ 2 | `---- - x typescript-eslint(no-array-delete): Using the `delete` operator with an array expression is unsafe. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-array-delete.html\typescript-eslint(no-array-delete)]8;;\: Using the `delete` operator with an array expression is unsafe. ,-[no-array-delete.ts:2:1] 1 | declare const arr: number[]; 2 | delete arr[0]; : ^^^^^^^^^^^^^ `---- - x typescript-eslint(no-base-to-string): '({})' will use Object's default stringification format ('[object Object]') when stringified. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-base-to-string.html\typescript-eslint(no-base-to-string)]8;;\: '({})' will use Object's default stringification format ('[object Object]') when stringified. ,-[no-base-to-string.ts:1:1] 1 | ({}).toString(); : ^^^^ `---- - x typescript-eslint(no-meaningless-void-operator): void operator shouldn't be used on void; it should convey that a return value is being ignored + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-meaningless-void-operator.html\typescript-eslint(no-meaningless-void-operator)]8;;\: void operator shouldn't be used on void; it should convey that a return value is being ignored ,-[no-confusing-void-expression.ts:2:19] 1 | declare function bar(): void; 2 | const foo = () => void bar(); @@ -34,7 +34,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-confusing-void-expression): Placing a void expression inside another expression is forbidden. Move it to its own statement instead. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-confusing-void-expression.html\typescript-eslint(no-confusing-void-expression)]8;;\: Placing a void expression inside another expression is forbidden. Move it to its own statement instead. ,-[no-confusing-void-expression.ts:2:24] 1 | declare function bar(): void; 2 | const foo = () => void bar(); @@ -42,28 +42,28 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-deprecated): `getVersion` is deprecated. Use apiV2 instead. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-deprecated.html\typescript-eslint(no-deprecated)]8;;\: `getVersion` is deprecated. Use apiV2 instead. ,-[no-deprecated.ts:8:1] 7 | 8 | getVersion(); : ^^^^^^^^^^ `---- - x typescript-eslint(no-duplicate-type-constituents): Union type constituent is duplicated with 'A'. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-duplicate-type-constituents.html\typescript-eslint(no-duplicate-type-constituents)]8;;\: Union type constituent is duplicated with 'A'. ,-[no-duplicate-type-constituents.ts:1:17] 1 | type T1 = 'A' | 'A'; : ^^^ 2 | `---- - x typescript-eslint(no-confusing-void-expression): Returning a void expression from an arrow function shorthand is forbidden. Please add braces to the arrow function. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-confusing-void-expression.html\typescript-eslint(no-confusing-void-expression)]8;;\: Returning a void expression from an arrow function shorthand is forbidden. Please add braces to the arrow function. ,-[no-floating-promises.ts:1:51] 1 | const promise = new Promise((resolve, _reject) => resolve("value")); : ^^^^^^^^^^^^^^^^ 2 | promise; `---- - x typescript-eslint(no-floating-promises): Promises must be awaited. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html\typescript-eslint(no-floating-promises)]8;;\: Promises must be awaited. ,-[no-floating-promises.ts:2:1] 1 | const promise = new Promise((resolve, _reject) => resolve("value")); 2 | promise; @@ -72,8 +72,8 @@ working directory: fixtures/tsgolint `---- help: The promise must end with a call to .catch, or end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator. - x typescript-eslint(no-for-in-array): For-in loops over arrays skips holes, returns indices as strings, and may visit the prototype chain or other enumerable properties. Use a more robust - | iteration method such as for-of or array.forEach instead. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-for-in-array.html\typescript-eslint(no-for-in-array)]8;;\: For-in loops over arrays skips holes, returns indices as strings, and may visit the prototype chain or other enumerable properties. Use a + | more robust iteration method such as for-of or array.forEach instead. ,-[no-for-in-array.ts:2:1] 1 | const arr = [1, 2, 3]; 2 | for (const i in arr) { @@ -81,13 +81,13 @@ working directory: fixtures/tsgolint 3 | console.log(arr[i]); `---- - x typescript-eslint(no-implied-eval): Implied eval. Consider passing a function. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-implied-eval.html\typescript-eslint(no-implied-eval)]8;;\: Implied eval. Consider passing a function. ,-[no-implied-eval.ts:1:12] 1 | setTimeout('alert("Hi!");', 100); : ^^^^^^^^^^^^^^^ `---- - x typescript-eslint(no-meaningless-void-operator): void operator shouldn't be used on void; it should convey that a return value is being ignored + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-meaningless-void-operator.html\typescript-eslint(no-meaningless-void-operator)]8;;\: void operator shouldn't be used on void; it should convey that a return value is being ignored ,-[no-meaningless-void-operator.ts:4:1] 3 | } 4 | void foo(); @@ -95,7 +95,7 @@ working directory: fixtures/tsgolint 5 | `---- - x typescript-eslint(no-confusing-void-expression): Placing a void expression inside another expression is forbidden. Move it to its own statement instead. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-confusing-void-expression.html\typescript-eslint(no-confusing-void-expression)]8;;\: Placing a void expression inside another expression is forbidden. Move it to its own statement instead. ,-[no-meaningless-void-operator.ts:4:6] 3 | } 4 | void foo(); @@ -103,14 +103,14 @@ working directory: fixtures/tsgolint 5 | `---- - x typescript-eslint(no-misused-spread): Using the spread operator on Promise in an object can cause unexpected behavior. Did you forget to await the promise? + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-misused-spread.html\typescript-eslint(no-misused-spread)]8;;\: Using the spread operator on Promise in an object can cause unexpected behavior. Did you forget to await the promise? ,-[no-misused-spread.ts:2:25] 1 | declare const promise: Promise; 2 | const spreadPromise = { ...promise }; : ^^^^^^^^^^ `---- - x typescript-eslint(no-mixed-enums): Mixing number and string enums can be confusing. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-mixed-enums.html\typescript-eslint(no-mixed-enums)]8;;\: Mixing number and string enums can be confusing. ,-[no-mixed-enums.ts:3:12] 2 | Open = 1, 3 | Closed = 'closed', @@ -118,13 +118,14 @@ working directory: fixtures/tsgolint 4 | } `---- - x typescript-eslint(no-redundant-type-constituents): 'unknown' overrides all other types in this union type. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-redundant-type-constituents.html\typescript-eslint(no-redundant-type-constituents)]8;;\: 'unknown' overrides all other types in this union type. ,-[no-redundant-type-constituents.ts:1:20] 1 | type T1 = string | unknown; : ^^^^^^^ `---- - x typescript-eslint(no-unnecessary-boolean-literal-compare): This expression unnecessarily compares a boolean value to a boolean instead of using it directly. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unnecessary-boolean-literal-compare.html\typescript-eslint(no-unnecessary-boolean-literal-compare)]8;;\: This expression unnecessarily compares a boolean value to a boolean instead of using it + | directly. ,-[no-unnecessary-boolean-literal-compare.ts:2:5] 1 | declare const someCondition: boolean; 2 | if (someCondition === true) { @@ -132,7 +133,7 @@ working directory: fixtures/tsgolint 3 | } `---- - x typescript-eslint(no-unnecessary-template-expression): Template literal expression is unnecessary and can be simplified. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unnecessary-template-expression.html\typescript-eslint(no-unnecessary-template-expression)]8;;\: Template literal expression is unnecessary and can be simplified. ,-[no-unnecessary-template-expression.ts:2:18] 1 | const text = 'hello'; 2 | const wrapped = `${text}`; @@ -140,14 +141,14 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-unnecessary-type-arguments): This is the default value for this type parameter, so it can be omitted. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unnecessary-type-arguments.html\typescript-eslint(no-unnecessary-type-arguments)]8;;\: This is the default value for this type parameter, so it can be omitted. ,-[no-unnecessary-type-arguments.ts:4:25] 3 | } 4 | const result = identity('hello'); : ^^^^^^ `---- - x typescript-eslint(no-unnecessary-type-assertion): This assertion is unnecessary since it does not change the type of the expression. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unnecessary-type-assertion.html\typescript-eslint(no-unnecessary-type-assertion)]8;;\: This assertion is unnecessary since it does not change the type of the expression. ,-[no-unnecessary-type-assertion.ts:2:19] 1 | const str: string = 'hello'; 2 | const redundant = str as string; @@ -155,7 +156,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-unsafe-argument): Unsafe argument of type any assigned to a parameter of type string. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-argument.html\typescript-eslint(no-unsafe-argument)]8;;\: Unsafe argument of type any assigned to a parameter of type string. ,-[no-unsafe-argument.ts:3:13] 2 | function takesString(str: string): void {} 3 | takesString(anyValue); @@ -163,7 +164,7 @@ working directory: fixtures/tsgolint 4 | `---- - x typescript-eslint(no-unsafe-assignment): Unsafe assignment of an any value. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-assignment.html\typescript-eslint(no-unsafe-assignment)]8;;\: Unsafe assignment of an any value. ,-[no-unsafe-assignment.ts:2:7] 1 | declare const anyValue: any; 2 | const str: string = anyValue; @@ -171,7 +172,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-unsafe-call): Unsafe call of a(n) `any` typed value. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-call.html\typescript-eslint(no-unsafe-call)]8;;\: Unsafe call of a(n) `any` typed value. ,-[no-unsafe-call.ts:2:1] 1 | declare const anyValue: any; 2 | anyValue(); @@ -179,7 +180,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-unsafe-enum-comparison): The two values in this comparison do not have a shared enum type. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-enum-comparison.html\typescript-eslint(no-unsafe-enum-comparison)]8;;\: The two values in this comparison do not have a shared enum type. ,-[no-unsafe-enum-comparison.ts:9:20] 8 | } 9 | const comparison = Status.Open === Color.Red; @@ -187,7 +188,7 @@ working directory: fixtures/tsgolint 10 | `---- - x typescript-eslint(no-unsafe-member-access): Unsafe member access .foo on an `any` value. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-member-access.html\typescript-eslint(no-unsafe-member-access)]8;;\: Unsafe member access .foo on an `any` value. ,-[no-unsafe-member-access.ts:2:10] 1 | declare const anyValue: any; 2 | anyValue.foo; @@ -195,7 +196,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-unsafe-return): Unsafe return of a value of type `any`. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-return.html\typescript-eslint(no-unsafe-return)]8;;\: Unsafe return of a value of type `any`. ,-[no-unsafe-return.ts:3:3] 2 | function getString(): string { 3 | return anyValue; @@ -203,7 +204,7 @@ working directory: fixtures/tsgolint 4 | } `---- - x typescript-eslint(no-unsafe-assignment): Unsafe assignment of an any value. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-assignment.html\typescript-eslint(no-unsafe-assignment)]8;;\: Unsafe assignment of an any value. ,-[no-unsafe-type-assertion.ts:2:7] 1 | declare const value: unknown; 2 | const str = value as any; @@ -211,7 +212,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-unsafe-type-assertion): Unsafe assertion to `any` detected: consider using a more specific type to ensure safety. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-type-assertion.html\typescript-eslint(no-unsafe-type-assertion)]8;;\: Unsafe assertion to `any` detected: consider using a more specific type to ensure safety. ,-[no-unsafe-type-assertion.ts:2:13] 1 | declare const value: unknown; 2 | const str = value as any; @@ -219,7 +220,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-unsafe-type-assertion): Unsafe type assertion: type 'string' is more narrow than the original type. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-type-assertion.html\typescript-eslint(no-unsafe-type-assertion)]8;;\: Unsafe type assertion: type 'string' is more narrow than the original type. ,-[non-nullable-type-assertion-style.ts:2:17] 1 | declare const value: string | null; 2 | const result1 = value as string; @@ -227,7 +228,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(non-nullable-type-assertion-style): Use a ! assertion to more succinctly remove null and undefined from the type. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/non-nullable-type-assertion-style.html\typescript-eslint(non-nullable-type-assertion-style)]8;;\: Use a ! assertion to more succinctly remove null and undefined from the type. ,-[non-nullable-type-assertion-style.ts:2:17] 1 | declare const value: string | null; 2 | const result1 = value as string; @@ -243,14 +244,14 @@ working directory: fixtures/tsgolint `---- help: Remove the debugger statement - x typescript-eslint(only-throw-error): Expected an error object to be thrown. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/only-throw-error.html\typescript-eslint(only-throw-error)]8;;\: Expected an error object to be thrown. ,-[only-throw-error.ts:1:7] 1 | throw 'error'; : ^^^^^^^ 2 | `---- - x typescript-eslint(prefer-includes): Use 'includes()' method instead. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-includes.html\typescript-eslint(prefer-includes)]8;;\: Use 'includes()' method instead. ,-[prefer-includes.ts:2:5] 1 | const text = 'hello'; 2 | if (text.indexOf('h') !== -1) { @@ -258,7 +259,7 @@ working directory: fixtures/tsgolint 3 | } `---- - x typescript-eslint(prefer-includes): Use 'includes()' method instead. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-includes.html\typescript-eslint(prefer-includes)]8;;\: Use 'includes()' method instead. ,-[prefer-includes.ts:6:5] 5 | const items = [1, 2]; 6 | if (items.indexOf(1) !== -1) { @@ -266,7 +267,7 @@ working directory: fixtures/tsgolint 7 | } `---- - x typescript-eslint(prefer-includes): Use `String#includes()` method with a string instead. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-includes.html\typescript-eslint(prefer-includes)]8;;\: Use `String#includes()` method with a string instead. ,-[prefer-includes.ts:9:5] 8 | 9 | if (/test/.test(text)) { @@ -274,34 +275,34 @@ working directory: fixtures/tsgolint 10 | } `---- - x typescript-eslint(prefer-nullish-coalescing): Prefer using nullish coalescing operator (`??`) instead of a ternary expression, as it is simpler to read. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-nullish-coalescing.html\typescript-eslint(prefer-nullish-coalescing)]8;;\: Prefer using nullish coalescing operator (`??`) instead of a ternary expression, as it is simpler to read. ,-[prefer-nullish-coalescing.ts:2:23] 1 | declare const nullableString: string | null; 2 | const nullishResult = nullableString !== null && nullableString !== undefined ? nullableString : 'default'; : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- - x typescript-eslint(prefer-optional-chain): Prefer using an optional chain expression instead, as it's more concise and easier to read. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-optional-chain.html\typescript-eslint(prefer-optional-chain)]8;;\: Prefer using an optional chain expression instead, as it's more concise and easier to read. ,-[prefer-optional-chain.ts:3:1] 2 | declare const fooOptC: { bar: number } | null | undefined; 3 | fooOptC && fooOptC.bar; : ^^^^^^^^^^^^^^^^^^^^^^ `---- - x typescript-eslint(prefer-promise-reject-errors): Expected the Promise rejection reason to be an Error. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-promise-reject-errors.html\typescript-eslint(prefer-promise-reject-errors)]8;;\: Expected the Promise rejection reason to be an Error. ,-[prefer-promise-reject-errors.ts:1:1] 1 | Promise.reject('error'); : ^^^^^^^^^^^^^^^^^^^^^^^ `---- - x typescript-eslint(no-floating-promises): Promises must be awaited. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html\typescript-eslint(no-floating-promises)]8;;\: Promises must be awaited. ,-[prefer-promise-reject-errors.ts:1:1] 1 | Promise.reject('error'); : ^^^^^^^^^^^^^^^^^^^^^^^^ `---- help: The promise must end with a call to .catch, or end with a call to .then with a rejection handler, or be explicitly marked as ignored with the `void` operator. - x typescript-eslint(no-unnecessary-type-assertion): This assertion is unnecessary since it does not change the type of the expression. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unnecessary-type-assertion.html\typescript-eslint(no-unnecessary-type-assertion)]8;;\: This assertion is unnecessary since it does not change the type of the expression. ,-[prefer-reduce-type-parameter.ts:2:13] 1 | const numbers = [1, 2, 3]; 2 | const sum = numbers.reduce((acc, val) => acc + val, 0) as number; @@ -309,7 +310,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(prefer-return-this-type): Use `this` type instead. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-return-this-type.html\typescript-eslint(prefer-return-this-type)]8;;\: Use `this` type instead. ,-[prefer-return-this-type.ts:3:28] 2 | private value: string = ''; 3 | setValue(value: string): Builder { @@ -317,7 +318,7 @@ working directory: fixtures/tsgolint 4 | this.value = value; `---- - x typescript-eslint(promise-function-async): Functions that return promises must be async. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/promise-function-async.html\typescript-eslint(promise-function-async)]8;;\: Functions that return promises must be async. ,-[promise-function-async.ts:2:1] 1 | declare function fetch(url: string): Promise; 2 | ,-> function fetchData(): Promise { @@ -326,7 +327,7 @@ working directory: fixtures/tsgolint 5 | `---- - x typescript-eslint(promise-function-async): Functions that return promises must be async. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/promise-function-async.html\typescript-eslint(promise-function-async)]8;;\: Functions that return promises must be async. ,-[promise-function-async.ts:3:34] 2 | function fetchData(): Promise { 3 | return fetch('/api/data').then(res => res.text()); @@ -334,7 +335,7 @@ working directory: fixtures/tsgolint 4 | } `---- - x typescript-eslint(related-getter-setter-pairs): `get()` type should be assignable to its equivalent `set()` type. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/related-getter-setter-pairs.html\typescript-eslint(related-getter-setter-pairs)]8;;\: `get()` type should be assignable to its equivalent `set()` type. ,-[related-getter-setter-pairs.ts:3:16] 2 | private _value: number = 0; 3 | get value(): string { @@ -342,7 +343,7 @@ working directory: fixtures/tsgolint 4 | return this._value.toString(); `---- - x typescript-eslint(require-array-sort-compare): Require 'compare' argument. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/require-array-sort-compare.html\typescript-eslint(require-array-sort-compare)]8;;\: Require 'compare' argument. ,-[require-array-sort-compare.ts:2:1] 1 | const numbers = [3, 1, 4, 1, 5]; 2 | numbers.sort(); @@ -350,19 +351,19 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(no-unsafe-assignment): Unsafe assignment of an any value. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-assignment.html\typescript-eslint(no-unsafe-assignment)]8;;\: Unsafe assignment of an any value. ,-[restrict-plus-operands.ts:1:5] 1 | let foo = 1n + 1; : ^^^^^^^^^^^^ `---- - x typescript-eslint(restrict-plus-operands): Numeric '+' operations must either be both bigints or both numbers. Got `bigint` + `number`. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/restrict-plus-operands.html\typescript-eslint(restrict-plus-operands)]8;;\: Numeric '+' operations must either be both bigints or both numbers. Got `bigint` + `number`. ,-[restrict-plus-operands.ts:1:11] 1 | let foo = 1n + 1; : ^^^^^^ `---- - x typescript-eslint(no-base-to-string): 'obj' will use Object's default stringification format ('[object Object]') when stringified. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-base-to-string.html\typescript-eslint(no-base-to-string)]8;;\: 'obj' will use Object's default stringification format ('[object Object]') when stringified. ,-[restrict-template-expressions.ts:2:24] 1 | declare const obj: object; 2 | const str1 = `Value: ${obj}`; @@ -370,7 +371,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(restrict-template-expressions): Invalid type "object" of template literal expression. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/restrict-template-expressions.html\typescript-eslint(restrict-template-expressions)]8;;\: Invalid type "object" of template literal expression. ,-[restrict-template-expressions.ts:2:24] 1 | declare const obj: object; 2 | const str1 = `Value: ${obj}`; @@ -378,7 +379,7 @@ working directory: fixtures/tsgolint 3 | `---- - x typescript-eslint(switch-exhaustiveness-check): Switch is not exhaustive + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/switch-exhaustiveness-check.html\typescript-eslint(switch-exhaustiveness-check)]8;;\: Switch is not exhaustive ,-[switch-exhaustiveness-check.ts:3:11] 2 | function handleStatus(status: Status) { 3 | switch (status) { @@ -395,7 +396,7 @@ working directory: fixtures/tsgolint `---- help: Remove the debugger statement - x typescript-eslint(unbound-method): Avoid referencing unbound methods which may cause unintentional scoping of `this`. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/unbound-method.html\typescript-eslint(unbound-method)]8;;\: Avoid referencing unbound methods which may cause unintentional scoping of `this`. | If your function does not access `this`, you can annotate it with `this: void`, or consider using an arrow function instead. ,-[unbound-method.ts:9:19] 8 | const calc = new Calculator(); diff --git a/apps/oxlint/src/snapshots/fixtures__tsgolint_disable_directives_--type-aware --report-unused-disable-directives unused.ts@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__tsgolint_disable_directives_--type-aware --report-unused-disable-directives unused.ts@oxlint.snap index b0458085853ce..199731463de9b 100644 --- a/apps/oxlint/src/snapshots/fixtures__tsgolint_disable_directives_--type-aware --report-unused-disable-directives unused.ts@oxlint.snap +++ b/apps/oxlint/src/snapshots/fixtures__tsgolint_disable_directives_--type-aware --report-unused-disable-directives unused.ts@oxlint.snap @@ -40,7 +40,7 @@ working directory: fixtures/tsgolint_disable_directives `---- help: Consider using this expression or removing it - ! typescript-eslint(no-floating-promises): Promises must be awaited. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html\typescript-eslint(no-floating-promises)]8;;\: Promises must be awaited. ,-[unused.ts:14:1] 13 | // oxlint-disable-next-line typescript/no-unsafe-assignment 14 | myPromise diff --git a/apps/oxlint/src/snapshots/fixtures__tsgolint_disable_directives_--type-aware test.ts@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__tsgolint_disable_directives_--type-aware test.ts@oxlint.snap index 22b827cfa9567..462057194e983 100644 --- a/apps/oxlint/src/snapshots/fixtures__tsgolint_disable_directives_--type-aware test.ts@oxlint.snap +++ b/apps/oxlint/src/snapshots/fixtures__tsgolint_disable_directives_--type-aware test.ts@oxlint.snap @@ -51,7 +51,7 @@ working directory: fixtures/tsgolint_disable_directives `---- help: Consider using this expression or removing it - ! typescript-eslint(no-floating-promises): Promises must be awaited. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html\typescript-eslint(no-floating-promises)]8;;\: Promises must be awaited. ,-[test.ts:19:1] 18 | // This should still report an error (no disable directive) 19 | myPromise @@ -87,7 +87,7 @@ working directory: fixtures/tsgolint_disable_directives `---- help: Consider using this expression or removing it - ! typescript-eslint(no-floating-promises): Promises must be awaited. + ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-floating-promises.html\typescript-eslint(no-floating-promises)]8;;\: Promises must be awaited. ,-[test.ts:39:1] 38 | // Should report error 39 | Promise.resolve(4) diff --git a/apps/oxlint/src/snapshots/fixtures__tsgolint_rule_options_--type-aware@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__tsgolint_rule_options_--type-aware@oxlint.snap index 8a10ebbe92e2d..90461c1ba4465 100644 --- a/apps/oxlint/src/snapshots/fixtures__tsgolint_rule_options_--type-aware@oxlint.snap +++ b/apps/oxlint/src/snapshots/fixtures__tsgolint_rule_options_--type-aware@oxlint.snap @@ -6,7 +6,7 @@ arguments: --type-aware working directory: fixtures/tsgolint_rule_options ---------- - x typescript-eslint(no-deprecated): `notAllowedDeprecated` is deprecated. Use anotherNewFunction instead + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-deprecated.html\typescript-eslint(no-deprecated)]8;;\: `notAllowedDeprecated` is deprecated. Use anotherNewFunction instead ,-[test.ts:36:1] 35 | // This SHOULD error because notAllowedDeprecated is NOT in the allow list 36 | notAllowedDeprecated(); @@ -14,7 +14,7 @@ working directory: fixtures/tsgolint_rule_options 37 | `---- - x typescript-eslint(no-misused-spread): Using the spread operator on a function without additional properties can cause unexpected behavior. Did you forget to call the function? + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-misused-spread.html\typescript-eslint(no-misused-spread)]8;;\: Using the spread operator on a function without additional properties can cause unexpected behavior. Did you forget to call the function? ,-[test.ts:47:28] 46 | // This SHOULD error because notAllowedFunc is NOT in the allow list 47 | const notAllowedSpread = { ...notAllowedFunc }; @@ -22,7 +22,7 @@ working directory: fixtures/tsgolint_rule_options 48 | `---- - x typescript-eslint(no-unsafe-member-access): Unsafe member access .bar on an `any` value. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-member-access.html\typescript-eslint(no-unsafe-member-access)]8;;\: Unsafe member access .bar on an `any` value. ,-[test.ts:58:31] 57 | // This SHOULD error because it's not using optional chaining 58 | const unsafeAccess = anyValue.bar; @@ -30,7 +30,7 @@ working directory: fixtures/tsgolint_rule_options 59 | `---- - x typescript-eslint(no-base-to-string): 'unknownValue' may use Object's default stringification format ('[object Object]') when stringified. + x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-base-to-string.html\typescript-eslint(no-base-to-string)]8;;\: 'unknownValue' may use Object's default stringification format ('[object Object]') when stringified. ,-[test.ts:63:20] 62 | // This SHOULD error because checkUnknown is true 63 | const unknownStr = unknownValue.toString(); diff --git a/crates/oxc_linter/src/context/mod.rs b/crates/oxc_linter/src/context/mod.rs index 59c927cde2520..e34b78edc97f6 100644 --- a/crates/oxc_linter/src/context/mod.rs +++ b/crates/oxc_linter/src/context/mod.rs @@ -14,6 +14,7 @@ use oxc_span::Span; use crate::rule::RuleFixMeta; use crate::{ AllowWarnDeny, FrameworkFlags, ModuleRecord, OxlintEnv, OxlintGlobals, OxlintSettings, + WEBSITE_BASE_RULES_URL, config::GlobalValue, disable_directives::DisableDirectives, fixer::{Fix, FixKind, Message, PossibleFixes, RuleFix, RuleFixer}, @@ -70,9 +71,6 @@ impl<'a> Deref for LintContext<'a> { } impl<'a> LintContext<'a> { - /// Base URL for the documentation, used to generate rule documentation URLs when a diagnostic is reported. - const WEBSITE_BASE_URL: &'static str = "https://oxc.rs/docs/guide/usage/linter/rules"; - /// Set the plugin name for the current rule. pub fn with_plugin_name(mut self, plugin: &'static str) -> Self { self.current_plugin_name = plugin; @@ -277,9 +275,7 @@ impl<'a> LintContext<'a> { .with_error_code(self.current_plugin_prefix, self.current_rule_name) .with_url(format!( "{}/{}/{}.html", - Self::WEBSITE_BASE_URL, - self.current_plugin_name, - self.current_rule_name + WEBSITE_BASE_RULES_URL, self.current_plugin_name, self.current_rule_name )); if message.error.severity != self.severity { message.error = message.error.with_severity(self.severity); diff --git a/crates/oxc_linter/src/lib.rs b/crates/oxc_linter/src/lib.rs index b702829e236d7..eb3b403f2f201 100644 --- a/crates/oxc_linter/src/lib.rs +++ b/crates/oxc_linter/src/lib.rs @@ -95,6 +95,9 @@ fn size_asserts() { assert_eq!(size_of::(), 16); } +/// Base URL for the documentation, used to generate rule documentation URLs when a diagnostic is reported. +const WEBSITE_BASE_RULES_URL: &str = "https://oxc.rs/docs/guide/usage/linter/rules"; + #[derive(Debug)] #[expect(clippy::struct_field_names)] pub struct Linter { diff --git a/crates/oxc_linter/src/tsgolint.rs b/crates/oxc_linter/src/tsgolint.rs index 502423c61f0db..a6414f48aff17 100644 --- a/crates/oxc_linter/src/tsgolint.rs +++ b/crates/oxc_linter/src/tsgolint.rs @@ -15,7 +15,7 @@ use oxc_span::{SourceType, Span}; use super::{AllowWarnDeny, ConfigStore, DisableDirectives, ResolvedLinterState, read_to_string}; -use crate::{CompositeFix, FixKind, Fixer, Message, PossibleFixes}; +use crate::{CompositeFix, FixKind, Fixer, Message, PossibleFixes, WEBSITE_BASE_RULES_URL}; /// State required to initialize the `tsgolint` linter. #[derive(Debug, Clone)] @@ -703,6 +703,7 @@ impl From for OxcDiagnostic { fn from(val: TsGoLintRuleDiagnostic) -> Self { let mut d = OxcDiagnostic::warn(val.message.description) .with_label(val.span) + .with_url(format!("{}/{}/{}.html", WEBSITE_BASE_RULES_URL, "typescript", val.rule)) .with_error_code("typescript-eslint", val.rule); if let Some(help) = val.message.help { d = d.with_help(help);