Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed May 10, 2024
1 parent e91a469 commit 0cf90e8
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 72 deletions.
86 changes: 82 additions & 4 deletions crates/oxc_diagnostics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ mod graphical_theme;
mod reporter;
mod service;

use std::path::PathBuf;
use std::{
fmt::{self, Display},
path::PathBuf,
};

pub use miette;
pub use thiserror;
Expand All @@ -20,12 +23,11 @@ pub use crate::{
pub type Error = miette::Error;
pub type Severity = miette::Severity;
pub type Report = miette::Report;
pub type OxcDiagnostic = miette::MietteDiagnostic;

pub type Result<T> = std::result::Result<T, Error>;
pub type Result<T> = std::result::Result<T, OxcDiagnostic>;

use miette::Diagnostic;
pub use miette::LabeledSpan;
use miette::{Diagnostic, SourceCode};
use thiserror::Error;

#[derive(Debug, Error, Diagnostic)]
Expand All @@ -37,3 +39,79 @@ pub struct MinifiedFileError(pub PathBuf);
#[error("Failed to open file {0:?} with error \"{1}\"")]
#[diagnostic(help("Failed to open file {0:?} with error \"{1}\""))]
pub struct FailedToOpenFileError(pub PathBuf, pub std::io::Error);

// [miette::MietteDiagnostic] is 128 bytes. This is a version with less fields (72 bytes).
#[derive(Debug, Clone)]
pub struct OxcDiagnostic {
pub message: String,
pub labels: Option<Vec<LabeledSpan>>,
pub help: Option<String>,
}

impl fmt::Display for OxcDiagnostic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.message)
}
}

impl std::error::Error for OxcDiagnostic {}

impl Diagnostic for OxcDiagnostic {
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
self.help.as_ref().map(Box::new).map(|c| c as Box<dyn Display>)
}

fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
self.labels
.as_ref()
.map(|ls| ls.iter().cloned())
.map(Box::new)
.map(|b| b as Box<dyn Iterator<Item = LabeledSpan>>)
}
}

impl OxcDiagnostic {
#[must_use]
pub fn new<T: Into<String>>(message: T) -> Self {
Self { message: message.into(), labels: None, help: None }
}

#[must_use]
pub fn with_help<T: Into<String>>(mut self, help: T) -> Self {
self.help = Some(help.into());
self
}

#[must_use]
pub fn with_label<T: Into<LabeledSpan>>(mut self, label: T) -> Self {
self.labels = Some(vec![label.into()]);
self
}

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

#[must_use]
pub fn and_label<T: Into<LabeledSpan>>(mut self, label: T) -> Self {
let mut labels = self.labels.unwrap_or_default();
labels.push(label.into());
self.labels = Some(labels);
self
}

#[must_use]
pub fn and_labels<T: IntoIterator<Item = LabeledSpan>>(mut self, labels: T) -> Self {
let mut all_labels = self.labels.unwrap_or_default();
all_labels.extend(labels);
self.labels = Some(all_labels);
self
}

#[must_use]
pub fn with_source_code<T: SourceCode + Send + Sync + 'static>(self, code: T) -> Error {
Error::from(self).with_source_code(code)
}
}
5 changes: 4 additions & 1 deletion crates/oxc_language_server/src/linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,10 @@ impl IsolatedLintHandler {
let reports = ret
.errors
.into_iter()
.map(|diagnostic| ErrorReport { error: diagnostic, fixed_content: None })
.map(|diagnostic| ErrorReport {
error: Error::from(diagnostic),
fixed_content: None,
})
.collect();
return Some(Self::wrap_diagnostics(path, &original_source_text, reports, start));
};
Expand Down
31 changes: 14 additions & 17 deletions crates/oxc_linter/examples/linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use std::{env, path::Path};

