mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
refactor: factor out AstParser from DocParser (#4923)
This commit is contained in:
parent
8e9ab9e33e
commit
1f52d180c0
7 changed files with 204 additions and 153 deletions
|
@ -118,7 +118,7 @@ pub fn get_doc_for_class_decl(
|
|||
Constructor(ctor) => {
|
||||
let ctor_js_doc = doc_parser.js_doc_for_span(ctor.span());
|
||||
let constructor_name =
|
||||
prop_name_to_string(&doc_parser.source_map, &ctor.key);
|
||||
prop_name_to_string(&doc_parser.ast_parser.source_map, &ctor.key);
|
||||
|
||||
let mut params = vec![];
|
||||
|
||||
|
@ -146,17 +146,16 @@ pub fn get_doc_for_class_decl(
|
|||
accessibility: ctor.accessibility,
|
||||
name: constructor_name,
|
||||
params,
|
||||
location: doc_parser
|
||||
.source_map
|
||||
.lookup_char_pos(ctor.span.lo())
|
||||
.into(),
|
||||
location: doc_parser.ast_parser.get_span_location(ctor.span).into(),
|
||||
};
|
||||
constructors.push(constructor_def);
|
||||
}
|
||||
Method(class_method) => {
|
||||
let method_js_doc = doc_parser.js_doc_for_span(class_method.span());
|
||||
let method_name =
|
||||
prop_name_to_string(&doc_parser.source_map, &class_method.key);
|
||||
let method_name = prop_name_to_string(
|
||||
&doc_parser.ast_parser.source_map,
|
||||
&class_method.key,
|
||||
);
|
||||
let fn_def = function_to_function_def(&class_method.function);
|
||||
let method_def = ClassMethodDef {
|
||||
js_doc: method_js_doc,
|
||||
|
@ -168,8 +167,8 @@ pub fn get_doc_for_class_decl(
|
|||
kind: class_method.kind,
|
||||
function_def: fn_def,
|
||||
location: doc_parser
|
||||
.source_map
|
||||
.lookup_char_pos(class_method.span.lo())
|
||||
.ast_parser
|
||||
.get_span_location(class_method.span)
|
||||
.into(),
|
||||
};
|
||||
methods.push(method_def);
|
||||
|
@ -198,8 +197,8 @@ pub fn get_doc_for_class_decl(
|
|||
accessibility: class_prop.accessibility,
|
||||
name: prop_name,
|
||||
location: doc_parser
|
||||
.source_map
|
||||
.lookup_char_pos(class_prop.span.lo())
|
||||
.ast_parser
|
||||
.get_span_location(class_prop.span)
|
||||
.into(),
|
||||
};
|
||||
properties.push(prop_def);
|
||||
|
|
|
@ -114,8 +114,8 @@ pub fn get_doc_for_ts_interface_decl(
|
|||
name,
|
||||
js_doc: method_js_doc,
|
||||
location: doc_parser
|
||||
.source_map
|
||||
.lookup_char_pos(ts_method_sig.span.lo())
|
||||
.ast_parser
|
||||
.get_span_location(ts_method_sig.span)
|
||||
.into(),
|
||||
optional: ts_method_sig.optional,
|
||||
params,
|
||||
|
@ -151,8 +151,8 @@ pub fn get_doc_for_ts_interface_decl(
|
|||
name,
|
||||
js_doc: prop_js_doc,
|
||||
location: doc_parser
|
||||
.source_map
|
||||
.lookup_char_pos(ts_prop_sig.span.lo())
|
||||
.ast_parser
|
||||
.get_span_location(ts_prop_sig.span)
|
||||
.into(),
|
||||
params,
|
||||
ts_type,
|
||||
|
@ -183,8 +183,8 @@ pub fn get_doc_for_ts_interface_decl(
|
|||
let call_sig_def = InterfaceCallSignatureDef {
|
||||
js_doc: call_sig_js_doc,
|
||||
location: doc_parser
|
||||
.source_map
|
||||
.lookup_char_pos(ts_call_sig.span.lo())
|
||||
.ast_parser
|
||||
.get_span_location(ts_call_sig.span)
|
||||
.into(),
|
||||
params,
|
||||
ts_type,
|
||||
|
|
|
@ -14,10 +14,7 @@ pub fn get_doc_node_for_export_decl(
|
|||
use crate::swc_ecma_ast::Decl;
|
||||
|
||||
let js_doc = doc_parser.js_doc_for_span(export_span);
|
||||
let location = doc_parser
|
||||
.source_map
|
||||
.lookup_char_pos(export_span.lo())
|
||||
.into();
|
||||
let location = doc_parser.ast_parser.get_span_location(export_span).into();
|
||||
|
||||
match &export_decl.decl {
|
||||
Decl::Class(class_decl) => {
|
||||
|
|
|
@ -17,8 +17,8 @@ pub fn get_doc_for_ts_namespace_decl(
|
|||
) -> DocNode {
|
||||
let js_doc = doc_parser.js_doc_for_span(ts_namespace_decl.span);
|
||||
let location = doc_parser
|
||||
.source_map
|
||||
.lookup_char_pos(ts_namespace_decl.span.lo())
|
||||
.ast_parser
|
||||
.get_span_location(ts_namespace_decl.span)
|
||||
.into();
|
||||
let namespace_name = ts_namespace_decl.id.sym.to_string();
|
||||
|
||||
|
|
|
@ -1,39 +1,20 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::op_error::OpError;
|
||||
use crate::swc_common;
|
||||
use crate::swc_common::comments::CommentKind;
|
||||
use crate::swc_common::comments::Comments;
|
||||
use crate::swc_common::errors::Diagnostic;
|
||||
use crate::swc_common::errors::DiagnosticBuilder;
|
||||
use crate::swc_common::errors::Emitter;
|
||||
use crate::swc_common::errors::Handler;
|
||||
use crate::swc_common::errors::HandlerFlags;
|
||||
use crate::swc_common::FileName;
|
||||
use crate::swc_common::Globals;
|
||||
use crate::swc_common::SourceMap;
|
||||
use crate::swc_common::Span;
|
||||
use crate::swc_ecma_ast;
|
||||
use crate::swc_ecma_ast::Decl;
|
||||
use crate::swc_ecma_ast::ModuleDecl;
|
||||
use crate::swc_ecma_ast::Stmt;
|
||||
use crate::swc_ecma_parser::lexer::Lexer;
|
||||
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 crate::swc_util::AstParser;
|
||||
use crate::swc_util::SwcDiagnosticBuffer;
|
||||
|
||||
use deno_core::ErrBox;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use futures::Future;
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use super::namespace::NamespaceDef;
|
||||
use super::node;
|
||||
|
@ -42,50 +23,6 @@ use super::DocNode;
|
|||
use super::DocNodeKind;
|
||||
use super::Location;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SwcDiagnosticBuffer {
|
||||
pub diagnostics: Vec<Diagnostic>,
|
||||
}
|
||||
|
||||
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(",");
|
||||
|
||||
f.pad(&msg)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SwcErrorBuffer(Arc<RwLock<SwcDiagnosticBuffer>>);
|
||||
|
||||
impl SwcErrorBuffer {
|
||||
pub fn default() -> Self {
|
||||
Self(Arc::new(RwLock::new(SwcDiagnosticBuffer {
|
||||
diagnostics: 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()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DocFileLoader {
|
||||
fn resolve(
|
||||
&self,
|
||||
|
@ -102,34 +39,15 @@ pub trait DocFileLoader {
|
|||
}
|
||||
|
||||
pub struct DocParser {
|
||||
pub ast_parser: AstParser,
|
||||
pub loader: Box<dyn DocFileLoader>,
|
||||
pub buffered_error: SwcErrorBuffer,
|
||||
pub source_map: Arc<SourceMap>,
|
||||
pub handler: Handler,
|
||||
pub comments: Comments,
|
||||
pub globals: Globals,
|
||||
}
|
||||
|
||||
impl DocParser {
|
||||
pub fn new(loader: Box<dyn DocFileLoader>) -> Self {
|
||||
let buffered_error = SwcErrorBuffer::default();
|
||||
|
||||
let handler = Handler::with_emitter_and_flags(
|
||||
Box::new(buffered_error.clone()),
|
||||
HandlerFlags {
|
||||
dont_buffer_diagnostics: true,
|
||||
can_emit_warnings: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
DocParser {
|
||||
loader,
|
||||
buffered_error,
|
||||
source_map: Arc::new(SourceMap::default()),
|
||||
handler,
|
||||
comments: Comments::default(),
|
||||
globals: Globals::new(),
|
||||
ast_parser: AstParser::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,47 +56,19 @@ impl DocParser {
|
|||
file_name: &str,
|
||||
source_code: &str,
|
||||
) -> Result<ModuleDoc, SwcDiagnosticBuffer> {
|
||||
swc_common::GLOBALS.set(&self.globals, || {
|
||||
let swc_source_file = self.source_map.new_source_file(
|
||||
FileName::Custom(file_name.to_string()),
|
||||
source_code.to_string(),
|
||||
);
|
||||
|
||||
let buffered_err = self.buffered_error.clone();
|
||||
let session = Session {
|
||||
handler: &self.handler,
|
||||
};
|
||||
|
||||
let mut ts_config = TsConfig::default();
|
||||
ts_config.dynamic_import = true;
|
||||
let syntax = Syntax::Typescript(ts_config);
|
||||
|
||||
let lexer = Lexer::new(
|
||||
session,
|
||||
syntax,
|
||||
JscTarget::Es2019,
|
||||
SourceFileInput::from(&*swc_source_file),
|
||||
Some(&self.comments),
|
||||
);
|
||||
|
||||
let mut parser = Parser::new_from(session, lexer);
|
||||
|
||||
let module =
|
||||
parser
|
||||
.parse_module()
|
||||
.map_err(move |mut err: DiagnosticBuilder| {
|
||||
err.cancel();
|
||||
SwcDiagnosticBuffer::from(buffered_err)
|
||||
})?;
|
||||
|
||||
let doc_entries = self.get_doc_nodes_for_module_body(module.body.clone());
|
||||
let reexports = self.get_reexports_for_module_body(module.body);
|
||||
let module_doc = ModuleDoc {
|
||||
exports: doc_entries,
|
||||
reexports,
|
||||
};
|
||||
Ok(module_doc)
|
||||
})
|
||||
self
|
||||
.ast_parser
|
||||
.parse_module(file_name, source_code, |parse_result| {
|
||||
let module = parse_result?;
|
||||
let doc_entries =
|
||||
self.get_doc_nodes_for_module_body(module.body.clone());
|
||||
let reexports = self.get_reexports_for_module_body(module.body);
|
||||
let module_doc = ModuleDoc {
|
||||
exports: doc_entries,
|
||||
reexports,
|
||||
};
|
||||
Ok(module_doc)
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn parse(&self, file_name: &str) -> Result<Vec<DocNode>, ErrBox> {
|
||||
|
@ -323,7 +213,7 @@ impl DocParser {
|
|||
|
||||
fn details_for_span(&self, span: Span) -> (Option<String>, Location) {
|
||||
let js_doc = self.js_doc_for_span(span);
|
||||
let location = self.source_map.lookup_char_pos(span.lo()).into();
|
||||
let location = self.ast_parser.get_span_location(span).into();
|
||||
(js_doc, location)
|
||||
}
|
||||
|
||||
|
@ -567,13 +457,13 @@ impl DocParser {
|
|||
}
|
||||
|
||||
pub fn js_doc_for_span(&self, span: Span) -> Option<String> {
|
||||
let comments = self.comments.take_leading_comments(span.lo())?;
|
||||
let comments = self.ast_parser.get_span_comments(span);
|
||||
let js_doc_comment = comments.iter().find(|comment| {
|
||||
comment.kind == CommentKind::Block && comment.text.starts_with('*')
|
||||
})?;
|
||||
|
||||
let mut margin_pat = String::from("");
|
||||
if let Some(margin) = self.source_map.span_to_margin(span) {
|
||||
if let Some(margin) = self.ast_parser.source_map.span_to_margin(span) {
|
||||
for _ in 0..margin {
|
||||
margin_pat.push(' ');
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ pub mod signal;
|
|||
pub mod source_maps;
|
||||
mod startup_data;
|
||||
pub mod state;
|
||||
mod swc_util;
|
||||
mod test_runner;
|
||||
pub mod test_util;
|
||||
mod tokio_util;
|
||||
|
|
164
cli/swc_util.rs
Normal file
164
cli/swc_util.rs
Normal file
|
@ -0,0 +1,164 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
use crate::swc_common;
|
||||
use crate::swc_common::comments::Comments;
|
||||
use crate::swc_common::errors::Diagnostic;
|
||||
use crate::swc_common::errors::DiagnosticBuilder;
|
||||
use crate::swc_common::errors::Emitter;
|
||||
use crate::swc_common::errors::Handler;
|
||||
use crate::swc_common::errors::HandlerFlags;
|
||||
use crate::swc_common::FileName;
|
||||
use crate::swc_common::Globals;
|
||||
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::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 std::error::Error;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SwcDiagnosticBuffer {
|
||||
pub diagnostics: Vec<Diagnostic>,
|
||||
}
|
||||
|
||||
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(",");
|
||||
|
||||
f.pad(&msg)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SwcErrorBuffer(Arc<RwLock<SwcDiagnosticBuffer>>);
|
||||
|
||||
impl SwcErrorBuffer {
|
||||
pub fn default() -> Self {
|
||||
Self(Arc::new(RwLock::new(SwcDiagnosticBuffer {
|
||||
diagnostics: 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()
|
||||
}
|
||||
}
|
||||
|
||||
/// Low-level utility structure with common AST parsing functions.
|
||||
///
|
||||
/// Allows to build more complicated parser by providing a callback
|
||||
/// to `parse_module`.
|
||||
pub struct AstParser {
|
||||
pub buffered_error: SwcErrorBuffer,
|
||||
pub source_map: Arc<SourceMap>,
|
||||
pub handler: Handler,
|
||||
pub comments: Comments,
|
||||
pub globals: Globals,
|
||||
}
|
||||
|
||||
impl AstParser {
|
||||
pub fn new() -> Self {
|
||||
let buffered_error = SwcErrorBuffer::default();
|
||||
|
||||
let handler = Handler::with_emitter_and_flags(
|
||||
Box::new(buffered_error.clone()),
|
||||
HandlerFlags {
|
||||
dont_buffer_diagnostics: true,
|
||||
can_emit_warnings: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
AstParser {
|
||||
buffered_error,
|
||||
source_map: Arc::new(SourceMap::default()),
|
||||
handler,
|
||||
comments: Comments::default(),
|
||||
globals: Globals::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_module<F, R>(
|
||||
&self,
|
||||
file_name: &str,
|
||||
source_code: &str,
|
||||
callback: F,
|
||||
) -> R
|
||||
where
|
||||
F: FnOnce(Result<swc_ecma_ast::Module, SwcDiagnosticBuffer>) -> R,
|
||||
{
|
||||
swc_common::GLOBALS.set(&self.globals, || {
|
||||
let swc_source_file = self.source_map.new_source_file(
|
||||
FileName::Custom(file_name.to_string()),
|
||||
source_code.to_string(),
|
||||
);
|
||||
|
||||
let buffered_err = self.buffered_error.clone();
|
||||
let session = Session {
|
||||
handler: &self.handler,
|
||||
};
|
||||
|
||||
let mut ts_config = TsConfig::default();
|
||||
ts_config.dynamic_import = true;
|
||||
let syntax = Syntax::Typescript(ts_config);
|
||||
|
||||
let lexer = Lexer::new(
|
||||
session,
|
||||
syntax,
|
||||
JscTarget::Es2019,
|
||||
SourceFileInput::from(&*swc_source_file),
|
||||
Some(&self.comments),
|
||||
);
|
||||
|
||||
let mut parser = Parser::new_from(session, lexer);
|
||||
|
||||
let parse_result =
|
||||
parser
|
||||
.parse_module()
|
||||
.map_err(move |mut err: DiagnosticBuilder| {
|
||||
err.cancel();
|
||||
SwcDiagnosticBuffer::from(buffered_err)
|
||||
});
|
||||
|
||||
callback(parse_result)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_span_location(&self, span: Span) -> swc_common::Loc {
|
||||
self.source_map.lookup_char_pos(span.lo())
|
||||
}
|
||||
|
||||
pub fn get_span_comments(
|
||||
&self,
|
||||
span: Span,
|
||||
) -> Vec<swc_common::comments::Comment> {
|
||||
self
|
||||
.comments
|
||||
.take_leading_comments(span.lo())
|
||||
.unwrap_or_else(|| vec![])
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue