diff --git a/crates/oxc_diagnostics/src/lib.rs b/crates/oxc_diagnostics/src/lib.rs index da858cce512ff..e955dab7cc23b 100644 --- a/crates/oxc_diagnostics/src/lib.rs +++ b/crates/oxc_diagnostics/src/lib.rs @@ -118,8 +118,11 @@ impl OxcDiagnostic { } #[must_use] - pub fn with_labels>(mut self, labels: T) -> Self { - self.inner.labels = Some(labels.into_iter().collect()); + pub fn with_labels, T: IntoIterator>( + mut self, + labels: T, + ) -> Self { + self.inner.labels = Some(labels.into_iter().map(Into::into).collect()); self } @@ -132,9 +135,12 @@ impl OxcDiagnostic { } #[must_use] - pub fn and_labels>(mut self, labels: T) -> Self { + pub fn and_labels, T: IntoIterator>( + 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 } diff --git a/crates/oxc_linter/examples/linter.rs b/crates/oxc_linter/examples/linter.rs index f73731a943977..0c70d1edeb989 100644 --- a/crates/oxc_linter/examples/linter.rs +++ b/crates/oxc_linter/examples/linter.rs @@ -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}; @@ -73,8 +73,8 @@ fn print_errors(source_text: &str, errors: Vec) { // 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: @@ -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"))) } diff --git a/crates/oxc_linter/src/fixer.rs b/crates/oxc_linter/src/fixer.rs index bfa29980cc940..8f198e907222a 100644 --- a/crates/oxc_linter/src/fixer.rs +++ b/crates/oxc_linter/src/fixer.rs @@ -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 { @@ -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;"; diff --git a/crates/oxc_linter/src/rules/eslint/default_case_last.rs b/crates/oxc_linter/src/rules/eslint/default_case_last.rs index 5267e2fff16d5..381f5755331da 100644 --- a/crates/oxc_linter/src/rules/eslint/default_case_last.rs +++ b/crates/oxc_linter/src/rules/eslint/default_case_last.rs @@ -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; @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/for_direction.rs b/crates/oxc_linter/src/rules/eslint/for_direction.rs index c7807eb08793f..2ae16af5c3150 100644 --- a/crates/oxc_linter/src/rules/eslint/for_direction.rs +++ b/crates/oxc_linter/src/rules/eslint/for_direction.rs @@ -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}; @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs index 5e1f47300b3e9..5fac263843826 100644 --- a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs @@ -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; @@ -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")), ]) } diff --git a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs index 1f730106b473a..e5ba9949a56e5 100644 --- a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs @@ -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; @@ -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")), ]) } diff --git a/crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs b/crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs index 8f34ad297d791..356ba48370a93 100644 --- a/crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs +++ b/crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs @@ -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; @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_dupe_else_if.rs b/crates/oxc_linter/src/rules/eslint/no_dupe_else_if.rs index 152848ac059e4..e90e8d35ae26b 100644 --- a/crates/oxc_linter/src/rules/eslint/no_dupe_else_if.rs +++ b/crates/oxc_linter/src/rules/eslint/no_dupe_else_if.rs @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_dupe_keys.rs b/crates/oxc_linter/src/rules/eslint/no_dupe_keys.rs index 9e2140835e614..7f2c5eaacf457 100644 --- a/crates/oxc_linter/src/rules/eslint/no_dupe_keys.rs +++ b/crates/oxc_linter/src/rules/eslint/no_dupe_keys.rs @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_duplicate_case.rs b/crates/oxc_linter/src/rules/eslint/no_duplicate_case.rs index fcbbf9d3598b0..0bb9d09414959 100644 --- a/crates/oxc_linter/src/rules/eslint/no_duplicate_case.rs +++ b/crates/oxc_linter/src/rules/eslint/no_duplicate_case.rs @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_empty.rs b/crates/oxc_linter/src/rules/eslint/no_empty.rs index 6cb20ea796d06..74c961351493d 100644 --- a/crates/oxc_linter/src/rules/eslint/no_empty.rs +++ b/crates/oxc_linter/src/rules/eslint/no_empty.rs @@ -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; @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_empty_pattern.rs b/crates/oxc_linter/src/rules/eslint/no_empty_pattern.rs index 9aeb5daeb2262..b4e46df4cbb6e 100644 --- a/crates/oxc_linter/src/rules/eslint/no_empty_pattern.rs +++ b/crates/oxc_linter/src/rules/eslint/no_empty_pattern.rs @@ -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; @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_func_assign.rs b/crates/oxc_linter/src/rules/eslint/no_func_assign.rs index a461bb7394b82..4bb1f98ec0e49 100644 --- a/crates/oxc_linter/src/rules/eslint/no_func_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_func_assign.rs @@ -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; @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs index 0a766e2afac2d..a8b3710bc5b32 100644 --- a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs @@ -1,4 +1,4 @@ -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::{CompactStr, Span}; @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs index 23ee7e980d391..c71798c26c9c1 100644 --- a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs +++ b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs @@ -2,7 +2,7 @@ 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; @@ -10,8 +10,8 @@ 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."), ]) } @@ -19,21 +19,9 @@ 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, diff --git a/crates/oxc_linter/src/rules/eslint/no_self_compare.rs b/crates/oxc_linter/src/rules/eslint/no_self_compare.rs index a9ce28ad97f7a..b098cfe2d3660 100644 --- a/crates/oxc_linter/src/rules/eslint/no_self_compare.rs +++ b/crates/oxc_linter/src/rules/eslint/no_self_compare.rs @@ -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)] diff --git a/crates/oxc_linter/src/rules/eslint/no_useless_catch.rs b/crates/oxc_linter/src/rules/eslint/no_useless_catch.rs index db4c3e84ac4a4..9b301ce49e423 100644 --- a/crates/oxc_linter/src/rules/eslint/no_useless_catch.rs +++ b/crates/oxc_linter/src/rules/eslint/no_useless_catch.rs @@ -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)] diff --git a/crates/oxc_linter/src/rules/oxc/bad_char_at_comparison.rs b/crates/oxc_linter/src/rules/oxc/bad_char_at_comparison.rs index 2ac77fd590884..01518b7dc4271 100644 --- a/crates/oxc_linter/src/rules/oxc/bad_char_at_comparison.rs +++ b/crates/oxc_linter/src/rules/oxc/bad_char_at_comparison.rs @@ -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)] diff --git a/crates/oxc_linter/src/rules/oxc/bad_replace_all_arg.rs b/crates/oxc_linter/src/rules/oxc/bad_replace_all_arg.rs index 39fe07fc24217..a59d17929b798 100644 --- a/crates/oxc_linter/src/rules/oxc/bad_replace_all_arg.rs +++ b/crates/oxc_linter/src/rules/oxc/bad_replace_all_arg.rs @@ -2,7 +2,7 @@ use oxc_ast::{ ast::{Expression, RegExpFlags}, AstKind, }; -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::Span; @@ -16,7 +16,10 @@ use crate::{ fn bad_replace_all_arg_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { OxcDiagnostic::warn("oxc(bad-replace-all-arg): Global flag (g) is missing in the regular expression supplied to the `replaceAll` method.") .with_help("To replace all occurrences of a string, use the `replaceAll` method with the global flag (g) in the regular expression.") - .with_labels([LabeledSpan::new_with_span(Some("`replaceAll` called here".into()), span0), LabeledSpan::new_with_span(Some("RegExp supplied here".into()), span1)]) + .with_labels([ + span0.label("`replaceAll` called here"), + span1.label("RegExp supplied here"), + ]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/oxc/const_comparisons.rs b/crates/oxc_linter/src/rules/oxc/const_comparisons.rs index 72c3a3c6ffb01..cd306628c9535 100644 --- a/crates/oxc_linter/src/rules/oxc/const_comparisons.rs +++ b/crates/oxc_linter/src/rules/oxc/const_comparisons.rs @@ -5,7 +5,7 @@ use oxc_ast::{ ast::{Expression, NumericLiteral}, 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, LogicalOperator}; @@ -16,8 +16,8 @@ fn redundant_left_hand_side(span0: Span, span1: Span, x2: &str) -> OxcDiagnostic OxcDiagnostic::warn("oxc(const-comparisons): Left-hand side of `&&` operator has no effect.") .with_help(x2.to_string()) .with_labels([ - LabeledSpan::new_with_span(Some("If this evaluates to `true`".into()), span0), - LabeledSpan::new_with_span(Some("This will always evaluate to true.".into()), span1), + span0.label("If this evaluates to `true`"), + span1.label("This will always evaluate to true."), ]) } @@ -25,8 +25,8 @@ fn redundant_right_hand_side(span0: Span, span1: Span, x2: &str) -> OxcDiagnosti OxcDiagnostic::warn("oxc(const-comparisons): Right-hand side of `&&` operator has no effect.") .with_help(x2.to_string()) .with_labels([ - LabeledSpan::new_with_span(Some("If this evaluates to `true`".into()), span0), - LabeledSpan::new_with_span(Some("This will always evaluate to true.".into()), span1), + span0.label("If this evaluates to `true`"), + span1.label("This will always evaluate to true."), ]) } @@ -34,8 +34,8 @@ fn impossible(span0: Span, span1: Span, x2: &str, x3: &str, x4: &str) -> OxcDiag OxcDiagnostic::warn("oxc(const-comparisons): Unexpected constant comparison") .with_help(x4.to_string()) .with_labels([ - LabeledSpan::new_with_span(Some(format!("Requires that {x2}")), span0), - LabeledSpan::new_with_span(Some(format!("Requires that {x3}")), span1), + span0.label(format!("Requires that {x2}")), + span1.label(format!("Requires that {x3}")), ]) } diff --git a/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs b/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs index 1cca3caf2696d..d8f112de31529 100644 --- a/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs +++ b/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs @@ -2,7 +2,7 @@ use oxc_ast::{ ast::{Argument, BindingPatternKind, CallExpression, Expression}, AstKind, }; -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::SymbolId; use oxc_span::Span; @@ -15,17 +15,30 @@ use crate::{ }; fn likely_array(span0: Span, span1: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("oxc(no-accumulating-spread): Do not spread accumulators in Array.prototype.reduce()").with_help("It looks like you're spreading an `Array`. Consider using the `Array.push` or `Array.concat` methods to mutate the accumulator instead.\nUsing spreads within accumulators leads to `O(n^2)` time complexity.").with_labels([LabeledSpan::new_with_span(Some("From this spread".into()), span0), LabeledSpan::new_with_span(Some("For this reduce".into()), span1)]) + OxcDiagnostic::warn("oxc(no-accumulating-spread): Do not spread accumulators in Array.prototype.reduce()") + .with_help("It looks like you're spreading an `Array`. Consider using the `Array.push` or `Array.concat` methods to mutate the accumulator instead.\nUsing spreads within accumulators leads to `O(n^2)` time complexity.") + .with_labels([ + span0.label("From this spread"), + span1.label("For this reduce") + ]) } fn likely_object(span0: Span, span1: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("oxc(no-accumulating-spread): Do not spread accumulators in Array.prototype.reduce()").with_help("It looks like you're spreading an `Object`. Consider using the `Object.assign` or assignment operators to mutate the accumulator instead.\nUsing spreads within accumulators leads to `O(n^2)` time complexity.").with_labels([LabeledSpan::new_with_span(Some("From this spread".into()), span0), LabeledSpan::new_with_span(Some("For this reduce".into()), span1)]) + OxcDiagnostic::warn("oxc(no-accumulating-spread): Do not spread accumulators in Array.prototype.reduce()") + .with_help("It looks like you're spreading an `Object`. Consider using the `Object.assign` or assignment operators to mutate the accumulator instead.\nUsing spreads within accumulators leads to `O(n^2)` time complexity.") + .with_labels([ + span0.label("From this spread"), + span1.label("For this reduce") + ]) } fn unknown(span0: Span, span1: Span) -> OxcDiagnostic { OxcDiagnostic::warn("oxc(no-accumulating-spread): Do not spread accumulators in Array.prototype.reduce()") .with_help("Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead.\nUsing spreads within accumulators leads to `O(n^2)` time complexity.") - .with_labels([LabeledSpan::new_with_span(Some("From this spread".into()), span0), LabeledSpan::new_with_span(Some("For this reduce".into()), span1)]) + .with_labels([ + span0.label("From this spread"), + span1.label("For this reduce") + ]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/oxc/no_barrel_file.rs b/crates/oxc_linter/src/rules/oxc/no_barrel_file.rs index 0c7eb2c6b2dde..d003cc9a99f2a 100644 --- a/crates/oxc_linter/src/rules/oxc/no_barrel_file.rs +++ b/crates/oxc_linter/src/rules/oxc/no_barrel_file.rs @@ -1,4 +1,4 @@ -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::ModuleRecord; use oxc_syntax::module_graph_visitor::{ModuleGraphVisitorBuilder, VisitFoldWhile}; @@ -89,10 +89,7 @@ impl Rule for NoBarrelFile { if let Some(remote_module) = module_record.loaded_modules.get(module_request.name()) { if let Some(count) = count_loaded_modules(remote_module.value()) { total += count; - labels.push(LabeledSpan::new_with_span( - Some(format!("{count} modules")), - module_request.span(), - )); + labels.push(module_request.span().label(format!("{count} modules"))); } }; } diff --git a/crates/oxc_linter/src/rules/oxc/uninvoked_array_callback.rs b/crates/oxc_linter/src/rules/oxc/uninvoked_array_callback.rs index eee72e5c57c31..75334d78ed700 100644 --- a/crates/oxc_linter/src/rules/oxc/uninvoked_array_callback.rs +++ b/crates/oxc_linter/src/rules/oxc/uninvoked_array_callback.rs @@ -2,7 +2,7 @@ use oxc_ast::{ ast::{Argument, MemberExpression}, AstKind, }; -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::{GetSpan, Span}; @@ -14,11 +14,8 @@ fn uninvoked_array_callback_diagnostic(span0: Span, span1: Span) -> OxcDiagnosti "consider filling the array with `undefined` values using `Array.prototype.fill()`", ) .with_labels([ - LabeledSpan::new_with_span(Some("this callback will not be invoked".into()), span0), - LabeledSpan::new_with_span( - Some("because this is an array with only empty slots".into()), - span1, - ), + span0.label("this callback will not be invoked"), + span1.label("because this is an array with only empty slots"), ]) } diff --git a/crates/oxc_linter/src/rules/react/checked_requires_onchange_or_readonly.rs b/crates/oxc_linter/src/rules/react/checked_requires_onchange_or_readonly.rs index f8f20d6fbf3d4..3059e93f6dbac 100644 --- a/crates/oxc_linter/src/rules/react/checked_requires_onchange_or_readonly.rs +++ b/crates/oxc_linter/src/rules/react/checked_requires_onchange_or_readonly.rs @@ -13,16 +13,16 @@ use crate::{ AstNode, }; -fn missing_property(span0: Span) -> OxcDiagnostic { +fn missing_property(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("eslint-plugin-react(checked-requires-onchange-or-readonly): `checked` should be used with either `onChange` or `readOnly`.") .with_help("Add either `onChange` or `readOnly`.") - .with_label(span0) + .with_label(span) } fn exclusive_checked_attribute(span0: Span, span1: Span) -> OxcDiagnostic { OxcDiagnostic::warn("eslint-plugin-react(checked-requires-onchange-or-readonly): Use either `checked` or `defaultChecked`, but not both.") .with_help("Remove either `checked` or `defaultChecked`.") - .with_labels([span0.into(), span1.into()]) + .with_labels([span0, span1]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/react/jsx_key.rs b/crates/oxc_linter/src/rules/react/jsx_key.rs index 0ac8d6642fbab..9417ea759b5ad 100644 --- a/crates/oxc_linter/src/rules/react/jsx_key.rs +++ b/crates/oxc_linter/src/rules/react/jsx_key.rs @@ -2,7 +2,7 @@ use oxc_ast::{ ast::{JSXAttributeItem, JSXAttributeName, JSXElement, JSXFragment, Statement}, AstKind, }; -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::{GetSpan, Span}; @@ -16,7 +16,10 @@ fn missing_key_prop_for_element_in_array(span0: Span) -> OxcDiagnostic { fn missing_key_prop_for_element_in_iterator(span0: Span, span1: Span) -> OxcDiagnostic { OxcDiagnostic::warn(r#"eslint-plugin-react(jsx-key): Missing "key" prop for element in iterator."#) .with_help(r#"Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key)."#) - .with_labels([LabeledSpan::new_with_span(Some("Iterator starts here".into()), span0), LabeledSpan::new_with_span(Some("Element generated here".into()), span1)]) + .with_labels([ + span0.label("Iterator starts here."), + span1.label("Element generated here."), + ]) } fn key_prop_must_be_placed_before_spread(span0: Span) -> OxcDiagnostic { diff --git a/crates/oxc_linter/src/rules/react/jsx_no_duplicate_props.rs b/crates/oxc_linter/src/rules/react/jsx_no_duplicate_props.rs index 3d21f8bce92ce..09e53f4a345dc 100644 --- a/crates/oxc_linter/src/rules/react/jsx_no_duplicate_props.rs +++ b/crates/oxc_linter/src/rules/react/jsx_no_duplicate_props.rs @@ -12,7 +12,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; fn jsx_no_duplicate_props_diagnostic(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { OxcDiagnostic::warn(format!("eslint-plugin-react(jsx-no-duplicate-props): No duplicate props allowed. The prop \"{x0}\" is duplicated.")) .with_help("Remove one of the props, or rename them so each prop is distinct.") - .with_labels([span1.into(), span2.into()]) + .with_labels([span1, span2]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs b/crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs index e4d27eae70280..b441c31c2f54b 100644 --- a/crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs +++ b/crates/oxc_linter/src/rules/typescript/consistent_type_definitions.rs @@ -2,7 +2,7 @@ use oxc_ast::{ ast::{ExportDefaultDeclarationKind, TSType}, AstKind, }; -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::Span; @@ -11,10 +11,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; fn consistent_type_definitions_diagnostic(x0: &str, x1: &str, span2: Span) -> OxcDiagnostic { OxcDiagnostic::warn("typescript-eslint(consistent-type-definitions):") .with_help(format!("Use an `{x0}` instead of a `{x1}`")) - .with_labels([LabeledSpan::new_with_span( - Some(format!("Use an `{x0}` instead of a `{x1}`")), - span2, - )]) + .with_label(span2.label(format!("Use an `{x0}` instead of a `{x1}`"))) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs b/crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs index 42a2b89af8ddc..67e27fce98135 100644 --- a/crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs +++ b/crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs @@ -11,7 +11,7 @@ fn no_duplicate_enum_values_diagnostic(span0: Span, span1: Span) -> OxcDiagnosti "typescript-eslint(no-duplicate-enum-values): Disallow duplicate enum member values", ) .with_help("Duplicate values can lead to bugs that are hard to track down") - .with_labels([span0.into(), span1.into()]) + .with_labels([span0, span1]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/typescript/no_non_null_asserted_optional_chain.rs b/crates/oxc_linter/src/rules/typescript/no_non_null_asserted_optional_chain.rs index a408360ab22b5..a49e0a538f6d6 100644 --- a/crates/oxc_linter/src/rules/typescript/no_non_null_asserted_optional_chain.rs +++ b/crates/oxc_linter/src/rules/typescript/no_non_null_asserted_optional_chain.rs @@ -11,7 +11,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; fn no_non_null_asserted_optional_chain_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { OxcDiagnostic::warn("typescript-eslint(no-non-null-asserted-optional-chain): non-null assertions after an optional chain expression") .with_help("Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong. You should remove the non-null assertion.") - .with_labels([span0.into(), span1.into()]) + .with_labels([span0, span1]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/typescript/no_unnecessary_type_constraint.rs b/crates/oxc_linter/src/rules/typescript/no_unnecessary_type_constraint.rs index 354e5963cb16e..d1421f0d26d04 100644 --- a/crates/oxc_linter/src/rules/typescript/no_unnecessary_type_constraint.rs +++ b/crates/oxc_linter/src/rules/typescript/no_unnecessary_type_constraint.rs @@ -13,7 +13,7 @@ fn no_unnecessary_type_constraint_diagnostic( ) -> OxcDiagnostic { OxcDiagnostic::warn(format!("typescript-eslint(no-unnecessary-type-constraint): constraining the generic type {x0:?} to {x1:?} does nothing and is unnecessary")) .with_help(format!("Remove the unnecessary {x1:?} constraint")) - .with_labels([span2.into(), span3.into()]) + .with_labels([span2, span3]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/typescript/no_unsafe_declaration_merging.rs b/crates/oxc_linter/src/rules/typescript/no_unsafe_declaration_merging.rs index ea290a39a6c7f..792b3747fd920 100644 --- a/crates/oxc_linter/src/rules/typescript/no_unsafe_declaration_merging.rs +++ b/crates/oxc_linter/src/rules/typescript/no_unsafe_declaration_merging.rs @@ -9,7 +9,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; fn no_unsafe_declaration_merging_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { OxcDiagnostic::warn("typescript-eslint(no-unsafe-declaration-merging): Unsafe declaration merging between classes and interfaces.") .with_help("The TypeScript compiler doesn't check whether properties are initialized, which can cause lead to TypeScript not detecting code that will cause runtime errors.") - .with_labels([span0.into(), span1.into()]) + .with_labels([span0, span1]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/unicorn/no_invalid_remove_event_listener.rs b/crates/oxc_linter/src/rules/unicorn/no_invalid_remove_event_listener.rs index f882fe261ee7e..5d5388e0d0daf 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_invalid_remove_event_listener.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_invalid_remove_event_listener.rs @@ -2,16 +2,19 @@ use oxc_ast::{ ast::{Argument, MemberExpression}, AstKind, }; -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_span::{GetSpan, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; -fn no_invalid_remove_event_listener_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { +fn no_invalid_remove_event_listener_diagnostic(call_span: Span, arg_span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("eslint-plugin-unicorn(no-invalid-remove-event-listener): Invalid `removeEventListener` call.") .with_help("The listener argument should be a function reference.") - .with_labels([LabeledSpan::new_with_span(Some("`removeEventListener` called here.".into()), span0), LabeledSpan::new_with_span(Some("Invalid argument here".into()), span1)]) + .with_labels([ + call_span.label("`removeEventListener` called here."), + arg_span.label("Invalid argument here"), + ]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/unicorn/no_lonely_if.rs b/crates/oxc_linter/src/rules/unicorn/no_lonely_if.rs index dc8b721b14585..70eecb4397710 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_lonely_if.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_lonely_if.rs @@ -8,7 +8,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; fn no_lonely_if_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { OxcDiagnostic::warn("eslint-plugin-unicorn(no-lonely-if): Unexpected `if` as the only statement in a `if` block without `else`.") .with_help("Move the inner `if` test to the outer `if` test.") - .with_labels([span0.into(), span1.into()]) + .with_labels([span0, span1]) } #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/snapshots/jsx_key.snap b/crates/oxc_linter/src/snapshots/jsx_key.snap index f2e07948ebb5e..ebcec50cab271 100644 --- a/crates/oxc_linter/src/snapshots/jsx_key.snap +++ b/crates/oxc_linter/src/snapshots/jsx_key.snap @@ -23,8 +23,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:11] 1 │ [1, 2 ,3].map(function(x) { return }); · ─┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -32,8 +32,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:11] 1 │ [1, 2 ,3].map(x => ); · ─┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -41,8 +41,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:11] 1 │ [1, 2 ,3].map(x => x && ); · ─┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -50,8 +50,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:11] 1 │ [1, 2 ,3].map(x => x ? : ); · ─┬─ ────┬─── - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -59,8 +59,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:11] 1 │ [1, 2 ,3].map(x => x ? : ); · ─┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -68,8 +68,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:11] 1 │ [1, 2 ,3].map(x => { return }); · ─┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -77,8 +77,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:7] 1 │ Array.from([1, 2 ,3], function(x) { return }); · ──┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -86,8 +86,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:7] 1 │ Array.from([1, 2 ,3], (x => { return })); · ──┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -95,8 +95,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:7] 1 │ Array.from([1, 2 ,3], (x => )); · ──┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -104,8 +104,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:12] 1 │ [1, 2, 3]?.map(x => ) · ─┬─ ───────┬────── - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -113,8 +113,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:12] 1 │ [1, 2, 3]?.map(x => ) · ─┬─ ─────────┬───────── - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -122,8 +122,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:12] 1 │ [1, 2, 3]?.map(x => <>) · ─┬─ ─┬ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -131,8 +131,8 @@ source: crates/oxc_linter/src/tester.rs ╭─[jsx_key.tsx:1:11] 1 │ [1, 2, 3].map(x => <>{x}); · ─┬─ ─┬ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -161,11 +161,11 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) { 9 │ return
{item}
; · ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 10 │ } ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -175,14 +175,14 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) { 9 │ return
{item}
; 10 │ } 11 │ 12 │ return
; · ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 13 │ })} ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -192,11 +192,11 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) { 9 │ return
{item}
; · ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 10 │ } else if (item < 5) { ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -206,13 +206,13 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) { 9 │ return
{item}
; 10 │ } else if (item < 5) { 11 │ return
· ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 12 │ } else { ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -222,7 +222,7 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) { 9 │ return
{item}
; 10 │ } else if (item < 5) { @@ -230,7 +230,7 @@ source: crates/oxc_linter/src/tester.rs 12 │ } else { 13 │ return
· ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 14 │ } ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -240,14 +240,14 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) { ╰──── ╭─[jsx_key.tsx:16:33] 15 │ 16 │ return
; · ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 17 │ })} ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -257,10 +257,10 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) return
{item}
; · ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 9 │ else if (item < 5) return
; ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -270,11 +270,11 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) return
{item}
; 9 │ else if (item < 5) return
; · ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 10 │ else return
; ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -284,12 +284,12 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => { · ─┬─ - · ╰── Iterator starts here + · ╰── Iterator starts here. 8 │ if (item < 2) return
{item}
; 9 │ else if (item < 5) return
; 10 │ else return
; · ─┬─ - · ╰── Element generated here + · ╰── Element generated here. 11 │ })} ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -299,8 +299,8 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => onClickHandler()} onPointerDown={() => onPointerDownHandler()} onMouseDown={() => onMouseDownHandler()} />)} · ─┬─ ──┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. 8 │
╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). @@ -310,8 +310,8 @@ source: crates/oxc_linter/src/tester.rs 6 │
7 │ {list.map(item => (
· ─┬─ ─┬─ - · │ ╰── Element generated here - · ╰── Iterator starts here + · │ ╰── Element generated here. + · ╰── Iterator starts here. 8 │ onClickHandler()} onPointerDown={() => onPointerDownHandler()} onMouseDown={() => onMouseDownHandler()} /> ╰──── help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). diff --git a/crates/oxc_parser/src/diagnostics.rs b/crates/oxc_parser/src/diagnostics.rs index d8d19f6faf986..9358bc20234f5 100644 --- a/crates/oxc_parser/src/diagnostics.rs +++ b/crates/oxc_parser/src/diagnostics.rs @@ -1,11 +1,11 @@ -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_span::Span; #[cold] -pub fn redeclaration(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { +pub fn redeclaration(x0: &str, declare_span: Span, redeclare_span: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("Identifier `{x0}` has already been declared")).with_labels([ - LabeledSpan::new_with_span(Some(format!("`{x0}` has already been declared here")), span1), - LabeledSpan::new_with_span(Some("It can not be redeclared here".to_string()), span2), + declare_span.label(format!("`{x0}` has already been declared here")), + redeclare_span.label("It can not be redeclared here"), ]) } @@ -25,9 +25,9 @@ pub fn unexpected_token(span0: Span) -> OxcDiagnostic { } #[cold] -pub fn expect_token(x0: &str, x1: &str, span2: Span) -> OxcDiagnostic { +pub fn expect_token(x0: &str, x1: &str, span: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("Expected `{x0}` but found `{x1}`")) - .with_labels([LabeledSpan::new_with_span(Some(format!("`{x0}` expected")), span2)]) + .with_label(span.label(format!("`{x0}` expected"))) } #[cold] @@ -290,8 +290,8 @@ pub fn empty_parenthesized_expression(span0: Span) -> OxcDiagnostic { #[cold] pub fn illegal_newline(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("Illegal newline after {x0}")).with_labels([ - LabeledSpan::new_with_span(Some(format!("{x0} starts here")), span1), - LabeledSpan::new_with_span(Some("A newline is not expected here".to_string()), span2), + span1.label(format!("{x0} starts here")), + span2.label("A newline is not expected here"), ]) } @@ -396,7 +396,7 @@ pub fn static_constructor(span0: Span) -> OxcDiagnostic { #[cold] pub fn jsx_element_no_match(span0: Span, span1: Span, name: &str) -> OxcDiagnostic { OxcDiagnostic::error(format!("Expected corresponding JSX closing tag for '{name}'.")) - .with_labels([span0.into(), span1.into()]) + .with_labels([span0, span1]) } #[cold] diff --git a/crates/oxc_semantic/src/checker/javascript.rs b/crates/oxc_semantic/src/checker/javascript.rs index f58f6533c4019..396c7cde49d33 100644 --- a/crates/oxc_semantic/src/checker/javascript.rs +++ b/crates/oxc_semantic/src/checker/javascript.rs @@ -58,8 +58,8 @@ fn undefined_export(x0: &str, span1: Span) -> OxcDiagnostic { fn duplicate_export(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("Duplicated export '{x0}'")).with_labels([ - LabeledSpan::new_with_span(Some("Export has already been declared here".into()), span1), - LabeledSpan::new_with_span(Some("It cannot be redeclared here".into()), span2), + span1.label("Export has already been declared here"), + span2.label("It cannot be redeclared here"), ]) } @@ -548,7 +548,10 @@ fn invalid_label_target(span0: Span) -> OxcDiagnostic { fn invalid_label_non_iteration(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("A `{x0}` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement.")) -.with_labels([LabeledSpan::new_with_span(Some("This is an non-iteration statement".into()), span1), LabeledSpan::new_with_span(Some("for this label".into()), span2)]) + .with_labels([ + span1.label("This is an non-iteration statement"), + span2.label("for this label") + ]) } fn check_label(label: &LabelIdentifier, ctx: &SemanticBuilder, is_continue: bool) { @@ -1068,12 +1071,8 @@ fn is_in_formal_parameters<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) -> } fn await_or_yield_in_parameter(x0: &str, span1: Span) -> OxcDiagnostic { - OxcDiagnostic::error(format!("{x0} expression not allowed in formal parameter")).with_labels([ - LabeledSpan::new_with_span( - Some(format!("{x0} expression not allowed in formal parameter")), - span1, - ), - ]) + OxcDiagnostic::error(format!("{x0} expression not allowed in formal parameter")) + .with_label(span1.label(format!("{x0} expression not allowed in formal parameter"))) } pub fn check_await_expression<'a>( diff --git a/crates/oxc_semantic/src/diagnostics.rs b/crates/oxc_semantic/src/diagnostics.rs index 520063ef99149..14a212b9e7fc7 100644 --- a/crates/oxc_semantic/src/diagnostics.rs +++ b/crates/oxc_semantic/src/diagnostics.rs @@ -1,9 +1,9 @@ -use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; +use oxc_diagnostics::OxcDiagnostic; use oxc_span::Span; pub fn redeclaration(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { OxcDiagnostic::error(format!("Identifier `{x0}` has already been declared")).with_labels([ - LabeledSpan::new_with_span(Some(format!("`{x0}` has already been declared here")), span1), - LabeledSpan::new_with_span(Some("It can not be redeclared here".into()), span2), + span1.label(format!("`{x0}` has already been declared here")), + span2.label("It can not be redeclared here"), ]) } diff --git a/crates/oxc_span/src/span.rs b/crates/oxc_span/src/span.rs index f1e41c6ec3249..638b47a22202f 100644 --- a/crates/oxc_span/src/span.rs +++ b/crates/oxc_span/src/span.rs @@ -275,6 +275,12 @@ impl Span { pub fn source_text<'a>(&self, source_text: &'a str) -> &'a str { &source_text[self.start as usize..self.end as usize] } + + /// Create a [`LabeledSpan`] covering this [`Span`] with the given label. + #[must_use] + pub fn label>(self, label: S) -> LabeledSpan { + LabeledSpan::new_with_span(Some(label.into()), self) + } } impl Index for str { diff --git a/crates/oxc_transformer/src/react/diagnostics.rs b/crates/oxc_transformer/src/react/diagnostics.rs index 92be1bfd542d8..0847aabaa39c3 100644 --- a/crates/oxc_transformer/src/react/diagnostics.rs +++ b/crates/oxc_transformer/src/react/diagnostics.rs @@ -21,16 +21,16 @@ pub fn invalid_import_source() -> OxcDiagnostic { .with_help("Fix `importSource` option.") } -pub fn namespace_does_not_support(span0: Span) -> OxcDiagnostic { +pub fn namespace_does_not_support(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("Namespace tags are not supported by default. React's JSX doesn't support namespace tags. You can set `throwIfNamespace: false` to bypass this warning.") -.with_labels([span0.into()]) + .with_label(span) } -pub fn valueless_key(span0: Span) -> OxcDiagnostic { +pub fn valueless_key(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("Please provide an explicit key value. Using \"key\" as a shorthand for \"key={true}\" is not allowed.") -.with_labels([span0.into()]) + .with_label(span) } -pub fn spread_children_are_not_supported(span0: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Spread children are not supported in React.").with_labels([span0.into()]) +pub fn spread_children_are_not_supported(span: Span) -> OxcDiagnostic { + OxcDiagnostic::warn("Spread children are not supported in React.").with_label(span) } diff --git a/crates/oxc_transformer/src/typescript/diagnostics.rs b/crates/oxc_transformer/src/typescript/diagnostics.rs index d3cf9bc5dbc2b..73d8a21223c89 100644 --- a/crates/oxc_transformer/src/typescript/diagnostics.rs +++ b/crates/oxc_transformer/src/typescript/diagnostics.rs @@ -1,14 +1,14 @@ use oxc_diagnostics::OxcDiagnostic; use oxc_span::Span; -pub fn import_equals_require_unsupported(span0: Span) -> OxcDiagnostic { +pub fn import_equals_require_unsupported(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("`import lib = require(...);` is only supported when compiling modules to CommonJS.\nPlease consider using `import lib from '...';` alongside Typescript's --allowSyntheticDefaultImports option, or add @babel/plugin-transform-modules-commonjs to your Babel config.") -.with_labels([span0.into()]) + .with_label(span) } -pub fn export_assignment_unsupported(span0: Span) -> OxcDiagnostic { +pub fn export_assignment_unsupported(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("`export = ;` is only supported when compiling modules to CommonJS.\nPlease consider using `export default ;`, or add @babel/plugin-transform-modules-commonjs to your Babel config.") -.with_labels([span0.into()]) + .with_label(span) } pub fn ambient_module_nested(span0: Span) -> OxcDiagnostic {