summaryrefslogtreecommitdiff
path: root/cli/lsp/tsc.rs
diff options
context:
space:
mode:
authorNathan Whitaker <17734409+nathanwhit@users.noreply.github.com>2024-04-10 18:06:37 -0700
committerGitHub <noreply@github.com>2024-04-10 18:06:37 -0700
commit736f73b008c3f0354b870b70b8d494983046b0f7 (patch)
treea6f51edc66cdc41fc5d8c4efa912f6e15231a393 /cli/lsp/tsc.rs
parent9304126be5633d4e7d384a8df87f5833a7a145e2 (diff)
perf(lsp): Only evict caches on JS side when things actually change (#23293)
Currently we evict a lot of the caches on the JS side of things on every request, namely script versions, script file names, and compiler settings (as of #23283, it's not quite every request but it's still unnecessarily often). This PR reports changes to the JS side, so that it can evict exactly the caches that it needs too. We might want to do some batching in the future so as not to do 1 request per change.
Diffstat (limited to 'cli/lsp/tsc.rs')
-rw-r--r--cli/lsp/tsc.rs57
1 files changed, 53 insertions, 4 deletions
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index 923a0d443..53a35c484 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -237,6 +237,23 @@ impl std::fmt::Debug for TsServer {
}
}
+#[derive(Debug, Clone, Copy)]
+#[repr(u8)]
+pub enum ChangeKind {
+ Opened = 0,
+ Modified = 1,
+ Closed = 2,
+}
+
+impl Serialize for ChangeKind {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ serializer.serialize_i32(*self as i32)
+ }
+}
+
impl TsServer {
pub fn new(performance: Arc<Performance>, cache: Arc<dyn HttpCache>) -> Self {
let (tx, request_rx) = mpsc::unbounded_channel::<Request>();
@@ -279,6 +296,27 @@ impl TsServer {
});
}
+ pub async fn project_changed(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ modified_scripts: &[(&ModuleSpecifier, ChangeKind)],
+ new_project_version: String,
+ config_changed: bool,
+ ) {
+ let req = TscRequest {
+ method: "$projectChanged",
+ args: json!([modified_scripts, new_project_version, config_changed,]),
+ };
+ self
+ .request::<()>(snapshot, req)
+ .await
+ .map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ .ok();
+ }
+
pub async fn get_diagnostics(
&self,
snapshot: Arc<StateSnapshot>,
@@ -287,10 +325,13 @@ impl TsServer {
) -> Result<HashMap<String, Vec<crate::tsc::Diagnostic>>, AnyError> {
let req = TscRequest {
method: "$getDiagnostics",
- args: json!([specifiers
- .into_iter()
- .map(|s| self.specifier_map.denormalize(&s))
- .collect::<Vec<String>>(),]),
+ args: json!([
+ specifiers
+ .into_iter()
+ .map(|s| self.specifier_map.denormalize(&s))
+ .collect::<Vec<String>>(),
+ snapshot.documents.project_version()
+ ]),
};
let raw_diagnostics = self.request_with_cancellation::<HashMap<String, Vec<crate::tsc::Diagnostic>>>(snapshot, req, token).await?;
let mut diagnostics_map = HashMap::with_capacity(raw_diagnostics.len());
@@ -5135,6 +5176,14 @@ mod tests {
..snapshot.as_ref().clone()
})
};
+ ts_server
+ .project_changed(
+ snapshot.clone(),
+ &[(&specifier_dep, ChangeKind::Opened)],
+ snapshot.documents.project_version(),
+ false,
+ )
+ .await;
let specifier = resolve_url("file:///a.ts").unwrap();
let diagnostics = ts_server
.get_diagnostics(snapshot.clone(), vec![specifier], Default::default())