use oxc_allocator::Allocator;
use oxc_ast::AstKind;
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::Error,
};
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use oxc_span::{SourceType, Span};
Expand Down Expand Up @@ -35,18 +32,18 @@ fn main() -> std::io::Result<()> {
let semantic_ret =
SemanticBuilder::new(&source_text, source_type).with_trivias(ret.trivias).build(program);

let mut errors: Vec<oxc_diagnostics::Error> = vec![];
let mut errors: Vec<OxcDiagnostic> = vec![];

for node in semantic_ret.semantic.nodes().iter() {
match node.kind() {
AstKind::DebuggerStatement(stmt) => {
errors.push(NoDebugger(stmt.span).into());
errors.push(no_debugger(stmt.span));
}
AstKind::ArrayPattern(array) if array.elements.is_empty() => {
errors.push(NoEmptyPattern("array", array.span).into());
errors.push(no_empty_pattern("array", array.span));
}
AstKind::ObjectPattern(object) if object.properties.is_empty() => {
errors.push(NoEmptyPattern("object", object.span).into());
errors.push(no_empty_pattern("object", object.span));
}
_ => {}
}
Expand All @@ -61,7 +58,7 @@ fn main() -> std::io::Result<()> {
Ok(())
}

fn print_errors(source_text: &str, errors: Vec<oxc_diagnostics::Error>) {
fn print_errors(source_text: &str, errors: Vec<OxcDiagnostic>) {
for error in errors {
let error = error.with_source_code(source_text.to_string());
println!("{error:?}");
Expand All @@ -75,10 +72,9 @@ fn print_errors(source_text: &str, errors: Vec<oxc_diagnostics::Error>) {
// 1 │ debugger;
// · ─────────
// ╰────
#[derive(Debug, Error, Diagnostic)]
#[error("`debugger` statement is not allowed")]
#[diagnostic(severity(warning))]
struct NoDebugger(#[label] pub Span);
fn no_debugger(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::new("`debugger` statement is not allowed").with_labels([span0.into()])
}

// This prints:
//
Expand All @@ -88,7 +84,8 @@ struct NoDebugger(#[label] pub Span);
// · ─┬
// · ╰── Empty object binding pattern
// ╰────
#[derive(Debug, Error, Diagnostic)]
#[error("empty destructuring pattern is not allowed")]
#[diagnostic(severity(warning))]
struct NoEmptyPattern(&'static str, #[label("Empty {0} binding pattern")] pub Span);
fn no_empty_pattern(s0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::new("empty destructuring pattern is not allowed").with_labels([
LabeledSpan::new_with_span(Some(format!("Empty {s0} binding pattern")), span1),
])
}
6 changes: 5 additions & 1 deletion crates/oxc_linter/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,11 @@ impl Runtime {
.parse();

if !ret.errors.is_empty() {
return ret.errors.into_iter().map(|err| Message::new(err, None)).collect();
return ret
.errors
.into_iter()
.map(|err| Message::new(Error::from(err), None))
.collect();
};

let program = allocator.alloc(ret.program);
Expand Down
6 changes: 2 additions & 4 deletions crates/oxc_parser/src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn asi(&mut self) -> Result<()> {
if !self.can_insert_semicolon() {
let span = Span::new(self.prev_token_end, self.cur_token().start);
return Err(diagnostics::auto_semicolon_insertion(span).into());
return Err(diagnostics::auto_semicolon_insertion(span));
}
if self.at(Kind::Semicolon) {
self.advance(Kind::Semicolon);
Expand All @@ -178,9 +178,7 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn expect_without_advance(&mut self, kind: Kind) -> Result<()> {
if !self.at(kind) {
let range = self.cur_token().span();
return Err(
diagnostics::expect_token(kind.to_str(), self.cur_kind().to_str(), range).into()
);
return Err(diagnostics::expect_token(kind.to_str(), self.cur_kind().to_str(), range));
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_parser/src/js/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ impl<'a> ParserImpl<'a> {
let paren_span = self.end_span(span);

if expressions.is_empty() {
return Err(diagnostics::empty_parenthesized_expression(paren_span).into());
return Err(diagnostics::empty_parenthesized_expression(paren_span));
}

// ParenthesizedExpression is from acorn --preserveParens
Expand Down
8 changes: 4 additions & 4 deletions crates/oxc_parser/src/js/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for SimpleAssignmentTarget<'a> {
let span = expr.span;
match expr.unbox().expression {
Expression::ObjectExpression(_) | Expression::ArrayExpression(_) => {
Err(diagnostics::invalid_assignment(span).into())
Err(diagnostics::invalid_assignment(span))
}
expr => SimpleAssignmentTarget::cover(expr, p),
}
Expand All @@ -59,7 +59,7 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for SimpleAssignmentTarget<'a> {
Expression::TSInstantiationExpression(expr) => {
Ok(SimpleAssignmentTarget::TSInstantiationExpression(expr))
}
expr => Err(diagnostics::invalid_assignment(expr.span()).into()),
expr => Err(diagnostics::invalid_assignment(expr.span())),
}
}
}
Expand Down Expand Up @@ -87,7 +87,7 @@ impl<'a> CoverGrammar<'a, ArrayExpression<'a>> for ArrayAssignmentTarget<'a> {
p.error(diagnostics::binding_rest_element_trailing_comma(span));
}
} else {
return Err(diagnostics::spread_last_element(elem.span).into());
return Err(diagnostics::spread_last_element(elem.span));
}
}
ArrayExpressionElement::Elision(_) => elements.push(None),
Expand Down Expand Up @@ -143,7 +143,7 @@ impl<'a> CoverGrammar<'a, ObjectExpression<'a>> for ObjectAssignmentTarget<'a> {
target: AssignmentTarget::cover(spread.unbox().argument, p)?,
});
} else {
return Err(diagnostics::spread_last_element(spread.span).into());
return Err(diagnostics::spread_last_element(spread.span));
}
}
}
Expand Down
24 changes: 9 additions & 15 deletions crates/oxc_parser/src/js/list.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use oxc_allocator::Vec;
use oxc_ast::ast::*;
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::{self, Error},
Result,
};
use oxc_span::{Atom, CompactStr, GetSpan, Span};
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic, Result};
use oxc_span::{Atom, GetSpan, Span};
use rustc_hash::FxHashMap;

use crate::{
Expand All @@ -15,14 +11,12 @@ use crate::{
ParserImpl,
};

#[derive(Debug, Error, Diagnostic)]
#[error("Identifier `{0}` has already been declared")]
#[diagnostic()]
struct Redeclaration(
pub CompactStr,
#[label("`{0}` has already been declared here")] pub Span,
#[label("It can not be redeclared here")] pub Span,
);
pub fn redeclaration(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::new(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),
])
}

/// ObjectExpression.properties
pub struct ObjectExpressionProperties<'a> {
Expand Down Expand Up @@ -321,7 +315,7 @@ impl<'a> SeparatedList<'a> for AssertEntries<'a> {
};

if let Some(old_span) = self.keys.get(&key.as_atom()) {
p.error(Redeclaration(key.as_atom().into_compact_str(), *old_span, key.span()));
p.error(redeclaration(key.as_atom().as_str(), *old_span, key.span()));
} else {
self.keys.insert(key.as_atom(), key.span());
}
Expand Down
4 changes: 1 addition & 3 deletions crates/oxc_parser/src/jsx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,7 @@ impl<'a> ParserImpl<'a> {
self.ctx = Context::default().and_await(ctx.has_await());
let expr = self.parse_expression();
if let Ok(Expression::SequenceExpression(seq)) = &expr {
return Err(
diagnostics::jsx_expressions_may_not_use_the_comma_operator(seq.span).into()
);
return Err(diagnostics::jsx_expressions_may_not_use_the_comma_operator(seq.span));
}
self.ctx = ctx;
expr
Expand Down
8 changes: 4 additions & 4 deletions crates/oxc_parser/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use std::collections::VecDeque;

use oxc_allocator::Allocator;
use oxc_ast::ast::RegExpFlags;
use oxc_diagnostics::Error;
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{SourceType, Span};

use self::{
Expand Down Expand Up @@ -80,7 +80,7 @@ pub struct Lexer<'a> {

token: Token,

pub(crate) errors: Vec<Error>,
pub(crate) errors: Vec<OxcDiagnostic>,

lookahead: VecDeque<Lookahead<'a>>,

Expand Down Expand Up @@ -223,8 +223,8 @@ impl<'a> Lexer<'a> {
}

// ---------- Private Methods ---------- //
fn error<T: Into<Error>>(&mut self, error: T) {
self.errors.push(error.into());
fn error(&mut self, error: OxcDiagnostic) {
self.errors.push(error);
}

/// Get the length offset from the source, in UTF-8 bytes
Expand Down

0 comments on commit 0cf90e8

Please sign in to comment.