Import and export improved
- Import paths are now vname and not sym - Imports and exports accept multiple space-delimited operators in [] as a result, we can now reliably import and export the operator * - error reporting ergonomics
This commit is contained in:
@@ -6,13 +6,12 @@ use std::{fs, io};
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
use crate::error::{ErrorPosition, ProjectError, ProjectResult};
|
||||
use crate::error::{ProjectError, ProjectResult};
|
||||
#[allow(unused)] // for doc
|
||||
use crate::facade::System;
|
||||
use crate::interner::Interner;
|
||||
use crate::utils::iter::box_once;
|
||||
use crate::utils::{BoxedIter, Cache};
|
||||
use crate::{Stok, VName};
|
||||
use crate::utils::Cache;
|
||||
use crate::{Location, Stok, VName};
|
||||
|
||||
/// All the data available about a failed source load call
|
||||
#[derive(Debug)]
|
||||
@@ -25,8 +24,8 @@ impl ProjectError for FileLoadingError {
|
||||
fn description(&self) -> &str {
|
||||
"Neither a file nor a directory could be read from the requested path"
|
||||
}
|
||||
fn positions(&self, _i: &Interner) -> BoxedIter<ErrorPosition> {
|
||||
box_once(ErrorPosition::just_file(self.path.clone()))
|
||||
fn one_position(&self, _i: &Interner) -> crate::Location {
|
||||
Location::File(Rc::new(self.path.clone()))
|
||||
}
|
||||
fn message(&self, _i: &Interner) -> String {
|
||||
format!("File: {}\nDirectory: {}", self.file, self.dir)
|
||||
|
||||
@@ -14,7 +14,10 @@ fn assert_visible(
|
||||
target: &[Tok<String>], // may point to a symbol or module of any kind
|
||||
project: &ProjectTree<VName>,
|
||||
) -> ProjectResult<()> {
|
||||
let (tgt_item, tgt_path) = unwrap_or!(target.split_last(); return Ok(()));
|
||||
let (tgt_item, tgt_path) = unwrap_or! {
|
||||
target.split_last();
|
||||
return Ok(())
|
||||
};
|
||||
let shared_len =
|
||||
source.iter().zip(tgt_path.iter()).take_while(|(a, b)| a == b).count();
|
||||
let vis_ignored_len = usize::min(tgt_path.len(), shared_len + 1);
|
||||
|
||||
@@ -75,7 +75,7 @@ fn source_to_module(
|
||||
.collect::<Vec<_>>();
|
||||
let imports_from = (imports.iter())
|
||||
.map(|imp| -> ProjectResult<_> {
|
||||
let mut imp_path_v = i.r(imp.path).clone();
|
||||
let mut imp_path_v = imp.path.clone();
|
||||
imp_path_v.push(imp.name.expect("glob imports had just been resolved"));
|
||||
let mut abs_path = absolute_path(&path_v, &imp_path_v, i)
|
||||
.expect("should have failed in preparsing");
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::error::{NotFound, ProjectError, ProjectResult};
|
||||
use crate::interner::{Interner, Tok};
|
||||
use crate::pipeline::source_loader::LoadedSourceTable;
|
||||
use crate::representations::tree::WalkErrorKind;
|
||||
use crate::utils::{split_max_prefix, unwrap_or, Cache};
|
||||
use crate::utils::{split_max_prefix, Cache};
|
||||
use crate::Sym;
|
||||
|
||||
pub type OpsResult = ProjectResult<Rc<HashSet<Tok<String>>>>;
|
||||
@@ -33,40 +33,43 @@ pub fn collect_exported_ops(
|
||||
) -> OpsResult {
|
||||
let injected = injected(path).unwrap_or_else(|| Rc::new(HashSet::new()));
|
||||
let path_s = &i.r(path)[..];
|
||||
let name_split = split_max_prefix(path_s, &|n| loaded.contains_key(n));
|
||||
let (fpath, subpath) = unwrap_or!(name_split; return Ok(Rc::new(
|
||||
(loaded.keys())
|
||||
.filter_map(|modname| {
|
||||
if path_s.len() == coprefix(path_s.iter(), modname.iter()) {
|
||||
Some(modname[path_s.len()])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.chain(injected.iter().copied())
|
||||
.collect::<HashSet<_>>(),
|
||||
)));
|
||||
let preparsed = &loaded[fpath].preparsed;
|
||||
let module =
|
||||
preparsed.0.walk_ref(subpath, false).map_err(
|
||||
|walk_err| match walk_err.kind {
|
||||
WalkErrorKind::Private => {
|
||||
unreachable!("visibility is not being checked here")
|
||||
match split_max_prefix(path_s, &|n| loaded.contains_key(n)) {
|
||||
None => {
|
||||
let ops = (loaded.keys())
|
||||
.filter_map(|modname| {
|
||||
if path_s.len() == coprefix(path_s.iter(), modname.iter()) {
|
||||
Some(modname[path_s.len()])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.chain(injected.iter().copied())
|
||||
.collect::<HashSet<_>>();
|
||||
Ok(Rc::new(ops))
|
||||
},
|
||||
Some((fpath, subpath)) => {
|
||||
let preparsed = &loaded[fpath].preparsed;
|
||||
let module = preparsed.0.walk_ref(subpath, false).map_err(
|
||||
|walk_err| match walk_err.kind {
|
||||
WalkErrorKind::Private => {
|
||||
unreachable!("visibility is not being checked here")
|
||||
},
|
||||
WalkErrorKind::Missing => NotFound {
|
||||
source: None,
|
||||
file: fpath.to_vec(),
|
||||
subpath: subpath[..walk_err.pos].to_vec(),
|
||||
}
|
||||
.rc(),
|
||||
},
|
||||
WalkErrorKind::Missing => NotFound {
|
||||
source: None,
|
||||
file: fpath.to_vec(),
|
||||
subpath: subpath[..walk_err.pos].to_vec(),
|
||||
}
|
||||
.rc(),
|
||||
},
|
||||
)?;
|
||||
let out = (module.items.iter())
|
||||
.filter(|(_, v)| v.exported)
|
||||
.map(|(k, _)| *k)
|
||||
.chain(injected.iter().copied())
|
||||
.collect::<HashSet<_>>();
|
||||
Ok(Rc::new(out))
|
||||
)?;
|
||||
let out = (module.items.iter())
|
||||
.filter(|(_, v)| v.exported)
|
||||
.map(|(k, _)| *k)
|
||||
.chain(injected.iter().copied())
|
||||
.collect::<HashSet<_>>();
|
||||
Ok(Rc::new(out))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_cache<'a>(
|
||||
|
||||
@@ -44,7 +44,7 @@ pub fn collect_ops_for(
|
||||
ret.insert(n);
|
||||
} else {
|
||||
let path = i.expect(
|
||||
import_abs_path(file, modpath, &i.r(import.path)[..], i),
|
||||
import_abs_path(file, modpath, &import.path, i),
|
||||
"This error should have been caught during loading",
|
||||
);
|
||||
ret.extend(ops_cache.find(&i.i(&path))?.iter().copied());
|
||||
|
||||
@@ -59,7 +59,7 @@ fn entv_rec(
|
||||
.flat_map(|import| {
|
||||
if let Import { name: None, path } = import {
|
||||
let p = i.expect(
|
||||
import_abs_path(mod_path, mod_stack, &i.r(path)[..], i),
|
||||
import_abs_path(mod_path, mod_stack, &path, i),
|
||||
"Should have emerged in preparsing",
|
||||
);
|
||||
let names = i.expect(
|
||||
@@ -67,7 +67,7 @@ fn entv_rec(
|
||||
"Should have emerged in second parsing",
|
||||
);
|
||||
let imports = (names.iter())
|
||||
.map(move |&n| Import { name: Some(n), path })
|
||||
.map(|&n| Import { name: Some(n), path: path.clone() })
|
||||
.collect::<Vec<_>>();
|
||||
Box::new(imports.into_iter()) as BoxedIter<Import>
|
||||
} else {
|
||||
|
||||
@@ -56,7 +56,7 @@ fn load_abs_path_rec(
|
||||
// recurse on all imported modules
|
||||
preparsed.0.visit_all_imports(&mut |modpath, _module, import| {
|
||||
let abs_pathv =
|
||||
import_abs_path(filename, modpath, &import.nonglob_path(i), i)?;
|
||||
import_abs_path(filename, modpath, &import.nonglob_path(), i)?;
|
||||
if abs_path.starts_with(&abs_pathv) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user