refactor(linter): improve diagnostic labeling (#3960)

This commit is contained in:
DonIsaac 2024-06-29 05:19:21 +00:00
parent f64ad4b7c2
commit 2705df93b3
41 changed files with 217 additions and 201 deletions

View file

@ -118,8 +118,11 @@ impl OxcDiagnostic {
} }
#[must_use] #[must_use]
pub fn with_labels<T: IntoIterator<Item = LabeledSpan>>(mut self, labels: T) -> Self { pub fn with_labels<L: Into<LabeledSpan>, T: IntoIterator<Item = L>>(
self.inner.labels = Some(labels.into_iter().collect()); mut self,
labels: T,
) -> Self {
self.inner.labels = Some(labels.into_iter().map(Into::into).collect());
self self
} }
@ -132,9 +135,12 @@ impl OxcDiagnostic {
} }
#[must_use] #[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(); 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.inner.labels = Some(all_labels);
self self
} }

View file

@ -5,7 +5,7 @@ use std::{env, path::Path};
use oxc_allocator::Allocator; use oxc_allocator::Allocator;
use oxc_ast::AstKind; use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_parser::Parser; use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder; use oxc_semantic::SemanticBuilder;
use oxc_span::{SourceType, Span}; use oxc_span::{SourceType, Span};
@ -73,8 +73,8 @@ fn print_errors(source_text: &str, errors: Vec<OxcDiagnostic>) {
// 1 │ debugger; // 1 │ debugger;
// · ───────── // · ─────────
// ╰──── // ╰────
fn no_debugger(span0: Span) -> OxcDiagnostic { fn no_debugger(debugger_span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("`debugger` statement is not allowed").with_labels([span0.into()]) OxcDiagnostic::error("`debugger` statement is not allowed").with_label(debugger_span)
} }
// This prints: // This prints:
@ -85,8 +85,7 @@ fn no_debugger(span0: Span) -> OxcDiagnostic {
// · ─┬ // · ─┬
// · ╰── Empty object binding pattern // · ╰── Empty object binding pattern
// ╰──── // ╰────
fn no_empty_pattern(s0: &str, span1: Span) -> OxcDiagnostic { fn no_empty_pattern(binding_kind: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("empty destructuring pattern is not allowed").with_labels([ OxcDiagnostic::error("empty destructuring pattern is not allowed")
LabeledSpan::new_with_span(Some(format!("Empty {s0} binding pattern")), span1), .with_label(span.label(format!("Empty {binding_kind} binding pattern")))
])
} }

View file

@ -290,8 +290,8 @@ mod test {
OxcDiagnostic::warn("removestart") OxcDiagnostic::warn("removestart")
} }
fn remove_middle(span0: Span) -> OxcDiagnostic { fn remove_middle(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("removemiddle").with_labels([span0.into()]) OxcDiagnostic::warn("removemiddle").with_labels([span])
} }
fn remove_end() -> OxcDiagnostic { fn remove_end() -> OxcDiagnostic {
@ -302,16 +302,16 @@ mod test {
OxcDiagnostic::warn("reversed range") OxcDiagnostic::warn("reversed range")
} }
fn no_fix(span0: Span) -> OxcDiagnostic { fn no_fix(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix").with_labels([span0.into()]) OxcDiagnostic::warn("nofix").with_labels([span])
} }
fn no_fix_1(span0: Span) -> OxcDiagnostic { fn no_fix_1(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix1").with_labels([span0.into()]) OxcDiagnostic::warn("nofix1").with_labels([span])
} }
fn no_fix_2(span0: Span) -> OxcDiagnostic { fn no_fix_2(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("nofix2").with_labels([span0.into()]) OxcDiagnostic::warn("nofix2").with_labels([span])
} }
const TEST_CODE: &str = "var answer = 6 * 7;"; const TEST_CODE: &str = "var answer = 6 * 7;";

View file

@ -1,5 +1,5 @@
use oxc_ast::AstKind; use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; use oxc_span::Span;
@ -9,10 +9,7 @@ fn default_case_last_diagnostic(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn( OxcDiagnostic::warn(
"eslint(default-case-last): Enforce default clauses in switch statements to be last", "eslint(default-case-last): Enforce default clauses in switch statements to be last",
) )
.with_labels([LabeledSpan::new_with_span( .with_label(span0.label("Default clause should be the last clause."))
Some("Default clause should be the last clause.".into()),
span0,
)])
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]

View file

@ -5,7 +5,7 @@ use oxc_ast::{
}, },
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; use oxc_span::Span;
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, UnaryOperator, UpdateOperator}; 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 { 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") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId; use oxc_semantic::SymbolId;
use oxc_span::Span; 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 { 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}")) OxcDiagnostic::warn(format!("eslint(no-class-assign): Unexpected re-assignment of class {x0}"))
.with_labels([ .with_labels([
LabeledSpan::new_with_span(Some(format!("{x0} is declared as class here")), span1), span1.label(format!("{x0} is declared as class here")),
LabeledSpan::new_with_span(Some(format!("{x0} is re-assigned here")), span2), span2.label(format!("{x0} is re-assigned here")),
]) ])
} }

View file

@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId; use oxc_semantic::SymbolId;
use oxc_span::Span; 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}" "eslint(no-const-assign): Unexpected re-assignment of const variable {x0}"
)) ))
.with_labels([ .with_labels([
LabeledSpan::new_with_span(Some(format!("{x0} is declared here as const")), span1), span1.label(format!("{x0} is declared here as const")),
LabeledSpan::new_with_span(Some(format!("{x0} is re-assigned here")), span2), span2.label(format!("{x0} is re-assigned here")),
]) ])
} }

View file

@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; use oxc_span::Span;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -12,7 +12,10 @@ fn no_dupe_class_members_diagnostic(
) -> OxcDiagnostic { ) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("eslint(no-dupe-class-members): Duplicate class member: {x0:?}")) 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -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 { 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") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -12,7 +12,7 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn no_dupe_keys_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { fn no_dupe_keys_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-dupe-keys): Disallow duplicate keys in object literals") OxcDiagnostic::warn("eslint(no-dupe-keys): Disallow duplicate keys in object literals")
.with_help("Consider removing the duplicated key") .with_help("Consider removing the duplicated key")
.with_labels([span0.into(), span1.into()]) .with_labels([span0, span1])
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]

View file

@ -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 { fn no_duplicate_case_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-duplicate-case): Disallow duplicate case labels") OxcDiagnostic::warn("eslint(no-duplicate-case): Disallow duplicate case labels")
.with_help("Remove the duplicated case") .with_help("Remove the duplicated case")
.with_labels([span0.into(), span1.into()]) .with_labels([span0, span1])
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]

View file

@ -1,5 +1,5 @@
use oxc_ast::AstKind; use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; use oxc_span::Span;
@ -8,7 +8,7 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn no_empty_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic { fn no_empty_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-empty): Disallow empty block statements") OxcDiagnostic::warn("eslint(no-empty): Disallow empty block statements")
.with_help(format!("Add comment inside empty {x0} statement")) .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)] #[derive(Debug, Default, Clone)]

View file

@ -1,5 +1,5 @@
use oxc_ast::AstKind; use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; 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 { fn no_empty_pattern_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-empty-pattern): Disallow empty destructuring patterns.") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -1,5 +1,5 @@
use oxc_ast::AstKind; use oxc_ast::AstKind;
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId; use oxc_semantic::SymbolId;
use oxc_span::Span; use oxc_span::Span;
@ -8,7 +8,7 @@ use crate::{context::LintContext, rule::Rule};
fn no_func_assign_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic { fn no_func_assign_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("eslint(no-func-assign): '{x0}' is a function.")) 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)] #[derive(Debug, Default, Clone)]

View file

@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::{CompactStr, Span}; use oxc_span::{CompactStr, Span};
@ -8,10 +8,7 @@ fn no_global_assign_diagnostic(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!( OxcDiagnostic::warn(format!(
"eslint(no-global-assign): Read-only global '{x0}' should not be modified." "eslint(no-global-assign): Read-only global '{x0}' should not be modified."
)) ))
.with_labels([LabeledSpan::new_with_span( .with_label(span1.label(format!("Read-only global '{x0}' should not be modified.")))
Some(format!("Read-only global '{x0}' should not be modified.")),
span1,
)])
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]

View file

