mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(linter): implement adjacent-overload-signature (#578)
This commit is contained in:
parent
fa20844802
commit
836d430a10
4 changed files with 1215 additions and 1 deletions
|
|
@ -2,7 +2,7 @@ use std::hash::{Hash, Hasher};
|
|||
|
||||
use oxc_ast::AstKind;
|
||||
use oxc_semantic::AstNode;
|
||||
use oxc_span::GetSpan;
|
||||
use oxc_span::{Atom, GetSpan};
|
||||
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator};
|
||||
use rustc_hash::FxHasher;
|
||||
|
||||
|
|
@ -243,3 +243,25 @@ pub fn outermost_paren<'a, 'b>(node: &'b AstNode<'a>, ctx: &'b LintContext<'a>)
|
|||
|
||||
node
|
||||
}
|
||||
|
||||
pub fn get_name_from_property_key(key: &PropertyKey<'_>) -> Option<Atom> {
|
||||
match key {
|
||||
PropertyKey::Identifier(ident) => Some(ident.name.clone()),
|
||||
PropertyKey::PrivateIdentifier(ident) => {
|
||||
let name = ident.name.clone();
|
||||
|
||||
Some(Atom::from(format!("#{name}")))
|
||||
}
|
||||
PropertyKey::Expression(expr) => match expr {
|
||||
Expression::StringLiteral(lit) => Some(lit.value.clone()),
|
||||
Expression::RegExpLiteral(lit) => Some(Atom::from(format!("{0}", lit.regex))),
|
||||
Expression::NumberLiteral(lit) => Some(Atom::from(lit.raw)),
|
||||
Expression::BigintLiteral(lit) => Some(Atom::from(format!("{0}", lit.value))),
|
||||
Expression::NullLiteral(_) => Some("null".into()),
|
||||
Expression::TemplateLiteral(lit) => {
|
||||
lit.expressions.is_empty().then(|| lit.quasi()).flatten().cloned()
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ oxc_macros::declare_all_lint_rules! {
|
|||
eslint::require_yield,
|
||||
eslint::use_isnan,
|
||||
eslint::valid_typeof,
|
||||
typescript::adjacent_overload_signatures,
|
||||
typescript::isolated_declaration,
|
||||
typescript::no_empty_interface,
|
||||
typescript::no_extra_non_null_assertion,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,808 @@
|
|||
use oxc_ast::{ast::{ClassElement, PropertyKey, TSSignature, ModuleDeclaration, Statement, ExportDefaultDeclarationKind, FunctionType, Declaration, Expression}, AstKind};
|
||||
use oxc_diagnostics::{
|
||||
miette::{self, Diagnostic},
|
||||
thiserror::Error,
|
||||
};
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::{Span, Atom, GetSpan};
|
||||
|
||||
use crate::{context::LintContext, rule::Rule, AstNode, ast_util::get_name_from_property_key};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("typescript-eslint(adjacent-overload-signatures): All {0:?} signatures should be adjacent.")]
|
||||
#[diagnostic(severity(warning))]
|
||||
struct AdjacentOverloadSignaturesDiagnostic(
|
||||
Atom, #[label] pub Option<Span>, #[label] pub Span
|
||||
);
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct AdjacentOverloadSignatures;
|
||||
|
||||
declare_oxc_lint!(
|
||||
/// ### What it does
|
||||
///
|
||||
/// Require that function overload signatures be consecutive.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Function overload signatures represent multiple ways
|
||||
/// a function can be called, potentially with different return types.
|
||||
/// It's typical for an interface or type alias describing a function to place all overload signatures next to each other.
|
||||
/// If Signatures placed elsewhere in the type are easier to be missed by future developers reading the code.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```typescript
|
||||
/// declare namespace Foo {
|
||||
/// export function foo(s: string): void;
|
||||
/// export function foo(n: number): void;
|
||||
/// export function bar(): void;
|
||||
/// export function foo(sn: string | number): void;
|
||||
/// }
|
||||
///
|
||||
/// type Foo = {
|
||||
/// foo(s: string): void;
|
||||
/// foo(n: number): void;
|
||||
/// bar(): void;
|
||||
/// foo(sn: string | number): void;
|
||||
/// };
|
||||
///
|
||||
/// interface Foo {
|
||||
/// foo(s: string): void;
|
||||
/// foo(n: number): void;
|
||||
/// bar(): void;
|
||||
/// foo(sn: string | number): void;
|
||||
/// }
|
||||
///
|
||||
/// class Foo {
|
||||
/// foo(s: string): void;
|
||||
/// foo(n: number): void;
|
||||
/// bar(): void {}
|
||||
/// foo(sn: string | number): void {}
|
||||
/// }
|
||||
///
|
||||
/// export function foo(s: string): void;
|
||||
/// export function foo(n: number): void;
|
||||
/// export function bar(): void;
|
||||
/// export function foo(sn: string | number): void;
|
||||
/// ```
|
||||
AdjacentOverloadSignatures,
|
||||
correctness
|
||||
);
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum MethodKind {
|
||||
Private,
|
||||
Quoted,
|
||||
Normal,
|
||||
Expression,
|
||||
}
|
||||
|
||||
fn get_kind_from_key(key: &PropertyKey) -> MethodKind {
|
||||
match key {
|
||||
PropertyKey::Identifier(_) => MethodKind::Normal,
|
||||
PropertyKey::PrivateIdentifier(_) => MethodKind::Private,
|
||||
PropertyKey::Expression(expr) => {
|
||||
match expr {
|
||||
Expression::StringLiteral(_) => MethodKind::Normal,
|
||||
Expression::NumberLiteral(_) |
|
||||
Expression::BigintLiteral(_) |
|
||||
Expression::TemplateLiteral(_) |
|
||||
Expression::RegExpLiteral(_) |
|
||||
Expression::NullLiteral(_) => MethodKind::Quoted,
|
||||
_ => MethodKind::Expression
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Method {
|
||||
name: Atom,
|
||||
r#static: bool,
|
||||
call_signature: bool,
|
||||
kind: MethodKind,
|
||||
span: Span
|
||||
}
|
||||
|
||||
impl Method {
|
||||
fn is_same_method(&self, other: Option<&Self>) -> bool {
|
||||
other.map_or(false, |other| self.name == other.name &&
|
||||
self.r#static == other.r#static &&
|
||||
self.call_signature == other.call_signature &&
|
||||
self.kind == other.kind
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
trait GetMethod {
|
||||
fn get_method(&self) -> Option<Method>;
|
||||
}
|
||||
|
||||
impl GetMethod for ClassElement<'_> {
|
||||
fn get_method(&self) -> Option<Method> {
|
||||
match self {
|
||||
ClassElement::MethodDefinition(def) => {
|
||||
get_name_from_property_key(&def.key).map(
|
||||
|name| Method {
|
||||
name,
|
||||
r#static: def.r#static,
|
||||
call_signature: false,
|
||||
kind: get_kind_from_key(&def.key),
|
||||
span: Span::new(def.span.start, def.key.span().end),
|
||||
}
|
||||
)
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetMethod for TSSignature<'_> {
|
||||
fn get_method(&self) -> Option<Method> {
|
||||
match self {
|
||||
TSSignature::TSMethodSignature(sig) => {
|
||||
get_name_from_property_key(&sig.key).map(
|
||||
|name| Method {
|
||||
name,
|
||||
r#static: false,
|
||||
call_signature: false,
|
||||
kind: get_kind_from_key(&sig.key),
|
||||
span: sig.key.span(),
|
||||
}
|
||||
)
|
||||
}
|
||||
TSSignature::TSCallSignatureDeclaration(sig) => {
|
||||
Some(Method {
|
||||
name: Atom::from("call"),
|
||||
r#static: false,
|
||||
call_signature: true,
|
||||
kind: MethodKind::Normal,
|
||||
span: sig.span,
|
||||
})
|
||||
}
|
||||
TSSignature::TSConstructSignatureDeclaration(decl) => {
|
||||
Some(Method {
|
||||
name: Atom::from("new"),
|
||||
r#static: false,
|
||||
call_signature: false,
|
||||
kind: MethodKind::Normal,
|
||||
span: Span::new(decl.span.start, decl.span.start + 3),
|
||||
})
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl GetMethod for ModuleDeclaration<'_> {
|
||||
fn get_method(&self) -> Option<Method> {
|
||||
match self {
|
||||
ModuleDeclaration::ExportDefaultDeclaration(default_decl) => {
|
||||
let decl_kind = &default_decl.declaration;
|
||||
|
||||
match decl_kind {
|
||||
ExportDefaultDeclarationKind::FunctionDeclaration(func_decl) => {
|
||||
if matches!(
|
||||
func_decl.r#type,
|
||||
FunctionType::FunctionDeclaration | FunctionType::TSDeclareFunction
|
||||
) {
|
||||
func_decl.id.as_ref().map(
|
||||
|id| Method {
|
||||
name: id.name.clone(),
|
||||
r#static: false,
|
||||
call_signature: false,
|
||||
kind: MethodKind::Normal,
|
||||
span: id.span,
|
||||
}
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
ModuleDeclaration::ExportNamedDeclaration(named_decl) => {
|
||||
if let Some(Declaration::FunctionDeclaration(func_decl)) = &named_decl.declaration {
|
||||
|
||||
return func_decl.id.as_ref().map(
|
||||
|id| Method {
|
||||
name: id.name.clone(),
|
||||
r#static: false,
|
||||
call_signature: false,
|
||||
kind: MethodKind::Normal,
|
||||
span: id.span,
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
None
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetMethod for Declaration<'_> {
|
||||
fn get_method(&self) -> Option<Method> {
|
||||
match self {
|
||||
Declaration::FunctionDeclaration(func_decl) => {
|
||||
if matches!(
|
||||
func_decl.r#type,
|
||||
FunctionType::FunctionDeclaration | FunctionType::TSDeclareFunction
|
||||
) {
|
||||
func_decl.id.as_ref().map(
|
||||
|id| Method {
|
||||
name: id.name.clone(),
|
||||
r#static: false,
|
||||
call_signature: false,
|
||||
kind: MethodKind::Normal,
|
||||
span: id.span,
|
||||
}
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetMethod for Statement<'_> {
|
||||
fn get_method(&self) -> Option<Method> {
|
||||
match self {
|
||||
Statement::ModuleDeclaration(decl) => {
|
||||
decl.get_method()
|
||||
}
|
||||
Statement::Declaration(decl) => {
|
||||
decl.get_method()
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_and_report(methods: &Vec<Option<Method>>, ctx: &LintContext<'_>) {
|
||||
let mut last_method: Option<&Method> = None;
|
||||
let mut seen_methods: Vec<&Method> = Vec::new();
|
||||
|
||||
for method in methods {
|
||||
if let Some(method) = method {
|
||||
let index = seen_methods.iter().position(|m| method.is_same_method(Some(m)));
|
||||
|
||||
if index.is_some() && !method.is_same_method(last_method) {
|
||||
let name = if method.r#static {
|
||||
Atom::from(format!("static {0}", method.name))
|
||||
} else {
|
||||
method.name.clone()
|
||||
};
|
||||
|
||||
let last_same_method = seen_methods
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|m| m.is_same_method(Some(method)));
|
||||
|
||||
ctx.diagnostic(
|
||||
AdjacentOverloadSignaturesDiagnostic(
|
||||
name,
|
||||
last_same_method.map(|m| m.span),
|
||||
method.span
|
||||
)
|
||||
);
|
||||
} else {
|
||||
seen_methods.push(method);
|
||||
}
|
||||
last_method = Some(method);
|
||||
} else {
|
||||
last_method = None;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl Rule for AdjacentOverloadSignatures {
|
||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
match node.kind() {
|
||||
AstKind::Class(class) => {
|
||||
let members = &class.body.body;
|
||||
let methods = members.iter()
|
||||
.map(GetMethod::get_method)
|
||||
.collect();
|
||||
check_and_report(&methods, ctx);
|
||||
}
|
||||
AstKind::TSTypeLiteral(literal) => {
|
||||
let methods = literal.members
|
||||
.iter()
|
||||
.map(GetMethod::get_method)
|
||||
.collect();
|
||||
check_and_report(&methods, ctx);
|
||||
}
|
||||
AstKind::Program(program) => {
|
||||
let methods = program.body
|
||||
.iter()
|
||||
.map(GetMethod::get_method)
|
||||
.collect();
|
||||
|
||||
check_and_report(&methods, ctx);
|
||||
}
|
||||
AstKind::TSModuleBlock(block) => {
|
||||
let methods = block.body
|
||||
.iter()
|
||||
.map(GetMethod::get_method)
|
||||
.collect();
|
||||
|
||||
check_and_report(&methods, ctx);
|
||||
}
|
||||
AstKind::TSInterfaceDeclaration(decl) => {
|
||||
let methods = decl.body.body
|
||||
.iter().
|
||||
map(GetMethod::get_method)
|
||||
.collect();
|
||||
|
||||
check_and_report(&methods, ctx);
|
||||
}
|
||||
AstKind::BlockStatement(stmt) => {
|
||||
let methods = stmt.body
|
||||
.iter()
|
||||
.map(GetMethod::get_method)
|
||||
.collect();
|
||||
|
||||
check_and_report(&methods, ctx);
|
||||
}
|
||||
AstKind::FunctionBody(body) => {
|
||||
let methods = body.statements
|
||||
.iter()
|
||||
.map(GetMethod::get_method)
|
||||
.collect();
|
||||
|
||||
check_and_report(&methods, ctx);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
#[test]
|
||||
fn test() {
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec: void;
|
||||
foo(sn: string | number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
};"#,
|
||||
r#"interface Foo {
|
||||
(s: string): void;
|
||||
(n: number): void;
|
||||
(sn: string | number): void;
|
||||
foo(n: number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
(s: string): void;
|
||||
(n: number): void;
|
||||
(sn: string | number): void;
|
||||
foo(n: number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
call(): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
foo(s: string): void;
|
||||
foo(n: number): void;
|
||||
foo(sn: string | number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
foo(s: string): void;
|
||||
['foo'](n: number): void;
|
||||
foo(sn: string | number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
foo(): void;
|
||||
bar: {
|
||||
baz(s: string): void;
|
||||
baz(n: number): void;
|
||||
baz(sn: string | number): void;
|
||||
};
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
new (s: string);
|
||||
new (n: number);
|
||||
new (sn: string | number);
|
||||
foo(): void;
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
constructor(s: string);
|
||||
constructor(n: number);
|
||||
constructor(sn: string | number) {}
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
foo(s: string): void;
|
||||
foo(n: number): void;
|
||||
foo(sn: string | number): void {}
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
foo(s: string): void;
|
||||
['foo'](n: number): void;
|
||||
foo(sn: string | number): void {}
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
name: string;
|
||||
foo(s: string): void;
|
||||
foo(n: number): void;
|
||||
foo(sn: string | number): void {}
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
name: string;
|
||||
static foo(s: string): void;
|
||||
static foo(n: number): void;
|
||||
static foo(sn: string | number): void {}
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
}"#,
|
||||
r#"class Test {
|
||||
static test() {}
|
||||
untest() {}
|
||||
test() {}
|
||||
}"#,
|
||||
"export default function <T>(foo: T) {}",
|
||||
"export default function named<T>(foo: T) {}",
|
||||
r#"interface Foo {
|
||||
[Symbol.toStringTag](): void;
|
||||
[Symbol.iterator](): void;
|
||||
}"#,
|
||||
r#"class Test {
|
||||
#private(): void;
|
||||
#private(arg: number): void {}
|
||||
|
||||
bar() {}
|
||||
|
||||
'#private'(): void;
|
||||
'#private'(arg: number): void {}
|
||||
}"#,
|
||||
r#"function wrap() {
|
||||
function foo(s: string);
|
||||
function foo(n: number);
|
||||
function foo(sn: string | number) {}
|
||||
}"#,
|
||||
r#"if (true) {
|
||||
function foo(s: string);
|
||||
function foo(n: number);
|
||||
function foo(sn: string | number) {}
|
||||
}"#
|
||||
];
|
||||
|
||||
let fail = vec: void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
foo(sn: string | number): void;
|
||||
};"#,
|
||||
r#"type Foo = {
|
||||
foo(s: string): void;
|
||||
name: string;
|
||||
foo(n: number): void;
|
||||
foo(sn: string | number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
};"#,
|
||||
r#"interface Foo {
|
||||
(s: string): void;
|
||||
foo(n: number): void;
|
||||
(n: number): void;
|
||||
(sn: string | number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
call(): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
foo(s: string): void;
|
||||
foo(n: number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
foo(sn: string | number): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
foo(s: string): void;
|
||||
['foo'](n: number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
foo(sn: string | number): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
foo(s: string): void;
|
||||
'foo'(n: number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
foo(sn: string | number): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
foo(s: string): void;
|
||||
name: string;
|
||||
foo(n: number): void;
|
||||
foo(sn: string | number): void;
|
||||
bar(): void;
|
||||
baz(): void;
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
foo(): void;
|
||||
bar: {
|
||||
baz(s: string): void;
|
||||
baz(n: number): void;
|
||||
foo(): void;
|
||||
baz(sn: string | number): void;
|
||||
};
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
new (s: string);
|
||||
new (n: number);
|
||||
foo(): void;
|
||||
bar(): void;
|
||||
new (sn: string | number);
|
||||
}"#,
|
||||
r#"interface Foo {
|
||||
new (s: string);
|
||||
foo(): void;
|
||||
new (n: number);
|
||||
bar(): void;
|
||||
new (sn: string | number);
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
constructor(s: string);
|
||||
constructor(n: number);
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
constructor(sn: string | number) {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
foo(s: string): void;
|
||||
foo(n: number): void;
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
foo(sn: string | number): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
foo(s: string): void;
|
||||
['foo'](n: number): void;
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
foo(sn: string | number): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
// prettier-ignore
|
||||
"foo"(s: string): void;
|
||||
foo(n: number): void;
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
foo(sn: string | number): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
constructor(s: string);
|
||||
name: string;
|
||||
constructor(n: number);
|
||||
constructor(sn: string | number) {}
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
foo(s: string): void;
|
||||
name: string;
|
||||
foo(n: number): void;
|
||||
foo(sn: string | number): void {}
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
}"#,
|
||||
r#"class Foo {
|
||||
static foo(s: string): void;
|
||||
name: string;
|
||||
static foo(n: number): void;
|
||||
static foo(sn: string | number): void {}
|
||||
bar(): void {}
|
||||
baz(): void {}
|
||||
}"#,
|
||||
r#"class Test {
|
||||
#private(): void;
|
||||
'#private'(): void;
|
||||
#private(arg: number): void {}
|
||||
'#private'(arg: number): void {}
|
||||
}"#
|
||||
];
|
||||
|
||||
Tester::new_without_config(AdjacentOverloadSignatures::NAME, pass, fail).test_and_snapshot();
|
||||
}
|
||||
|
|
@ -0,0 +1,383 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
expression: adjacent_overload_signatures
|
||||
---
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ function foo(s: string);
|
||||
3 │ function foo(n: number);
|
||||
· ───
|
||||
4 │ type bar = number;
|
||||
5 │ function foo(sn: string | number) {}
|
||||
· ───
|
||||
6 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ function foo(s: string);
|
||||
3 │ function foo(n: number);
|
||||
· ───
|
||||
4 │ let a = 1;
|
||||
5 │ function foo(sn: string | number) {}
|
||||
· ───
|
||||
6 │ foo(a);
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ export function foo(s: string);
|
||||
2 │ export function foo(n: number);
|
||||
· ───
|
||||
3 │ export function bar(): void {}
|
||||
4 │ export function baz(): void {}
|
||||
5 │ export function foo(sn: string | number) {}
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ export function foo(s: string);
|
||||
2 │ export function foo(n: number);
|
||||
· ───
|
||||
3 │ export type bar = number;
|
||||
4 │ export type baz = number | string;
|
||||
5 │ export function foo(sn: string | number) {}
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ function foo(s: string);
|
||||
2 │ function foo(n: number);
|
||||
· ───
|
||||
3 │ function bar(): void {}
|
||||
4 │ function baz(): void {}
|
||||
5 │ function foo(sn: string | number) {}
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ function foo(s: string);
|
||||
2 │ function foo(n: number);
|
||||
· ───
|
||||
3 │ type bar = number;
|
||||
4 │ type baz = number | string;
|
||||
5 │ function foo(sn: string | number) {}
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ declare function foo(s: string);
|
||||
2 │ declare function foo(n: number);
|
||||
· ───
|
||||
3 │ declare function bar(): void;
|
||||
4 │ declare function baz(): void;
|
||||
5 │ declare function foo(sn: string | number);
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ declare function foo(s: string);
|
||||
2 │ declare function foo(n: number);
|
||||
· ───
|
||||
3 │ const a = '';
|
||||
4 │ const b = '';
|
||||
5 │ declare function foo(sn: string | number);
|
||||
· ───
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ export function foo(s: string): void;
|
||||
3 │ export function foo(n: number): void;
|
||||
· ───
|
||||
4 │ export function bar(): void;
|
||||
5 │ export function baz(): void;
|
||||
6 │ export function foo(sn: string | number): void;
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "baz" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:4:1]
|
||||
4 │ export function foo(sn: string | number): void;
|
||||
5 │ function baz(s: string): void;
|
||||
· ───
|
||||
6 │ export function bar(): void;
|
||||
7 │ function baz(n: number): void;
|
||||
· ───
|
||||
8 │ function baz(sn: string | number): void;
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ export function foo(s: string): void;
|
||||
3 │ export function foo(n: number): void;
|
||||
· ───
|
||||
4 │ export function bar(): void;
|
||||
5 │ export function baz(): void;
|
||||
6 │ export function foo(sn: string | number): void;
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "baz" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:4:1]
|
||||
4 │ export function foo(sn: string | number): void;
|
||||
5 │ function baz(s: string): void;
|
||||
· ───
|
||||
6 │ export function bar(): void;
|
||||
7 │ function baz(n: number): void;
|
||||
· ───
|
||||
8 │ function baz(sn: string | number): void;
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ foo(s: string): void;
|
||||
3 │ foo(n: number): void;
|
||||
· ───
|
||||
4 │ bar(): void;
|
||||
5 │ baz(): void;
|
||||
6 │ foo(sn: string | number): void;
|
||||
· ───
|
||||
7 │ };
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ foo(s: string): void;
|
||||
3 │ ['foo'](n: number): void;
|
||||
· ─────
|
||||
4 │ bar(): void;
|
||||
5 │ baz(): void;
|
||||
6 │ foo(sn: string | number): void;
|
||||
· ───
|
||||
7 │ };
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ type Foo = {
|
||||
2 │ foo(s: string): void;
|
||||
· ───
|
||||
3 │ name: string;
|
||||
4 │ foo(n: number): void;
|
||||
· ───
|
||||
5 │ foo(sn: string | number): void;
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "call" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ interface Foo {
|
||||
2 │ (s: string): void;
|
||||
· ──────────────────
|
||||
3 │ foo(n: number): void;
|
||||
4 │ (n: number): void;
|
||||
· ──────────────────
|
||||
5 │ (sn: string | number): void;
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ foo(s: string): void;
|
||||
3 │ foo(n: number): void;
|
||||
· ───
|
||||
4 │ bar(): void;
|
||||
5 │ baz(): void;
|
||||
6 │ foo(sn: string | number): void;
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ foo(s: string): void;
|
||||
3 │ ['foo'](n: number): void;
|
||||
· ─────
|
||||
4 │ bar(): void;
|
||||
5 │ baz(): void;
|
||||
6 │ foo(sn: string | number): void;
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ foo(s: string): void;
|
||||
3 │ 'foo'(n: number): void;
|
||||
· ─────
|
||||
4 │ bar(): void;
|
||||
5 │ baz(): void;
|
||||
6 │ foo(sn: string | number): void;
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ interface Foo {
|
||||
2 │ foo(s: string): void;
|
||||
· ───
|
||||
3 │ name: string;
|
||||
4 │ foo(n: number): void;
|
||||
· ───
|
||||
5 │ foo(sn: string | number): void;
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "baz" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:4:1]
|
||||
4 │ baz(s: string): void;
|
||||
5 │ baz(n: number): void;
|
||||
· ───
|
||||
6 │ foo(): void;
|
||||
7 │ baz(sn: string | number): void;
|
||||
· ───
|
||||
8 │ };
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "new" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ new (s: string);
|
||||
3 │ new (n: number);
|
||||
· ───
|
||||
4 │ foo(): void;
|
||||
5 │ bar(): void;
|
||||
6 │ new (sn: string | number);
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "new" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ interface Foo {
|
||||
2 │ new (s: string);
|
||||
· ───
|
||||
3 │ foo(): void;
|
||||
4 │ new (n: number);
|
||||
· ───
|
||||
5 │ bar(): void;
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "new" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ interface Foo {
|
||||
2 │ new (s: string);
|
||||
· ───
|
||||
3 │ foo(): void;
|
||||
╰────
|
||||
╭─[adjacent_overload_signatures.tsx:5:1]
|
||||
5 │ bar(): void;
|
||||
6 │ new (sn: string | number);
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "constructor" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ constructor(s: string);
|
||||
3 │ constructor(n: number);
|
||||
· ───────────
|
||||
4 │ bar(): void {}
|
||||
5 │ baz(): void {}
|
||||
6 │ constructor(sn: string | number) {}
|
||||
· ───────────
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ foo(s: string): void;
|
||||
3 │ foo(n: number): void;
|
||||
· ───
|
||||
4 │ bar(): void {}
|
||||
5 │ baz(): void {}
|
||||
6 │ foo(sn: string | number): void {}
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ foo(s: string): void;
|
||||
3 │ ['foo'](n: number): void;
|
||||
· ──────
|
||||
4 │ bar(): void {}
|
||||
5 │ baz(): void {}
|
||||
6 │ foo(sn: string | number): void {}
|
||||
· ───
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:3:1]
|
||||
3 │ "foo"(s: string): void;
|
||||
4 │ foo(n: number): void;
|
||||
· ───
|
||||
5 │ bar(): void {}
|
||||
6 │ baz(): void {}
|
||||
7 │ foo(sn: string | number): void {}
|
||||
· ───
|
||||
8 │ }
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "constructor" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ class Foo {
|
||||
2 │ constructor(s: string);
|
||||
· ───────────
|
||||
3 │ name: string;
|
||||
4 │ constructor(n: number);
|
||||
· ───────────
|
||||
5 │ constructor(sn: string | number) {}
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ class Foo {
|
||||
2 │ foo(s: string): void;
|
||||
· ───
|
||||
3 │ name: string;
|
||||
4 │ foo(n: number): void;
|
||||
· ───
|
||||
5 │ foo(sn: string | number): void {}
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "static foo" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ class Foo {
|
||||
2 │ static foo(s: string): void;
|
||||
· ──────────
|
||||
3 │ name: string;
|
||||
4 │ static foo(n: number): void;
|
||||
· ──────────
|
||||
5 │ static foo(sn: string | number): void {}
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "#private" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:1:1]
|
||||
1 │ class Test {
|
||||
2 │ #private(): void;
|
||||
· ────────
|
||||
3 │ '#private'(): void;
|
||||
4 │ #private(arg: number): void {}
|
||||
· ────────
|
||||
5 │ '#private'(arg: number): void {}
|
||||
╰────
|
||||
|
||||
⚠ typescript-eslint(adjacent-overload-signatures): All "#private" signatures should be adjacent.
|
||||
╭─[adjacent_overload_signatures.tsx:2:1]
|
||||
2 │ #private(): void;
|
||||
3 │ '#private'(): void;
|
||||
· ──────────
|
||||
4 │ #private(arg: number): void {}
|
||||
5 │ '#private'(arg: number): void {}
|
||||
· ──────────
|
||||
6 │ }
|
||||
╰────
|
||||
|
||||
|
||||
Loading…
Reference in a new issue