mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
fix: path resolution bug
This commit is contained in:
parent
829b0d11b6
commit
ac7a57a094
5 changed files with 62 additions and 49 deletions
|
@ -441,16 +441,16 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolution order:
|
/// resolution order:
|
||||||
/// 1. `{path}.er`
|
/// 1. `{path/to}.er`
|
||||||
/// 2. `{path}/__init__.er`
|
/// 2. `{path/to}/__init__.er`
|
||||||
fn resolve_local(&self, path: &Path) -> Result<PathBuf, std::io::Error> {
|
fn resolve_local(&self, path: &Path) -> Result<PathBuf, std::io::Error> {
|
||||||
let mut dir = self.dir();
|
let mut dir = self.dir();
|
||||||
dir.push(path);
|
dir.push(path);
|
||||||
dir.set_extension("er"); // {path}.er
|
dir.set_extension("er"); // {path/to}.er
|
||||||
let path = dir.canonicalize().or_else(|_| {
|
let path = dir.canonicalize().or_else(|_| {
|
||||||
dir.pop();
|
dir.pop(); // {path}
|
||||||
dir.push(path);
|
dir.push(path.iter().last().unwrap_or_default()); // {path/to}
|
||||||
dir.push("__init__.er"); // -> {path}/__init__.er
|
dir.push("__init__.er"); // -> {path/to}/__init__.er
|
||||||
dir.canonicalize()
|
dir.canonicalize()
|
||||||
})?;
|
})?;
|
||||||
Ok(normalize_path(path))
|
Ok(normalize_path(path))
|
||||||
|
@ -464,10 +464,10 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolution order:
|
/// resolution order:
|
||||||
/// 1. `{path}.d.er`
|
/// 1. `{path/to}.d.er`
|
||||||
/// 2. `{path}/__init__.d.er`
|
/// 2. `{path/to}/__init__.d.er`
|
||||||
/// 3. `__pycache__/{path}.d.er`
|
/// 3. `{path}/__pycache__/{to}.d.er`
|
||||||
/// 4. `{path}/__pycache__/__init__.d.er`
|
/// 4. `{path/to}/__pycache__/__init__.d.er`
|
||||||
fn _resolve_local_decl(&self, path: &Path) -> Result<PathBuf, std::io::Error> {
|
fn _resolve_local_decl(&self, path: &Path) -> Result<PathBuf, std::io::Error> {
|
||||||
let mut dir = self.dir();
|
let mut dir = self.dir();
|
||||||
let mut comps = path.components();
|
let mut comps = path.components();
|
||||||
|
@ -477,29 +477,29 @@ impl Input {
|
||||||
let last_path = Path::new(&last);
|
let last_path = Path::new(&last);
|
||||||
dir.push(comps);
|
dir.push(comps);
|
||||||
dir.push(last_path);
|
dir.push(last_path);
|
||||||
dir.set_extension("d.er"); // {path}.d.er
|
dir.set_extension("d.er"); // {path/to}.d.er
|
||||||
let path = dir
|
let path = dir
|
||||||
.canonicalize()
|
.canonicalize()
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
dir.pop(); // {path}.d.er -> ./
|
dir.pop(); // {path/to}.d.er -> {path}
|
||||||
dir.push(last_path); // -> {path}
|
dir.push(last_path); // -> {path/to}
|
||||||
dir.push("__init__.d.er"); // -> {path}/__init__.d.er
|
dir.push("__init__.d.er"); // -> {path/to}/__init__.d.er
|
||||||
dir.canonicalize()
|
dir.canonicalize()
|
||||||
})
|
})
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
|
dir.pop(); // -> {path/to}
|
||||||
dir.pop(); // -> {path}
|
dir.pop(); // -> {path}
|
||||||
dir.pop(); // -> ./
|
dir.push("__pycache__"); // -> {path}/__pycache__
|
||||||
dir.push("__pycache__");
|
dir.push(last_path); // -> {path}/__pycache__/{to}
|
||||||
dir.push(last_path);
|
dir.set_extension("d.er"); // -> {path}/__pycache__/{to}.d.er
|
||||||
dir.set_extension("d.er"); // -> __pycache__/{path}.d.er
|
|
||||||
dir.canonicalize()
|
dir.canonicalize()
|
||||||
})
|
})
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
dir.pop(); // -> __pycache__
|
dir.pop(); // -> {path}/__pycache__
|
||||||
dir.pop(); // -> ./
|
dir.pop(); // -> {path}
|
||||||
dir.push(last_path); // -> {path}
|
dir.push(last_path); // -> {path/to}
|
||||||
dir.push("__pycache__"); // -> {path}/__pycache__
|
dir.push("__pycache__"); // -> {path/to}/__pycache__
|
||||||
dir.push("__init__.d.er"); // -> {path}/__pycache__/__init__.d.er
|
dir.push("__init__.d.er"); // -> {path/to}/__pycache__/__init__.d.er
|
||||||
dir.canonicalize()
|
dir.canonicalize()
|
||||||
})?;
|
})?;
|
||||||
Ok(normalize_path(path))
|
Ok(normalize_path(path))
|
||||||
|
@ -551,10 +551,10 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolution order:
|
/// resolution order:
|
||||||
/// 1. `./{path}.er`
|
/// 1. `./{path/to}.er`
|
||||||
/// 2. `./{path}/__init__.er`
|
/// 2. `./{path/to}/__init__.er`
|
||||||
/// 3. `std/{path}.er`
|
/// 3. `std/{path/to}.er`
|
||||||
/// 4. `std/{path}/__init__.er`
|
/// 4. `std/{path/to}/__init__.er`
|
||||||
pub fn resolve_real_path(&self, path: &Path) -> Option<PathBuf> {
|
pub fn resolve_real_path(&self, path: &Path) -> Option<PathBuf> {
|
||||||
if let Ok(path) = self.resolve_local(path) {
|
if let Ok(path) = self.resolve_local(path) {
|
||||||
Some(path)
|
Some(path)
|
||||||
|
@ -575,16 +575,16 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolution order:
|
/// resolution order:
|
||||||
/// 1. `{path}.d.er`
|
/// 1. `{path/to}.d.er`
|
||||||
/// 2. `{path}/__init__.d.er`
|
/// 2. `{path/to}/__init__.d.er`
|
||||||
/// 3. `__pycache__/{path}.d.er`
|
/// 3. `{path}/__pycache__/{to}.d.er`
|
||||||
/// 4. `{path}/__pycache__/__init__.d.er`
|
/// 4. `{path/to}/__pycache__/__init__.d.er`
|
||||||
/// 5. `{path}.d/__init__.d.er`
|
/// 5. `{path.d/to.d}/__init__.d.er`
|
||||||
/// 6. `{path}.d/__pycache__/__init__.d.er`
|
/// 6. `{path.d/to.d}/__pycache__/__init__.d.er`
|
||||||
/// 7. `std/{path}.d.er`
|
/// 7. `std/{path/to}.d.er`
|
||||||
/// 8. `std/{path}/__init__.d.er`
|
/// 8. `std/{path/to}/__init__.d.er`
|
||||||
/// 9. `site-packages/__pycache__/{path}.d.er`
|
/// 9. `site-packages/{path}/__pycache__/{to}.d.er`
|
||||||
/// 10. `site-packages/{path}/__pycache__/__init__.d.er`
|
/// 10. `site-packages/{path/to}/__pycache__/__init__.d.er`
|
||||||
pub fn resolve_decl_path(&self, path: &Path) -> Option<PathBuf> {
|
pub fn resolve_decl_path(&self, path: &Path) -> Option<PathBuf> {
|
||||||
if let Ok(path) = self.resolve_local_decl(path) {
|
if let Ok(path) = self.resolve_local_decl(path) {
|
||||||
Some(path)
|
Some(path)
|
||||||
|
|
|
@ -1793,12 +1793,12 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_err(&self, __name__: &Str, loc: &impl Locational) -> TyCheckErrors {
|
fn import_err(&self, line: u32, __name__: &Str, loc: &impl Locational) -> TyCheckErrors {
|
||||||
let mod_cache = self.mod_cache();
|
let mod_cache = self.mod_cache();
|
||||||
let py_mod_cache = self.py_mod_cache();
|
let py_mod_cache = self.py_mod_cache();
|
||||||
TyCheckErrors::from(TyCheckError::import_error(
|
TyCheckErrors::from(TyCheckError::import_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line as usize,
|
||||||
format!("module {__name__} not found"),
|
format!("module {__name__} not found"),
|
||||||
loc.loc(),
|
loc.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
|
@ -1813,7 +1813,7 @@ impl Context {
|
||||||
let path = match self.cfg.input.resolve_real_path(Path::new(&__name__[..])) {
|
let path = match self.cfg.input.resolve_real_path(Path::new(&__name__[..])) {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => {
|
None => {
|
||||||
return Err(self.import_err(__name__, loc));
|
return Err(self.import_err(line!(), __name__, loc));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.check_mod_vis(path.as_path(), __name__, loc)?;
|
self.check_mod_vis(path.as_path(), __name__, loc)?;
|
||||||
|
@ -1834,8 +1834,14 @@ impl Context {
|
||||||
__name__: &Str,
|
__name__: &Str,
|
||||||
loc: &impl Locational,
|
loc: &impl Locational,
|
||||||
) -> CompileResult<()> {
|
) -> CompileResult<()> {
|
||||||
if let Some(parent) = path.parent() {
|
let file_kind = FileKind::from(path);
|
||||||
if FileKind::from(path).is_simple_erg_file() && DirKind::from(parent).is_erg_module() {
|
let parent = if file_kind.is_init_er() {
|
||||||
|
path.parent().and_then(|p| p.parent())
|
||||||
|
} else {
|
||||||
|
path.parent()
|
||||||
|
};
|
||||||
|
if let Some(parent) = parent {
|
||||||
|
if DirKind::from(parent).is_erg_module() {
|
||||||
let parent = parent.join("__init__.er");
|
let parent = parent.join("__init__.er");
|
||||||
let parent_module = if let Some(parent) = self.get_mod_with_path(&parent) {
|
let parent_module = if let Some(parent) = self.get_mod_with_path(&parent) {
|
||||||
Some(parent)
|
Some(parent)
|
||||||
|
@ -1845,10 +1851,10 @@ impl Context {
|
||||||
self.get_mod_with_path(&parent)
|
self.get_mod_with_path(&parent)
|
||||||
};
|
};
|
||||||
if let Some(parent_module) = parent_module {
|
if let Some(parent_module) = parent_module {
|
||||||
let import_err = || {
|
let import_err = |line| {
|
||||||
TyCheckErrors::from(TyCheckError::import_error(
|
TyCheckErrors::from(TyCheckError::import_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line as usize,
|
||||||
format!("module `{__name__}` is not public"),
|
format!("module `{__name__}` is not public"),
|
||||||
loc.loc(),
|
loc.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
|
@ -1856,13 +1862,18 @@ impl Context {
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
let mod_name = path.file_stem().unwrap_or_default().to_string_lossy();
|
let file_stem = if file_kind.is_init_er() {
|
||||||
|
path.parent().unwrap().file_stem()
|
||||||
|
} else {
|
||||||
|
path.file_stem()
|
||||||
|
};
|
||||||
|
let mod_name = file_stem.unwrap_or_default().to_string_lossy();
|
||||||
if let Some((_, vi)) = parent_module.get_var_info(&mod_name) {
|
if let Some((_, vi)) = parent_module.get_var_info(&mod_name) {
|
||||||
if !vi.vis.compatible(&ast::AccessModifier::Public, self) {
|
if !vi.vis.compatible(&ast::AccessModifier::Public, self) {
|
||||||
return Err(import_err());
|
return Err(import_err(line!()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(import_err());
|
return Err(import_err(line!()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1881,7 +1892,7 @@ impl Context {
|
||||||
let src = cfg
|
let src = cfg
|
||||||
.input
|
.input
|
||||||
.try_read()
|
.try_read()
|
||||||
.map_err(|_| self.import_err(__name__, loc))?;
|
.map_err(|_| self.import_err(line!(), __name__, loc))?;
|
||||||
let mut builder =
|
let mut builder =
|
||||||
HIRBuilder::new_with_cache(cfg, __name__, self.shared.as_ref().unwrap().clone());
|
HIRBuilder::new_with_cache(cfg, __name__, self.shared.as_ref().unwrap().clone());
|
||||||
match builder.build(src, "exec") {
|
match builder.build(src, "exec") {
|
||||||
|
@ -2040,7 +2051,7 @@ impl Context {
|
||||||
let src = cfg
|
let src = cfg
|
||||||
.input
|
.input
|
||||||
.try_read()
|
.try_read()
|
||||||
.map_err(|_| self.import_err(__name__, loc))?;
|
.map_err(|_| self.import_err(line!(), __name__, loc))?;
|
||||||
let mut builder = HIRBuilder::new_with_cache(
|
let mut builder = HIRBuilder::new_with_cache(
|
||||||
cfg,
|
cfg,
|
||||||
self.mod_name(&path),
|
self.mod_name(&path),
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
.bar = import "./bar"
|
.bar = import "./bar"
|
||||||
|
.quux = import "./quux"
|
||||||
|
|
0
tests/should_err/foo/quux/__init__.er
Normal file
0
tests/should_err/foo/quux/__init__.er
Normal file
|
@ -2,3 +2,4 @@ _ = import "foo" # OK
|
||||||
_ = import "foo/bar" # OK
|
_ = import "foo/bar" # OK
|
||||||
_ = import "foo/baz" # ERR
|
_ = import "foo/baz" # ERR
|
||||||
_ = import "foo/qux" # ERR
|
_ = import "foo/qux" # ERR
|
||||||
|
_ = import "foo/quux" # OK
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue