0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

fix: SWC lexer settings and silent errors (#5752)

This commit changes how error occurring in SWC are handled.
Changed lexer settings to properly handle TS decorators.
Changed output of SWC error to annotate with position in file.
This commit is contained in:
Bartek Iwańczuk 2020-05-22 19:23:35 +02:00 committed by GitHub
parent e191c70989
commit 960f9ccb2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 86 additions and 26 deletions

View file

@ -2,6 +2,7 @@ cli/compilers/wasm_wrap.js
cli/tests/error_syntax.js
cli/tests/badly_formatted.js
cli/tests/top_level_for_await.js
cli/tests/swc_syntax_error.ts
std/**/testdata
std/**/vendor
std/node_modules

View file

@ -188,6 +188,7 @@ impl ModuleGraphLoader {
};
let (import_descs, ref_descs) = analyze_dependencies_and_references(
&specifier,
&source_code,
self.analyze_dynamic_imports,
)?;
@ -402,6 +403,7 @@ impl ModuleGraphLoader {
}
let (import_descs, ref_descs) = analyze_dependencies_and_references(
&module_specifier.to_string(),
&source_code,
self.analyze_dynamic_imports,
)?;

View file

@ -29,45 +29,63 @@ use std::sync::RwLock;
#[derive(Clone, Debug)]
pub struct SwcDiagnosticBuffer {
pub diagnostics: Vec<Diagnostic>,
pub diagnostics: Vec<String>,
}
impl Error for SwcDiagnosticBuffer {}
impl fmt::Display for SwcDiagnosticBuffer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let msg = self
.diagnostics
.iter()
.map(|d| d.message())
.collect::<Vec<String>>()
.join(",");
let msg = self.diagnostics.join(",");
f.pad(&msg)
}
}
impl SwcDiagnosticBuffer {
pub fn from_swc_error(
error_buffer: SwcErrorBuffer,
parser: &AstParser,
) -> Self {
let s = error_buffer.0.read().unwrap().clone();
let diagnostics = s
.iter()
.map(|d| {
let mut msg = d.message();
if let Some(span) = d.span.primary_span() {
let location = parser.get_span_location(span);
let filename = match &location.file.name {
FileName::Custom(n) => n,
_ => unreachable!(),
};
msg = format!(
"{} at {}:{}:{}",
msg, filename, location.line, location.col_display
);
}
msg
})
.collect::<Vec<String>>();
Self { diagnostics }
}
}
#[derive(Clone)]
pub struct SwcErrorBuffer(Arc<RwLock<SwcDiagnosticBuffer>>);
pub struct SwcErrorBuffer(Arc<RwLock<Vec<Diagnostic>>>);
impl SwcErrorBuffer {
pub fn default() -> Self {
Self(Arc::new(RwLock::new(SwcDiagnosticBuffer {
diagnostics: vec![],
})))
Self(Arc::new(RwLock::new(vec![])))
}
}
impl Emitter for SwcErrorBuffer {
fn emit(&mut self, db: &DiagnosticBuilder) {
self.0.write().unwrap().diagnostics.push((**db).clone());
}
}
impl From<SwcErrorBuffer> for SwcDiagnosticBuffer {
fn from(buf: SwcErrorBuffer) -> Self {
let s = buf.0.read().unwrap();
s.clone()
self.0.write().unwrap().push((**db).clone());
}
}
@ -125,8 +143,10 @@ impl AstParser {
handler: &self.handler,
};
// TODO(bartlomieju): lexer should be configurable by the caller
let mut ts_config = TsConfig::default();
ts_config.dynamic_import = true;
ts_config.decorators = true;
let syntax = Syntax::Typescript(ts_config);
let lexer = Lexer::new(
@ -143,8 +163,8 @@ impl AstParser {
parser
.parse_module()
.map_err(move |mut err: DiagnosticBuilder| {
err.cancel();
SwcDiagnosticBuffer::from(buffered_err)
err.emit();
SwcDiagnosticBuffer::from_swc_error(buffered_err, self)
});
callback(parse_result)
@ -411,6 +431,7 @@ pub struct TsReferenceDescriptor {
}
pub fn analyze_dependencies_and_references(
file_name: &str,
source_code: &str,
analyze_dynamic_imports: bool,
) -> Result<
@ -418,7 +439,7 @@ pub fn analyze_dependencies_and_references(
SwcDiagnosticBuffer,
> {
let parser = AstParser::new();
parser.parse_module("root.ts", source_code, |parse_result| {
parser.parse_module(file_name, source_code, |parse_result| {
let module = parse_result?;
let mut collector = NewDependencyVisitor {
dependencies: vec![],
@ -526,7 +547,8 @@ console.log(qat.qat);
"#;
let (imports, references) =
analyze_dependencies_and_references(source, true).expect("Failed to parse");
analyze_dependencies_and_references("some/file.ts", source, true)
.expect("Failed to parse");
assert_eq!(
imports,

View file

@ -1575,7 +1575,17 @@ itest!(ts_type_imports {
args: "run --reload ts_type_imports.ts",
output: "ts_type_imports.ts.out",
exit_code: 1,
http_server: true,
});
itest!(ts_decorators {
args: "run --reload -c tsconfig.decorators.json ts_decorators.ts",
output: "ts_decorators.ts.out",
});
itest!(swc_syntax_error {
args: "run --reload swc_syntax_error.ts",
output: "swc_syntax_error.ts.out",
exit_code: 1,
});
itest!(types {

View file

@ -0,0 +1,3 @@
for await (const req of s) {
let something:
}

View file

@ -0,0 +1 @@
error: Unexpected token Some(RBrace) at [WILDCARD]syntax_error.ts:3:0

View file

@ -0,0 +1,14 @@
/* eslint-disable */
function Decorate() {
return function (constructor: any): any {
return class extends constructor {
protected someField: string = "asdf";
};
};
}
@Decorate()
class SomeClass {}
console.log(new SomeClass());

View file

@ -0,0 +1,2 @@
Compile [WILDCARD]
SomeClass { someField: "asdf" }

View file

@ -0,0 +1,5 @@
{
"compilerOptions": {
"experimentalDecorators": true
}
}

View file

@ -466,7 +466,6 @@ impl TsCompiler {
let module_graph = module_graph_loader.get_graph();
let module_graph_json =
serde_json::to_value(module_graph).expect("Failed to serialize data");
let target = match target {
TargetLib::Main => "main",
TargetLib::Worker => "worker",

View file

@ -61,7 +61,8 @@ def eslint():
"eslint")
# Find all *directories* in the main repo that contain .ts/.js files.
source_files = get_sources(root_path, [
"*.js", "*.ts", ":!:std/**/testdata/*", ":!:std/**/node_modules/*",
"*.js", "*.ts", ":!:cli/tests/swc_syntax_error.ts",
":!:std/**/testdata/*", ":!:std/**/node_modules/*",
":!:cli/compilers/wasm_wrap.js", ":!:cli/tests/error_syntax.js"
])
if source_files: