about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-11-29 18:37:00 +0000
committerbors <bors@rust-lang.org>2022-11-29 18:37:00 +0000
commit398a71affb05aeeea1991044ec9ca1229e68f0f3 (patch)
tree10b95b31f435de1ecd165bb885abdfa72a2254af
parente69fb5e9ef1051eb405865ad4aad7cc5a02877a2 (diff)
parent32f59cf01de639d0b23753687f5fb5b08c0758c0 (diff)
downloadrust-398a71affb05aeeea1991044ec9ca1229e68f0f3.tar.gz
rust-398a71affb05aeeea1991044ec9ca1229e68f0f3.zip
Auto merge of #13697 - jonas-schievink:version-inlay-hint-resolve-data, r=jonas-schievink
internal: Version the inlay hint resolve data

cc https://github.com/rust-lang/rust-analyzer/issues/13657
cc https://github.com/rust-lang/rust-analyzer/issues/13372
cc https://github.com/rust-lang/rust-analyzer/issues/13170

This will make us log an error and return the unmodified inlay hints when the client attempts to resolve inlay hints in a file that has since been modified.
-rw-r--r--crates/rust-analyzer/src/from_proto.rs10
-rw-r--r--crates/rust-analyzer/src/handlers.rs22
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs4
-rw-r--r--crates/rust-analyzer/src/to_proto.rs10
-rw-r--r--docs/dev/lsp-extensions.md2
5 files changed, 40 insertions, 8 deletions
diff --git a/crates/rust-analyzer/src/from_proto.rs b/crates/rust-analyzer/src/from_proto.rs
index dd433b0f4d3..4e7095b3ce3 100644
--- a/crates/rust-analyzer/src/from_proto.rs
+++ b/crates/rust-analyzer/src/from_proto.rs
@@ -67,7 +67,15 @@ pub(crate) fn file_range(
     text_document_identifier: lsp_types::TextDocumentIdentifier,
     range: lsp_types::Range,
 ) -> Result<FileRange> {
-    let file_id = file_id(snap, &text_document_identifier.uri)?;
+    file_range_uri(snap, &text_document_identifier.uri, range)
+}
+
+pub(crate) fn file_range_uri(
+    snap: &GlobalStateSnapshot,
+    document: &lsp_types::Url,
+    range: lsp_types::Range,
+) -> Result<FileRange> {
+    let file_id = file_id(snap, document)?;
     let line_index = snap.file_line_index(file_id)?;
     let range = text_range(&line_index, range)?;
     Ok(FileRange { file_id, range })
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 4f318f39de5..1604a02fb13 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -29,6 +29,7 @@ use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
 use serde_json::json;
 use stdx::{format_to, never};
 use syntax::{algo, ast, AstNode, TextRange, TextSize};
+use tracing::error;
 use vfs::AbsPathBuf;
 
 use crate::{
@@ -1372,9 +1373,26 @@ pub(crate) fn handle_inlay_hints_resolve(
 
     let resolve_data: lsp_ext::InlayHintResolveData = serde_json::from_value(data)?;
 
-    let file_range = from_proto::file_range(
+    match snap.url_file_version(&resolve_data.text_document.uri) {
+        Some(version) if version == resolve_data.text_document.version => {}
+        Some(version) => {
+            error!(
+                "attempted inlayHints/resolve of '{}' at version {} while server version is {}",
+                resolve_data.text_document.uri, resolve_data.text_document.version, version,
+            );
+            return Ok(hint);
+        }
+        None => {
+            error!(
+                "attempted inlayHints/resolve of unknown file '{}' at version {}",
+                resolve_data.text_document.uri, resolve_data.text_document.version,
+            );
+            return Ok(hint);
+        }
+    }
+    let file_range = from_proto::file_range_uri(
         &snap,
-        resolve_data.text_document,
+        &resolve_data.text_document.uri,
         match resolve_data.position {
             PositionOrRange::Position(pos) => Range::new(pos, pos),
             PositionOrRange::Range(range) => range,
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 8cc5648f3ce..a1df0b6d7dd 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -3,11 +3,11 @@
 use std::{collections::HashMap, path::PathBuf};
 
 use lsp_types::request::Request;
-use lsp_types::PositionEncodingKind;
 use lsp_types::{
     notification::Notification, CodeActionKind, DocumentOnTypeFormattingParams,
     PartialResultParams, Position, Range, TextDocumentIdentifier, WorkDoneProgressParams,
 };
+use lsp_types::{PositionEncodingKind, VersionedTextDocumentIdentifier};
 use serde::{Deserialize, Serialize};
 
 pub enum AnalyzerStatus {}
@@ -550,7 +550,7 @@ pub struct CompletionResolveData {
 
 #[derive(Debug, Serialize, Deserialize)]
 pub struct InlayHintResolveData {
-    pub text_document: TextDocumentIdentifier,
+    pub text_document: VersionedTextDocumentIdentifier,
     pub position: PositionOrRange,
 }
 
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index d1f805af1d4..3ce24bdd14f 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -492,7 +492,10 @@ pub(crate) fn inlay_hint(
                 let uri = url(snap, file_id);
                 let line_index = snap.file_line_index(file_id).ok()?;
 
-                let text_document = lsp_types::TextDocumentIdentifier { uri };
+                let text_document = lsp_types::VersionedTextDocumentIdentifier {
+                    version: snap.url_file_version(&uri)?,
+                    uri,
+                };
                 to_value(lsp_ext::InlayHintResolveData {
                     text_document,
                     position: lsp_ext::PositionOrRange::Position(position(&line_index, offset)),
@@ -501,7 +504,10 @@ pub(crate) fn inlay_hint(
             }
             Some(ide::InlayTooltip::HoverRanged(file_id, text_range)) => {
                 let uri = url(snap, file_id);
-                let text_document = lsp_types::TextDocumentIdentifier { uri };
+                let text_document = lsp_types::VersionedTextDocumentIdentifier {
+                    version: snap.url_file_version(&uri)?,
+                    uri,
+                };
                 let line_index = snap.file_line_index(file_id).ok()?;
                 to_value(lsp_ext::InlayHintResolveData {
                     text_document,
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index fe316fcae9b..5aced035d52 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: 62068e53ac202dc8
+lsp_ext.rs hash: 61fe425627f9baaa
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue: