summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/lib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tools/rust-analyzer/lib/la-arena/src/lib.rs50
-rw-r--r--src/tools/rust-analyzer/lib/la-arena/src/map.rs169
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/msg.rs10
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs7
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/socket.rs2
6 files changed, 236 insertions, 12 deletions
diff --git a/src/tools/rust-analyzer/lib/la-arena/src/lib.rs b/src/tools/rust-analyzer/lib/la-arena/src/lib.rs
index dadee43b1..ccaaf3991 100644
--- a/src/tools/rust-analyzer/lib/la-arena/src/lib.rs
+++ b/src/tools/rust-analyzer/lib/la-arena/src/lib.rs
@@ -6,13 +6,12 @@
use std::{
fmt,
hash::{Hash, Hasher},
- iter::FromIterator,
marker::PhantomData,
ops::{Index, IndexMut, Range, RangeInclusive},
};
mod map;
-pub use map::ArenaMap;
+pub use map::{ArenaMap, Entry, OccupiedEntry, VacantEntry};
/// The raw index of a value in an arena.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -208,6 +207,16 @@ impl<T> Arena<T> {
Arena { data: Vec::new() }
}
+ /// Create a new empty arena with specific capacity.
+ ///
+ /// ```
+ /// let arena: la_arena::Arena<i32> = la_arena::Arena::with_capacity(42);
+ /// assert!(arena.is_empty());
+ /// ```
+ pub fn with_capacity(capacity: usize) -> Arena<T> {
+ Arena { data: Vec::with_capacity(capacity) }
+ }
+
/// Empties the arena, removing all contained values.
///
/// ```
@@ -313,6 +322,43 @@ impl<T> Arena<T> {
.map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value))
}
+ /// Returns an iterator over the arena’s values.
+ ///
+ /// ```
+ /// let mut arena = la_arena::Arena::new();
+ /// let idx1 = arena.alloc(20);
+ /// let idx2 = arena.alloc(40);
+ /// let idx3 = arena.alloc(60);
+ ///
+ /// let mut iterator = arena.values();
+ /// assert_eq!(iterator.next(), Some(&20));
+ /// assert_eq!(iterator.next(), Some(&40));
+ /// assert_eq!(iterator.next(), Some(&60));
+ /// ```
+ pub fn values(&mut self) -> impl Iterator<Item = &T> + ExactSizeIterator + DoubleEndedIterator {
+ self.data.iter()
+ }
+
+ /// Returns an iterator over the arena’s mutable values.
+ ///
+ /// ```
+ /// let mut arena = la_arena::Arena::new();
+ /// let idx1 = arena.alloc(20);
+ ///
+ /// assert_eq!(arena[idx1], 20);
+ ///
+ /// let mut iterator = arena.values_mut();
+ /// *iterator.next().unwrap() = 10;
+ /// drop(iterator);
+ ///
+ /// assert_eq!(arena[idx1], 10);
+ /// ```
+ pub fn values_mut(
+ &mut self,
+ ) -> impl Iterator<Item = &mut T> + ExactSizeIterator + DoubleEndedIterator {
+ self.data.iter_mut()
+ }
+
/// Reallocates the arena to make it take up as little space as possible.
pub fn shrink_to_fit(&mut self) {
self.data.shrink_to_fit();
diff --git a/src/tools/rust-analyzer/lib/la-arena/src/map.rs b/src/tools/rust-analyzer/lib/la-arena/src/map.rs
index d27f086d3..5f347e274 100644
--- a/src/tools/rust-analyzer/lib/la-arena/src/map.rs
+++ b/src/tools/rust-analyzer/lib/la-arena/src/map.rs
@@ -11,12 +11,52 @@ pub struct ArenaMap<IDX, V> {
}
impl<T, V> ArenaMap<Idx<T>, V> {
+ /// Creates a new empty map.
+ pub const fn new() -> Self {
+ Self { v: Vec::new(), _ty: PhantomData }
+ }
+
+ /// Create a new empty map with specific capacity.
+ pub fn with_capacity(capacity: usize) -> Self {
+ Self { v: Vec::with_capacity(capacity), _ty: PhantomData }
+ }
+
+ /// Reserves capacity for at least additional more elements to be inserted in the map.
+ pub fn reserve(&mut self, additional: usize) {
+ self.v.reserve(additional);
+ }
+
+ /// Clears the map, removing all elements.
+ pub fn clear(&mut self) {
+ self.v.clear();
+ }
+
+ /// Shrinks the capacity of the map as much as possible.
+ pub fn shrink_to_fit(&mut self) {
+ let min_len = self.v.iter().rposition(|slot| slot.is_some()).map_or(0, |i| i + 1);
+ self.v.truncate(min_len);
+ self.v.shrink_to_fit();
+ }
+
+ /// Returns whether the map contains a value for the specified index.
+ pub fn contains_idx(&self, idx: Idx<T>) -> bool {
+ matches!(self.v.get(Self::to_idx(idx)), Some(Some(_)))
+ }
+
+ /// Removes an index from the map, returning the value at the index if the index was previously in the map.
+ pub fn remove(&mut self, idx: Idx<T>) -> Option<V> {
+ self.v.get_mut(Self::to_idx(idx))?.take()
+ }
+
/// Inserts a value associated with a given arena index into the map.
- pub fn insert(&mut self, idx: Idx<T>, t: V) {
+ ///
+ /// If the map did not have this index present, None is returned.
+ /// Otherwise, the value is updated, and the old value is returned.
+ pub fn insert(&mut self, idx: Idx<T>, t: V) -> Option<V> {
let idx = Self::to_idx(idx);
self.v.resize_with((idx + 1).max(self.v.len()), || None);
- self.v[idx] = Some(t);
+ self.v[idx].replace(t)
}
/// Returns a reference to the value associated with the provided index
@@ -46,6 +86,16 @@ impl<T, V> ArenaMap<Idx<T>, V> {
self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
}
+ /// Gets the given key's corresponding entry in the map for in-place manipulation.
+ pub fn entry(&mut self, idx: Idx<T>) -> Entry<'_, Idx<T>, V> {
+ let idx = Self::to_idx(idx);
+ self.v.resize_with((idx + 1).max(self.v.len()), || None);
+ match &mut self.v[idx] {
+ slot @ Some(_) => Entry::Occupied(OccupiedEntry { slot, _ty: PhantomData }),
+ slot @ None => Entry::Vacant(VacantEntry { slot, _ty: PhantomData }),
+ }
+ }
+
fn to_idx(idx: Idx<T>) -> usize {
u32::from(idx.into_raw()) as usize
}
@@ -70,6 +120,119 @@ impl<T, V> std::ops::IndexMut<Idx<V>> for ArenaMap<Idx<V>, T> {
impl<T, V> Default for ArenaMap<Idx<V>, T> {
fn default() -> Self {
- ArenaMap { v: Vec::new(), _ty: PhantomData }
+ Self::new()
+ }
+}
+
+impl<T, V> Extend<(Idx<V>, T)> for ArenaMap<Idx<V>, T> {
+ fn extend<I: IntoIterator<Item = (Idx<V>, T)>>(&mut self, iter: I) {
+ iter.into_iter().for_each(move |(k, v)| {
+ self.insert(k, v);
+ });
+ }
+}
+
+impl<T, V> FromIterator<(Idx<V>, T)> for ArenaMap<Idx<V>, T> {
+ fn from_iter<I: IntoIterator<Item = (Idx<V>, T)>>(iter: I) -> Self {
+ let mut this = Self::new();
+ this.extend(iter);
+ this
+ }
+}
+
+/// A view into a single entry in a map, which may either be vacant or occupied.
+///
+/// This `enum` is constructed from the [`entry`] method on [`ArenaMap`].
+///
+/// [`entry`]: ArenaMap::entry
+pub enum Entry<'a, IDX, V> {
+ /// A vacant entry.
+ Vacant(VacantEntry<'a, IDX, V>),
+ /// An occupied entry.
+ Occupied(OccupiedEntry<'a, IDX, V>),
+}
+
+impl<'a, IDX, V> Entry<'a, IDX, V> {
+ /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable reference to
+ /// the value in the entry.
+ pub fn or_insert(self, default: V) -> &'a mut V {
+ match self {
+ Self::Vacant(ent) => ent.insert(default),
+ Self::Occupied(ent) => ent.into_mut(),
+ }
+ }
+
+ /// Ensures a value is in the entry by inserting the result of the default function if empty, and returns
+ /// a mutable reference to the value in the entry.
+ pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
+ match self {
+ Self::Vacant(ent) => ent.insert(default()),
+ Self::Occupied(ent) => ent.into_mut(),
+ }
+ }
+
+ /// Provides in-place mutable access to an occupied entry before any potential inserts into the map.
+ pub fn and_modify<F: FnOnce(&mut V)>(mut self, f: F) -> Self {
+ if let Self::Occupied(ent) = &mut self {
+ f(ent.get_mut());
+ }
+ self
+ }
+}
+
+impl<'a, IDX, V> Entry<'a, IDX, V>
+where
+ V: Default,
+{
+ /// Ensures a value is in the entry by inserting the default value if empty, and returns a mutable reference
+ /// to the value in the entry.
+ pub fn or_default(self) -> &'a mut V {
+ self.or_insert_with(Default::default)
+ }
+}
+
+/// A view into an vacant entry in a [`ArenaMap`]. It is part of the [`Entry`] enum.
+pub struct VacantEntry<'a, IDX, V> {
+ slot: &'a mut Option<V>,
+ _ty: PhantomData<IDX>,
+}
+
+impl<'a, IDX, V> VacantEntry<'a, IDX, V> {
+ /// Sets the value of the entry with the `VacantEntry`’s key, and returns a mutable reference to it.
+ pub fn insert(self, value: V) -> &'a mut V {
+ self.slot.insert(value)
+ }
+}
+
+/// A view into an occupied entry in a [`ArenaMap`]. It is part of the [`Entry`] enum.
+pub struct OccupiedEntry<'a, IDX, V> {
+ slot: &'a mut Option<V>,
+ _ty: PhantomData<IDX>,
+}
+
+impl<'a, IDX, V> OccupiedEntry<'a, IDX, V> {
+ /// Gets a reference to the value in the entry.
+ pub fn get(&self) -> &V {
+ self.slot.as_ref().expect("Occupied")
+ }
+
+ /// Gets a mutable reference to the value in the entry.
+ pub fn get_mut(&mut self) -> &mut V {
+ self.slot.as_mut().expect("Occupied")
+ }
+
+ /// Converts the entry into a mutable reference to its value.
+ pub fn into_mut(self) -> &'a mut V {
+ self.slot.as_mut().expect("Occupied")
+ }
+
+ /// Sets the value of the entry with the `OccupiedEntry`’s key, and returns the entry’s old value.
+ pub fn insert(&mut self, value: V) -> V {
+ self.slot.replace(value).expect("Occupied")
+ }
+
+ /// Takes the value of the entry out of the map, and returns it.
+ pub fn remove(self) -> V {
+ self.slot.take().expect("Occupied")
}
}
diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
index 204d120d0..5922bbfdb 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
+++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lsp-server"
-version = "0.6.0"
+version = "0.7.0"
description = "Generic LSP server scaffold."
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server"
@@ -8,9 +8,9 @@ edition = "2021"
[dependencies]
log = "0.4.17"
-serde_json = "1.0.81"
-serde = { version = "1.0.137", features = ["derive"] }
-crossbeam-channel = "0.5.5"
+serde_json = "1.0.86"
+serde = { version = "1.0.144", features = ["derive"] }
+crossbeam-channel = "0.5.6"
[dev-dependencies]
-lsp-types = "0.93.0"
+lsp-types = "0.93.1"
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
index 97e5bd35c..b241561f9 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
@@ -98,7 +98,7 @@ pub struct ResponseError {
}
#[derive(Clone, Copy, Debug)]
-#[allow(unused)]
+#[non_exhaustive]
pub enum ErrorCode {
// Defined by JSON RPC:
ParseError = -32700,
@@ -135,6 +135,14 @@ pub enum ErrorCode {
///
/// @since 3.17.0
ServerCancelled = -32802,
+
+ /// A request failed but it was syntactically correct, e.g the
+ /// method name was known and the parameters were valid. The error
+ /// message should contain human readable information about why
+ /// the request failed.
+ ///
+ /// @since 3.17.0
+ RequestFailed = -32803,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs b/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
index 1f3d44715..e5f19be20 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
@@ -35,6 +35,7 @@ impl<I> Incoming<I> {
pub fn register(&mut self, id: RequestId, data: I) {
self.pending.insert(id, data);
}
+
pub fn cancel(&mut self, id: RequestId) -> Option<Response> {
let _data = self.complete(id.clone())?;
let error = ResponseError {
@@ -44,9 +45,14 @@ impl<I> Incoming<I> {
};
Some(Response { id, result: None, error: Some(error) })
}
+
pub fn complete(&mut self, id: RequestId) -> Option<I> {
self.pending.remove(&id)
}
+
+ pub fn is_completed(&self, id: &RequestId) -> bool {
+ !self.pending.contains_key(id)
+ }
}
impl<O> Outgoing<O> {
@@ -56,6 +62,7 @@ impl<O> Outgoing<O> {
self.next_id += 1;
Request::new(id, method, params)
}
+
pub fn complete(&mut self, id: RequestId) -> Option<O> {
self.pending.remove(&id)
}
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs b/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs
index 4a59c4c0f..36d728456 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs
@@ -15,7 +15,7 @@ pub(crate) fn socket_transport(
stream: TcpStream,
) -> (Sender<Message>, Receiver<Message>, IoThreads) {
let (reader_receiver, reader) = make_reader(stream.try_clone().unwrap());
- let (writer_sender, writer) = make_write(stream.try_clone().unwrap());
+ let (writer_sender, writer) = make_write(stream);
let io_threads = make_io_threads(reader, writer);
(writer_sender, reader_receiver, io_threads)
}