mirror of
https://github.com/denoland/deno.git
synced 2024-10-29 08:58:01 -04:00
reafactor(lsp): use generics with JSON values (#9587)
This commit is contained in:
parent
ae8874b4b2
commit
90e4c5dcde
2 changed files with 189 additions and 196 deletions
|
@ -227,14 +227,13 @@ impl Inner {
|
||||||
self.performance.measure(mark);
|
self.performance.measure(mark);
|
||||||
Ok(navigation_tree.clone())
|
Ok(navigation_tree.clone())
|
||||||
} else {
|
} else {
|
||||||
let res = self
|
let navigation_tree: tsc::NavigationTree = self
|
||||||
.ts_server
|
.ts_server
|
||||||
.request(
|
.request(
|
||||||
self.snapshot(),
|
self.snapshot(),
|
||||||
tsc::RequestMethod::GetNavigationTree(specifier.clone()),
|
tsc::RequestMethod::GetNavigationTree(specifier.clone()),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let navigation_tree: tsc::NavigationTree = serde_json::from_value(res)?;
|
|
||||||
self
|
self
|
||||||
.navigation_trees
|
.navigation_trees
|
||||||
.insert(specifier.clone(), navigation_tree.clone());
|
.insert(specifier.clone(), navigation_tree.clone());
|
||||||
|
@ -512,7 +511,7 @@ impl Inner {
|
||||||
warn!("{}", ignored_options);
|
warn!("{}", ignored_options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
let _ok: bool = self
|
||||||
.ts_server
|
.ts_server
|
||||||
.request(self.snapshot(), tsc::RequestMethod::Configure(tsconfig))
|
.request(self.snapshot(), tsc::RequestMethod::Configure(tsconfig))
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -588,7 +587,7 @@ impl Inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
if capabilities.code_action_provider.is_some() {
|
if capabilities.code_action_provider.is_some() {
|
||||||
let res = self
|
let fixable_diagnostics: Vec<String> = self
|
||||||
.ts_server
|
.ts_server
|
||||||
.request(self.snapshot(), tsc::RequestMethod::GetSupportedCodeFixes)
|
.request(self.snapshot(), tsc::RequestMethod::GetSupportedCodeFixes)
|
||||||
.await
|
.await
|
||||||
|
@ -596,11 +595,6 @@ impl Inner {
|
||||||
error!("Unable to get fixable diagnostics: {}", err);
|
error!("Unable to get fixable diagnostics: {}", err);
|
||||||
LspError::internal_error()
|
LspError::internal_error()
|
||||||
})?;
|
})?;
|
||||||
let fixable_diagnostics: Vec<String> =
|
|
||||||
from_value(res).map_err(|err| {
|
|
||||||
error!("Unable to get fixable diagnostics: {}", err);
|
|
||||||
LspError::internal_error()
|
|
||||||
})?;
|
|
||||||
self.ts_fixable_diagnostics = fixable_diagnostics;
|
self.ts_fixable_diagnostics = fixable_diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,11 +871,14 @@ impl Inner {
|
||||||
specifier,
|
specifier,
|
||||||
line_index.offset_tsc(params.text_document_position_params.position)?,
|
line_index.offset_tsc(params.text_document_position_params.position)?,
|
||||||
));
|
));
|
||||||
// TODO(lucacasonato): handle error correctly
|
let maybe_quick_info: Option<tsc::QuickInfo> = self
|
||||||
let res = self.ts_server.request(self.snapshot(), req).await.unwrap();
|
.ts_server
|
||||||
// TODO(lucacasonato): handle error correctly
|
.request(self.snapshot(), req)
|
||||||
let maybe_quick_info: Option<tsc::QuickInfo> =
|
.await
|
||||||
serde_json::from_value(res).unwrap();
|
.map_err(|err| {
|
||||||
|
error!("Unable to get quick info: {}", err);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?;
|
||||||
if let Some(quick_info) = maybe_quick_info {
|
if let Some(quick_info) = maybe_quick_info {
|
||||||
let hover = quick_info.to_hover(&line_index);
|
let hover = quick_info.to_hover(&line_index);
|
||||||
self.performance.measure(mark);
|
self.performance.measure(mark);
|
||||||
|
@ -953,18 +950,13 @@ impl Inner {
|
||||||
line_index.offset_tsc(diagnostic.range.end)?,
|
line_index.offset_tsc(diagnostic.range.end)?,
|
||||||
codes,
|
codes,
|
||||||
));
|
));
|
||||||
let res =
|
let actions: Vec<tsc::CodeFixAction> =
|
||||||
self.ts_server.request(self.snapshot(), req).await.map_err(
|
self.ts_server.request(self.snapshot(), req).await.map_err(
|
||||||
|err| {
|
|err| {
|
||||||
error!("Error getting actions from TypeScript: {}", err);
|
error!("Error getting actions from TypeScript: {}", err);
|
||||||
LspError::internal_error()
|
LspError::internal_error()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let actions: Vec<tsc::CodeFixAction> =
|
|
||||||
from_value(res).map_err(|err| {
|
|
||||||
error!("Cannot decode actions from TypeScript: {}", err);
|
|
||||||
LspError::internal_error()
|
|
||||||
})?;
|
|
||||||
for action in actions {
|
for action in actions {
|
||||||
code_actions
|
code_actions
|
||||||
.add_ts_fix_action(&action, diagnostic, self)
|
.add_ts_fix_action(&action, diagnostic, self)
|
||||||
|
@ -1005,46 +997,42 @@ impl Inner {
|
||||||
params: CodeAction,
|
params: CodeAction,
|
||||||
) -> LspResult<CodeAction> {
|
) -> LspResult<CodeAction> {
|
||||||
let mark = self.performance.mark("code_action_resolve");
|
let mark = self.performance.mark("code_action_resolve");
|
||||||
let result =
|
let result = if let Some(data) = params.data.clone() {
|
||||||
if let Some(data) = params.data.clone() {
|
let code_action_data: CodeActionData =
|
||||||
let code_action_data: CodeActionData =
|
from_value(data).map_err(|err| {
|
||||||
from_value(data).map_err(|err| {
|
error!("Unable to decode code action data: {}", err);
|
||||||
error!("Unable to decode code action data: {}", err);
|
LspError::invalid_params("The CodeAction's data is invalid.")
|
||||||
LspError::invalid_params("The CodeAction's data is invalid.")
|
})?;
|
||||||
})?;
|
let req = tsc::RequestMethod::GetCombinedCodeFix((
|
||||||
let req = tsc::RequestMethod::GetCombinedCodeFix((
|
code_action_data.specifier,
|
||||||
code_action_data.specifier,
|
json!(code_action_data.fix_id.clone()),
|
||||||
json!(code_action_data.fix_id.clone()),
|
));
|
||||||
));
|
let combined_code_actions: tsc::CombinedCodeActions = self
|
||||||
let res = self.ts_server.request(self.snapshot(), req).await.map_err(
|
.ts_server
|
||||||
|err| {
|
.request(self.snapshot(), req)
|
||||||
error!("Unable to get combined fix from TypeScript: {}", err);
|
.await
|
||||||
LspError::internal_error()
|
.map_err(|err| {
|
||||||
},
|
error!("Unable to get combined fix from TypeScript: {}", err);
|
||||||
)?;
|
LspError::internal_error()
|
||||||
let combined_code_actions: tsc::CombinedCodeActions =
|
})?;
|
||||||
from_value(res).map_err(|err| {
|
if combined_code_actions.commands.is_some() {
|
||||||
error!("Cannot decode combined actions from TypeScript: {}", err);
|
error!("Deno does not support code actions with commands.");
|
||||||
LspError::internal_error()
|
Err(LspError::invalid_request())
|
||||||
})?;
|
|
||||||
if combined_code_actions.commands.is_some() {
|
|
||||||
error!("Deno does not support code actions with commands.");
|
|
||||||
Err(LspError::invalid_request())
|
|
||||||
} else {
|
|
||||||
let mut code_action = params.clone();
|
|
||||||
code_action.edit =
|
|
||||||
ts_changes_to_edit(&combined_code_actions.changes, self)
|
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
error!("Unable to convert changes to edits: {}", err);
|
|
||||||
LspError::internal_error()
|
|
||||||
})?;
|
|
||||||
Ok(code_action)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// The code action doesn't need to be resolved
|
let mut code_action = params.clone();
|
||||||
Ok(params)
|
code_action.edit =
|
||||||
};
|
ts_changes_to_edit(&combined_code_actions.changes, self)
|
||||||
|
.await
|
||||||
|
.map_err(|err| {
|
||||||
|
error!("Unable to convert changes to edits: {}", err);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?;
|
||||||
|
Ok(code_action)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The code action doesn't need to be resolved
|
||||||
|
Ok(params)
|
||||||
|
};
|
||||||
self.performance.measure(mark);
|
self.performance.measure(mark);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -1191,18 +1179,13 @@ impl Inner {
|
||||||
code_lens_data.specifier.clone(),
|
code_lens_data.specifier.clone(),
|
||||||
line_index.offset_tsc(params.range.start)?,
|
line_index.offset_tsc(params.range.start)?,
|
||||||
));
|
));
|
||||||
let res =
|
let maybe_implementations: Option<Vec<tsc::ImplementationLocation>> =
|
||||||
self.ts_server.request(self.snapshot(), req).await.map_err(
|
self.ts_server.request(self.snapshot(), req).await.map_err(
|
||||||
|err| {
|
|err| {
|
||||||
error!("Error processing TypeScript request: {}", err);
|
error!("Error processing TypeScript request: {}", err);
|
||||||
LspError::internal_error()
|
LspError::internal_error()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let maybe_implementations: Option<Vec<tsc::ImplementationLocation>> =
|
|
||||||
serde_json::from_value(res).map_err(|err| {
|
|
||||||
error!("Error deserializing response: {}", err);
|
|
||||||
LspError::internal_error()
|
|
||||||
})?;
|
|
||||||
if let Some(implementations) = maybe_implementations {
|
if let Some(implementations) = maybe_implementations {
|
||||||
let mut locations = Vec::new();
|
let mut locations = Vec::new();
|
||||||
for implementation in implementations {
|
for implementation in implementations {
|
||||||
|
@ -1275,18 +1258,13 @@ impl Inner {
|
||||||
code_lens_data.specifier.clone(),
|
code_lens_data.specifier.clone(),
|
||||||
line_index.offset_tsc(params.range.start)?,
|
line_index.offset_tsc(params.range.start)?,
|
||||||
));
|
));
|
||||||
let res =
|
let maybe_references: Option<Vec<tsc::ReferenceEntry>> =
|
||||||
self.ts_server.request(self.snapshot(), req).await.map_err(
|
self.ts_server.request(self.snapshot(), req).await.map_err(
|
||||||
|err| {
|
|err| {
|
||||||
error!("Error processing TypeScript request: {}", err);
|
error!("Error processing TypeScript request: {}", err);
|
||||||
LspError::internal_error()
|
LspError::internal_error()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let maybe_references: Option<Vec<tsc::ReferenceEntry>> =
|
|
||||||
serde_json::from_value(res).map_err(|err| {
|
|
||||||
error!("Error deserializing response: {}", err);
|
|
||||||
LspError::internal_error()
|
|
||||||
})?;
|
|
||||||
if let Some(references) = maybe_references {
|
if let Some(references) = maybe_references {
|
||||||
let mut locations = Vec::new();
|
let mut locations = Vec::new();
|
||||||
for reference in references {
|
for reference in references {
|
||||||
|
@ -1393,11 +1371,14 @@ impl Inner {
|
||||||
line_index.offset_tsc(params.text_document_position_params.position)?,
|
line_index.offset_tsc(params.text_document_position_params.position)?,
|
||||||
files_to_search,
|
files_to_search,
|
||||||
));
|
));
|
||||||
// TODO(lucacasonato): handle error correctly
|
let maybe_document_highlights: Option<Vec<tsc::DocumentHighlights>> = self
|
||||||
let res = self.ts_server.request(self.snapshot(), req).await.unwrap();
|
.ts_server
|
||||||
// TODO(lucacasonato): handle error correctly
|
.request(self.snapshot(), req)
|
||||||
let maybe_document_highlights: Option<Vec<tsc::DocumentHighlights>> =
|
.await
|
||||||
serde_json::from_value(res).unwrap();
|
.map_err(|err| {
|
||||||
|
error!("Unable to get document highlights from TypeScript: {}", err);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?;
|
||||||
|
|
||||||
if let Some(document_highlights) = maybe_document_highlights {
|
if let Some(document_highlights) = maybe_document_highlights {
|
||||||
let result = document_highlights
|
let result = document_highlights
|
||||||
|
@ -1437,11 +1418,14 @@ impl Inner {
|
||||||
specifier,
|
specifier,
|
||||||
line_index.offset_tsc(params.text_document_position.position)?,
|
line_index.offset_tsc(params.text_document_position.position)?,
|
||||||
));
|
));
|
||||||
// TODO(lucacasonato): handle error correctly
|
let maybe_references: Option<Vec<tsc::ReferenceEntry>> = self
|
||||||
let res = self.ts_server.request(self.snapshot(), req).await.unwrap();
|
.ts_server
|
||||||
// TODO(lucacasonato): handle error correctly
|
.request(self.snapshot(), req)
|
||||||
let maybe_references: Option<Vec<tsc::ReferenceEntry>> =
|
.await
|
||||||
serde_json::from_value(res).unwrap();
|
.map_err(|err| {
|
||||||
|
error!("Unable to get references from TypeScript: {}", err);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?;
|
||||||
|
|
||||||
if let Some(references) = maybe_references {
|
if let Some(references) = maybe_references {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
@ -1489,11 +1473,14 @@ impl Inner {
|
||||||
specifier,
|
specifier,
|
||||||
line_index.offset_tsc(params.text_document_position_params.position)?,
|
line_index.offset_tsc(params.text_document_position_params.position)?,
|
||||||
));
|
));
|
||||||
// TODO(lucacasonato): handle error correctly
|
let maybe_definition: Option<tsc::DefinitionInfoAndBoundSpan> = self
|
||||||
let res = self.ts_server.request(self.snapshot(), req).await.unwrap();
|
.ts_server
|
||||||
// TODO(lucacasonato): handle error correctly
|
.request(self.snapshot(), req)
|
||||||
let maybe_definition: Option<tsc::DefinitionInfoAndBoundSpan> =
|
.await
|
||||||
serde_json::from_value(res).unwrap();
|
.map_err(|err| {
|
||||||
|
error!("Unable to get definition from TypeScript: {}", err);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?;
|
||||||
|
|
||||||
if let Some(definition) = maybe_definition {
|
if let Some(definition) = maybe_definition {
|
||||||
let results = definition.to_definition(&line_index, self).await;
|
let results = definition.to_definition(&line_index, self).await;
|
||||||
|
@ -1535,11 +1522,14 @@ impl Inner {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
// TODO(lucacasonato): handle error correctly
|
let maybe_completion_info: Option<tsc::CompletionInfo> = self
|
||||||
let res = self.ts_server.request(self.snapshot(), req).await.unwrap();
|
.ts_server
|
||||||
// TODO(lucacasonato): handle error correctly
|
.request(self.snapshot(), req)
|
||||||
let maybe_completion_info: Option<tsc::CompletionInfo> =
|
.await
|
||||||
serde_json::from_value(res).unwrap();
|
.map_err(|err| {
|
||||||
|
error!("Unable to get completion info from TypeScript: {}", err);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?;
|
||||||
|
|
||||||
if let Some(completions) = maybe_completion_info {
|
if let Some(completions) = maybe_completion_info {
|
||||||
let results = completions.into_completion_response(&line_index);
|
let results = completions.into_completion_response(&line_index);
|
||||||
|
@ -1576,20 +1566,13 @@ impl Inner {
|
||||||
specifier,
|
specifier,
|
||||||
line_index.offset_tsc(params.text_document_position_params.position)?,
|
line_index.offset_tsc(params.text_document_position_params.position)?,
|
||||||
));
|
));
|
||||||
let res =
|
let maybe_implementations: Option<Vec<tsc::ImplementationLocation>> = self
|
||||||
self
|
.ts_server
|
||||||
.ts_server
|
.request(self.snapshot(), req)
|
||||||
.request(self.snapshot(), req)
|
.await
|
||||||
.await
|
|
||||||
.map_err(|err| {
|
|
||||||
error!("Failed to request to tsserver {}", err);
|
|
||||||
LspError::invalid_request()
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let maybe_implementations: Option<Vec<tsc::ImplementationLocation>> = serde_json::from_value(res)
|
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!("Failed to deserialized tsserver response to Vec<ImplementationLocation> {}", err);
|
error!("Failed to request to tsserver {}", err);
|
||||||
LspError::internal_error()
|
LspError::invalid_request()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = if let Some(implementations) = maybe_implementations {
|
let result = if let Some(implementations) = maybe_implementations {
|
||||||
|
@ -1638,26 +1621,14 @@ impl Inner {
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
|
|
||||||
let res =
|
let maybe_locations: Option<Vec<tsc::RenameLocation>> = self
|
||||||
self
|
.ts_server
|
||||||
.ts_server
|
.request(self.snapshot(), req)
|
||||||
.request(self.snapshot(), req)
|
.await
|
||||||
.await
|
.map_err(|err| {
|
||||||
.map_err(|err| {
|
error!("Failed to request to tsserver {}", err);
|
||||||
error!("Failed to request to tsserver {}", err);
|
LspError::invalid_request()
|
||||||
LspError::invalid_request()
|
})?;
|
||||||
})?;
|
|
||||||
|
|
||||||
let maybe_locations = serde_json::from_value::<
|
|
||||||
Option<Vec<tsc::RenameLocation>>,
|
|
||||||
>(res)
|
|
||||||
.map_err(|err| {
|
|
||||||
error!(
|
|
||||||
"Failed to deserialize tsserver response to Vec<RenameLocation> {}",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
LspError::internal_error()
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if let Some(locations) = maybe_locations {
|
if let Some(locations) = maybe_locations {
|
||||||
let rename_locations = tsc::RenameLocations { locations };
|
let rename_locations = tsc::RenameLocations { locations };
|
||||||
|
@ -1751,19 +1722,13 @@ impl Inner {
|
||||||
line_index.offset_tsc(params.text_document_position_params.position)?,
|
line_index.offset_tsc(params.text_document_position_params.position)?,
|
||||||
options,
|
options,
|
||||||
));
|
));
|
||||||
let res =
|
let maybe_signature_help_items: Option<tsc::SignatureHelpItems> = self
|
||||||
self
|
.ts_server
|
||||||
.ts_server
|
.request(self.snapshot(), req)
|
||||||
.request(self.snapshot(), req)
|
.await
|
||||||
.await
|
.map_err(|err| {
|
||||||
.map_err(|err| {
|
error!("Failed to request to tsserver: {}", err);
|
||||||
error!("Failed to request to tsserver: {}", err);
|
LspError::invalid_request()
|
||||||
LspError::invalid_request()
|
|
||||||
})?;
|
|
||||||
let maybe_signature_help_items: Option<tsc::SignatureHelpItems> =
|
|
||||||
serde_json::from_value(res).map_err(|err| {
|
|
||||||
error!("Failed to deserialize tsserver response: {}", err);
|
|
||||||
LspError::internal_error()
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(signature_help_items) = maybe_signature_help_items {
|
if let Some(signature_help_items) = maybe_signature_help_items {
|
||||||
|
|
146
cli/lsp/tsc.rs
146
cli/lsp/tsc.rs
|
@ -19,6 +19,7 @@ use deno_core::error::custom_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::json_op_sync;
|
use deno_core::json_op_sync;
|
||||||
use deno_core::resolve_url;
|
use deno_core::resolve_url;
|
||||||
|
use deno_core::serde::de;
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
use deno_core::serde::Serialize;
|
use deno_core::serde::Serialize;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
|
@ -71,16 +72,19 @@ impl TsServer {
|
||||||
Self(tx)
|
Self(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request(
|
pub async fn request<R>(
|
||||||
&self,
|
&self,
|
||||||
snapshot: StateSnapshot,
|
snapshot: StateSnapshot,
|
||||||
req: RequestMethod,
|
req: RequestMethod,
|
||||||
) -> Result<Value, AnyError> {
|
) -> Result<R, AnyError>
|
||||||
|
where
|
||||||
|
R: de::DeserializeOwned,
|
||||||
|
{
|
||||||
let (tx, rx) = oneshot::channel::<Result<Value, AnyError>>();
|
let (tx, rx) = oneshot::channel::<Result<Value, AnyError>>();
|
||||||
if self.0.send((req, snapshot, tx)).is_err() {
|
if self.0.send((req, snapshot, tx)).is_err() {
|
||||||
return Err(anyhow!("failed to send request to tsc thread"));
|
return Err(anyhow!("failed to send request to tsc thread"));
|
||||||
}
|
}
|
||||||
rx.await?
|
rx.await?.map(|v| serde_json::from_value::<R>(v).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,9 +1108,11 @@ fn cache_snapshot(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op<F>(op_fn: F) -> Box<OpFn>
|
fn op<F, V, R>(op_fn: F) -> Box<OpFn>
|
||||||
where
|
where
|
||||||
F: Fn(&mut State, Value) -> Result<Value, AnyError> + 'static,
|
F: Fn(&mut State, V) -> Result<R, AnyError> + 'static,
|
||||||
|
V: de::DeserializeOwned,
|
||||||
|
R: Serialize,
|
||||||
{
|
{
|
||||||
json_op_sync(move |s, args, _bufs| {
|
json_op_sync(move |s, args, _bufs| {
|
||||||
let state = s.borrow_mut::<State>();
|
let state = s.borrow_mut::<State>();
|
||||||
|
@ -1123,14 +1129,17 @@ struct SourceSnapshotArgs {
|
||||||
|
|
||||||
/// The language service is dropping a reference to a source file snapshot, and
|
/// The language service is dropping a reference to a source file snapshot, and
|
||||||
/// we can drop our version of that document.
|
/// we can drop our version of that document.
|
||||||
fn dispose(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
|
fn dispose(
|
||||||
|
state: &mut State,
|
||||||
|
args: SourceSnapshotArgs,
|
||||||
|
) -> Result<bool, AnyError> {
|
||||||
let mark = state.state_snapshot.performance.mark("op_dispose");
|
let mark = state.state_snapshot.performance.mark("op_dispose");
|
||||||
let v: SourceSnapshotArgs = serde_json::from_value(args)?;
|
|
||||||
state
|
state
|
||||||
.snapshots
|
.snapshots
|
||||||
.remove(&(v.specifier.into(), v.version.into()));
|
.remove(&(args.specifier.into(), args.version.into()));
|
||||||
state.state_snapshot.performance.measure(mark);
|
state.state_snapshot.performance.measure(mark);
|
||||||
Ok(json!(true))
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -1144,18 +1153,20 @@ struct GetChangeRangeArgs {
|
||||||
|
|
||||||
/// The language service wants to compare an old snapshot with a new snapshot to
|
/// The language service wants to compare an old snapshot with a new snapshot to
|
||||||
/// determine what source hash changed.
|
/// determine what source hash changed.
|
||||||
fn get_change_range(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
fn get_change_range(
|
||||||
|
state: &mut State,
|
||||||
|
args: GetChangeRangeArgs,
|
||||||
|
) -> Result<Value, AnyError> {
|
||||||
let mark = state.state_snapshot.performance.mark("op_get_change_range");
|
let mark = state.state_snapshot.performance.mark("op_get_change_range");
|
||||||
let v: GetChangeRangeArgs = serde_json::from_value(args.clone())?;
|
cache_snapshot(state, args.specifier.clone(), args.version.clone())?;
|
||||||
cache_snapshot(state, v.specifier.clone(), v.version.clone())?;
|
|
||||||
if let Some(current) = state
|
if let Some(current) = state
|
||||||
.snapshots
|
.snapshots
|
||||||
.get(&(v.specifier.clone().into(), v.version.into()))
|
.get(&(args.specifier.clone().into(), args.version.clone().into()))
|
||||||
{
|
{
|
||||||
if let Some(prev) = state
|
if let Some(prev) = state.snapshots.get(&(
|
||||||
.snapshots
|
args.specifier.clone().into(),
|
||||||
.get(&(v.specifier.clone().into(), v.old_version.clone().into()))
|
args.old_version.clone().into(),
|
||||||
{
|
)) {
|
||||||
state.state_snapshot.performance.measure(mark);
|
state.state_snapshot.performance.measure(mark);
|
||||||
Ok(text::get_range_change(prev, current))
|
Ok(text::get_range_change(prev, current))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1168,7 +1179,7 @@ fn get_change_range(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"span": {
|
"span": {
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"length": v.old_length,
|
"length": args.old_length,
|
||||||
},
|
},
|
||||||
"newLength": new_length,
|
"newLength": new_length,
|
||||||
}))
|
}))
|
||||||
|
@ -1178,31 +1189,33 @@ fn get_change_range(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
||||||
Err(custom_error(
|
Err(custom_error(
|
||||||
"MissingSnapshot",
|
"MissingSnapshot",
|
||||||
format!(
|
format!(
|
||||||
"The current snapshot version is missing.\n Args: \"{}\"",
|
"The current snapshot version is missing.\n Args: \"{:?}\"",
|
||||||
args
|
args
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_length(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
fn get_length(
|
||||||
|
state: &mut State,
|
||||||
|
args: SourceSnapshotArgs,
|
||||||
|
) -> Result<usize, AnyError> {
|
||||||
let mark = state.state_snapshot.performance.mark("op_get_length");
|
let mark = state.state_snapshot.performance.mark("op_get_length");
|
||||||
let v: SourceSnapshotArgs = serde_json::from_value(args)?;
|
let specifier = resolve_url(&args.specifier)?;
|
||||||
let specifier = resolve_url(&v.specifier)?;
|
|
||||||
if let Some(Some(asset)) = state.state_snapshot.assets.get(&specifier) {
|
if let Some(Some(asset)) = state.state_snapshot.assets.get(&specifier) {
|
||||||
Ok(json!(asset.length))
|
Ok(asset.length)
|
||||||
} else if state.state_snapshot.documents.contains_key(&specifier) {
|
} else if state.state_snapshot.documents.contains_key(&specifier) {
|
||||||
cache_snapshot(state, v.specifier.clone(), v.version.clone())?;
|
cache_snapshot(state, args.specifier.clone(), args.version.clone())?;
|
||||||
let content = state
|
let content = state
|
||||||
.snapshots
|
.snapshots
|
||||||
.get(&(v.specifier.into(), v.version.into()))
|
.get(&(args.specifier.into(), args.version.into()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
state.state_snapshot.performance.measure(mark);
|
state.state_snapshot.performance.measure(mark);
|
||||||
Ok(json!(content.encode_utf16().count()))
|
Ok(content.encode_utf16().count())
|
||||||
} else {
|
} else {
|
||||||
let sources = &mut state.state_snapshot.sources;
|
let sources = &mut state.state_snapshot.sources;
|
||||||
state.state_snapshot.performance.measure(mark);
|
state.state_snapshot.performance.measure(mark);
|
||||||
Ok(json!(sources.get_length_utf16(&specifier).unwrap()))
|
Ok(sources.get_length_utf16(&specifier).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1215,39 +1228,40 @@ struct GetTextArgs {
|
||||||
end: usize,
|
end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_text(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
fn get_text(state: &mut State, args: GetTextArgs) -> Result<String, AnyError> {
|
||||||
let mark = state.state_snapshot.performance.mark("op_get_text");
|
let mark = state.state_snapshot.performance.mark("op_get_text");
|
||||||
let v: GetTextArgs = serde_json::from_value(args)?;
|
let specifier = resolve_url(&args.specifier)?;
|
||||||
let specifier = resolve_url(&v.specifier)?;
|
|
||||||
let content =
|
let content =
|
||||||
if let Some(Some(content)) = state.state_snapshot.assets.get(&specifier) {
|
if let Some(Some(content)) = state.state_snapshot.assets.get(&specifier) {
|
||||||
content.text.clone()
|
content.text.clone()
|
||||||
} else if state.state_snapshot.documents.contains_key(&specifier) {
|
} else if state.state_snapshot.documents.contains_key(&specifier) {
|
||||||
cache_snapshot(state, v.specifier.clone(), v.version.clone())?;
|
cache_snapshot(state, args.specifier.clone(), args.version.clone())?;
|
||||||
state
|
state
|
||||||
.snapshots
|
.snapshots
|
||||||
.get(&(v.specifier.into(), v.version.into()))
|
.get(&(args.specifier.into(), args.version.into()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone()
|
.clone()
|
||||||
} else {
|
} else {
|
||||||
state.state_snapshot.sources.get_source(&specifier).unwrap()
|
state.state_snapshot.sources.get_source(&specifier).unwrap()
|
||||||
};
|
};
|
||||||
state.state_snapshot.performance.measure(mark);
|
state.state_snapshot.performance.measure(mark);
|
||||||
Ok(json!(text::slice(&content, v.start..v.end)))
|
Ok(text::slice(&content, args.start..args.end).to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
fn resolve(
|
||||||
|
state: &mut State,
|
||||||
|
args: ResolveArgs,
|
||||||
|
) -> Result<Vec<Option<(String, String)>>, AnyError> {
|
||||||
let mark = state.state_snapshot.performance.mark("op_resolve");
|
let mark = state.state_snapshot.performance.mark("op_resolve");
|
||||||
let v: ResolveArgs = serde_json::from_value(args)?;
|
let mut resolved = Vec::new();
|
||||||
let mut resolved = Vec::<Option<(String, String)>>::new();
|
let referrer = resolve_url(&args.base)?;
|
||||||
let referrer = resolve_url(&v.base)?;
|
|
||||||
let sources = &mut state.state_snapshot.sources;
|
let sources = &mut state.state_snapshot.sources;
|
||||||
|
|
||||||
if state.state_snapshot.documents.contains_key(&referrer) {
|
if state.state_snapshot.documents.contains_key(&referrer) {
|
||||||
if let Some(dependencies) =
|
if let Some(dependencies) =
|
||||||
state.state_snapshot.documents.dependencies(&referrer)
|
state.state_snapshot.documents.dependencies(&referrer)
|
||||||
{
|
{
|
||||||
for specifier in &v.specifiers {
|
for specifier in &args.specifiers {
|
||||||
if specifier.starts_with("asset:///") {
|
if specifier.starts_with("asset:///") {
|
||||||
resolved.push(Some((
|
resolved.push(Some((
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
|
@ -1297,7 +1311,7 @@ fn resolve(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if sources.contains_key(&referrer) {
|
} else if sources.contains_key(&referrer) {
|
||||||
for specifier in &v.specifiers {
|
for specifier in &args.specifiers {
|
||||||
if let Some((resolved_specifier, media_type)) =
|
if let Some((resolved_specifier, media_type)) =
|
||||||
sources.resolve_import(specifier, &referrer)
|
sources.resolve_import(specifier, &referrer)
|
||||||
{
|
{
|
||||||
|
@ -1321,17 +1335,29 @@ fn resolve(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.state_snapshot.performance.measure(mark);
|
state.state_snapshot.performance.measure(mark);
|
||||||
Ok(json!(resolved))
|
Ok(resolved)
|
||||||
}
|
|
||||||
|
|
||||||
fn respond(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
|
||||||
state.response = Some(serde_json::from_value(args)?);
|
|
||||||
Ok(json!(true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
fn script_names(state: &mut State, _args: Value) -> Result<Value, AnyError> {
|
fn respond(state: &mut State, args: Response) -> Result<bool, AnyError> {
|
||||||
Ok(json!(state.state_snapshot.documents.open_specifiers()))
|
state.response = Some(args);
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
|
fn script_names(
|
||||||
|
state: &mut State,
|
||||||
|
_args: Value,
|
||||||
|
) -> Result<Vec<ModuleSpecifier>, AnyError> {
|
||||||
|
Ok(
|
||||||
|
state
|
||||||
|
.state_snapshot
|
||||||
|
.documents
|
||||||
|
.open_specifiers()
|
||||||
|
.into_iter()
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -1340,29 +1366,31 @@ struct ScriptVersionArgs {
|
||||||
specifier: String,
|
specifier: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_version(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
fn script_version(
|
||||||
|
state: &mut State,
|
||||||
|
args: ScriptVersionArgs,
|
||||||
|
) -> Result<Option<String>, AnyError> {
|
||||||
let mark = state.state_snapshot.performance.mark("op_script_version");
|
let mark = state.state_snapshot.performance.mark("op_script_version");
|
||||||
let v: ScriptVersionArgs = serde_json::from_value(args)?;
|
let specifier = resolve_url(&args.specifier)?;
|
||||||
let specifier = resolve_url(&v.specifier)?;
|
|
||||||
if specifier.scheme() == "asset" {
|
if specifier.scheme() == "asset" {
|
||||||
return if state.state_snapshot.assets.contains_key(&specifier) {
|
return if state.state_snapshot.assets.contains_key(&specifier) {
|
||||||
Ok(json!("1"))
|
Ok(Some("1".to_string()))
|
||||||
} else {
|
} else {
|
||||||
Ok(json!(null))
|
Ok(None)
|
||||||
};
|
};
|
||||||
} else if let Some(version) =
|
} else if let Some(version) =
|
||||||
state.state_snapshot.documents.version(&specifier)
|
state.state_snapshot.documents.version(&specifier)
|
||||||
{
|
{
|
||||||
return Ok(json!(version.to_string()));
|
return Ok(Some(version.to_string()));
|
||||||
} else {
|
} else {
|
||||||
let sources = &mut state.state_snapshot.sources;
|
let sources = &mut state.state_snapshot.sources;
|
||||||
if let Some(version) = sources.get_script_version(&specifier) {
|
if let Some(version) = sources.get_script_version(&specifier) {
|
||||||
return Ok(json!(version));
|
return Ok(Some(version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.state_snapshot.performance.measure(mark);
|
state.state_snapshot.performance.measure(mark);
|
||||||
Ok(json!(null))
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -1371,10 +1399,10 @@ struct SetAssetArgs {
|
||||||
text: Option<String>,
|
text: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_asset(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
let v: SetAssetArgs = serde_json::from_value(args)?;
|
fn set_asset(state: &mut State, args: SetAssetArgs) -> Result<bool, AnyError> {
|
||||||
state.asset = v.text;
|
state.asset = args.text;
|
||||||
Ok(json!(true))
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and setup a JsRuntime based on a snapshot. It is expected that the
|
/// Create and setup a JsRuntime based on a snapshot. It is expected that the
|
||||||
|
|
Loading…
Reference in a new issue