mirror of
https://github.com/denoland/deno.git
synced 2025-01-04 21:38:47 -05:00
refactor(ast): Change AST parsing error to return struct with message and location (#10911)
* Remove unused check js emit option. * Improve parse error. * Format.
This commit is contained in:
parent
9d706d71b5
commit
1a92c39b77
3 changed files with 20 additions and 86 deletions
91
cli/ast.rs
91
cli/ast.rs
|
@ -11,23 +11,16 @@ use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use swc_common::chain;
|
use swc_common::chain;
|
||||||
use swc_common::comments::Comment;
|
use swc_common::comments::Comment;
|
||||||
use swc_common::comments::CommentKind;
|
use swc_common::comments::CommentKind;
|
||||||
use swc_common::comments::SingleThreadedComments;
|
use swc_common::comments::SingleThreadedComments;
|
||||||
use swc_common::errors::Diagnostic;
|
|
||||||
use swc_common::errors::DiagnosticBuilder;
|
|
||||||
use swc_common::errors::Emitter;
|
|
||||||
use swc_common::errors::Handler;
|
|
||||||
use swc_common::errors::HandlerFlags;
|
|
||||||
use swc_common::FileName;
|
use swc_common::FileName;
|
||||||
use swc_common::Globals;
|
use swc_common::Globals;
|
||||||
use swc_common::Loc;
|
|
||||||
use swc_common::SourceFile;
|
use swc_common::SourceFile;
|
||||||
use swc_common::SourceMap;
|
use swc_common::SourceMap;
|
||||||
use swc_common::Span;
|
use swc_common::Span;
|
||||||
|
use swc_common::Spanned;
|
||||||
use swc_ecmascript::ast::Module;
|
use swc_ecmascript::ast::Module;
|
||||||
use swc_ecmascript::ast::Program;
|
use swc_ecmascript::ast::Program;
|
||||||
use swc_ecmascript::codegen::text_writer::JsWriter;
|
use swc_ecmascript::codegen::text_writer::JsWriter;
|
||||||
|
@ -89,57 +82,18 @@ impl std::fmt::Display for Location {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A buffer for collecting diagnostic messages from the AST parser.
|
/// A diagnostic from the AST parser.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct DiagnosticBuffer(Vec<String>);
|
pub struct Diagnostic {
|
||||||
|
pub location: Location,
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
impl Error for DiagnosticBuffer {}
|
impl Error for Diagnostic {}
|
||||||
|
|
||||||
impl fmt::Display for DiagnosticBuffer {
|
impl fmt::Display for Diagnostic {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let s = self.0.join(",");
|
write!(f, "{} at {}", self.message, self.location)
|
||||||
f.pad(&s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DiagnosticBuffer {
|
|
||||||
pub fn from_error_buffer<F>(error_buffer: ErrorBuffer, get_loc: F) -> Self
|
|
||||||
where
|
|
||||||
F: Fn(Span) -> Loc,
|
|
||||||
{
|
|
||||||
let s = error_buffer.0.lock().unwrap().clone();
|
|
||||||
let diagnostics = s
|
|
||||||
.iter()
|
|
||||||
.map(|d| {
|
|
||||||
let mut msg = d.message();
|
|
||||||
|
|
||||||
if let Some(span) = d.span.primary_span() {
|
|
||||||
let loc = get_loc(span);
|
|
||||||
let file_name = match &loc.file.name {
|
|
||||||
FileName::Custom(n) => n,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
msg = format!(
|
|
||||||
"{} at {}:{}:{}",
|
|
||||||
msg, file_name, loc.line, loc.col_display
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg
|
|
||||||
})
|
|
||||||
.collect::<Vec<String>>();
|
|
||||||
|
|
||||||
Self(diagnostics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A buffer for collecting errors from the AST parser.
|
|
||||||
#[derive(Debug, Clone, Default)]
|
|
||||||
pub struct ErrorBuffer(Arc<Mutex<Vec<Diagnostic>>>);
|
|
||||||
|
|
||||||
impl Emitter for ErrorBuffer {
|
|
||||||
fn emit(&mut self, db: &DiagnosticBuilder) {
|
|
||||||
self.0.lock().unwrap().push((**db).clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,9 +146,6 @@ pub enum ImportsNotUsedAsValues {
|
||||||
/// Options which can be adjusted when transpiling a module.
|
/// Options which can be adjusted when transpiling a module.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EmitOptions {
|
pub struct EmitOptions {
|
||||||
/// Indicate if JavaScript is being checked/transformed as well, or if it is
|
|
||||||
/// only TypeScript.
|
|
||||||
pub check_js: bool,
|
|
||||||
/// When emitting a legacy decorator, also emit experimental decorator meta
|
/// When emitting a legacy decorator, also emit experimental decorator meta
|
||||||
/// data. Defaults to `false`.
|
/// data. Defaults to `false`.
|
||||||
pub emit_metadata: bool,
|
pub emit_metadata: bool,
|
||||||
|
@ -221,7 +172,6 @@ pub struct EmitOptions {
|
||||||
impl Default for EmitOptions {
|
impl Default for EmitOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
EmitOptions {
|
EmitOptions {
|
||||||
check_js: false,
|
|
||||||
emit_metadata: false,
|
emit_metadata: false,
|
||||||
imports_not_used_as_values: ImportsNotUsedAsValues::Remove,
|
imports_not_used_as_values: ImportsNotUsedAsValues::Remove,
|
||||||
inline_source_map: true,
|
inline_source_map: true,
|
||||||
|
@ -244,7 +194,6 @@ impl From<config_file::TsConfig> for EmitOptions {
|
||||||
_ => ImportsNotUsedAsValues::Remove,
|
_ => ImportsNotUsedAsValues::Remove,
|
||||||
};
|
};
|
||||||
EmitOptions {
|
EmitOptions {
|
||||||
check_js: options.check_js,
|
|
||||||
emit_metadata: options.emit_decorator_metadata,
|
emit_metadata: options.emit_decorator_metadata,
|
||||||
imports_not_used_as_values,
|
imports_not_used_as_values,
|
||||||
inline_source_map: options.inline_source_map,
|
inline_source_map: options.inline_source_map,
|
||||||
|
@ -424,31 +373,17 @@ pub fn parse_with_source_map(
|
||||||
FileName::Custom(specifier.to_string()),
|
FileName::Custom(specifier.to_string()),
|
||||||
source.to_string(),
|
source.to_string(),
|
||||||
);
|
);
|
||||||
let error_buffer = ErrorBuffer::default();
|
|
||||||
let syntax = get_syntax(media_type);
|
let syntax = get_syntax(media_type);
|
||||||
let input = StringInput::from(&*source_file);
|
let input = StringInput::from(&*source_file);
|
||||||
let comments = SingleThreadedComments::default();
|
let comments = SingleThreadedComments::default();
|
||||||
|
|
||||||
let handler = Handler::with_emitter_and_flags(
|
|
||||||
Box::new(error_buffer.clone()),
|
|
||||||
HandlerFlags {
|
|
||||||
can_emit_warnings: true,
|
|
||||||
dont_buffer_diagnostics: true,
|
|
||||||
..HandlerFlags::default()
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let lexer = Lexer::new(syntax, TARGET, input, Some(&comments));
|
let lexer = Lexer::new(syntax, TARGET, input, Some(&comments));
|
||||||
let mut parser = swc_ecmascript::parser::Parser::new_from(lexer);
|
let mut parser = swc_ecmascript::parser::Parser::new_from(lexer);
|
||||||
|
|
||||||
let sm = &source_map;
|
let sm = &source_map;
|
||||||
let module = parser.parse_module().map_err(move |err| {
|
let module = parser.parse_module().map_err(move |err| Diagnostic {
|
||||||
let mut diagnostic = err.into_diagnostic(&handler);
|
location: sm.lookup_char_pos(err.span().lo).into(),
|
||||||
diagnostic.emit();
|
message: err.into_kind().msg().to_string(),
|
||||||
|
|
||||||
DiagnosticBuffer::from_error_buffer(error_buffer, |span| {
|
|
||||||
sm.lookup_char_pos(span.lo)
|
|
||||||
})
|
|
||||||
})?;
|
})?;
|
||||||
let leading_comments =
|
let leading_comments =
|
||||||
comments.with_leading(module.span.lo, |comments| comments.to_vec());
|
comments.with_leading(module.span.lo, |comments| comments.to_vec());
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
//! Diagnostics are compile-time type errors, whereas JsErrors are runtime
|
//! Diagnostics are compile-time type errors, whereas JsErrors are runtime
|
||||||
//! exceptions.
|
//! exceptions.
|
||||||
|
|
||||||
use crate::ast::DiagnosticBuffer;
|
use crate::ast::Diagnostic;
|
||||||
use crate::import_map::ImportMapError;
|
use crate::import_map::ImportMapError;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ fn get_import_map_error_class(_: &ImportMapError) -> &'static str {
|
||||||
"URIError"
|
"URIError"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_diagnostic_class(_: &DiagnosticBuffer) -> &'static str {
|
fn get_diagnostic_class(_: &Diagnostic) -> &'static str {
|
||||||
"SyntaxError"
|
"SyntaxError"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,10 +27,7 @@ pub(crate) fn get_error_class_name(e: &AnyError) -> &'static str {
|
||||||
e.downcast_ref::<ImportMapError>()
|
e.downcast_ref::<ImportMapError>()
|
||||||
.map(get_import_map_error_class)
|
.map(get_import_map_error_class)
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| e.downcast_ref::<Diagnostic>().map(get_diagnostic_class))
|
||||||
e.downcast_ref::<DiagnosticBuffer>()
|
|
||||||
.map(get_diagnostic_class)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!(
|
panic!(
|
||||||
"Error '{}' contains boxed error of unknown type:{}",
|
"Error '{}' contains boxed error of unknown type:{}",
|
||||||
|
|
|
@ -1102,10 +1102,11 @@ impl Graph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BundleType::None => {
|
BundleType::None => {
|
||||||
|
let check_js = config.get_check_js();
|
||||||
let emit_options: ast::EmitOptions = config.into();
|
let emit_options: ast::EmitOptions = config.into();
|
||||||
for (_, module_slot) in self.modules.iter_mut() {
|
for (_, module_slot) in self.modules.iter_mut() {
|
||||||
if let ModuleSlot::Module(module) = module_slot {
|
if let ModuleSlot::Module(module) = module_slot {
|
||||||
if !(emit_options.check_js
|
if !(check_js
|
||||||
|| module.media_type == MediaType::Jsx
|
|| module.media_type == MediaType::Jsx
|
||||||
|| module.media_type == MediaType::Tsx
|
|| module.media_type == MediaType::Tsx
|
||||||
|| module.media_type == MediaType::TypeScript)
|
|| module.media_type == MediaType::TypeScript)
|
||||||
|
@ -1669,6 +1670,7 @@ impl Graph {
|
||||||
.merge_tsconfig_from_config_file(options.maybe_config_file.as_ref())?;
|
.merge_tsconfig_from_config_file(options.maybe_config_file.as_ref())?;
|
||||||
|
|
||||||
let config = ts_config.as_bytes();
|
let config = ts_config.as_bytes();
|
||||||
|
let check_js = ts_config.get_check_js();
|
||||||
let emit_options: ast::EmitOptions = ts_config.into();
|
let emit_options: ast::EmitOptions = ts_config.into();
|
||||||
let mut emit_count = 0_u32;
|
let mut emit_count = 0_u32;
|
||||||
for (_, module_slot) in self.modules.iter_mut() {
|
for (_, module_slot) in self.modules.iter_mut() {
|
||||||
|
@ -1683,7 +1685,7 @@ impl Graph {
|
||||||
}
|
}
|
||||||
// if we don't have check_js enabled, we won't touch non TypeScript or JSX
|
// if we don't have check_js enabled, we won't touch non TypeScript or JSX
|
||||||
// modules
|
// modules
|
||||||
if !(emit_options.check_js
|
if !(check_js
|
||||||
|| module.media_type == MediaType::Jsx
|
|| module.media_type == MediaType::Jsx
|
||||||
|| module.media_type == MediaType::Tsx
|
|| module.media_type == MediaType::Tsx
|
||||||
|| module.media_type == MediaType::TypeScript)
|
|| module.media_type == MediaType::TypeScript)
|
||||||
|
|
Loading…
Reference in a new issue