Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsonk committed Aug 21, 2020
1 parent 0c5d6e8 commit 3f04a42
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 96 deletions.
114 changes: 66 additions & 48 deletions compiler/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ struct EmptyHandler;

impl swc_ecmascript::codegen::Handlers for EmptyHandler {}

/// A buffer for collecting diagnostic messages from the AST parser.
#[derive(Debug)]
pub struct DiagnosticBuffer(Vec<String>);

Expand Down Expand Up @@ -170,6 +171,39 @@ fn get_syntax(media_type: MediaType) -> Syntax {
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DependencyDescriptor {
/// A flag indicating if the import is dynamic or not.
pub is_dynamic: bool,
/// A flag indicating that the import is a `type` only type of import.
pub is_type: bool,
/// Any leading comments associated with the dependency. This is used for
/// further processing of supported pragma that impact the dependency.
pub leading_comments: Vec<Comment>,
/// The location of the import/export statement.
pub location: Location,
/// The text specifier associated with the import/export statement.
pub specifier: String,
}

impl Default for DependencyDescriptor {
fn default() -> Self {
DependencyDescriptor {
is_dynamic: false,
is_type: false,
leading_comments: Vec::new(),
location: Location::default(),
specifier: String::default(),
}
}
}

struct DependencyCollector<'a> {
comments: &'a SingleThreadedComments,
pub items: Vec<DependencyDescriptor>,
source_map: &'a SourceMap,
}

