"unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "ra_arena"
+version = "0.1.0"
+
[[package]]
name = "ra_cli"
version = "0.1.0"
dependencies = [
"crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ra_arena 0.1.0",
"relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
--- /dev/null
+[package]
+edition = "2018"
+name = "ra_arena"
+version = "0.1.0"
+authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
--- /dev/null
+//! Yet another index-based arena.
+
+use std::{
+ fmt,
+ marker::PhantomData,
+ ops::{Index, IndexMut},
+};
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct RawId(u32);
+
+impl From<RawId> for u32 {
+ fn from(raw: RawId) -> u32 {
+ raw.0
+ }
+}
+
+impl From<u32> for RawId {
+ fn from(id: u32) -> RawId {
+ RawId(id)
+ }
+}
+
+impl fmt::Debug for RawId {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl fmt::Display for RawId {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct Arena<ID: ArenaId, T> {
+ data: Vec<T>,
+ _ty: PhantomData<ID>,
+}
+
+#[macro_export]
+macro_rules! impl_arena_id {
+ ($name:ident) => {
+ impl $crate::ArenaId for $name {
+ fn from_raw(raw: $crate::RawId) -> Self {
+ $name(raw)
+ }
+ fn into_raw(self) -> $crate::RawId {
+ self.0
+ }
+ }
+ };
+}
+
+pub trait ArenaId {
+ fn from_raw(raw: RawId) -> Self;
+ fn into_raw(self) -> RawId;
+}
+
+impl<ID: ArenaId, T> Arena<ID, T> {
+ pub fn alloc(&mut self, value: T) -> ID {
+ let id = RawId(self.data.len() as u32);
+ self.data.push(value);
+ ID::from_raw(id)
+ }
+ pub fn iter<'a>(&'a self) -> impl Iterator<Item = (ID, &'a T)> {
+ self.data
+ .iter()
+ .enumerate()
+ .map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value))
+ }
+}
+
+impl<ID: ArenaId, T> Default for Arena<ID, T> {
+ fn default() -> Arena<ID, T> {
+ Arena {
+ data: Vec::new(),
+ _ty: PhantomData,
+ }
+ }
+}
+
+impl<ID: ArenaId, T> Index<ID> for Arena<ID, T> {
+ type Output = T;
+ fn index(&self, idx: ID) -> &T {
+ let idx = idx.into_raw().0 as usize;
+ &self.data[idx]
+ }
+}
+
+impl<ID: ArenaId, T> IndexMut<ID> for Arena<ID, T> {
+ fn index_mut(&mut self, idx: ID) -> &mut T {
+ let idx = idx.into_raw().0 as usize;
+ &mut self.data[idx]
+ }
+}
.write()
.add_file_overlay(&path, params.text_document.text)
{
- subs.add_sub(FileId(file_id.0));
+ subs.add_sub(FileId(file_id.0.into()));
}
return Ok(());
}
.to_file_path()
.map_err(|()| format_err!("invalid uri: {}", uri))?;
if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) {
- subs.remove_sub(FileId(file_id.0));
+ subs.remove_sub(FileId(file_id.0.into()));
}
let params = req::PublishDiagnosticsParams {
uri,
None => return Ok(None),
};
let file_id = world.analysis().crate_root(crate_id)?;
- let path = world.vfs.read().file2path(ra_vfs::VfsFile(file_id.0));
+ let path = world
+ .vfs
+ .read()
+ .file2path(ra_vfs::VfsFile(file_id.0.into()));
let res = world.workspaces.iter().find_map(|ws| {
let tgt = ws.target_by_root(&path)?;
let res = CargoTargetSpec {
let (mut vfs, roots) = Vfs::new(roots);
for r in roots {
let is_local = vfs.root2path(r).starts_with(&root);
- change.add_root(SourceRootId(r.0), is_local);
+ change.add_root(SourceRootId(r.0.into()), is_local);
}
let mut crate_graph = CrateGraph::default();
for tgt in pkg.targets(ws) {
let root = tgt.root(ws);
if let Some(file_id) = vfs.load(root) {
- let file_id = FileId(file_id.0);
+ let file_id = FileId(file_id.0.into());
let crate_id = crate_graph.add_crate_root(file_id);
if tgt.kind(ws) == TargetKind::Lib {
pkg_to_lib_crate.insert(pkg, crate_id);
if root_path.starts_with(&self.root) {
self.roots_to_scan -= 1;
for (file, path, text) in files {
- change.add_file(SourceRootId(root.0), FileId(file.0), path, text);
+ change.add_file(
+ SourceRootId(root.0.into()),
+ FileId(file.0.into()),
+ path,
+ text,
+ );
}
} else {
let files = files
.into_iter()
- .map(|(vfsfile, path, text)| (FileId(vfsfile.0), path, text))
+ .map(|(vfsfile, path, text)| (FileId(vfsfile.0.into()), path, text))
.collect();
- libs.push((SourceRootId(root.0), files));
+ libs.push((SourceRootId(root.0.into()), files));
}
}
VfsChange::AddFile {
path,
text,
} => {
- change.add_file(SourceRootId(root.0), FileId(file.0), path, text);
+ change.add_file(
+ SourceRootId(root.0.into()),
+ FileId(file.0.into()),
+ path,
+ text,
+ );
}
VfsChange::RemoveFile { root, file, path } => {
- change.remove_file(SourceRootId(root.0), FileId(file.0), path)
+ change.remove_file(SourceRootId(root.0.into()), FileId(file.0.into()), path)
}
VfsChange::ChangeFile { file, text } => {
- change.change_file(FileId(file.0), text);
+ change.change_file(FileId(file.0.into()), text);
}
}
}
.read()
.path2file(&path)
.ok_or_else(|| format_err!("unknown file: {}", path.display()))?;
- Ok(FileId(file.0))
+ Ok(FileId(file.0.into()))
}
pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> {
- let path = self.vfs.read().file2path(VfsFile(id.0));
+ let path = self.vfs.read().file2path(VfsFile(id.0.into()));
let url = Url::from_file_path(&path)
.map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
Ok(url)
}
pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> {
- let base = self.vfs.read().root2path(VfsRoot(root.0));
+ let base = self.vfs.read().root2path(VfsRoot(root.0.into()));
let path = path.to_path(base);
let url = Url::from_file_path(&path)
.map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
log = "0.4.6"
thread_worker = { path = "../thread_worker" }
+ra_arena = { path = "../ra_arena" }
[dev-dependencies]
tempfile = "3"
+++ /dev/null
-use std::{
- marker::PhantomData,
- ops::{Index, IndexMut},
-};
-
-#[derive(Clone, Debug)]
-pub(crate) struct Arena<ID: ArenaId, T> {
- data: Vec<T>,
- _ty: PhantomData<ID>,
-}
-
-pub(crate) trait ArenaId {
- fn from_u32(id: u32) -> Self;
- fn to_u32(self) -> u32;
-}
-
-impl<ID: ArenaId, T> Arena<ID, T> {
- pub fn alloc(&mut self, value: T) -> ID {
- let id = self.data.len() as u32;
- self.data.push(value);
- ID::from_u32(id)
- }
- pub fn iter<'a>(&'a self) -> impl Iterator<Item = (ID, &'a T)> {
- self.data
- .iter()
- .enumerate()
- .map(|(idx, value)| (ID::from_u32(idx as u32), value))
- }
-}
-
-impl<ID: ArenaId, T> Default for Arena<ID, T> {
- fn default() -> Arena<ID, T> {
- Arena {
- data: Vec::new(),
- _ty: PhantomData,
- }
- }
-}
-
-impl<ID: ArenaId, T> Index<ID> for Arena<ID, T> {
- type Output = T;
- fn index(&self, idx: ID) -> &T {
- let idx = idx.to_u32() as usize;
- &self.data[idx]
- }
-}
-
-impl<ID: ArenaId, T> IndexMut<ID> for Arena<ID, T> {
- fn index_mut(&mut self, idx: ID) -> &mut T {
- let idx = idx.to_u32() as usize;
- &mut self.data[idx]
- }
-}
//! VFS is based on a concept of roots: a set of directories on the file system
//! which are watched for changes. Typically, there will be a root for each
//! Cargo package.
-mod arena;
mod io;
use std::{
use crossbeam_channel::Receiver;
use walkdir::DirEntry;
use thread_worker::WorkerHandle;
-
-use crate::{
- arena::{ArenaId, Arena},
-};
+use ra_arena::{Arena, RawId, impl_arena_id};
pub use crate::io::TaskResult as VfsTask;
p.extension() == Some(OsStr::new("rs"))
}
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
-pub struct VfsRoot(pub u32);
-
-impl ArenaId for VfsRoot {
- fn from_u32(idx: u32) -> VfsRoot {
- VfsRoot(idx)
- }
- fn to_u32(self) -> u32 {
- self.0
- }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
-pub struct VfsFile(pub u32);
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct VfsRoot(pub RawId);
+impl_arena_id!(VfsRoot);
-impl ArenaId for VfsFile {
- fn from_u32(idx: u32) -> VfsFile {
- VfsFile(idx)
- }
- fn to_u32(self) -> u32 {
- self.0
- }
-}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct VfsFile(pub RawId);
+impl_arena_id!(VfsFile);
struct VfsFileData {
root: VfsRoot,