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:
parent
e191c70989
commit
960f9ccb2e
11 changed files with 86 additions and 26 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
)?;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
3
cli/tests/swc_syntax_error.ts
Normal file
3
cli/tests/swc_syntax_error.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
for await (const req of s) {
|
||||
let something:
|
||||
}
|
1
cli/tests/swc_syntax_error.ts.out
Normal file
1
cli/tests/swc_syntax_error.ts.out
Normal file
|
@ -0,0 +1 @@
|
|||
error: Unexpected token Some(RBrace) at [WILDCARD]syntax_error.ts:3:0
|
14
cli/tests/ts_decorators.ts
Normal file
14
cli/tests/ts_decorators.ts
Normal 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());
|
2
cli/tests/ts_decorators.ts.out
Normal file
2
cli/tests/ts_decorators.ts.out
Normal file
|
@ -0,0 +1,2 @@
|
|||
Compile [WILDCARD]
|
||||
SomeClass { someField: "asdf" }
|
5
cli/tests/tsconfig.decorators.json
Normal file
5
cli/tests/tsconfig.decorators.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Reference in a new issue