Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 121 additions & 13 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions rust/ruby-rbs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ xxhash-rust = { version = "0.8", features = ["xxh3"] }
[build-dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"

[dev-dependencies]
tempfile = "3"
66 changes: 66 additions & 0 deletions rust/ruby-rbs/src/environment/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
pub mod source;

pub use source::{Source, SourceKind};

use crate::interners::Interners;
use crate::loader::{EnvironmentLoader, LoadError};

/// Owning the interners here gives a single `Environment` value the same
/// role as the Ruby implementation's global name pool: names interned while
/// loading stay resolvable and displayable for the environment's lifetime.
#[derive(Default)]
pub struct Environment {
interners: Interners,
sources: Vec<Source>,
}

impl Environment {
#[must_use]
pub fn new() -> Self {
Self::default()
}

pub fn interners(&self) -> &Interners {
&self.interners
}

pub fn sources(&self) -> &[Source] {
&self.sources
}

pub(crate) fn interners_mut(&mut self) -> &mut Interners {
&mut self.interners
}

pub(crate) fn add_source(&mut self, source: Source) {
self.sources.push(source);
}

pub fn from_loader(loader: &EnvironmentLoader) -> Result<Environment, LoadError> {
let mut env = Environment::new();
loader.load(&mut env)?;
Ok(env)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn environment_owns_interners() {
let mut env = Environment::new();

let interners = env.interners_mut();
let symbol = interners.strings.intern("Foo");
let root = interners.type_names.absolute_root();
let name = interners.type_names.append(root, symbol);

let interners = env.interners();
assert_eq!(
interners.type_names.display(name, &interners.strings),
"::Foo"
);
assert!(env.sources().is_empty());
}
}
35 changes: 35 additions & 0 deletions rust/ruby-rbs/src/environment/source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use std::path::PathBuf;

use crate::ast::{Declaration, Directive};

/// Corresponds to the `source` values yielded by
/// `RBS::EnvironmentLoader#each_dir`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SourceKind {
Core,
/// `path` is the library's version directory, already resolved by the
/// caller (Ruby's `Repository#lookup` / `gem_sig_path`), holding the
/// library's RBS files directly. Version alone could not recover where a
/// library's signatures came from; the path can.
Library {
name: String,
path: PathBuf,
},
Dir {
path: PathBuf,
},
}

impl SourceKind {
pub(crate) fn skips_hidden(&self) -> bool {
!matches!(self, SourceKind::Dir { .. })
}
}

#[derive(Debug)]
pub struct Source {
pub path: PathBuf,
pub directives: Vec<Directive>,
pub declarations: Vec<Declaration>,
pub kind: SourceKind,
}
Loading
Loading