#[derive(Debug, Clone)]
pub struct EmitTranspileOptions {
/// When emitting a legacy decorator, also emit experimental decorator meta
Expand Down Expand Up @@ -221,7 +255,7 @@ impl fmt::Debug for ParsedModule {

impl ParsedModule {
/// Identifies all syntactical dependencies of a module (e.g. `import` and
/// `export` statements).
/// `export` statements) and returns them as a vector of descriptors.
pub fn get_dependencies(&self) -> Vec<DependencyDescriptor> {
let mut collector = DependencyCollector {
comments: &self.comments,
Expand Down Expand Up @@ -315,6 +349,13 @@ impl ParsedModule {

/// For a given specifier, source, and media type, parse the source of the
/// module and return a representation which can be further processed.
///
/// # Arguments
///
/// - `specifier` - The module specifier for the module.
/// - `source` - The source code for the module.
/// - `media_type` - The media type for the module.
///
pub fn parse(
specifier: &ModuleSpecifier,
source: &str,
Expand Down Expand Up @@ -362,33 +403,6 @@ pub fn parse(
})
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DependencyDescriptor {
pub is_dynamic: bool,
pub is_type: bool,
pub leading_comments: Vec<Comment>,
pub location: Location,
pub specifier: String,
}

impl Default for DependencyDescriptor {
fn default() -> Self {
DependencyDescriptor {
is_dynamic: false,
is_type: false,
leading_comments: Vec::new(),
location: Location::default(),
specifier: String::default(),
}
}
}

struct DependencyCollector<'a> {
comments: &'a SingleThreadedComments,
pub items: Vec<DependencyDescriptor>,
source_map: &'a SourceMap,
}

impl<'a> Visit for DependencyCollector<'a> {
fn visit_import_decl(
&mut self,
Expand Down Expand Up @@ -540,7 +554,7 @@ mod tests {
location: Location {
filename: "https://deno.land/x/mod.js".to_owned(),
col: 0,
line: 0,
line: 1,
},
specifier: "./test.ts".to_owned()
},
Expand All @@ -550,32 +564,36 @@ mod tests {
leading_comments: Vec::new(),
location: Location {
filename: "https://deno.land/x/mod.js".to_owned(),
col: 18,
line: 1,
col: 22,
line: 2,
},
specifier: "./foo.ts".to_owned()
}
]
);
}

// #[test]
// fn test_parsed_module_get_leading_comments() {
// let specifier =
// ModuleSpecifier::resolve_url_or_path("https://deno.land/x/mod.ts")
// .unwrap();
// let source = r#"// this is the first comment
// // this is the second comment
// import * as bar from "./test.ts";"#;
// let parsed_module = parse(&specifier, source, MediaType::TypeScript)
// .expect("could not parse module");
// let dependencies = parsed_module.get_dependencies();
// let first = dependencies.first().unwrap();
// let actual = parsed_module.get_leading_comments(&first.span);
// assert_eq!(actual[0].text, " this is the first comment".to_string());
// assert_eq!(actual[1].text, " this is the second comment".to_string());
// assert_eq!(actual.len(), 2);
// }
#[test]
fn test_parsed_module_get_leading_comments() {
let specifier =
ModuleSpecifier::resolve_url_or_path("https://deno.land/x/mod.ts")
.unwrap();
let source = r#"// this is the first comment
// this is the second comment
import * as bar from "./test.ts";"#;
let parsed_module = parse(&specifier, source, MediaType::TypeScript)
.expect("could not parse module");
let dependencies = parsed_module.get_dependencies();
let leading_comments: Vec<&str> = dependencies[0]
.leading_comments
.iter()
.map(|c| c.text.as_str())
.collect();
assert_eq!(
leading_comments,
vec![" this is the first comment", " this is the second comment"]
);
}

#[test]
fn test_transpile() {
Expand Down
43 changes: 2 additions & 41 deletions compiler/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ use crate::msg::IgnoredCompilerOptions;
use crate::ops;
use crate::ops::compiler_op;
use crate::ops::json_op;
use crate::CompileOptions;
use crate::Result;
use crate::TranspileOptions;

use deno_core::js_check;
use deno_core::CoreIsolate;
Expand Down Expand Up @@ -48,47 +50,6 @@ pub struct CompilerState {
pub written_files: Vec<EmittedFile>,
}

/// A structure which provides options to `CompilerIsolate::compile()`
#[derive(Default)]
pub struct CompileOptions<'a> {
/// If `true` then files will be transpiled in a way that they can be combined
/// together in a bundle. This will not actually perform the bundling, but
/// just provide individual files back that could be.
pub bundle: bool,
/// If `true` then debug logging will be output from the isolate.
pub debug: bool,
/// A flag to indicate that the compilation should be incremental, and only
/// changed sources will be emitted based on information supplied in the
/// `maybe_build_info` argument.
pub incremental: bool,
/// A vector of libs to be used when type checking the code. For example:
///
/// ```rust
/// let libs = vec!["deno.ns"];
/// ```
///
pub lib: Vec<&'a str>,
/// A string of configuration data that augments the the default configuration
/// passed to the TypeScript compiler. This is typically the contents of a
/// user supplied `tsconfig.json`.
pub maybe_config: Option<String>,
}

/// A structure which provides options to `CompilerIsolate::compile()`
#[derive(Default)]
pub struct TranspileOptions {
/// If `true` then files will be transpiled in a way that they can be combined
/// together in a bundle. This will not actually perform the bundling, but
/// just provide individual files back that could be.
pub bundle: bool,
/// If `true` then debug logging will be output from the isolate.
pub debug: bool,
/// A string of configuration data that augments the the default configuration
/// passed to the TypeScript compiler. This is typically the contents of a
/// user supplied `tsconfig.json`.
pub maybe_config: Option<String>,
}

#[derive(Debug, Clone, PartialEq)]
/// The result of a compilation.
pub struct CompilerEmit {
Expand Down
43 changes: 41 additions & 2 deletions compiler/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ use std::result;

pub use crate::bundler::bundle;
pub use crate::compiler::create_compiler_snapshot;
pub use crate::compiler::CompileOptions;
pub use crate::compiler::CompilerIsolate;
pub use crate::compiler::Sources;
pub use crate::compiler::TranspileOptions;
pub use crate::import_map::ImportMap;
pub use crate::import_map::ImportMapError;
pub use crate::module_graph::CacheType;
Expand All @@ -56,6 +54,47 @@ pub use crate::msg::MediaType;

type Result<V> = result::Result<V, ErrBox>;

/// A structure which provides options when compiling modules.
#[derive(Default)]
pub struct CompileOptions<'a> {
/// If `true` then files will be transpiled in a way that they can be combined
/// together in a bundle. This will not actually perform the bundling, but
/// just provide individual files back that could be.
pub bundle: bool,
/// If `true` then debug logging will be output from the isolate.
pub debug: bool,
/// A flag to indicate that the compilation should be incremental, and only
/// changed sources will be emitted based on information supplied in the
/// `maybe_build_info` argument.
pub incremental: bool,
/// A vector of libs to be used when type checking the code. For example:
///
/// ```rust
/// let libs = vec!["deno.ns"];
/// ```
///
pub lib: Vec<&'a str>,
/// A string of configuration data that augments the the default configuration
/// passed to the TypeScript compiler. This is typically the contents of a
/// user supplied `tsconfig.json`.
pub maybe_config: Option<String>,
}

/// A structure which provides options when transpiling modules.
#[derive(Default)]
pub struct TranspileOptions {
/// If `true` then files will be transpiled in a way that they can be combined
/// together in a bundle. This will not actually perform the bundling, but
/// just provide individual files back that could be.
pub bundle: bool,
/// If `true` then debug logging will be output from the isolate.
pub debug: bool,
/// A string of configuration data that augments the the default configuration
/// passed to the TypeScript compiler. This is typically the contents of a
/// user supplied `tsconfig.json`.
pub maybe_config: Option<String>,
}

#[cfg(test)]
pub mod tests {
use super::*;
Expand Down
39 changes: 34 additions & 5 deletions compiler/module_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ use crate::ast::parse;
use crate::ast::EmitTranspileOptions;
use crate::ast::Location;
use crate::ast::ParsedModule;
use crate::compiler::CompileOptions;
use crate::compiler::CompilerIsolate;
use crate::compiler::TranspileOptions;
use crate::config::json_merge;
use crate::config::parse_config;
use crate::import_map::ImportMap;
use crate::msg::CompilerStats;
use crate::msg::EmittedFile;
use crate::msg::IgnoredCompilerOptions;
use crate::msg::MediaType;
use crate::CompileOptions;
use crate::Result;
use crate::TranspileOptions;

use deno_core::ModuleSpecifier;
use deno_core::Snapshot;
Expand Down Expand Up @@ -546,9 +546,7 @@ struct TranspileTsOptions {
pub struct Graph {
build_info: HashMap<CacheType, String>,
handler: Rc<RefCell<dyn SpecifierHandler>>,
/// A hash map of a representation of all the modules within the graph, with
/// a key of the module specifier of that module.
pub modules: HashMap<ModuleSpecifier, Module>,
modules: HashMap<ModuleSpecifier, Module>,
roots: Vec<ModuleSpecifier>,
}

Expand All @@ -562,6 +560,20 @@ impl Graph {
}
}

/// Compile (type check and transform) the graph, updating any emitted modules
/// and build info with the specifier handler. The result contains any
/// performance stats from the compiler and optionally any user provided
/// configuration compiler options that were ignored.
///
/// # Arguments
///
/// - `options` - A structure of compiler options which effect how the modules
/// in the graph are compiled.
/// - `maybe_snapshot_data` - A snapshot of a TypeScript compiler isolate,
/// which will be used to compile the modules. Currently, this is required
/// but maybe optional in the future. If not present, the result will
/// error.
///
pub fn compile(
self,
options: CompileOptions,
Expand All @@ -587,6 +599,7 @@ impl Graph {
maybe_build_info,
options,
)?;
drop(p);
let mut p = provider.borrow_mut();
p.update(emit.written_files, &cache_type)?;
p.flush(&cache_type)?;
Expand Down Expand Up @@ -667,6 +680,20 @@ impl Graph {
sources
}

/// Transpile (only transform) the graph, updating any emitted modules
/// with the specifier handler. The result contains any performance stats
/// from the compiler and optionally any user provided configuration compiler
/// options that were ignored.
///
/// # Arguments
///
/// - `options` - A structure of options which impact how the code is
/// transpiled.
/// - `maybe_shanpshot_data` - If provided, it is expected that the data is
/// a snapshot of the TypeScript compiler, which will in turn be used to
/// perform the transpilation. If none, then the transpilation will be
/// performed by swc.
///
pub fn transpile(
mut self,
options: TranspileOptions,
Expand Down Expand Up @@ -753,6 +780,8 @@ impl Graph {
}
self.flush(&cache_type)?;

// TODO @kitsonk - provide some useful stats

Ok((CompilerStats { items: vec![] }, maybe_ignored_options))
}
}
Expand Down

0 comments on commit 3f04a42

Please sign in to comment.