Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions crates/oxc_diagnostics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,11 @@ impl OxcDiagnostic {
}

#[must_use]
pub fn with_labels<T: IntoIterator<Item = LabeledSpan>>(mut self, labels: T) -> Self {
self.inner.labels = Some(labels.into_iter().collect());
pub fn with_labels<L: Into<LabeledSpan>, T: IntoIterator<Item = L>>(
mut self,
labels: T,
) -> Self {
self.inner.labels = Some(labels.into_iter().map(Into::into).collect());
self
}

Expand All @@ -132,9 +135,12 @@ impl OxcDiagnostic {
}

#[must_use]
pub fn and_labels<T: IntoIterator<Item = LabeledSpan>>(mut self, labels: T) -> Self {
pub fn and_labels<L: Into<LabeledSpan>, T: IntoIterator<Item = L>>(
mut self,
labels: T,
) -> Self {
let mut all_labels = self.inner.labels.unwrap_or_default();
all_labels.extend(labels);
all_labels.extend(labels.into_iter().map(Into::into));
self.inner.labels = Some(all_labels);
self
}
Expand Down
13 changes: 6 additions & 7 deletions crates/oxc_linter/examples/linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{env, path::Path};

use oxc_allocator::Allocator;
use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use oxc_span::{SourceType, Span};
Expand Down Expand Up @@ -73,8 +73,8 @@ fn print_errors(source_text: &str, errors: Vec<OxcDiagnostic>) {
// 1 │ debugger;
// · ─────────
// ╰────
fn no_debugger(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("`debugger` statement is not allowed").with_labels([span0.into()])
fn no_debugger(debugger_span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("`debugger` statement is not allowed").with_label(debugger_span)
}

// This prints:
Expand All @@ -85,8 +85,7 @@ fn no_debugger(span0: Span) -> OxcDiagnostic {
// · ─┬
// · ╰── Empty object binding pattern
// ╰────
fn no_empty_pattern(s0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::error("empty destructuring pattern is not allowed").with_labels([
LabeledSpan::new_with_span(Some(format!("Empty {s0} binding pattern")), span1),
])
fn no_empty_pattern(binding_kind: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("empty destructuring pattern is not allowed")
.with_label(span.label(format!("Empty {binding_kind} binding pattern")))
}
16 changes: 8 additions & 8 deletions crates/oxc_linter/src/fixer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ mod test {
OxcDiagnostic::warn("removestart")
}

fn remove_middle(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("removemiddle").with_labels([span0.into()])
fn remove_middle(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("removemiddle").with_labels([span])
}

fn remove_end() -> OxcDiagnostic {
Expand All @@ -302,16 +302,16 @@ mod test {
OxcDiagnostic::warn("reversed range")
}

fn no_fix(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix").with_labels([span0.into()])
fn no_fix(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix").with_labels([span])
}

fn no_fix_1(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix1").with_labels([span0.into()])
fn no_fix_1(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix1").with_labels([span])
}

fn no_fix_2(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix2").with_labels([span0.into()])
fn no_fix_2(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix2").with_labels([span])
}

const TEST_CODE: &str = "var answer = 6 * 7;";
Expand Down
7 changes: 2 additions & 5 deletions crates/oxc_linter/src/rules/eslint/default_case_last.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

Expand All @@ -9,10 +9,7 @@ fn default_case_last_diagnostic(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(
"eslint(default-case-last): Enforce default clauses in switch statements to be last",
)
.with_labels([LabeledSpan::new_with_span(
Some("Default clause should be the last clause.".into()),
span0,
)])
.with_label(span0.label("Default clause should be the last clause."))
}

#[derive(Debug, Default, Clone)]
Expand Down
7 changes: 5 additions & 2 deletions crates/oxc_linter/src/rules/eslint/for_direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use oxc_ast::{
},
AstKind,
};
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, UnaryOperator, UpdateOperator};
Expand All @@ -15,7 +15,10 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn for_direction_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(for-direction): The update clause in this loop moves the variable in the wrong direction")
.with_help("Use while loop for intended infinite loop")
.with_labels([LabeledSpan::new_with_span(Some("This test moves in the wrong direction".into()), span0), LabeledSpan::new_with_span(Some("with this update".into()), span1)])
.with_labels([
span0.label("This test moves in the wrong direction"),
span1.label("with this update"),
])
}

#[derive(Debug, Default, Clone)]
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_linter/src/rules/eslint/no_class_assign.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId;
use oxc_span::Span;
Expand All @@ -8,8 +8,8 @@ use crate::{context::LintContext, rule::Rule};
fn no_class_assign_diagnostic(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("eslint(no-class-assign): Unexpected re-assignment of class {x0}"))
.with_labels([
LabeledSpan::new_with_span(Some(format!("{x0} is declared as class here")), span1),
LabeledSpan::new_with_span(Some(format!("{x0} is re-assigned here")), span2),
span1.label(format!("{x0} is declared as class here")),
span2.label(format!("{x0} is re-assigned here")),
])
}

Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_linter/src/rules/eslint/no_const_assign.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId;
use oxc_span::Span;
Expand All @@ -10,8 +10,8 @@ fn no_const_assign_diagnostic(x0: &str, span1: Span, span2: Span) -> OxcDiagnost
"eslint(no-const-assign): Unexpected re-assignment of const variable {x0}"
))
.with_labels([
LabeledSpan::new_with_span(Some(format!("{x0} is declared here as const")), span1),
LabeledSpan::new_with_span(Some(format!("{x0} is re-assigned here")), span2),
span1.label(format!("{x0} is declared here as const")),
span2.label(format!("{x0} is re-assigned here")),
])
}

Expand Down
7 changes: 5 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use rustc_hash::FxHashMap;
Expand All @@ -12,7 +12,10 @@ fn no_dupe_class_members_diagnostic(
) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("eslint(no-dupe-class-members): Duplicate class member: {x0:?}"))
.with_help("The last declaration overwrites previous ones, remove one of them or rename if both should be retained")
.with_labels([LabeledSpan::new_with_span(Some(format!("{x0:?} is previously declared here")), span1), LabeledSpan::new_with_span(Some(format!("{x0:?} is re-declared here")), span2)])
.with_labels([
span1.label(format!("{x0:?} is previously declared here")),
span2.label(format!("{x0:?} is re-declared here")),
])
}

#[derive(Debug, Default, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_dupe_else_if.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{ast_util::calculate_hash, context::LintContext, rule::Rule, AstNode}
fn no_dupe_else_if_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-dupe-else-if): duplicate conditions in if-else-if chains")
.with_help("This branch can never execute. Its condition is a duplicate or covered by previous conditions in the if-else-if chain")
.with_labels([span0.into(), span1.into()])
.with_labels([span0, span1])
}

