diff --git a/crates/els/diagnostics.rs b/crates/els/diagnostics.rs index 82a03455a..d8abb3884 100644 --- a/crates/els/diagnostics.rs +++ b/crates/els/diagnostics.rs @@ -8,6 +8,7 @@ use std::time::Duration; use erg_common::consts::PYTHON_MODE; use erg_common::dict::Dict; +use erg_common::pathutil::{project_entry_file_of, project_root_dir_of}; use erg_common::spawn::{safe_yield, spawn_new_thread}; use erg_common::style::*; use erg_common::traits::Stream; @@ -31,7 +32,7 @@ use crate::channels::WorkerMessage; use crate::diff::{ASTDiff, HIRDiff}; use crate::server::{DefaultFeatures, ELSResult, RedirectableStdout, Server}; use crate::server::{ASK_AUTO_SAVE_ID, HEALTH_CHECKER_ID}; -use crate::util::{self, project_root_of, NormalizedUrl}; +use crate::util::{self, NormalizedUrl}; #[derive(Debug)] pub enum BuildASTError { @@ -408,7 +409,7 @@ impl Server { "method": "window/workDoneProgress/create", "params": progress_token, })); - let Some(project_root) = project_root_of(¤t_dir().unwrap()) else { + let Some(project_root) = project_root_dir_of(¤t_dir().unwrap()) else { work_done!(token); }; let src_dir = if project_root.join("src").is_dir() { @@ -416,11 +417,7 @@ impl Server { } else { project_root }; - let main_path = if src_dir.join("main.er").exists() { - src_dir.join("main.er") - } else if src_dir.join("lib.er").exists() { - src_dir.join("lib.er") - } else { + let Some(main_path) = project_entry_file_of(¤t_dir().unwrap()) else { work_done!(token); }; let Ok(main_uri) = NormalizedUrl::from_file_path(main_path) else { diff --git a/crates/els/server.rs b/crates/els/server.rs index f5bae411d..0dcdedf09 100644 --- a/crates/els/server.rs +++ b/crates/els/server.rs @@ -11,7 +11,7 @@ use erg_common::config::ErgConfig; use erg_common::consts::PYTHON_MODE; use erg_common::dict::Dict; use erg_common::env::erg_path; -use erg_common::pathutil::NormalizedPathBuf; +use erg_common::pathutil::{project_root_dir_of, NormalizedPathBuf}; use erg_common::shared::{MappedRwLockReadGuard, Shared}; use erg_common::spawn::{safe_yield, spawn_new_thread}; use erg_common::traits::Stream; @@ -61,7 +61,7 @@ use crate::file_cache::FileCache; use crate::hir_visitor::{ExprKind, HIRVisitor}; use crate::message::{ErrorMessage, LSPResult}; use crate::scheduler::Scheduler; -use crate::util::{self, loc_to_pos, project_root_of, NormalizedUrl}; +use crate::util::{self, loc_to_pos, NormalizedUrl}; pub const HEALTH_CHECKER_ID: i64 = 10000; pub const ASK_AUTO_SAVE_ID: i64 = 10001; @@ -952,7 +952,7 @@ impl Server { } pub(crate) fn get_workspace_ctxs(&self) -> Vec<&Context> { - let project_root = project_root_of(&self.home).unwrap_or(self.home.clone()); + let project_root = project_root_dir_of(&self.home).unwrap_or(self.home.clone()); let mut ctxs = vec![]; for (path, ent) in self.shared.raw_path_and_modules() { if path.starts_with(&project_root) { diff --git a/crates/els/util.rs b/crates/els/util.rs index 1ef2c57fc..5b3035386 100644 --- a/crates/els/util.rs +++ b/crates/els/util.rs @@ -183,17 +183,3 @@ pub(crate) fn abs_loc_to_lsp_loc(loc: &AbsLocation) -> Option Option { - if path.is_dir() && path.join("package.er").exists() { - return Some(path.to_path_buf()); - } - let mut path = path.to_path_buf(); - while let Some(parent) = path.parent() { - if parent.join("package.er").exists() { - return Some(parent.to_path_buf()); - } - path = parent.to_path_buf(); - } - None -} diff --git a/crates/erg_common/pathutil.rs b/crates/erg_common/pathutil.rs index 2faeabc7f..d22a05c62 100644 --- a/crates/erg_common/pathutil.rs +++ b/crates/erg_common/pathutil.rs @@ -11,7 +11,7 @@ use crate::{normalize_path, Str}; /// `PathBuf` may give false equivalence decisions in non-case-sensitive file systems. /// Use this for dictionary keys, etc. /// See also: `els::util::NormalizedUrl` -#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, PartialOrd, Ord)] pub struct NormalizedPathBuf(PathBuf); impl fmt::Display for NormalizedPathBuf { @@ -254,3 +254,30 @@ pub fn mod_name(path: &Path) -> Str { } Str::from(name) } + +pub fn project_root_dir_of(path: &Path) -> Option { + if path.is_dir() && path.join("package.er").exists() { + return Some(path.to_path_buf()); + } + let mut path = path.to_path_buf(); + while let Some(parent) = path.parent() { + if parent.join("package.er").exists() { + return Some(parent.to_path_buf()); + } + path = parent.to_path_buf(); + } + None +} + +pub fn project_entry_file_of(path: &Path) -> Option { + let project_root = project_root_dir_of(path)?; + if project_root.join("src/lib.er").exists() { + Some(project_root.join("src/lib.er")) + } else if project_root.join("src/main.er").exists() { + Some(project_root.join("src/main.er")) + } else if project_root.join("src/lib.d.er").exists() { + Some(project_root.join("src/lib.d.er")) + } else { + None + } +} diff --git a/crates/erg_common/tsort.rs b/crates/erg_common/tsort.rs index 45155ed8d..8b114d441 100644 --- a/crates/erg_common/tsort.rs +++ b/crates/erg_common/tsort.rs @@ -67,6 +67,10 @@ impl Node { self.depends_on.insert(dep); } + pub fn pop_dep(&mut self, dep: &T) -> bool { + self.depends_on.remove(dep) + } + pub fn depends_on(&self, dep: &T) -> bool { self.depends_on.contains(dep) } diff --git a/crates/erg_compiler/module/graph.rs b/crates/erg_compiler/module/graph.rs index 2d82e31ac..214314f5a 100644 --- a/crates/erg_compiler/module/graph.rs +++ b/crates/erg_compiler/module/graph.rs @@ -108,13 +108,13 @@ impl ModuleGraph { depends_on: NormalizedPathBuf, ) -> Result<(), IncRefError> { self.add_node_if_none(referrer); - if self.ancestors(&depends_on).contains(referrer) && referrer != &depends_on { + if referrer == &depends_on { + return Ok(()); + } + if self.ancestors(&depends_on).contains(referrer) { return Err(IncRefError::CycleDetected); } if let Some(node) = self.0.iter_mut().find(|n| &n.id == referrer) { - if referrer == &depends_on { - return Ok(()); - } node.push_dep(depends_on); } else { unreachable!("node not found: {}", referrer.display());