mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(linter): implement typescript/consistent-generic-constructors (#7497)
This commit is contained in:
parent
32c7db0ec6
commit
60b28fc23a
3 changed files with 943 additions and 0 deletions
|
|
@ -155,6 +155,7 @@ mod typescript {
|
|||
pub mod ban_ts_comment;
|
||||
pub mod ban_tslint_comment;
|
||||
pub mod ban_types;
|
||||
pub mod consistent_generic_constructors;
|
||||
pub mod consistent_indexed_object_style;
|
||||
pub mod consistent_type_definitions;
|
||||
pub mod consistent_type_imports;
|
||||
|
|
@ -848,6 +849,7 @@ oxc_macros::declare_all_lint_rules! {
|
|||
typescript::ban_ts_comment,
|
||||
typescript::ban_tslint_comment,
|
||||
typescript::ban_types,
|
||||
typescript::consistent_generic_constructors,
|
||||
typescript::consistent_indexed_object_style,
|
||||
typescript::consistent_type_definitions,
|
||||
typescript::consistent_type_imports,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,689 @@
|
|||
use oxc_ast::{
|
||||
ast::{Expression, TSType, TSTypeAnnotation, TSTypeName},
|
||||
AstKind,
|
||||
};
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule, AstNode};
|
||||
|
||||
fn consistent_generic_constructors_diagnostic_prefer_annotation(span: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn(
|
||||
"The generic type arguments should be specified as part of the type annotation.",
|
||||
)
|
||||
.with_help("Move the generic type to the type annotation")
|
||||
.with_label(span)
|
||||
}
|
||||
fn consistent_generic_constructors_diagnostic_prefer_constructor(span: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn(
|
||||
"The generic type arguments should be specified as part of the constructor type arguments.",
|
||||
)
|
||||
.with_help("Move the type annotation to the constructor")
|
||||
.with_label(span)
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ConsistentGenericConstructors(Box<ConsistentGenericConstructorsConfig>);
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ConsistentGenericConstructorsConfig {
|
||||
option: PreferGenericType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
enum PreferGenericType {
|
||||
#[default]
|
||||
Constructor,
|
||||
TypeAnnotation,
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for PreferGenericType {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
"constructor" => Ok(Self::Constructor),
|
||||
"type-annotation" => Ok(Self::TypeAnnotation),
|
||||
_ => Err("Invalid value"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_oxc_lint!(
|
||||
/// ### What it does
|
||||
///
|
||||
/// When constructing a generic class, you can specify the type arguments on either the left-hand side (as a type annotation) or the right-hand side (as part of the constructor call).
|
||||
///
|
||||
/// This rule enforces consistency in the way generic constructors are used.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
/// Inconsistent usage of generic constructors can make the code harder to read and maintain.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// Examples of **incorrect** code for this rule:
|
||||
/// ```ts
|
||||
/// const a: Foo<string> = new Foo();
|
||||
/// const a = new Foo<string>(); // prefer type annotation
|
||||
/// ```
|
||||
///
|
||||
/// Examples of **correct** code for this rule:
|
||||
/// ```ts
|
||||
/// const a = new Foo<string>();
|
||||
/// const a: Foo<string> = new Foo(); // prefer type annotation
|
||||
/// ```
|
||||
ConsistentGenericConstructors,
|
||||
style,
|
||||
pending
|
||||
);
|
||||
|
||||
impl Rule for ConsistentGenericConstructors {
|
||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
match node.kind() {
|
||||
AstKind::VariableDeclarator(variable_declarator) => {
|
||||
let type_ann = &variable_declarator.id.type_annotation;
|
||||
let init = &variable_declarator.init;
|
||||
self.check(type_ann, init.as_ref(), ctx);
|
||||
}
|
||||
AstKind::AssignmentPattern(assignment_pattern) => {
|
||||
let Some(parent) = ctx.nodes().parent_kind(node.id()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !matches!(parent, AstKind::FormalParameter(_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let type_ann = &assignment_pattern.left.type_annotation;
|
||||
let init = &assignment_pattern.right;
|
||||
self.check(type_ann, Some(init), ctx);
|
||||
}
|
||||
AstKind::PropertyDefinition(property_definition) => {
|
||||
let type_ann = &property_definition.type_annotation;
|
||||
let init = &property_definition.value;
|
||||
|
||||
self.check(type_ann, init.as_ref(), ctx);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_configuration(value: serde_json::Value) -> Self {
|
||||
Self(Box::new(ConsistentGenericConstructorsConfig {
|
||||
option: value
|
||||
.get(0)
|
||||
.and_then(|v| v.as_str())
|
||||
.and_then(|s| PreferGenericType::try_from(s).ok())
|
||||
.unwrap_or_default(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl ConsistentGenericConstructors {
|
||||
fn check(
|
||||
&self,
|
||||
type_annotation: &Option<oxc_allocator::Box<TSTypeAnnotation>>,
|
||||
init: Option<&Expression>,
|
||||
ctx: &LintContext,
|
||||
) {
|
||||
let Some(init) = init else { return };
|
||||
let Expression::NewExpression(new_expression) = init.get_inner_expression() else {
|
||||
return;
|
||||
};
|
||||
let Expression::Identifier(identifier) = &new_expression.callee else {
|
||||
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 {
|
||||
if ident.name != identifier.name {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if matches!(self.0.option, PreferGenericType::TypeAnnotation) {
|
||||
if type_annotation.is_none() {
|
||||
if let Some(type_arguments) = &new_expression.type_parameters {
|
||||
ctx.diagnostic(consistent_generic_constructors_diagnostic_prefer_annotation(
|
||||
type_arguments.span,
|
||||
));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(type_arguments) = &type_annotation {
|
||||
if has_type_parameters(&type_arguments.type_annotation)
|
||||
&& new_expression.type_parameters.is_none()
|
||||
{
|
||||
ctx.diagnostic(consistent_generic_constructors_diagnostic_prefer_constructor(
|
||||
type_arguments.span,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn has_type_parameters(ts_type: &TSType) -> bool {
|
||||
match ts_type {
|
||||
TSType::TSTypeReference(type_ref) => type_ref.type_parameters.is_some(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec![
|
||||
("const a = new Foo();", None),
|
||||
("const a = new Foo<string>();", None),
|
||||
("const a: Foo<string> = new Foo<string>();", None),
|
||||
("const a: Foo = new Foo();", None),
|
||||
("const a: Bar<string> = new Foo();", None),
|
||||
("const a: Foo = new Foo<string>();", None),
|
||||
("const a: Bar = new Foo<string>();", None),
|
||||
("const a: Bar<string> = new Foo<string>();", None),
|
||||
("const a: Foo<string> = Foo<string>();", None),
|
||||
("const a: Foo<string> = Foo();", None),
|
||||
("const a: Foo = Foo<string>();", None),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
a = new Foo<string>();
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo(a: Foo = new Foo<string>()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo({ a }: Foo = new Foo<string>()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo([a]: Foo = new Foo<string>()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
class A {
|
||||
constructor(a: Foo = new Foo<string>()) {}
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
const a = function (a: Foo = new Foo<string>()) {};
|
||||
",
|
||||
None,
|
||||
),
|
||||
("const a = new Foo();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a: Foo<string> = new Foo();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a: Foo<string> = new Foo<string>();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a: Foo = new Foo();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a: Bar = new Foo<string>();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a: Bar<string> = new Foo<string>();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a: Foo<string> = Foo<string>();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a: Foo<string> = Foo();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a: Foo = Foo<string>();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a = new (class C<T> {})<string>();", Some(serde_json::json!(["type-annotation"]))),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
a: Foo<string> = new Foo();
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo(a: Foo<string> = new Foo()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo({ a }: Foo<string> = new Foo()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo([a]: Foo<string> = new Foo()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class A {
|
||||
constructor(a: Foo<string> = new Foo()) {}
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
const a = function (a: Foo<string> = new Foo()) {};
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
const [a = new Foo<string>()] = [];
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function a([a = new Foo<string>()]) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
("const a: Foo<string> = new Foo();", None),
|
||||
("const a: Map<string, number> = new Map();", None),
|
||||
("const a: Map <string, number> = new Map();", None),
|
||||
("const a: Map< string, number > = new Map();", None),
|
||||
("const a: Map<string, number> = new Map ();", None),
|
||||
("const a: Foo<number> = new Foo;", None),
|
||||
("const a: /* comment */ Foo/* another */ <string> = new Foo();", None),
|
||||
("const a: Foo/* comment */ <string> = new Foo /* another */();", None),
|
||||
(
|
||||
"const a: Foo<string> = new
|
||||
Foo
|
||||
();",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
a: Foo<string> = new Foo();
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
[a]: Foo<string> = new Foo();
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo(a: Foo<string> = new Foo()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo({ a }: Foo<string> = new Foo()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo([a]: Foo<string> = new Foo()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
class A {
|
||||
constructor(a: Foo<string> = new Foo()) {}
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
const a = function (a: Foo<string> = new Foo()) {};
|
||||
",
|
||||
None,
|
||||
),
|
||||
("const a = new Foo<string>();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a = new Map<string, number>();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a = new Map <string, number> ();", Some(serde_json::json!(["type-annotation"]))),
|
||||
("const a = new Map< string, number >();", Some(serde_json::json!(["type-annotation"]))),
|
||||
(
|
||||
"const a = new
|
||||
Foo<string>
|
||||
();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"const a = new Foo/* comment */ <string> /* another */();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"const a = new Foo</* comment */ string, /* another */ number>();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
a = new Foo<string>();
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
[a] = new Foo<string>();
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
[a + b] = new Foo<string>();
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo(a = new Foo<string>()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo({ a } = new Foo<string>()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo([a] = new Foo<string>()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class A {
|
||||
constructor(a = new Foo<string>()) {}
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
const a = function (a = new Foo<string>()) {};
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
];
|
||||
|
||||
let _fix = vec![
|
||||
("const a: Foo<string> = new Foo();", "const a = new Foo<string>();", None),
|
||||
("const a: Map<string, number> = new Map();", "const a = new Map<string, number>();", None),
|
||||
(
|
||||
"const a: Map <string, number> = new Map();",
|
||||
"const a = new Map<string, number>();",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"const a: Map< string, number > = new Map();",
|
||||
"const a = new Map< string, number >();",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"const a: Map<string, number> = new Map ();",
|
||||
"const a = new Map<string, number> ();",
|
||||
None,
|
||||
),
|
||||
("const a: Foo<number> = new Foo;", "const a = new Foo<number>();", None),
|
||||
(
|
||||
"const a: /* comment */ Foo/* another */ <string> = new Foo();",
|
||||
"const a = new Foo/* comment *//* another */<string>();",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"const a: Foo/* comment */ <string> = new Foo /* another */();",
|
||||
"const a = new Foo/* comment */<string> /* another */();",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"const a: Foo<string> = new
|
||||
Foo
|
||||
();",
|
||||
"const a = new
|
||||
Foo<string>
|
||||
();",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
a: Foo<string> = new Foo();
|
||||
}
|
||||
",
|
||||
"
|
||||
class Foo {
|
||||
a = new Foo<string>();
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
[a]: Foo<string> = new Foo();
|
||||
}
|
||||
",
|
||||
"
|
||||
class Foo {
|
||||
[a] = new Foo<string>();
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo(a: Foo<string> = new Foo()) {}
|
||||
",
|
||||
"
|
||||
function foo(a = new Foo<string>()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo({ a }: Foo<string> = new Foo()) {}
|
||||
",
|
||||
"
|
||||
function foo({ a } = new Foo<string>()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo([a]: Foo<string> = new Foo()) {}
|
||||
",
|
||||
"
|
||||
function foo([a] = new Foo<string>()) {}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
class A {
|
||||
constructor(a: Foo<string> = new Foo()) {}
|
||||
}
|
||||
",
|
||||
"
|
||||
class A {
|
||||
constructor(a = new Foo<string>()) {}
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
const a = function (a: Foo<string> = new Foo()) {};
|
||||
",
|
||||
"
|
||||
const a = function (a = new Foo<string>()) {};
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"const a = new Foo<string>();",
|
||||
"const a: Foo<string> = new Foo();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"const a = new Map<string, number>();",
|
||||
"const a: Map<string, number> = new Map();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"const a = new Map <string, number> ();",
|
||||
"const a: Map<string, number> = new Map ();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"const a = new Map< string, number >();",
|
||||
"const a: Map< string, number > = new Map();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"const a = new
|
||||
Foo<string>
|
||||
();",
|
||||
"const a: Foo<string> = new
|
||||
Foo
|
||||
();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"const a = new Foo/* comment */ <string> /* another */();",
|
||||
"const a: Foo<string> = new Foo/* comment */ /* another */();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"const a = new Foo</* comment */ string, /* another */ number>();",
|
||||
"const a: Foo</* comment */ string, /* another */ number> = new Foo();",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
a = new Foo<string>();
|
||||
}
|
||||
",
|
||||
"
|
||||
class Foo {
|
||||
a: Foo<string> = new Foo();
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
[a] = new Foo<string>();
|
||||
}
|
||||
",
|
||||
"
|
||||
class Foo {
|
||||
[a]: Foo<string> = new Foo();
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class Foo {
|
||||
[a + b] = new Foo<string>();
|
||||
}
|
||||
",
|
||||
"
|
||||
class Foo {
|
||||
[a + b]: Foo<string> = new Foo();
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo(a = new Foo<string>()) {}
|
||||
",
|
||||
"
|
||||
function foo(a: Foo<string> = new Foo()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo({ a } = new Foo<string>()) {}
|
||||
",
|
||||
"
|
||||
function foo({ a }: Foo<string> = new Foo()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
function foo([a] = new Foo<string>()) {}
|
||||
",
|
||||
"
|
||||
function foo([a]: Foo<string> = new Foo()) {}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
class A {
|
||||
constructor(a = new Foo<string>()) {}
|
||||
}
|
||||
",
|
||||
"
|
||||
class A {
|
||||
constructor(a: Foo<string> = new Foo()) {}
|
||||
}
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
(
|
||||
"
|
||||
const a = function (a = new Foo<string>()) {};
|
||||
",
|
||||
"
|
||||
const a = function (a: Foo<string> = new Foo()) {};
|
||||
",
|
||||
Some(serde_json::json!(["type-annotation"])),
|
||||
),
|
||||
];
|
||||
Tester::new(
|
||||
ConsistentGenericConstructors::NAME,
|
||||
ConsistentGenericConstructors::CATEGORY,
|
||||
pass,
|
||||
fail,
|
||||
)
|
||||
.test_and_snapshot();
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
---
|
||||
⚠ typescript-eslint(consistent-generic-constructors): The generic type arguments should be specified as part of the constructor type arguments.
|
||||
╭─[consistent_generic_constructors.tsx:1:8]
|
||||
1 │ const a: Foo<string> = new Foo();
|
||||
· ─────────────
|
||||
╰────
|
||||
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:1:8]
|
||||
1 │ const a: Map<string, number> = new Map();
|
||||
· ─────────────────────
|
||||
╰────
|
||||
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:1:8]
|
||||
1 │ const a: Map <string, number> = new Map();
|
||||
· ──────────────────────
|
||||
╰────
|
||||
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:1:8]
|
||||
1 │ const a: Map< string, number > = new Map();
|
||||
· ───────────────────────
|
||||
╰────
|
||||
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:1:8]
|
||||
1 │ const a: Map<string, number> = new Map ();
|
||||
· ─────────────────────
|
||||
╰────
|
||||
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:1:8]
|
||||
1 │ const a: Foo<number> = new Foo;
|
||||
· ─────────────
|
||||
╰────
|
||||
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:1:8]
|
||||
1 │ const a: /* comment */ Foo/* another */ <string> = new Foo();
|
||||
· ─────────────────────────────────────────
|
||||
╰────
|
||||
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:1:8]
|
||||
1 │ const a: Foo/* comment */ <string> = new Foo /* another */();
|
||||
· ───────────────────────────
|
||||
╰────
|
||||
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:1:8]
|
||||
1 │ const a: Foo<string> = new
|
||||
· ─────────────
|
||||
2 │ Foo
|
||||
╰────
|
||||
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:7]
|
||||
2 │ class Foo {
|
||||
3 │ a: Foo<string> = 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:3:9]
|
||||
2 │ class Foo {
|
||||
3 │ [a]: Foo<string> = 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:18]
|
||||
1 │
|
||||
2 │ function foo(a: Foo<string> = new Foo()) {}
|
||||
· ─────────────
|
||||
3 │
|
||||
╰────
|
||||
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:22]
|
||||
1 │
|
||||
2 │ function foo({ a }: Foo<string> = new Foo()) {}
|
||||
· ─────────────
|
||||
3 │
|
||||
╰────
|
||||
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:20]
|
||||
1 │
|
||||
2 │ function foo([a]: Foo<string> = new Foo()) {}
|
||||
· ─────────────
|
||||
3 │
|
||||
╰────
|
||||
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:19]
|
||||
2 │ class A {
|
||||
3 │ constructor(a: Foo<string> = 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:25]
|
||||
1 │
|
||||
2 │ const a = function (a: Foo<string> = new Foo()) {};
|
||||
· ─────────────
|
||||
3 │
|
||||
╰────
|
||||
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:1:18]
|
||||
1 │ const a = new Foo<string>();
|
||||
· ────────
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:1:18]
|
||||
1 │ const a = new Map<string, number>();
|
||||
· ────────────────
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:1:19]
|
||||
1 │ const a = new Map <string, number> ();
|
||||
· ────────────────
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:1:18]
|
||||
1 │ const a = new Map< string, number >();
|
||||
· ──────────────────
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:2:8]
|
||||
1 │ const a = new
|
||||
2 │ Foo<string>
|
||||
· ────────
|
||||
3 │ ();
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:1:32]
|
||||
1 │ const a = new Foo/* comment */ <string> /* another */();
|
||||
· ────────
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:1:18]
|
||||
1 │ const a = new Foo</* comment */ string, /* another */ number>();
|
||||
· ────────────────────────────────────────────
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:3:17]
|
||||
2 │ class Foo {
|
||||
3 │ a = new Foo<string>();
|
||||
· ────────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:3:19]
|
||||
2 │ class Foo {
|
||||
3 │ [a] = new Foo<string>();
|
||||
· ────────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:3:23]
|
||||
2 │ class Foo {
|
||||
3 │ [a + b] = new Foo<string>();
|
||||
· ────────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:2:28]
|
||||
1 │
|
||||
2 │ function foo(a = new Foo<string>()) {}
|
||||
· ────────
|
||||
3 │
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:2:32]
|
||||
1 │
|
||||
2 │ function foo({ a } = new Foo<string>()) {}
|
||||
· ────────
|
||||
3 │
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:2:30]
|
||||
1 │
|
||||
2 │ function foo([a] = new Foo<string>()) {}
|
||||
· ────────
|
||||
3 │
|
||||
╰────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:3:29]
|
||||
2 │ class A {
|
||||
3 │ constructor(a = new Foo<string>()) {}
|
||||
· ────────
|
||||
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 type annotation.
|
||||
╭─[consistent_generic_constructors.tsx:2:35]
|
||||
1 │
|
||||
2 │ const a = function (a = new Foo<string>()) {};
|
||||
· ────────
|
||||
3 │
|
||||
╰────
|
||||
help: Move the generic type to the type annotation
|
||||
Loading…
Reference in a new issue