Skip to content

Commit

Permalink
Merge branch 'master' into boolean-and
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed Jul 20, 2023
2 parents 50b42df + 0449518 commit 7b5915d
Show file tree
Hide file tree
Showing 49 changed files with 1,059 additions and 365 deletions.
30 changes: 16 additions & 14 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ edition = "2021"
rust-version = "1.66"

[workspace.dependencies]
acvm = "0.19.0"
acvm = "0.19.1"
arena = { path = "crates/arena" }
fm = { path = "crates/fm" }
iter-extended = { path = "crates/iter-extended" }
Expand All @@ -40,7 +40,7 @@ noir_wasm = { path = "crates/wasm" }

cfg-if = "1.0.0"
clap = { version = "4.1.4", features = ["derive"] }
codespan = {version = "0.11.1", features = ["serialization"]}
codespan = { version = "0.11.1", features = ["serialization"] }
codespan-lsp = "0.11.1"
codespan-reporting = "0.11.1"
chumsky = { git = "https://github.com/jfecher/chumsky", rev = "ad9d312" }
Expand Down
11 changes: 11 additions & 0 deletions crates/fm/src/file_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ use std::path::Path;
#[cfg_attr(target_os = "windows", prefix = r"std\")] // Note reversed slash direction
struct StdLibAssets;

#[cfg(target_os = "windows")]
pub(super) fn is_stdlib_asset(path: &Path) -> bool {
path.starts_with("std\\")
}

#[cfg(not(target_os = "windows"))]
pub(super) fn is_stdlib_asset(path: &Path) -> bool {
path.starts_with("std/")
}

cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
use wasm_bindgen::{prelude::*, JsValue};
Expand Down Expand Up @@ -41,6 +51,7 @@ cfg_if::cfg_if! {
}
}
} else {

pub(crate) fn read_file_to_string(path_to_file: &Path) -> Result<String, Error> {

match StdLibAssets::get(path_to_file.to_str().unwrap()) {
Expand Down
118 changes: 84 additions & 34 deletions crates/fm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,55 @@ mod file_map;
mod file_reader;

pub use file_map::{File, FileId, FileMap};
use file_reader::is_stdlib_asset;

use std::{
collections::HashMap,
path::{Path, PathBuf},
path::{Component, Path, PathBuf},
};

pub const FILE_EXTENSION: &str = "nr";

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
struct VirtualPath(PathBuf);

#[derive(Debug, Default)]
#[derive(Debug)]
pub struct FileManager {
root: PathBuf,
file_map: file_map::FileMap,
id_to_path: HashMap<FileId, VirtualPath>,
path_to_id: HashMap<VirtualPath, FileId>,
}

impl FileManager {
// XXX: Maybe use a AsRef<Path> here, for API ergonomics
pub fn add_file(&mut self, path_to_file: &Path) -> Option<FileId> {
pub fn new(root: &Path) -> Self {
Self {
root: normalize_path(root),
file_map: Default::default(),
id_to_path: Default::default(),
path_to_id: Default::default(),
}
}

pub fn add_file(&mut self, file_name: &Path) -> Option<FileId> {
// Handle both relative file paths and std/lib virtual paths.
let base = Path::new(".").canonicalize().expect("Base path canonicalize failed");
let res = path_to_file.canonicalize().unwrap_or_else(|_| path_to_file.to_path_buf());
let resolved_path = res.strip_prefix(base).unwrap_or(&res);
let resolved_path: PathBuf = if is_stdlib_asset(file_name) {
// Special case for stdlib where we want to read specifically the `std/` relative path
// TODO: The stdlib path should probably be an absolute path rooted in something people would never create
file_name.to_path_buf()
} else {
normalize_path(&self.root.join(file_name))
};

// Check that the resolved path already exists in the file map, if it is, we return it.
let path_to_file = virtualize_path(resolved_path);
let path_to_file = virtualize_path(&resolved_path);
if let Some(file_id) = self.path_to_id.get(&path_to_file) {
return Some(*file_id);
}

// Otherwise we add the file
let source = file_reader::read_file_to_string(resolved_path).ok()?;
let file_id = self.file_map.add_file(resolved_path.to_path_buf().into(), source);
let source = file_reader::read_file_to_string(&resolved_path).ok()?;
let file_id = self.file_map.add_file(resolved_path.into(), source);
self.register_path(file_id, path_to_file);
Some(file_id)
}
Expand Down Expand Up @@ -87,6 +101,37 @@ impl FileManager {
}
}

/// Replacement for `std::fs::canonicalize` that doesn't verify the path exists.
///
/// Plucked from https://github.com/rust-lang/cargo/blob/fede83ccf973457de319ba6fa0e36ead454d2e20/src/cargo/util/paths.rs#L61
/// Advice from https://www.reddit.com/r/rust/comments/hkkquy/comment/fwtw53s/
fn normalize_path(path: &Path) -> PathBuf {
let mut components = path.components().peekable();
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
components.next();
PathBuf::from(c.as_os_str())
} else {
PathBuf::new()
};

for component in components {
match component {
Component::Prefix(..) => unreachable!(),
Component::RootDir => {
ret.push(component.as_os_str());
}
Component::CurDir => {}
Component::ParentDir => {
ret.pop();
}
Component::Normal(c) => {
ret.push(c);
}
}
}
ret
}

/// Takes a path to a noir file. This will panic on paths to directories
/// Returns the file path with the extension removed
fn virtualize_path(path: &Path) -> VirtualPath {
Expand All @@ -102,46 +147,49 @@ mod tests {
use super::*;
use tempfile::{tempdir, TempDir};

fn dummy_file_path(dir: &TempDir, file_name: &str) -> PathBuf {
fn create_dummy_file(dir: &TempDir, file_name: &Path) {
let file_path = dir.path().join(file_name);
let _file = std::fs::File::create(file_path.clone()).unwrap();

file_path
}

#[test]
fn path_resolve_file_module() {
let dir = tempdir().unwrap();
let file_path = dummy_file_path(&dir, "my_dummy_file.nr");

let mut fm = FileManager::default();
let entry_file_name = Path::new("my_dummy_file.nr");
create_dummy_file(&dir, entry_file_name);

let mut fm = FileManager::new(dir.path());

let file_id = fm.add_file(&file_path).unwrap();
let file_id = fm.add_file(entry_file_name).unwrap();

let _foo_file_path = dummy_file_path(&dir, "foo.nr");
let dep_file_name = Path::new("foo.nr");
create_dummy_file(&dir, dep_file_name);
fm.resolve_path(file_id, "foo").unwrap();
}
#[test]
fn path_resolve_file_module_other_ext() {
let dir = tempdir().unwrap();
let file_path = dummy_file_path(&dir, "foo.noir");
let file_name = Path::new("foo.noir");
create_dummy_file(&dir, file_name);

let mut fm = FileManager::default();
let mut fm = FileManager::new(dir.path());

let file_id = fm.add_file(&file_path).unwrap();
let file_id = fm.add_file(&file_name).unwrap();

assert!(fm.path(file_id).ends_with("foo"));
}
#[test]
fn path_resolve_sub_module() {
let mut fm = FileManager::default();

let dir = tempdir().unwrap();
let mut fm = FileManager::new(dir.path());

// Create a lib.nr file at the root.
// we now have dir/lib.nr
let file_path = dummy_file_path(&dir, "lib.nr");
let file_name = Path::new("lib.nr");
create_dummy_file(&dir, file_name);

let file_id = fm.add_file(&file_path).unwrap();
let file_id = fm.add_file(&file_name).unwrap();

// Create a sub directory
// we now have:
Expand All @@ -154,14 +202,14 @@ mod tests {
// we no have:
// - dir/lib.nr
// - dir/sub_dir/foo.nr
let _foo_file_path = dummy_file_path(&sub_dir, "foo.nr");
create_dummy_file(&sub_dir, Path::new("foo.nr"));

// Add a parent module for the sub_dir
// we no have:
// - dir/lib.nr
// - dir/sub_dir.nr
// - dir/sub_dir/foo.nr
let _sub_dir_root_file_path = dummy_file_path(&dir, &format!("{}.nr", sub_dir_name));
create_dummy_file(&dir, Path::new(&format!("{}.nr", sub_dir_name)));

// First check for the sub_dir.nr file and add it to the FileManager
let sub_dir_file_id = fm.resolve_path(file_id, sub_dir_name).unwrap();
Expand All @@ -176,20 +224,22 @@ mod tests {
/// they should both resolve to ../foo.nr
#[test]
fn path_resolve_modules_with_different_paths_as_same_file() {
let mut fm = FileManager::default();

// Create a lib.nr file at the root.
let dir = tempdir().unwrap();
let sub_dir = TempDir::new_in(&dir).unwrap();
let sub_sub_dir = TempDir::new_in(&sub_dir).unwrap();
let file_path = dummy_file_path(&dir, "lib.nr");

// Create another file in a subdirectory with a convoluted path
let second_file_path = dummy_file_path(&sub_sub_dir, "./../../lib.nr");
let mut fm = FileManager::new(dir.path());

// Create a lib.nr file at the root.
let file_name = Path::new("lib.nr");
create_dummy_file(&dir, file_name);

// Create another path with `./` and `../` inside it
let second_file_name = PathBuf::from(sub_sub_dir.path()).join("./../../lib.nr");

// Add both files to the file manager
let file_id = fm.add_file(&file_path).unwrap();
let second_file_id = fm.add_file(&second_file_path).unwrap();
let file_id = fm.add_file(&file_name).unwrap();
let second_file_id = fm.add_file(&second_file_name).unwrap();

assert_eq!(file_id, second_file_id);
}
Expand Down
1 change: 1 addition & 0 deletions crates/lsp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ edition.workspace = true
acvm.workspace = true
codespan-lsp.workspace = true
codespan-reporting.workspace = true
fm.workspace = true
lsp-types.workspace = true
noirc_driver.workspace = true
noirc_errors.workspace = true
Expand Down
Loading

0 comments on commit 7b5915d

Please sign in to comment.