@ -2,7 +2,7 @@ use oxc_ast::{
ast::{BindingIdentifier, BindingPatternKind}, ast::{BindingIdentifier, BindingPatternKind},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; 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 { fn no_redeclare_diagnostic(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("eslint(no-redeclare): '{x0}' is already defined.")).with_labels([ OxcDiagnostic::warn(format!("eslint(no-redeclare): '{x0}' is already defined.")).with_labels([
LabeledSpan::new_with_span(Some(format!("'{x0}' is already defined.")), span1), span1.label(format!("'{x0}' is already defined.")),
LabeledSpan::new_with_span(Some("It can not be redeclare here.".into()), span2), 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!( OxcDiagnostic::warn(format!(
"eslint(no-redeclare): '{x0}' is already defined as a built-in global variable." "eslint(no-redeclare): '{x0}' is already defined as a built-in global variable."
)) ))
.with_labels([LabeledSpan::new_with_span( .with_label(span1.label(format!("'{x0}' is already defined as a built-in global variable.")))
Some(format!("'{x0}' is already defined as a built-in global variable.")),
span1,
)])
} }
// #[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)] #[derive(Debug, Default, Clone)]
pub struct NoRedeclare { pub struct NoRedeclare {
built_in_globals: bool, built_in_globals: bool,

View file

@ -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", "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_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)] #[derive(Debug, Default, Clone)]

View file

@ -2,24 +2,20 @@ use oxc_ast::{
ast::{BindingPatternKind, Expression, Statement}, ast::{BindingPatternKind, Expression, Statement},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; use oxc_span::Span;
use crate::{context::LintContext, rule::Rule, AstNode}; use crate::{context::LintContext, rule::Rule, AstNode};
fn no_useless_catch_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { fn no_useless_catch_diagnostic(catch: Span, rethrow: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-useless-catch): Unnecessary try/catch wrapper").with_labels([ OxcDiagnostic::warn("eslint(no-useless-catch): Unnecessary try/catch wrapper")
LabeledSpan::new_with_span(Some("is caught here".into()), span0), .with_labels([catch.label("is caught here"), rethrow.label("and re-thrown here")])
LabeledSpan::new_with_span(Some("and re-thrown here".into()), span1),
])
} }
fn no_useless_catch_finalizer_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { fn no_useless_catch_finalizer_diagnostic(catch: Span, rethrow: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("eslint(no-useless-catch): Unnecessary catch clause").with_labels([ OxcDiagnostic::warn("eslint(no-useless-catch): Unnecessary catch clause")
LabeledSpan::new_with_span(Some("is caught here".into()), span0), .with_labels([catch.label("is caught here"), rethrow.label("and re-thrown here")])
LabeledSpan::new_with_span(Some("and re-thrown here".into()), span1),
])
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]

View file

@ -1,15 +1,22 @@
use oxc_ast::{ast::Expression, AstKind}; use oxc_ast::{ast::Expression, AstKind};
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span}; use oxc_span::{GetSpan, Span};
use oxc_syntax::operator::BinaryOperator; use oxc_syntax::operator::BinaryOperator;
use crate::{ast_util::is_method_call, context::LintContext, rule::Rule, AstNode}; 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") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -2,7 +2,7 @@ use oxc_ast::{
ast::{Expression, RegExpFlags}, ast::{Expression, RegExpFlags},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; use oxc_span::Span;
@ -16,7 +16,10 @@ use crate::{
fn bad_replace_all_arg_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { 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.") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -5,7 +5,7 @@ use oxc_ast::{
ast::{Expression, NumericLiteral}, ast::{Expression, NumericLiteral},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span}; use oxc_span::{GetSpan, Span};
use oxc_syntax::operator::{BinaryOperator, LogicalOperator}; 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.") OxcDiagnostic::warn("oxc(const-comparisons): Left-hand side of `&&` operator has no effect.")
.with_help(x2.to_string()) .with_help(x2.to_string())
.with_labels([ .with_labels([
LabeledSpan::new_with_span(Some("If this evaluates to `true`".into()), span0), span0.label("If this evaluates to `true`"),
LabeledSpan::new_with_span(Some("This will always evaluate to true.".into()), span1), 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.") OxcDiagnostic::warn("oxc(const-comparisons): Right-hand side of `&&` operator has no effect.")
.with_help(x2.to_string()) .with_help(x2.to_string())
.with_labels([ .with_labels([
LabeledSpan::new_with_span(Some("If this evaluates to `true`".into()), span0), span0.label("If this evaluates to `true`"),
LabeledSpan::new_with_span(Some("This will always evaluate to true.".into()), span1), 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") OxcDiagnostic::warn("oxc(const-comparisons): Unexpected constant comparison")
.with_help(x4.to_string()) .with_help(x4.to_string())
.with_labels([ .with_labels([
LabeledSpan::new_with_span(Some(format!("Requires that {x2}")), span0), span0.label(format!("Requires that {x2}")),
LabeledSpan::new_with_span(Some(format!("Requires that {x3}")), span1), span1.label(format!("Requires that {x3}")),
]) ])
} }

View file

@ -2,7 +2,7 @@ use oxc_ast::{
ast::{Argument, BindingPatternKind, CallExpression, Expression}, ast::{Argument, BindingPatternKind, CallExpression, Expression},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId; use oxc_semantic::SymbolId;
use oxc_span::Span; use oxc_span::Span;
@ -15,17 +15,30 @@ use crate::{
}; };
fn likely_array(span0: Span, span1: Span) -> OxcDiagnostic { 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 { 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 { fn unknown(span0: Span, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("oxc(no-accumulating-spread): Do not spread accumulators in Array.prototype.reduce()") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -1,4 +1,4 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_semantic::ModuleRecord; use oxc_semantic::ModuleRecord;
use oxc_syntax::module_graph_visitor::{ModuleGraphVisitorBuilder, VisitFoldWhile}; 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(remote_module) = module_record.loaded_modules.get(module_request.name()) {
if let Some(count) = count_loaded_modules(remote_module.value()) { if let Some(count) = count_loaded_modules(remote_module.value()) {
total += count; total += count;
labels.push(LabeledSpan::new_with_span( labels.push(module_request.span().label(format!("{count} modules")));
Some(format!("{count} modules")),
module_request.span(),
));
} }
}; };
} }

View file

@ -2,7 +2,7 @@ use oxc_ast::{
ast::{Argument, MemberExpression}, ast::{Argument, MemberExpression},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span}; 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()`", "consider filling the array with `undefined` values using `Array.prototype.fill()`",
) )
.with_labels([ .with_labels([
LabeledSpan::new_with_span(Some("this callback will not be invoked".into()), span0), span0.label("this callback will not be invoked"),
LabeledSpan::new_with_span( span1.label("because this is an array with only empty slots"),
Some("because this is an array with only empty slots".into()),
span1,
),
]) ])
} }

View file

@ -13,16 +13,16 @@ use crate::{
AstNode, 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`.") 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_help("Add either `onChange` or `readOnly`.")
.with_label(span0) .with_label(span)
} }
fn exclusive_checked_attribute(span0: Span, span1: Span) -> OxcDiagnostic { 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.") 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_help("Remove either `checked` or `defaultChecked`.")
.with_labels([span0.into(), span1.into()]) .with_labels([span0, span1])
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]

View file

@ -2,7 +2,7 @@ use oxc_ast::{
ast::{JSXAttributeItem, JSXAttributeName, JSXElement, JSXFragment, Statement}, ast::{JSXAttributeItem, JSXAttributeName, JSXElement, JSXFragment, Statement},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span}; 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 { 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."#) 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_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 { fn key_prop_must_be_placed_before_spread(span0: Span) -> OxcDiagnostic {

View file

@ -12,7 +12,7 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn jsx_no_duplicate_props_diagnostic(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { 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.")) 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -2,7 +2,7 @@ use oxc_ast::{
ast::{ExportDefaultDeclarationKind, TSType}, ast::{ExportDefaultDeclarationKind, TSType},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::Span; 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 { fn consistent_type_definitions_diagnostic(x0: &str, x1: &str, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("typescript-eslint(consistent-type-definitions):") OxcDiagnostic::warn("typescript-eslint(consistent-type-definitions):")
.with_help(format!("Use an `{x0}` instead of a `{x1}`")) .with_help(format!("Use an `{x0}` instead of a `{x1}`"))
.with_labels([LabeledSpan::new_with_span( .with_label(span2.label(format!("Use an `{x0}` instead of a `{x1}`")))
Some(format!("Use an `{x0}` instead of a `{x1}`")),
span2,
)])
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]

View file

@ -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", "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_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)] #[derive(Debug, Default, Clone)]

View file

@ -11,7 +11,7 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn no_non_null_asserted_optional_chain_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { 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") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -13,7 +13,7 @@ fn no_unnecessary_type_constraint_diagnostic(
) -> OxcDiagnostic { ) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("typescript-eslint(no-unnecessary-type-constraint): constraining the generic type {x0:?} to {x1:?} does nothing and is unnecessary")) 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_help(format!("Remove the unnecessary {x1:?} constraint"))
.with_labels([span2.into(), span3.into()]) .with_labels([span2, span3])
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]

View file

@ -9,7 +9,7 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn no_unsafe_declaration_merging_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { 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.") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -2,16 +2,19 @@ use oxc_ast::{
ast::{Argument, MemberExpression}, ast::{Argument, MemberExpression},
AstKind, AstKind,
}; };
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span}; use oxc_span::{GetSpan, Span};
use crate::{context::LintContext, rule::Rule, AstNode}; 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.") OxcDiagnostic::warn("eslint-plugin-unicorn(no-invalid-remove-event-listener): Invalid `removeEventListener` call.")
.with_help("The listener argument should be a function reference.") .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)] #[derive(Debug, Default, Clone)]

View file

@ -8,7 +8,7 @@ use crate::{context::LintContext, rule::Rule, AstNode};
fn no_lonely_if_diagnostic(span0: Span, span1: Span) -> OxcDiagnostic { 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`.") 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_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)] #[derive(Debug, Default, Clone)]

View file

@ -23,8 +23,8 @@ source: crates/oxc_linter/src/tester.rs
╭─[jsx_key.tsx:1:11] ╭─[jsx_key.tsx:1:11]
1 │ [1, 2 ,3].map(function(x) { return <App /> }); 1 │ [1, 2 ,3].map(function(x) { return <App /> });
· ─┬─ ─┬─ · ─┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:11]
1 │ [1, 2 ,3].map(x => <App />); 1 │ [1, 2 ,3].map(x => <App />);
· ─┬─ ─┬─ · ─┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:11]
1 │ [1, 2 ,3].map(x => x && <App x={x} />); 1 │ [1, 2 ,3].map(x => x && <App x={x} />);
· ─┬─ ─┬─ · ─┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:11]
1 │ [1, 2 ,3].map(x => x ? <App x={x} key="1" /> : <OtherApp x={x} />); 1 │ [1, 2 ,3].map(x => x ? <App x={x} key="1" /> : <OtherApp x={x} />);
· ─┬─ ────┬─── · ─┬─ ────┬───
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:11]
1 │ [1, 2 ,3].map(x => x ? <App x={x} /> : <OtherApp x={x} key="2" />); 1 │ [1, 2 ,3].map(x => x ? <App x={x} /> : <OtherApp x={x} key="2" />);
· ─┬─ ─┬─ · ─┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:11]
1 │ [1, 2 ,3].map(x => { return <App /> }); 1 │ [1, 2 ,3].map(x => { return <App /> });
· ─┬─ ─┬─ · ─┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:7]
1 │ Array.from([1, 2 ,3], function(x) { return <App /> }); 1 │ Array.from([1, 2 ,3], function(x) { return <App /> });
· ──┬─ ─┬─ · ──┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:7]
1 │ Array.from([1, 2 ,3], (x => { return <App /> })); 1 │ Array.from([1, 2 ,3], (x => { return <App /> }));
· ──┬─ ─┬─ · ──┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:7]
1 │ Array.from([1, 2 ,3], (x => <App />)); 1 │ Array.from([1, 2 ,3], (x => <App />));
· ──┬─ ─┬─ · ──┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:12]
1 │ [1, 2, 3]?.map(x => <BabelEslintApp />) 1 │ [1, 2, 3]?.map(x => <BabelEslintApp />)
· ─┬─ ───────┬────── · ─┬─ ───────┬──────
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:12]
1 │ [1, 2, 3]?.map(x => <TypescriptEslintApp />) 1 │ [1, 2, 3]?.map(x => <TypescriptEslintApp />)
· ─┬─ ─────────┬───────── · ─┬─ ─────────┬─────────
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:12]
1 │ [1, 2, 3]?.map(x => <><OxcCompilerHello /></>) 1 │ [1, 2, 3]?.map(x => <><OxcCompilerHello /></>)
· ─┬─ ─┬ · ─┬─ ─┬
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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] ╭─[jsx_key.tsx:1:11]
1 │ [1, 2, 3].map(x => <>{x}</>); 1 │ [1, 2, 3].map(x => <>{x}</>);
· ─┬─ ─┬ · ─┬─ ─┬
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts 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). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) { 8 │ if (item < 2) {
9 │ return <div>{item}</div>; 9 │ return <div>{item}</div>;
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
10 │ } 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). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) { 8 │ if (item < 2) {
9 │ return <div>{item}</div>; 9 │ return <div>{item}</div>;
10 │ } 10 │ }
11 │ 11 │
12 │ return <div />; 12 │ return <div />;
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
13 │ })} 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). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) { 8 │ if (item < 2) {
9 │ return <div>{item}</div>; 9 │ return <div>{item}</div>;
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
10 │ } else if (item < 5) { 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). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) { 8 │ if (item < 2) {
9 │ return <div>{item}</div>; 9 │ return <div>{item}</div>;
10 │ } else if (item < 5) { 10 │ } else if (item < 5) {
11 │ return <div></div> 11 │ return <div></div>
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
12 │ } else { 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). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) { 8 │ if (item < 2) {
9 │ return <div>{item}</div>; 9 │ return <div>{item}</div>;
10 │ } else if (item < 5) { 10 │ } else if (item < 5) {
@ -230,7 +230,7 @@ source: crates/oxc_linter/src/tester.rs
12 │ } else { 12 │ } else {
13 │ return <div></div> 13 │ return <div></div>
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
14 │ } 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). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) { 8 │ if (item < 2) {
╰──── ╰────
╭─[jsx_key.tsx:16:33] ╭─[jsx_key.tsx:16:33]
15 │ 15 │
16 │ return <div />; 16 │ return <div />;
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
17 │ })} 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). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) return <div>{item}</div>; 8 │ if (item < 2) return <div>{item}</div>;
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
9 │ else if (item < 5) return <div />; 9 │ else if (item < 5) return <div />;
╰──── ╰────
help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) return <div>{item}</div>; 8 │ if (item < 2) return <div>{item}</div>;
9 │ else if (item < 5) return <div />; 9 │ else if (item < 5) return <div />;
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
10 │ else return <div />; 10 │ else return <div />;
╰──── ╰────
help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). 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 │ <div> 6 │ <div>
7 │ {list.map(item => { 7 │ {list.map(item => {
· ─┬─ · ─┬─
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ if (item < 2) return <div>{item}</div>; 8 │ if (item < 2) return <div>{item}</div>;
9 │ else if (item < 5) return <div />; 9 │ else if (item < 5) return <div />;
10 │ else return <div />; 10 │ else return <div />;
· ─┬─ · ─┬─
· ╰── Element generated here · ╰── Element generated here.
11 │ })} 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). 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 │ <div> 6 │ <div>
7 │ {list.map(item => <Text foo bar baz qux onClick={() => onClickHandler()} onPointerDown={() => onPointerDownHandler()} onMouseDown={() => onMouseDownHandler()} />)} 7 │ {list.map(item => <Text foo bar baz qux onClick={() => onClickHandler()} onPointerDown={() => onPointerDownHandler()} onMouseDown={() => onMouseDownHandler()} />)}
· ─┬─ ──┬─ · ─┬─ ──┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ </div> 8 │ </div>
╰──── ╰────
help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key). 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 │ <div> 6 │ <div>
7 │ {list.map(item => (<div> 7 │ {list.map(item => (<div>
· ─┬─ ─┬─ · ─┬─ ─┬─
· │ ╰── Element generated here · │ ╰── Element generated here.
· ╰── Iterator starts here · ╰── Iterator starts here.
8 │ <Text foo bar baz qux onClick={() => onClickHandler()} onPointerDown={() => onPointerDownHandler()} onMouseDown={() => onMouseDownHandler()} /> 8 │ <Text foo bar baz qux onClick={() => 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). help: Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key).

View file

@ -1,11 +1,11 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_span::Span; use oxc_span::Span;
#[cold] #[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([ OxcDiagnostic::error(format!("Identifier `{x0}` has already been declared")).with_labels([
LabeledSpan::new_with_span(Some(format!("`{x0}` has already been declared here")), span1), declare_span.label(format!("`{x0}` has already been declared here")),
LabeledSpan::new_with_span(Some("It can not be redeclared here".to_string()), span2), redeclare_span.label("It can not be redeclared here"),
]) ])
} }
@ -25,9 +25,9 @@ pub fn unexpected_token(span0: Span) -> OxcDiagnostic {
} }
#[cold] #[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}`")) 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] #[cold]
@ -290,8 +290,8 @@ pub fn empty_parenthesized_expression(span0: Span) -> OxcDiagnostic {
#[cold] #[cold]
pub fn illegal_newline(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { pub fn illegal_newline(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::error(format!("Illegal newline after {x0}")).with_labels([ OxcDiagnostic::error(format!("Illegal newline after {x0}")).with_labels([
LabeledSpan::new_with_span(Some(format!("{x0} starts here")), span1), span1.label(format!("{x0} starts here")),
LabeledSpan::new_with_span(Some("A newline is not expected here".to_string()), span2), span2.label("A newline is not expected here"),
]) ])
} }
@ -396,7 +396,7 @@ pub fn static_constructor(span0: Span) -> OxcDiagnostic {
#[cold] #[cold]
pub fn jsx_element_no_match(span0: Span, span1: Span, name: &str) -> OxcDiagnostic { pub fn jsx_element_no_match(span0: Span, span1: Span, name: &str) -> OxcDiagnostic {
OxcDiagnostic::error(format!("Expected corresponding JSX closing tag for '{name}'.")) OxcDiagnostic::error(format!("Expected corresponding JSX closing tag for '{name}'."))
.with_labels([span0.into(), span1.into()]) .with_labels([span0, span1])
} }
#[cold] #[cold]

View file

@ -58,8 +58,8 @@ fn undefined_export(x0: &str, span1: Span) -> OxcDiagnostic {
fn duplicate_export(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { fn duplicate_export(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::error(format!("Duplicated export '{x0}'")).with_labels([ OxcDiagnostic::error(format!("Duplicated export '{x0}'")).with_labels([
LabeledSpan::new_with_span(Some("Export has already been declared here".into()), span1), span1.label("Export has already been declared here"),
LabeledSpan::new_with_span(Some("It cannot be redeclared here".into()), span2), 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 { 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.")) 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) { 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 { fn await_or_yield_in_parameter(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::error(format!("{x0} expression not allowed in formal parameter")).with_labels([ OxcDiagnostic::error(format!("{x0} expression not allowed in formal parameter"))
LabeledSpan::new_with_span( .with_label(span1.label(format!("{x0} expression not allowed in formal parameter")))
Some(format!("{x0} expression not allowed in formal parameter")),
span1,
),
])
} }
pub fn check_await_expression<'a>( pub fn check_await_expression<'a>(

View file

@ -1,9 +1,9 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_diagnostics::OxcDiagnostic;
use oxc_span::Span; use oxc_span::Span;
pub fn redeclaration(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic { pub fn redeclaration(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::error(format!("Identifier `{x0}` has already been declared")).with_labels([ OxcDiagnostic::error(format!("Identifier `{x0}` has already been declared")).with_labels([
LabeledSpan::new_with_span(Some(format!("`{x0}` has already been declared here")), span1), span1.label(format!("`{x0}` has already been declared here")),
LabeledSpan::new_with_span(Some("It can not be redeclared here".into()), span2), span2.label("It can not be redeclared here"),
]) ])
} }

View file

@ -275,6 +275,12 @@ impl Span {
pub fn source_text<'a>(&self, source_text: &'a str) -> &'a str { pub fn source_text<'a>(&self, source_text: &'a str) -> &'a str {
&source_text[self.start as usize..self.end as usize] &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<S: Into<String>>(self, label: S) -> LabeledSpan {
LabeledSpan::new_with_span(Some(label.into()), self)
}
} }
impl Index<Span> for str { impl Index<Span> for str {

View file

@ -21,16 +21,16 @@ pub fn invalid_import_source() -> OxcDiagnostic {
.with_help("Fix `importSource` option.") .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.") 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.") 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 { pub fn spread_children_are_not_supported(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Spread children are not supported in React.").with_labels([span0.into()]) OxcDiagnostic::warn("Spread children are not supported in React.").with_label(span)
} }

View file

@ -1,14 +1,14 @@
use oxc_diagnostics::OxcDiagnostic; use oxc_diagnostics::OxcDiagnostic;
use oxc_span::Span; 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.") 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 = <value>;` is only supported when compiling modules to CommonJS.\nPlease consider using `export default <value>;`, or add @babel/plugin-transform-modules-commonjs to your Babel config.") OxcDiagnostic::warn("`export = <value>;` is only supported when compiling modules to CommonJS.\nPlease consider using `export default <value>;`, 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 { pub fn ambient_module_nested(span0: Span) -> OxcDiagnostic {