#[derive(Debug, Default, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_dupe_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn no_dupe_keys_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-dupe-keys): Disallow duplicate keys in object literals")
.with_help("Consider removing the duplicated key")
.with_labels([span0.into(), span1.into()])
.with_labels([span0, span1])
}

#[derive(Debug, Default, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_duplicate_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{ast_util::calculate_hash, context::LintContext, rule::Rule, AstNode}
fn no_duplicate_case_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-duplicate-case): Disallow duplicate case labels")
.with_help("Remove the duplicated case")
.with_labels([span0.into(), span1.into()])
.with_labels([span0, span1])
}

#[derive(Debug, Default, Clone)]
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_empty.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

Expand All @@ -8,7 +8,7 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn no_empty_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-empty): Disallow empty block statements")
.with_help(format!("Add comment inside empty {x0} statement"))
.with_labels([LabeledSpan::new_with_span(Some(format!("Empty {x0} statement")), span1)])
.with_label(span1.label(format!("Empty {x0} statement")))
}

#[derive(Debug, Default, Clone)]
Expand Down
6 changes: 4 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_empty_pattern.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

Expand All @@ -8,7 +8,9 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn no_empty_pattern_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-empty-pattern): Disallow empty destructuring patterns.")
.with_help("Passing `null` or `undefined` will result in runtime error because `null` and `undefined` cannot be destructured.")
.with_labels([LabeledSpan::new_with_span(Some(format!("Empty {x0} binding pattern")), span1)])
.with_label(
span1.label(format!("Empty {x0} binding pattern")),
)
}

#[derive(Debug, Default, Clone)]
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_func_assign.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId;
use oxc_span::Span;
Expand All @@ -8,7 +8,7 @@ use crate::{context::LintContext, rule::Rule};

fn no_func_assign_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("eslint(no-func-assign): '{x0}' is a function."))
.with_labels([LabeledSpan::new_with_span(Some(format!("{x0} is re-assigned here")), span1)])
.with_label(span1.label(format!("{x0} is re-assigned here")))
}

#[derive(Debug, Default, Clone)]
Expand Down
7 changes: 2 additions & 5 deletions crates/oxc_linter/src/rules/eslint/no_global_assign.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{CompactStr, Span};

Expand All @@ -8,10 +8,7 @@ fn no_global_assign_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(
"eslint(no-global-assign): Read-only global '{x0}' should not be modified."
))
.with_labels([LabeledSpan::new_with_span(
Some(format!("Read-only global '{x0}' should not be modified.")),
span1,
)])
.with_label(span1.label(format!("Read-only global '{x0}' should not be modified.")))
}

#[derive(Debug, Default, Clone)]
Expand Down
20 changes: 4 additions & 16 deletions crates/oxc_linter/src/rules/eslint/no_redeclare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,26 @@ use oxc_ast::{
ast::{BindingIdentifier, BindingPatternKind},
AstKind,
};
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{context::LintContext, rule::Rule};

fn no_redeclare_diagnostic(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("eslint(no-redeclare): '{x0}' is already defined.")).with_labels([
LabeledSpan::new_with_span(Some(format!("'{x0}' is already defined.")), span1),
LabeledSpan::new_with_span(Some("It can not be redeclare here.".into()), span2),
span1.label(format!("'{x0}' is already defined.")),
span2.label("It can not be redeclare here."),
])
}

fn no_redeclare_as_builti_in_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(
"eslint(no-redeclare): '{x0}' is already defined as a built-in global variable."
))
.with_labels([LabeledSpan::new_with_span(
Some(format!("'{x0}' is already defined as a built-in global variable.")),
span1,
)])
.with_label(span1.label(format!("'{x0}' is already defined as a built-in global variable.")))
}

// #[derive(Debug, Error, Diagnostic)]
// #[error("eslint(no-redeclare): '{0}' is already defined by a variable declaration.")]
// #[diagnostic(severity(warning))]
// struct NoRedeclareBySyntaxDiagnostic(
// String,
// #[label("'{0}' is already defined by a variable declaration.")] pub Span,
// #[label("It cannot be redeclared here.")] pub Span,
// );

#[derive(Debug, Default, Clone)]
pub struct NoRedeclare {
built_in_globals: bool,
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_self_compare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn no_self_compare_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
"eslint(no-self-compare): Disallow comparisons where both sides are exactly the same",
)
.with_help("If you are testing for NaN, you can use Number.isNaN function.")
.with_labels([span0.into(), span1.into()])
.with_labels([span0, span1])
}

#[derive(Debug, Default, Clone)]
Expand Down
18 changes: 7 additions & 11 deletions crates/oxc_linter/src/rules/eslint/no_useless_catch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,20 @@ use oxc_ast::{
ast::{BindingPatternKind, Expression, Statement},
AstKind,
};
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{context::LintContext, rule::Rule, AstNode};

fn no_useless_catch_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-useless-catch): Unnecessary try/catch wrapper").with_labels([
LabeledSpan::new_with_span(Some("is caught here".into()), span0),
LabeledSpan::new_with_span(Some("and re-thrown here".into()), span1),
])
fn no_useless_catch_diagnostic(catch: Span, rethrow: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-useless-catch): Unnecessary try/catch wrapper")
.with_labels([catch.label("is caught here"), rethrow.label("and re-thrown here")])
}

fn no_useless_catch_finalizer_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-useless-catch): Unnecessary catch clause").with_labels([
LabeledSpan::new_with_span(Some("is caught here".into()), span0),
LabeledSpan::new_with_span(Some("and re-thrown here".into()), span1),
])
fn no_useless_catch_finalizer_diagnostic(catch: Span, rethrow: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-useless-catch): Unnecessary catch clause")
.with_labels([catch.label("is caught here"), rethrow.label("and re-thrown here")])
}

#[derive(Debug, Default, Clone)]
Expand Down
13 changes: 10 additions & 3 deletions crates/oxc_linter/src/rules/oxc/bad_char_at_comparison.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
use oxc_ast::{ast::Expression, AstKind};
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_syntax::operator::BinaryOperator;

use crate::{ast_util::is_method_call, context::LintContext, rule::Rule, AstNode};

fn bad_char_at_comparison_diagnostic(span0: Span, span1: Span, x2: usize) -> OxcDiagnostic {
fn bad_char_at_comparison_diagnostic(
char_at: Span,
compared_string: Span,
x2: usize,
) -> OxcDiagnostic {
OxcDiagnostic::warn("oxc(bad-char-at-comparison): Invalid comparison with `charAt` method")
.with_help("`String.prototype.charAt` returns a string of length 1. If the return value is compared with a string of length greater than 1, the comparison will always be false.")
.with_labels([LabeledSpan::new_with_span(Some("`charAt` called here".into()), span0), LabeledSpan::new_with_span(Some(format!("And compared with a string of length {x2} here")), span1)])
.with_labels([
char_at.label("`charAt` called here"),
compared_string.label(format!("And compared with a string of length {x2} here")),
])
}

#[derive(Debug, Default, Clone)]
Expand Down
Loading