diff --git a/crates/oxc_linter/src/generated/rule_runner_impls.rs b/crates/oxc_linter/src/generated/rule_runner_impls.rs index 7c2f4b454c3fb..67a1952ad6caa 100644 --- a/crates/oxc_linter/src/generated/rule_runner_impls.rs +++ b/crates/oxc_linter/src/generated/rule_runner_impls.rs @@ -1396,6 +1396,7 @@ impl RuleRunner for crate::rules::typescript::consistent_generic_constructors::ConsistentGenericConstructors { const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[ + AstType::AccessorProperty, AstType::FormalParameter, AstType::PropertyDefinition, AstType::VariableDeclarator, diff --git a/crates/oxc_linter/src/rules/typescript/consistent_generic_constructors.rs b/crates/oxc_linter/src/rules/typescript/consistent_generic_constructors.rs index d255e16bcd7f7..d3d469f890d5a 100644 --- a/crates/oxc_linter/src/rules/typescript/consistent_generic_constructors.rs +++ b/crates/oxc_linter/src/rules/typescript/consistent_generic_constructors.rs @@ -7,6 +7,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; +use oxc_semantic::IsGlobalReference; use oxc_span::{GetSpan, Span}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -114,6 +115,11 @@ impl Rule for ConsistentGenericConstructors { let init = property_definition.value.as_ref(); self.check(node, type_ann, init, ctx); } + AstKind::AccessorProperty(accessor_property) => { + let type_ann = accessor_property.type_annotation.as_ref(); + let init = accessor_property.value.as_ref(); + self.check(node, type_ann, init, ctx); + } _ => {} } } @@ -148,6 +154,11 @@ impl ConsistentGenericConstructors { let Expression::Identifier(identifier) = &new_expression.callee else { return; }; + if is_built_in_typed_array(&identifier.name) + && identifier.is_global_reference_name(identifier.name, ctx.scoping()) + { + return; + } if let Some(type_annotation) = type_annotation { if let TSType::TSTypeReference(type_annotation) = &type_annotation.type_annotation { if let TSTypeName::IdentifierReference(ident) = &type_annotation.type_name { @@ -368,6 +379,7 @@ impl ConsistentGenericConstructors { AstKind::VariableDeclarator(var_decl) => Some(var_decl.id.span().end), AstKind::FormalParameter(param) => Some(param.pattern.span().end), AstKind::PropertyDefinition(prop_def) => Some(prop_def.key.span().end), + AstKind::AccessorProperty(accessor) => Some(accessor.key.span().end), _ => { debug_assert!(false, "Unexpected node kind in find_binding_end_position"); None @@ -411,11 +423,34 @@ impl ConsistentGenericConstructors { Some(prop_def.key.span().end) } } + AstKind::AccessorProperty(accessor) => { + if accessor.computed { + let key_end = accessor.key.span().end; + ctx.find_next_token_from(key_end, "]").map(|offset| key_end + offset + 1) + } else { + Some(accessor.key.span().end) + } + } _ => None, } } } +fn is_built_in_typed_array(name: &str) -> bool { + matches!( + name, + "Float32Array" + | "Float64Array" + | "Int16Array" + | "Int32Array" + | "Int8Array" + | "Uint16Array" + | "Uint32Array" + | "Uint8Array" + | "Uint8ClampedArray" + ) +} + #[test] fn test() { use crate::tester::Tester; @@ -480,63 +515,62 @@ fn test() { ", None, ), - // TODO: Fix the rule so these pass. - // ( - // " - // const a: Float32Array = new Float32Array(); - // export {}; - // ", - // None, - // ), - // ( - // " - // const a: Float64Array = new Float64Array(); - // export {}; - // ", - // None, - // ), - // ( - // " - // const a: Int16Array = new Int16Array(); - // export {}; - // ", - // None, - // ), - // ( - // " - // const a: Int8Array = new Int8Array(); - // export {}; - // ", - // None, - // ), - // ( - // " - // const a: Uint16Array = new Uint16Array(); - // export {}; - // ", - // None, - // ), - // ( - // " - // const a: Uint32Array = new Uint32Array(); - // export {}; - // ", - // None, - // ), - // ( - // " - // const a: Uint8Array = new Uint8Array(); - // export {}; - // ", - // None, - // ), - // ( - // " - // const a: Uint8ClampedArray = new Uint8ClampedArray(); - // export {}; - // ", - // None, - // ), + ( + " + const a: Float32Array = new Float32Array(); + export {}; + ", + None, + ), + ( + " + const a: Float64Array = new Float64Array(); + export {}; + ", + None, + ), + ( + " + const a: Int16Array = new Int16Array(); + export {}; + ", + None, + ), + ( + " + const a: Int8Array = new Int8Array(); + export {}; + ", + None, + ), + ( + " + const a: Uint16Array = new Uint16Array(); + export {}; + ", + None, + ), + ( + " + const a: Uint32Array = new Uint32Array(); + export {}; + ", + None, + ), + ( + " + const a: Uint8Array = new Uint8Array(); + export {}; + ", + None, + ), + ( + " + const a: Uint8ClampedArray = new Uint8ClampedArray(); + export {}; + ", + None, + ), // TODO: Fix? // ( // " @@ -647,31 +681,30 @@ fn test() { ", None, ), - // TODO: Fix these. - // ( - // " - // class Foo { - // accessor a: Foo = new Foo(); - // } - // ", - // None, - // ), - // ( - // " - // class Foo { - // accessor a = new Foo(); - // } - // ", - // Some(serde_json::json!(["type-annotation"])), - // ), - // ( - // " - // class Foo { - // accessor [a]: Foo = new Foo(); - // } - // ", - // None, - // ), + ( + " + class Foo { + accessor a: Foo = new Foo(); + } + ", + None, + ), + ( + " + class Foo { + accessor a = new Foo(); + } + ", + Some(serde_json::json!(["type-annotation"])), + ), + ( + " + class Foo { + accessor [a]: Foo = new Foo(); + } + ", + None, + ), ( " function foo(a: Foo = new Foo()) {} @@ -852,46 +885,45 @@ fn test() { ", None, ), - // TODO: Fix these - // ( - // " - // class Foo { - // accessor a: Foo = new Foo(); - // } - // ", - // " - // class Foo { - // accessor a = new Foo(); - // } - // ", - // None, - // ), - // ( - // " - // class Foo { - // accessor a = new Foo(); - // } - // ", - // " - // class Foo { - // accessor a: Foo = new Foo(); - // } - // ", - // Some(serde_json::json!(["type-annotation"])), - // ), - // ( - // " - // class Foo { - // accessor [a]: Foo = new Foo(); - // } - // ", - // " - // class Foo { - // accessor [a] = new Foo(); - // } - // ", - // None, - // ), + ( + " + class Foo { + accessor a: Foo = new Foo(); + } + ", + " + class Foo { + accessor a = new Foo(); + } + ", + None, + ), + ( + " + class Foo { + accessor a = new Foo(); + } + ", + " + class Foo { + accessor a: Foo = new Foo(); + } + ", + Some(serde_json::json!(["type-annotation"])), + ), + ( + " + class Foo { + accessor [a]: Foo = new Foo(); + } + ", + " + class Foo { + accessor [a] = new Foo(); + } + ", + None, + ), ( " function foo(a: Foo = new Foo()) {} diff --git a/crates/oxc_linter/src/snapshots/typescript_consistent_generic_constructors.snap b/crates/oxc_linter/src/snapshots/typescript_consistent_generic_constructors.snap index 93a30d7413a37..6755edf9a4b19 100644 --- a/crates/oxc_linter/src/snapshots/typescript_consistent_generic_constructors.snap +++ b/crates/oxc_linter/src/snapshots/typescript_consistent_generic_constructors.snap @@ -84,6 +84,33 @@ source: crates/oxc_linter/src/tester.rs ╰──── help: Move the type annotation to the constructor + ⚠ typescript-eslint(consistent-generic-constructors): The generic type arguments should be specified as part of the constructor type arguments. + ╭─[consistent_generic_constructors.tsx:3:25] + 2 │ class Foo { + 3 │ accessor a: Foo = new Foo(); + · ───────────── + 4 │ } + ╰──── + help: Move the type annotation to the constructor + + ⚠ typescript-eslint(consistent-generic-constructors): The generic type arguments should be specified as part of the type annotation. + ╭─[consistent_generic_constructors.tsx:3:35] + 2 │ class Foo { + 3 │ accessor a = new Foo(); + · ──────── + 4 │ } + ╰──── + help: Move the generic type to the type annotation + + ⚠ typescript-eslint(consistent-generic-constructors): The generic type arguments should be specified as part of the constructor type arguments. + ╭─[consistent_generic_constructors.tsx:3:27] + 2 │ class Foo { + 3 │ accessor [a]: Foo = new Foo(); + · ───────────── + 4 │ } + ╰──── + help: Move the type annotation to the constructor + ⚠ typescript-eslint(consistent-generic-constructors): The generic type arguments should be specified as part of the constructor type arguments. ╭─[consistent_generic_constructors.tsx:2:27] 1 │