diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
commit | 94a0819fe3a0d679c3042a77bfe6a2afc505daea (patch) | |
tree | 2b827afe6a05f3538db3f7803a88c4587fe85648 /src/tools/rust-analyzer/lib | |
parent | Adding upstream version 1.64.0+dfsg1. (diff) | |
download | rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.tar.xz rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.zip |
Adding upstream version 1.66.0+dfsg1.upstream/1.66.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/lib')
-rw-r--r-- | src/tools/rust-analyzer/lib/la-arena/src/lib.rs | 50 | ||||
-rw-r--r-- | src/tools/rust-analyzer/lib/la-arena/src/map.rs | 169 | ||||
-rw-r--r-- | src/tools/rust-analyzer/lib/lsp-server/Cargo.toml | 10 | ||||
-rw-r--r-- | src/tools/rust-analyzer/lib/lsp-server/src/msg.rs | 10 | ||||
-rw-r--r-- | src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs | 7 | ||||
-rw-r--r-- | src/tools/rust-analyzer/lib/lsp-server/src/socket.rs | 2 |
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) } |