summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-09-12 02:55:57 +0200
committerGitHub <noreply@github.com>2023-09-12 00:55:57 +0000
commit82c28640658df400e5bed2e208912247b1e83d0f (patch)
treedf8e55c5c311ab5306818761ff5efccb1b33fb1c
parent950e0e9cd65bd634d59fe60d5a0cb8651958c7fb (diff)
refactor: strongly typed TSC ops (#20466)
Removes usage of `serde_json::Value` in several ops used in TSC, in favor of using strongly typed structs. This will unblock more changes in https://github.com/denoland/deno/pull/20462.
-rw-r--r--cli/build.rs78
-rw-r--r--cli/lsp/tsc.rs28
-rw-r--r--cli/tsc/mod.rs34
3 files changed, 83 insertions, 57 deletions
diff --git a/cli/build.rs b/cli/build.rs
index edefd3c49..dd8f78020 100644
--- a/cli/build.rs
+++ b/cli/build.rs
@@ -16,8 +16,7 @@ mod ts {
use deno_core::OpState;
use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES;
use serde::Deserialize;
- use serde_json::json;
- use serde_json::Value;
+ use serde::Serialize;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
@@ -28,17 +27,31 @@ mod ts {
specifier: String,
}
- #[op]
- fn op_build_info(state: &mut OpState) -> Value {
- let build_specifier = "asset:///bootstrap.ts";
+ #[derive(Debug, Serialize)]
+ #[serde(rename_all = "camelCase")]
+ struct BuildInfoResponse {
+ build_specifier: String,
+ libs: Vec<String>,
+ node_built_in_module_names: Vec<String>,
+ }
- let node_built_in_module_names = SUPPORTED_BUILTIN_NODE_MODULES.to_vec();
- let build_libs = state.borrow::<Vec<&str>>();
- json!({
- "buildSpecifier": build_specifier,
- "libs": build_libs,
- "nodeBuiltInModuleNames": node_built_in_module_names,
- })
+ #[op]
+ fn op_build_info<'s>(state: &mut OpState) -> BuildInfoResponse {
+ let build_specifier = "asset:///bootstrap.ts".to_string();
+ let build_libs = state
+ .borrow::<Vec<&str>>()
+ .iter()
+ .map(|s| s.to_string())
+ .collect();
+ let node_built_in_module_names = SUPPORTED_BUILTIN_NODE_MODULES
+ .iter()
+ .map(|s| s.to_string())
+ .collect();
+ BuildInfoResponse {
+ build_specifier,
+ libs: build_libs,
+ node_built_in_module_names,
+ }
}
#[op]
@@ -46,18 +59,35 @@ mod ts {
false
}
+ #[derive(Debug, Deserialize, Serialize)]
+ #[serde(rename_all = "camelCase")]
+ struct ScriptVersionArgs {
+ specifier: String,
+ }
+
#[op]
fn op_script_version(
_state: &mut OpState,
- _args: Value,
+ _args: ScriptVersionArgs,
) -> Result<Option<String>, AnyError> {
Ok(Some("1".to_string()))
}
+ #[derive(Debug, Serialize)]
+ #[serde(rename_all = "camelCase")]
+ struct LoadResponse {
+ data: String,
+ version: String,
+ script_kind: i32,
+ }
+
#[op]
// using the same op that is used in `tsc.rs` for loading modules and reading
// files, but a slightly different implementation at build time.
- fn op_load(state: &mut OpState, args: LoadArgs) -> Result<Value, AnyError> {
+ fn op_load(
+ state: &mut OpState,
+ args: LoadArgs,
+ ) -> Result<LoadResponse, AnyError> {
let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>();
let path_dts = state.borrow::<PathBuf>();
let re_asset = lazy_regex::regex!(r"asset:/{3}lib\.(\S+)\.d\.ts");
@@ -65,12 +95,12 @@ mod ts {
// we need a basic file to send to tsc to warm it up.
if args.specifier == build_specifier {
- Ok(json!({
- "data": r#"Deno.writeTextFile("hello.txt", "hello deno!");"#,
- "version": "1",
+ Ok(LoadResponse {
+ data: r#"Deno.writeTextFile("hello.txt", "hello deno!");"#.to_string(),
+ version: "1".to_string(),
// this corresponds to `ts.ScriptKind.TypeScript`
- "scriptKind": 3
- }))
+ script_kind: 3,
+ })
// specifiers come across as `asset:///lib.{lib_name}.d.ts` and we need to
// parse out just the name so we can lookup the asset.
} else if let Some(caps) = re_asset.captures(&args.specifier) {
@@ -84,12 +114,12 @@ mod ts {
path_dts.join(format!("lib.{lib}.d.ts"))
};
let data = std::fs::read_to_string(path)?;
- Ok(json!({
- "data": data,
- "version": "1",
+ Ok(LoadResponse {
+ data,
+ version: "1".to_string(),
// this corresponds to `ts.ScriptKind.TypeScript`
- "scriptKind": 3
- }))
+ script_kind: 3,
+ })
} else {
Err(custom_error(
"InvalidSpecifier",
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index ae4a00e6a..425856d52 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -3252,26 +3252,29 @@ fn op_is_node_file(state: &mut OpState, path: String) -> bool {
}
}
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct LoadResponse {
+ data: Arc<str>,
+ script_kind: i32,
+ version: Option<String>,
+}
+
#[op]
fn op_load(
state: &mut OpState,
args: SpecifierArgs,
-) -> Result<Value, AnyError> {
+) -> Result<Option<LoadResponse>, AnyError> {
let state = state.borrow_mut::<State>();
let mark = state.performance.mark("op_load", Some(&args));
let specifier = state.normalize_specifier(args.specifier)?;
let asset_or_document = state.get_asset_or_document(&specifier);
state.performance.measure(mark);
- Ok(match asset_or_document {
- Some(doc) => {
- json!({
- "data": doc.text(),
- "scriptKind": crate::tsc::as_ts_script_kind(doc.media_type()),
- "version": state.script_version(&specifier),
- })
- }
- None => Value::Null,
- })
+ Ok(asset_or_document.map(|doc| LoadResponse {
+ data: doc.text(),
+ script_kind: crate::tsc::as_ts_script_kind(doc.media_type()),
+ version: state.script_version(&specifier),
+ }))
}
#[op]
@@ -3312,10 +3315,9 @@ fn op_resolve(
}
#[op]
-fn op_respond(state: &mut OpState, args: Response) -> bool {
+fn op_respond(state: &mut OpState, args: Response) {
let state = state.borrow_mut::<State>();
state.response = Some(args);
- true
}
#[op]
diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs
index 22f9d3290..af4c67c0d 100644
--- a/cli/tsc/mod.rs
+++ b/cli/tsc/mod.rs
@@ -733,12 +733,9 @@ struct RespondArgs {
}
#[op]
-fn op_respond(state: &mut OpState, args: Value) -> Result<Value, AnyError> {
+fn op_respond(state: &mut OpState, args: RespondArgs) {
let state = state.borrow_mut::<State>();
- let v: RespondArgs = serde_json::from_value(args)
- .context("Error converting the result for \"op_respond\".")?;
- state.maybe_response = Some(v);
- Ok(json!(true))
+ state.maybe_response = Some(args);
}
/// Execute a request on the supplied snapshot, returning a response which
@@ -1160,21 +1157,18 @@ mod tests {
#[tokio::test]
async fn test_respond() {
let mut state = setup(None, None, None).await;
- let actual = op_respond::call(
- &mut state,
- json!({
- "diagnostics": [
- {
- "messageText": "Unknown compiler option 'invalid'.",
- "category": 1,
- "code": 5023
- }
- ],
- "stats": [["a", 12]]
- }),
- )
- .expect("should have invoked op");
- assert_eq!(actual, json!(true));
+ let args = serde_json::from_value(json!({
+ "diagnostics": [
+ {
+ "messageText": "Unknown compiler option 'invalid'.",
+ "category": 1,
+ "code": 5023
+ }
+ ],
+ "stats": [["a", 12]]
+ }))
+ .unwrap();
+ op_respond::call(&mut state, args);
let state = state.borrow::<State>();
assert_eq!(
state.maybe_response,