diff options
Diffstat (limited to 'cli/diagnostics.rs')
-rw-r--r-- | cli/diagnostics.rs | 219 |
1 files changed, 22 insertions, 197 deletions
diff --git a/cli/diagnostics.rs b/cli/diagnostics.rs index aca86913e..a21ba654f 100644 --- a/cli/diagnostics.rs +++ b/cli/diagnostics.rs @@ -7,48 +7,17 @@ use crate::colors; use crate::fmt_errors::format_stack; -use serde_json::value::Value; +use serde::Deserialize; +use serde::Deserializer; use std::error::Error; use std::fmt; -#[derive(Debug, PartialEq, Clone)] +#[derive(Clone, Debug, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] pub struct Diagnostic { pub items: Vec<DiagnosticItem>, } -impl Diagnostic { - /// Take a JSON value and attempt to map it to a - pub fn from_json_value(v: &serde_json::Value) -> Option<Self> { - if !v.is_object() { - return None; - } - let obj = v.as_object().unwrap(); - - let mut items = Vec::<DiagnosticItem>::new(); - let items_v = &obj["items"]; - if items_v.is_array() { - let items_values = items_v.as_array().unwrap(); - - for item_v in items_values { - items.push(DiagnosticItem::from_json_value(item_v)?); - } - } - - Some(Self { items }) - } - - pub fn from_emit_result(json_str: &str) -> Option<Self> { - let v = serde_json::from_str::<serde_json::Value>(json_str) - .expect("Error decoding JSON string."); - let diagnostics_o = v.get("diagnostics"); - if let Some(diagnostics_v) = diagnostics_o { - return Self::from_json_value(diagnostics_v); - } - - None - } -} - impl fmt::Display for Diagnostic { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut i = 0; @@ -74,7 +43,8 @@ impl Error for Diagnostic { } } -#[derive(Debug, PartialEq, Clone)] +#[derive(Clone, Debug, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] pub struct DiagnosticItem { /// The top level message relating to the diagnostic item. pub message: String, @@ -114,71 +84,6 @@ pub struct DiagnosticItem { pub end_column: Option<i64>, } -impl DiagnosticItem { - pub fn from_json_value(v: &serde_json::Value) -> Option<Self> { - let obj = v.as_object().unwrap(); - - // required attributes - let message = obj - .get("message") - .and_then(|v| v.as_str().map(String::from))?; - let category = DiagnosticCategory::from( - obj.get("category").and_then(Value::as_i64).unwrap(), - ); - let code = obj.get("code").and_then(Value::as_i64).unwrap(); - - // optional attributes - let source_line = obj - .get("sourceLine") - .and_then(|v| v.as_str().map(String::from)); - let script_resource_name = obj - .get("scriptResourceName") - .and_then(|v| v.as_str().map(String::from)); - let line_number = obj.get("lineNumber").and_then(Value::as_i64); - let start_position = obj.get("startPosition").and_then(Value::as_i64); - let end_position = obj.get("endPosition").and_then(Value::as_i64); - let start_column = obj.get("startColumn").and_then(Value::as_i64); - let end_column = obj.get("endColumn").and_then(Value::as_i64); - - let message_chain_v = obj.get("messageChain"); - let message_chain = match message_chain_v { - Some(v) => DiagnosticMessageChain::from_json_value(v), - _ => None, - }; - - let related_information_v = obj.get("relatedInformation"); - let related_information = match related_information_v { - Some(r) => { - let mut related_information = Vec::<DiagnosticItem>::new(); - let related_info_values = r.as_array().unwrap(); - - for related_info_v in related_info_values { - related_information - .push(DiagnosticItem::from_json_value(related_info_v)?); - } - - Some(related_information) - } - _ => None, - }; - - Some(Self { - message, - message_chain, - related_information, - code, - source_line, - script_resource_name, - line_number, - start_position, - end_position, - category, - start_column, - end_column, - }) - } -} - fn format_category_and_code( category: &DiagnosticCategory, code: i64, @@ -303,7 +208,8 @@ impl fmt::Display for DiagnosticItem { } } -#[derive(Debug, PartialEq, Clone)] +#[derive(Clone, Debug, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] pub struct DiagnosticMessageChain { pub message: String, pub code: i64, @@ -312,54 +218,6 @@ pub struct DiagnosticMessageChain { } impl DiagnosticMessageChain { - fn from_value(v: &serde_json::Value) -> Self { - let obj = v.as_object().unwrap(); - let message = obj - .get("message") - .and_then(|v| v.as_str().map(String::from)) - .unwrap(); - let code = obj.get("code").and_then(Value::as_i64).unwrap(); - let category = DiagnosticCategory::from( - obj.get("category").and_then(Value::as_i64).unwrap(), - ); - - let next_v = obj.get("next"); - let next = match next_v { - Some(n) => DiagnosticMessageChain::from_next_array(n), - _ => None, - }; - - Self { - message, - code, - category, - next, - } - } - - fn from_next_array(v: &serde_json::Value) -> Option<Vec<Self>> { - if !v.is_array() { - return None; - } - - let vec = v - .as_array() - .unwrap() - .iter() - .map(|item| Self::from_value(&item)) - .collect::<Vec<Self>>(); - - Some(vec) - } - - pub fn from_json_value(v: &serde_json::Value) -> Option<Self> { - if !v.is_object() { - return None; - } - - Some(Self::from_value(v)) - } - pub fn format_message(&self, level: usize) -> String { let mut s = String::new(); @@ -377,7 +235,7 @@ impl DiagnosticMessageChain { } } -#[derive(Debug, PartialEq, Clone)] +#[derive(Clone, Debug, PartialEq)] pub enum DiagnosticCategory { Log, // 0 Debug, // 1 @@ -387,6 +245,16 @@ pub enum DiagnosticCategory { Suggestion, // 5 } +impl<'de> Deserialize<'de> for DiagnosticCategory { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let s: i64 = Deserialize::deserialize(deserializer)?; + Ok(DiagnosticCategory::from(s)) + } +} + impl From<i64> for DiagnosticCategory { fn from(value: i64) -> Self { match value { @@ -496,7 +364,7 @@ mod tests { #[test] fn from_json() { - let v = serde_json::from_str::<serde_json::Value>( + let r = serde_json::from_str::<Diagnostic>( &r#"{ "items": [ { @@ -526,8 +394,7 @@ mod tests { ] }"#, ).unwrap(); - let r = Diagnostic::from_json_value(&v); - let expected = Some( + let expected = Diagnostic { items: vec![ DiagnosticItem { @@ -559,53 +426,11 @@ mod tests { end_column: Some(1) } ] - } - ); + }; assert_eq!(expected, r); } #[test] - fn from_emit_result() { - let r = Diagnostic::from_emit_result( - &r#"{ - "emitSkipped": false, - "diagnostics": { - "items": [ - { - "message": "foo bar", - "code": 9999, - "category": 3 - } - ] - } - }"#, - ); - let expected = Some(Diagnostic { - items: vec![DiagnosticItem { - message: "foo bar".to_string(), - message_chain: None, - related_information: None, - source_line: None, - line_number: None, - script_resource_name: None, - start_position: None, - end_position: None, - category: DiagnosticCategory::Error, - code: 9999, - start_column: None, - end_column: None, - }], - }); - assert_eq!(expected, r); - } - - #[test] - fn from_emit_result_none() { - let r = &r#"{"emitSkipped":false}"#; - assert!(Diagnostic::from_emit_result(r).is_none()); - } - - #[test] fn diagnostic_to_string1() { let d = diagnostic1(); let expected = "error TS2322: Type \'(o: T) => { v: any; f: (x: B) => string; }[]\' is not assignable to type \'(r: B) => Value<B>[]\'.\n Types of parameters \'o\' and \'r\' are incompatible.\n Type \'B\' is not assignable to type \'T\'.\n values: o => [\n ~~~~~~\n at deno/tests/complex_diagnostics.ts:19:3\n\n The expected type comes from property \'values\' which is declared here on type \'SettingsInterface<B>\'\n values?: (r: T) => Array<Value<T>>;\n ~~~~~~\n at deno/tests/complex_diagnostics.ts:7:3"; |