diff options
Diffstat (limited to 'cli/tsc_config.rs')
-rw-r--r-- | cli/tsc_config.rs | 107 |
1 files changed, 100 insertions, 7 deletions
diff --git a/cli/tsc_config.rs b/cli/tsc_config.rs index f748c7a5c..b52ed2abd 100644 --- a/cli/tsc_config.rs +++ b/cli/tsc_config.rs @@ -5,19 +5,40 @@ use deno_core::serde_json; use deno_core::serde_json::Value; use jsonc_parser::JsonValue; use serde::Deserialize; +use serde::Serialize; +use serde::Serializer; use std::collections::HashMap; use std::fmt; +use std::path::Path; +use std::path::PathBuf; use std::str::FromStr; -#[derive(Clone, Debug, PartialEq)] -pub struct IgnoredCompilerOptions(pub Vec<String>); +/// The transpile options that are significant out of a user provided tsconfig +/// file, that we want to deserialize out of the final config for a transpile. +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TranspileConfigOptions { + pub check_js: bool, + pub emit_decorator_metadata: bool, + pub jsx: String, + pub jsx_factory: String, + pub jsx_fragment_factory: String, +} + +/// A structure that represents a set of options that were ignored and the +/// path those options came from. +#[derive(Debug, Clone, PartialEq)] +pub struct IgnoredCompilerOptions { + pub items: Vec<String>, + pub path: PathBuf, +} impl fmt::Display for IgnoredCompilerOptions { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut codes = self.0.clone(); + let mut codes = self.items.clone(); codes.sort(); - write!(f, "{}", codes.join(", ")) + write!(f, "Unsupported compiler options in \"{}\".\n The following options were ignored:\n {}", self.path.to_string_lossy(), codes.join(", ")) } } @@ -149,6 +170,7 @@ pub fn parse_raw_config(config_text: &str) -> Result<Value, AnyError> { /// The result also contains any options that were ignored. pub fn parse_config( config_text: &str, + path: &Path, ) -> Result<(Value, Option<IgnoredCompilerOptions>), AnyError> { assert!(!config_text.is_empty()); let jsonc = jsonc_parser::parse_to_value(config_text)?.unwrap(); @@ -167,7 +189,10 @@ pub fn parse_config( } let options_value = serde_json::to_value(compiler_options)?; let ignored_options = if !items.is_empty() { - Some(IgnoredCompilerOptions(items)) + Some(IgnoredCompilerOptions { + items, + path: path.to_path_buf(), + }) } else { None }; @@ -175,6 +200,70 @@ pub fn parse_config( Ok((options_value, ignored_options)) } +/// A structure for managing the configuration of TypeScript +#[derive(Debug, Clone)] +pub struct TsConfig(Value); + +impl TsConfig { + /// Create a new `TsConfig` with the base being the `value` supplied. + pub fn new(value: Value) -> Self { + TsConfig(value) + } + + /// Take an optional string representing a user provided TypeScript config file + /// which was passed in via the `--config` compiler option and merge it with + /// the configuration. Returning the result which optionally contains any + /// compiler options that were ignored. + /// + /// When there are options ignored out of the file, a warning will be written + /// to stderr regarding the options that were ignored. + pub fn merge_user_config( + &mut self, + maybe_path: Option<String>, + ) -> Result<Option<IgnoredCompilerOptions>, AnyError> { + if let Some(path) = maybe_path { + let cwd = std::env::current_dir()?; + let config_file = cwd.join(path); + let config_path = config_file.canonicalize().map_err(|_| { + std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!( + "Could not find the config file: {}", + config_file.to_string_lossy() + ), + ) + })?; + let config_text = std::fs::read_to_string(config_path.clone())?; + let (value, maybe_ignored_options) = + parse_config(&config_text, &config_path)?; + json_merge(&mut self.0, &value); + + Ok(maybe_ignored_options) + } else { + Ok(None) + } + } + + /// Return the current configuration as a `TranspileConfigOptions` structure. + pub fn as_transpile_config( + &self, + ) -> Result<TranspileConfigOptions, AnyError> { + let options: TranspileConfigOptions = + serde_json::from_value(self.0.clone())?; + Ok(options) + } +} + +impl Serialize for TsConfig { + /// Serializes inner hash map which is ordered by the key + fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> + where + S: Serializer, + { + Serialize::serialize(&self.0, serializer) + } +} + #[cfg(test)] mod tests { use super::*; @@ -210,15 +299,19 @@ mod tests { "strict": true } }"#; + let config_path = PathBuf::from("/deno/tsconfig.json"); let (options_value, ignored) = - parse_config(config_text).expect("error parsing"); + parse_config(config_text, &config_path).expect("error parsing"); assert!(options_value.is_object()); let options = options_value.as_object().unwrap(); assert!(options.contains_key("strict")); assert_eq!(options.len(), 1); assert_eq!( ignored, - Some(IgnoredCompilerOptions(vec!["build".to_string()])), + Some(IgnoredCompilerOptions { + items: vec!["build".to_string()], + path: config_path, + }), ); } |