summaryrefslogtreecommitdiff
path: root/cli/tsc_config.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tsc_config.rs')
-rw-r--r--cli/tsc_config.rs107
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,
+ }),
);
}