mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 04:24:43 +00:00
fix: retry path resolution if failed
This commit is contained in:
parent
a9025507d3
commit
dab9def08a
2 changed files with 51 additions and 7 deletions
|
@ -2,6 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! コマンドオプション(パーサー)を定義する
|
//! コマンドオプション(パーサー)を定義する
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::ffi::OsStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{stdin, BufRead, BufReader, Read, Write};
|
use std::io::{stdin, BufRead, BufReader, Read, Write};
|
||||||
|
@ -319,6 +320,26 @@ impl Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn module_name(&self) -> String {
|
||||||
|
match &self.kind {
|
||||||
|
InputKind::File(filename) => {
|
||||||
|
let file_stem = if filename.file_stem() == Some(OsStr::new("__init__")) {
|
||||||
|
filename.parent().and_then(|p| p.file_stem())
|
||||||
|
} else {
|
||||||
|
filename.file_stem()
|
||||||
|
};
|
||||||
|
file_stem
|
||||||
|
.and_then(|f| f.to_str())
|
||||||
|
.unwrap_or("_")
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
InputKind::REPL | InputKind::Pipe(_) => "<stdin>".to_string(),
|
||||||
|
InputKind::DummyREPL(stdin) => stdin.name.clone(),
|
||||||
|
InputKind::Str(_) => "<string>".to_string(),
|
||||||
|
InputKind::Dummy => "<dummy>".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read(&mut self) -> String {
|
pub fn read(&mut self) -> String {
|
||||||
match &mut self.kind {
|
match &mut self.kind {
|
||||||
InputKind::File(filename) => {
|
InputKind::File(filename) => {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::BufRead;
|
use std::fs::{metadata, remove_file, File};
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
use std::option::Option;
|
use std::option::Option;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::time::SystemTime;
|
use std::thread::sleep;
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
use erg_common::config::ErgMode;
|
use erg_common::config::ErgMode;
|
||||||
use erg_common::consts::{ERG_MODE, PYTHON_MODE};
|
use erg_common::consts::{ERG_MODE, PYTHON_MODE};
|
||||||
|
@ -1953,15 +1955,22 @@ impl Context {
|
||||||
Str::from(name)
|
Str::from(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn analysis_in_progress(path: &Path) -> bool {
|
||||||
|
let Ok(meta) = metadata(path) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
!is_std_decl_path(path) && meta.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
fn availability(path: &Path) -> Availability {
|
fn availability(path: &Path) -> Availability {
|
||||||
let Ok(file) = std::fs::File::open(path) else {
|
let Ok(file) = File::open(path) else {
|
||||||
return Availability::NotFound;
|
return Availability::NotFound;
|
||||||
};
|
};
|
||||||
if is_std_decl_path(path) {
|
if is_std_decl_path(path) {
|
||||||
return Availability::Available;
|
return Availability::Available;
|
||||||
}
|
}
|
||||||
let mut line = "".to_string();
|
let mut line = "".to_string();
|
||||||
let Ok(_) = std::io::BufReader::new(file).read_line(&mut line) else {
|
let Ok(_) = BufReader::new(file).read_line(&mut line) else {
|
||||||
return Availability::Unreadable;
|
return Availability::Unreadable;
|
||||||
};
|
};
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
|
@ -1970,7 +1979,7 @@ impl Context {
|
||||||
let Ok(status) = line.parse::<PylyzerStatus>() else {
|
let Ok(status) = line.parse::<PylyzerStatus>() else {
|
||||||
return Availability::Available;
|
return Availability::Available;
|
||||||
};
|
};
|
||||||
let Some(meta) = std::fs::metadata(&status.file).ok() else {
|
let Some(meta) = metadata(&status.file).ok() else {
|
||||||
return Availability::NotFound;
|
return Availability::NotFound;
|
||||||
};
|
};
|
||||||
let dummy_hash = meta.len();
|
let dummy_hash = meta.len();
|
||||||
|
@ -1987,6 +1996,12 @@ impl Context {
|
||||||
if self.cfg.input.decl_file_is(&path) {
|
if self.cfg.input.decl_file_is(&path) {
|
||||||
return Ok(path);
|
return Ok(path);
|
||||||
}
|
}
|
||||||
|
for _ in 0..600 {
|
||||||
|
if !Self::analysis_in_progress(&path) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sleep(Duration::from_millis(100));
|
||||||
|
}
|
||||||
if matches!(Self::availability(&path), OutOfDate | NotFound | Unreadable) {
|
if matches!(Self::availability(&path), OutOfDate | NotFound | Unreadable) {
|
||||||
let _ = self.try_gen_py_decl_file(__name__);
|
let _ = self.try_gen_py_decl_file(__name__);
|
||||||
}
|
}
|
||||||
|
@ -2038,7 +2053,7 @@ impl Context {
|
||||||
// It can convert a Python script to an Erg AST for code analysis.
|
// It can convert a Python script to an Erg AST for code analysis.
|
||||||
// There is also an option to output the analysis result as `d.er`. Use this if the system have pylyzer installed.
|
// There is also an option to output the analysis result as `d.er`. Use this if the system have pylyzer installed.
|
||||||
// A type definition file may be generated even if not all type checks succeed.
|
// A type definition file may be generated even if not all type checks succeed.
|
||||||
if let Ok(_status) = Command::new("pylyzer")
|
if let Ok(status) = Command::new("pylyzer")
|
||||||
.arg("--dump-decl")
|
.arg("--dump-decl")
|
||||||
.arg(path.to_str().unwrap())
|
.arg(path.to_str().unwrap())
|
||||||
.stdout(out)
|
.stdout(out)
|
||||||
|
@ -2047,7 +2062,15 @@ impl Context {
|
||||||
.and_then(|mut child| child.wait())
|
.and_then(|mut child| child.wait())
|
||||||
{
|
{
|
||||||
if let Some(path) = self.cfg.input.resolve_decl_path(Path::new(&__name__[..])) {
|
if let Some(path) = self.cfg.input.resolve_decl_path(Path::new(&__name__[..])) {
|
||||||
return Ok(path);
|
let size = metadata(&path).unwrap().len();
|
||||||
|
// if pylyzer crashed
|
||||||
|
if !status.success() && size == 0 {
|
||||||
|
// The presence of the decl file indicates that the analysis is in progress or completed,
|
||||||
|
// so if pylyzer crashes in the middle of the analysis, delete the file.
|
||||||
|
remove_file(&path).unwrap();
|
||||||
|
} else {
|
||||||
|
return Ok(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue