Skip to content

Commit

Permalink
fix: parsing of JSX and TSX in SWC (#5870)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartlomieju authored May 26, 2020
1 parent 9090023 commit f462f7f
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 17 deletions.
14 changes: 10 additions & 4 deletions cli/doc/parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::file_fetcher::map_file_extension;
use crate::op_error::OpError;
use crate::swc_common::comments::CommentKind;
use crate::swc_common::Span;
Expand All @@ -15,6 +16,7 @@ use deno_core::ModuleSpecifier;
use futures::Future;
use regex::Regex;
use std::collections::HashMap;
use std::path::PathBuf;
use std::pin::Pin;

use super::namespace::NamespaceDef;
Expand Down Expand Up @@ -57,9 +59,12 @@ impl DocParser {
file_name: &str,
source_code: &str,
) -> Result<ModuleDoc, SwcDiagnosticBuffer> {
self
.ast_parser
.parse_module(file_name, source_code, |parse_result| {
let media_type = map_file_extension(&PathBuf::from(file_name));
self.ast_parser.parse_module(
file_name,
media_type,
source_code,
|parse_result| {
let module = parse_result?;
let doc_entries =
self.get_doc_nodes_for_module_body(module.body.clone());
Expand All @@ -69,7 +74,8 @@ impl DocParser {
reexports,
};
Ok(module_doc)
})
},
)
}

pub async fn parse(&self, file_name: &str) -> Result<Vec<DocNode>, ErrBox> {
Expand Down
21 changes: 21 additions & 0 deletions cli/module_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ impl ModuleGraphLoader {

let (import_descs, ref_descs) = analyze_dependencies_and_references(
&specifier,
map_file_extension(&PathBuf::from(&specifier)),
&source_code,
self.analyze_dynamic_imports,
)?;
Expand Down Expand Up @@ -409,6 +410,7 @@ impl ModuleGraphLoader {

let (import_descs, ref_descs) = analyze_dependencies_and_references(
&module_specifier.to_string(),
source_file.media_type,
&source_code,
self.analyze_dynamic_imports,
)?;
Expand Down Expand Up @@ -786,4 +788,23 @@ mod tests {
);
drop(http_server_guard);
}

#[tokio::test]
async fn source_graph_different_langs() {
let http_server_guard = crate::test_util::http_server();

// ModuleGraphLoader was mistakenly parsing this file as TSX
// https://github.com/denoland/deno/issues/5867

let module_specifier = ModuleSpecifier::resolve_url_or_path(
"http://localhost:4545/cli/tests/ts_with_generic.ts",
)
.unwrap();

build_graph(&module_specifier)
.await
.expect("Failed to build graph");

drop(http_server_guard);
}
}
65 changes: 52 additions & 13 deletions cli/swc_util.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::msg::MediaType;
use crate::swc_common;
use crate::swc_common::comments::CommentKind;
use crate::swc_common::comments::Comments;
Expand All @@ -13,19 +14,42 @@ use crate::swc_common::SourceMap;
use crate::swc_common::Span;
use crate::swc_ecma_ast;
use crate::swc_ecma_parser::lexer::Lexer;
use crate::swc_ecma_parser::EsConfig;
use crate::swc_ecma_parser::JscTarget;
use crate::swc_ecma_parser::Parser;
use crate::swc_ecma_parser::Session;
use crate::swc_ecma_parser::SourceFileInput;
use crate::swc_ecma_parser::Syntax;
use crate::swc_ecma_parser::TsConfig;
use swc_ecma_visit::Node;
use swc_ecma_visit::Visit;

use std::error::Error;
use std::fmt;
use std::sync::Arc;
use std::sync::RwLock;
use swc_ecma_visit::Node;
use swc_ecma_visit::Visit;

fn get_default_es_config() -> EsConfig {
let mut config = EsConfig::default();
config.num_sep = true;
config.class_private_props = false;
config.class_private_methods = false;
config.class_props = false;
config.export_default_from = true;
config.export_namespace_from = true;
config.dynamic_import = true;
config.nullish_coalescing = true;
config.optional_chaining = true;
config.import_meta = true;
config.top_level_await = true;
config
}

fn get_default_ts_config() -> TsConfig {
let mut ts_config = TsConfig::default();
ts_config.dynamic_import = true;
ts_config.decorators = true;
ts_config
}

#[derive(Clone, Debug)]
pub struct SwcDiagnosticBuffer {
Expand Down Expand Up @@ -126,6 +150,7 @@ impl AstParser {
pub fn parse_module<F, R>(
&self,
file_name: &str,
media_type: MediaType,
source_code: &str,
callback: F,
) -> R
Expand All @@ -143,12 +168,21 @@ 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;
ts_config.tsx = true;
let syntax = Syntax::Typescript(ts_config);
let syntax = match media_type {
MediaType::JavaScript => Syntax::Es(get_default_es_config()),
MediaType::JSX => {
let mut config = get_default_es_config();
config.jsx = true;
Syntax::Es(config)
}
MediaType::TypeScript => Syntax::Typescript(get_default_ts_config()),
MediaType::TSX => {
let mut config = get_default_ts_config();
config.tsx = true;
Syntax::Typescript(config)
}
_ => Syntax::Es(get_default_es_config()),
};

let lexer = Lexer::new(
session,
Expand Down Expand Up @@ -433,14 +467,15 @@ pub struct TsReferenceDescriptor {

pub fn analyze_dependencies_and_references(
file_name: &str,
media_type: MediaType,
source_code: &str,
analyze_dynamic_imports: bool,
) -> Result<
(Vec<ImportDescriptor>, Vec<TsReferenceDescriptor>),
SwcDiagnosticBuffer,
> {
let parser = AstParser::new();
parser.parse_module(file_name, source_code, |parse_result| {
parser.parse_module(file_name, media_type, source_code, |parse_result| {
let module = parse_result?;
let mut collector = NewDependencyVisitor {
dependencies: vec![],
Expand Down Expand Up @@ -547,9 +582,13 @@ console.log(fizz);
console.log(qat.qat);
"#;

let (imports, references) =
analyze_dependencies_and_references("some/file.ts", source, true)
.expect("Failed to parse");
let (imports, references) = analyze_dependencies_and_references(
"some/file.ts",
MediaType::TypeScript,
source,
true,
)
.expect("Failed to parse");

assert_eq!(
imports,
Expand Down
3 changes: 3 additions & 0 deletions cli/tests/ts_with_generic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* eslint-disable */

const foo = { delete<S>() {} };

0 comments on commit f462f7f

Please sign in to comment.