chore(els): remove AnalysisResultCache

This commit is contained in:
Shunsuke Shibayama 2023-09-14 13:59:42 +09:00
parent d92e3f5425
commit 94b5fc27e9
13 changed files with 198 additions and 282 deletions

28
Cargo.lock generated
View file

@ -186,9 +186,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.147" version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -257,9 +257,9 @@ dependencies = [
[[package]] [[package]]
name = "molc" name = "molc"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9485212d67a88d2169ee683420e1a2fe763afb96a3901ebfabb5ba095d0d2eaa" checksum = "b266c0d03bfc46984d579c11d4fa2ea76f2cb4680477f4af7c97a306745e12d5"
dependencies = [ dependencies = [
"lsp-types", "lsp-types",
"serde", "serde",
@ -325,9 +325,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.66" version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -385,14 +385,14 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.31", "syn 2.0.33",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.105" version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -407,7 +407,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.31", "syn 2.0.33",
] ]
[[package]] [[package]]
@ -459,9 +459,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.31" version = "2.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" checksum = "9caece70c63bfba29ec2fed841a09851b14a235c60010fa4de58089b6c025668"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -501,9 +501,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.11" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"

View file

@ -19,6 +19,7 @@ pretty = ["erg_common/pretty", "erg_compiler/pretty"]
large_thread = ["erg_common/large_thread", "erg_compiler/large_thread"] large_thread = ["erg_common/large_thread", "erg_compiler/large_thread"]
py_compat = ["erg_compiler/py_compat"] py_compat = ["erg_compiler/py_compat"]
experimental = ["erg_common/experimental", "erg_compiler/experimental"] experimental = ["erg_common/experimental", "erg_compiler/experimental"]
backtrace = ["erg_common/backtrace"]
[dependencies] [dependencies]
erg_common = { workspace = true, features = ["els"] } erg_common = { workspace = true, features = ["els"] }

View file

@ -42,10 +42,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
let Ok(loc) = AbsLocation::from_str(data) else { let Ok(loc) = AbsLocation::from_str(data) else {
return Ok(None); return Ok(None);
}; };
let Some(shared) = self.get_shared() else { if let Some(refs) = self.shared.index.get_refs(&loc) {
return Ok(None);
};
if let Some(refs) = shared.index.get_refs(&loc) {
for referrer_loc in refs.referrers.iter() { for referrer_loc in refs.referrers.iter() {
let Some(uri) = referrer_loc let Some(uri) = referrer_loc
.module .module

View file

@ -32,13 +32,11 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
self.send_log("visitor not found")?; self.send_log("visitor not found")?;
return Ok(None); return Ok(None);
}; };
let Some(result) = self.analysis_result.get(&uri) else { let Some(warns) = self.get_warns(&uri) else {
self.send_log("artifact not found")?; self.send_log("artifact not found")?;
return Ok(None); return Ok(None);
}; };
let warns = result let warns = warns
.artifact
.warns
.iter() .iter()
.filter(|warn| warn.core.main_message.ends_with("is not used")) .filter(|warn| warn.core.main_message.ends_with("is not used"))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -72,7 +70,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
} }
Some(";") => range.end.character += 1, Some(";") => range.end.character += 1,
Some(other) => { Some(other) => {
self.send_log(format!("? {other}"))?; crate::_log!(self, "? {other}");
} }
} }
let edit = TextEdit::new(range, "".to_string()); let edit = TextEdit::new(range, "".to_string());
@ -116,7 +114,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
let def_loc = visitor.get_info(&token)?.def_loc; let def_loc = visitor.get_info(&token)?.def_loc;
let edit = TextEdit::new(util::loc_to_range(def_loc.loc)?, new_text.clone()); let edit = TextEdit::new(util::loc_to_range(def_loc.loc)?, new_text.clone());
map.insert(uri.clone().raw(), vec![edit]); map.insert(uri.clone().raw(), vec![edit]);
if let Some(value) = self.get_index().and_then(|ind| ind.get_refs(&def_loc)) { if let Some(value) = self.shared.index.get_refs(&def_loc) {
for refer in value.referrers.iter() { for refer in value.referrers.iter() {
let url = Url::from_file_path(refer.module.as_ref()?).ok()?; let url = Url::from_file_path(refer.module.as_ref()?).ok()?;
let range = util::loc_to_range(refer.loc)?; let range = util::loc_to_range(refer.loc)?;
@ -389,10 +387,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
code code
}; };
changes.insert(uri.raw(), vec![delete]); changes.insert(uri.raw(), vec![delete]);
if let Some(index) = self if let Some(index) = self.shared.index.get_refs(&def.sig.ident().vi.def_loc) {
.get_index()
.and_then(|index| index.get_refs(&def.sig.ident().vi.def_loc))
{
for ref_ in index.referrers.iter() { for ref_ in index.referrers.iter() {
let Some(path) = ref_.module.as_ref() else { let Some(path) = ref_.module.as_ref() else {
continue; continue;

View file

@ -8,7 +8,6 @@ use std::time::Duration;
use erg_common::consts::PYTHON_MODE; use erg_common::consts::PYTHON_MODE;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::shared::MappedRwLockReadGuard;
use erg_common::spawn::{safe_yield, spawn_new_thread}; use erg_common::spawn::{safe_yield, spawn_new_thread};
use erg_common::style::*; use erg_common::style::*;
use erg_common::traits::Stream; use erg_common::traits::Stream;
@ -28,7 +27,7 @@ use serde_json::json;
use crate::_log; use crate::_log;
use crate::channels::WorkerMessage; use crate::channels::WorkerMessage;
use crate::diff::{ASTDiff, HIRDiff}; use crate::diff::{ASTDiff, HIRDiff};
use crate::server::{AnalysisResult, DefaultFeatures, ELSResult, RedirectableStdout, Server}; use crate::server::{DefaultFeatures, ELSResult, RedirectableStdout, Server};
use crate::server::{ASK_AUTO_SAVE_ID, HEALTH_CHECKER_ID}; use crate::server::{ASK_AUTO_SAVE_ID, HEALTH_CHECKER_ID};
use crate::util::{self, project_root_of, NormalizedUrl}; use crate::util::{self, project_root_of, NormalizedUrl};
@ -43,45 +42,40 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
uri: NormalizedUrl, uri: NormalizedUrl,
code: S, code: S,
) -> ELSResult<()> { ) -> ELSResult<()> {
self.send_log(format!("checking {uri}"))?; _log!(self, "checking {uri}");
let path = util::uri_to_path(&uri); let path = util::uri_to_path(&uri);
let mode = if path.to_string_lossy().ends_with(".d.er") { let mode = if path.to_string_lossy().ends_with(".d.er") {
"declare" "declare"
} else { } else {
"exec" "exec"
}; };
let old = self.analysis_result.get_ast(&uri).or_else(|| { let old = self.get_ast(&uri);
let ent = self.get_shared()?.mod_cache.get(&path)?;
ent.ast.as_ref()?;
Some(MappedRwLockReadGuard::map(ent, |ent| {
ent.ast.as_ref().unwrap()
}))
});
if let Some((old, new)) = old.zip(self.build_ast(&uri)) { if let Some((old, new)) = old.zip(self.build_ast(&uri)) {
if ASTDiff::diff(old, &new).is_nop() { if ASTDiff::diff(old, &new).is_nop() {
crate::_log!(self, "no changes: {uri}"); _log!(self, "no changes: {uri}");
return Ok(()); return Ok(());
} }
} }
let mut checker = self.get_checker(path.clone()); let mut checker = self.get_checker(path.clone());
let artifact = match checker.build(code.into(), mode) { let artifact = match checker.build(code.into(), mode) {
Ok(artifact) => { Ok(artifact) => {
self.send_log(format!( _log!(
self,
"checking {uri} passed, found warns: {}", "checking {uri} passed, found warns: {}",
artifact.warns.len() artifact.warns.len()
))?; );
let uri_and_diags = self.make_uri_and_diags(artifact.warns.clone()); let uri_and_diags = self.make_uri_and_diags(artifact.warns.clone());
// clear previous diagnostics // clear previous diagnostics
self.send_diagnostics(uri.clone().raw(), vec![])?; self.send_diagnostics(uri.clone().raw(), vec![])?;
for (uri, diags) in uri_and_diags.into_iter() { for (uri, diags) in uri_and_diags.into_iter() {
self.send_log(format!("{uri}, warns: {}", diags.len()))?; _log!(self, "{uri}, warns: {}", diags.len());
self.send_diagnostics(uri, diags)?; self.send_diagnostics(uri, diags)?;
} }
artifact.into() artifact.into()
} }
Err(artifact) => { Err(artifact) => {
self.send_log(format!("found errors: {}", artifact.errors.len()))?; _log!(self, "found errors: {}", artifact.errors.len());
self.send_log(format!("found warns: {}", artifact.warns.len()))?; _log!(self, "found warns: {}", artifact.warns.len());
let diags = artifact let diags = artifact
.errors .errors
.clone() .clone()
@ -93,36 +87,32 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
self.send_diagnostics(uri.clone().raw(), vec![])?; self.send_diagnostics(uri.clone().raw(), vec![])?;
} }
for (uri, diags) in uri_and_diags.into_iter() { for (uri, diags) in uri_and_diags.into_iter() {
self.send_log(format!("{uri}, errs & warns: {}", diags.len()))?; _log!(self, "{uri}, errs & warns: {}", diags.len());
self.send_diagnostics(uri, diags)?; self.send_diagnostics(uri, diags)?;
} }
artifact artifact
} }
}; };
if let Some(shared) = self.get_shared() { let ast = self.build_ast(&uri);
let ast = self.build_ast(&uri); if mode == "declare" {
if mode == "declare" { self.shared.py_mod_cache.register(
shared.py_mod_cache.register( path,
path, ast,
ast, artifact.object,
artifact.object.clone(), checker.get_context().unwrap().clone(),
checker.get_context().unwrap().clone(), );
); } else {
} else { self.shared.mod_cache.register(
shared.mod_cache.register( path,
path, ast,
ast, artifact.object,
artifact.object.clone(), checker.get_context().unwrap().clone(),
checker.get_context().unwrap().clone(), );
);
}
}
if let Some(module) = self.build_ast(&uri) {
self.analysis_result
.insert(uri.clone(), AnalysisResult::new(module, artifact));
} }
self.shared.errors.extend(artifact.errors);
self.shared.warns.extend(artifact.warns);
if let Some(module) = checker.pop_context() { if let Some(module) = checker.pop_context() {
self.send_log(format!("{uri}: {}", module.context.name))?; _log!(self, "{uri}: {}", module.context.name);
self.modules.insert(uri.clone(), module); self.modules.insert(uri.clone(), module);
} }
let dependents = self.dependents_of(&uri); let dependents = self.dependents_of(&uri);
@ -135,7 +125,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
} }
pub(crate) fn quick_check_file(&mut self, uri: NormalizedUrl) -> ELSResult<()> { pub(crate) fn quick_check_file(&mut self, uri: NormalizedUrl) -> ELSResult<()> {
let Some(old) = self.analysis_result.get_ast(&uri) else { let Some(old) = self.get_ast(&uri) else {
crate::_log!(self, "not found"); crate::_log!(self, "not found");
return Ok(()); return Ok(());
}; };
@ -146,11 +136,16 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
let ast_diff = ASTDiff::diff(old, &new); let ast_diff = ASTDiff::diff(old, &new);
crate::_log!(self, "diff: {ast_diff}"); crate::_log!(self, "diff: {ast_diff}");
if let Some(mut lowerer) = self.steal_lowerer(&uri) { if let Some(mut lowerer) = self.steal_lowerer(&uri) {
let hir = self.get_mut_hir(&uri); let mut ent = self.steal_entry(&uri);
if let Some((hir_diff, hir)) = HIRDiff::new(ast_diff, &mut lowerer).zip(hir) { if let Some((hir_diff, hir)) = HIRDiff::new(ast_diff, &mut lowerer)
.zip(ent.as_mut().and_then(|ent| ent.hir.as_mut()))
{
crate::_log!(self, "hir_diff: {hir_diff}"); crate::_log!(self, "hir_diff: {hir_diff}");
hir_diff.update(hir); hir_diff.update(hir);
} }
if let Some(ent) = ent {
self.restore_entry(uri.clone(), ent);
}
self.restore_lowerer(uri, lowerer); self.restore_lowerer(uri, lowerer);
} }
// skip checking for dependents // skip checking for dependents

View file

@ -33,7 +33,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
pub(crate) fn get_refs_from_abs_loc(&self, referee: &AbsLocation) -> Vec<lsp_types::Location> { pub(crate) fn get_refs_from_abs_loc(&self, referee: &AbsLocation) -> Vec<lsp_types::Location> {
let mut refs = vec![]; let mut refs = vec![];
if let Some(value) = self.get_index().and_then(|ind| ind.get_refs(referee)) { if let Some(value) = self.shared.index.get_refs(referee) {
if value.vi.def_loc == AbsLocation::unknown() { if value.vi.def_loc == AbsLocation::unknown() {
return vec![]; return vec![];
} }

View file

@ -70,7 +70,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
return self.send_error_info(error_reason); return self.send_error_info(error_reason);
} }
Self::commit_change(&mut changes, &vi.def_loc, params.new_name.clone()); Self::commit_change(&mut changes, &vi.def_loc, params.new_name.clone());
if let Some(value) = self.get_index().and_then(|ind| ind.get_refs(&vi.def_loc)) { if let Some(value) = self.shared.index.get_refs(&vi.def_loc) {
// self.send_log(format!("referrers: {referrers:?}"))?; // self.send_log(format!("referrers: {referrers:?}"))?;
for referrer in value.referrers.iter() { for referrer in value.referrers.iter() {
Self::commit_change(&mut changes, referrer, params.new_name.clone()); Self::commit_change(&mut changes, referrer, params.new_name.clone());
@ -147,7 +147,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
/// self is __included__ /// self is __included__
pub fn dependencies_of(&self, uri: &NormalizedUrl) -> Vec<NormalizedUrl> { pub fn dependencies_of(&self, uri: &NormalizedUrl) -> Vec<NormalizedUrl> {
let graph = self.get_graph().unwrap(); let graph = &self.shared.graph;
let path = NormalizedPathBuf::from(util::uri_to_path(uri)); let path = NormalizedPathBuf::from(util::uri_to_path(uri));
graph.sort().unwrap(); graph.sort().unwrap();
let self_node = graph.get_node(&path).unwrap(); let self_node = graph.get_node(&path).unwrap();
@ -161,7 +161,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
/// self is __not included__ /// self is __not included__
pub fn dependents_of(&self, uri: &NormalizedUrl) -> Vec<NormalizedUrl> { pub fn dependents_of(&self, uri: &NormalizedUrl) -> Vec<NormalizedUrl> {
let graph = self.get_graph().unwrap(); let graph = &self.shared.graph;
let path = NormalizedPathBuf::from(util::uri_to_path(uri)); let path = NormalizedPathBuf::from(util::uri_to_path(uri));
graph graph
.ref_inner() .ref_inner()
@ -304,19 +304,17 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
let new_uri = NormalizedUrl::new(new); let new_uri = NormalizedUrl::new(new);
edits.extend(self.collect_module_changes(&old_uri, &new_uri)); edits.extend(self.collect_module_changes(&old_uri, &new_uri));
self.rename_linked_files(&mut renames, &old_uri, &new_uri); self.rename_linked_files(&mut renames, &old_uri, &new_uri);
let Some(entry) = self.analysis_result.remove(&old_uri) else { let Some(entry) = self.remove_module_entry(&old_uri) else {
continue; continue;
}; };
self.analysis_result.insert(new_uri.clone(), entry); self.insert_module_entry(new_uri.clone(), entry);
let Some(entry) = self.modules.remove(&old_uri) else { let Some(entry) = self.modules.remove(&old_uri) else {
continue; continue;
}; };
if let Some(shared) = self.get_shared() { self.shared.rename_path(
shared.rename_path( &old_uri.to_file_path().unwrap(),
&old_uri.to_file_path().unwrap(), new_uri.to_file_path().unwrap(),
new_uri.to_file_path().unwrap(), );
);
}
self.modules.insert(new_uri, entry); self.modules.insert(new_uri, entry);
} }
self.file_cache.rename_files(&params)?; self.file_cache.rename_files(&params)?;

View file

@ -11,20 +11,20 @@ use erg_common::config::ErgConfig;
use erg_common::consts::PYTHON_MODE; use erg_common::consts::PYTHON_MODE;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::env::erg_path; use erg_common::env::erg_path;
use erg_common::shared::{ use erg_common::pathutil::NormalizedPathBuf;
MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLockReadGuard, RwLockWriteGuard, Shared, use erg_common::shared::{MappedRwLockReadGuard, Shared};
};
use erg_common::spawn::{safe_yield, spawn_new_thread}; use erg_common::spawn::{safe_yield, spawn_new_thread};
use erg_common::{fn_name, normalize_path}; use erg_common::{fn_name, normalize_path};
use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact}; use erg_compiler::artifact::BuildRunnable;
use erg_compiler::build_hir::HIRBuilder; use erg_compiler::build_hir::HIRBuilder;
use erg_compiler::context::{Context, ModuleContext}; use erg_compiler::context::{Context, ModuleContext};
use erg_compiler::erg_parser::ast::Module; use erg_compiler::erg_parser::ast::Module;
use erg_compiler::erg_parser::parse::{Parsable, SimpleParser}; use erg_compiler::erg_parser::parse::{Parsable, SimpleParser};
use erg_compiler::error::CompileWarning;
use erg_compiler::hir::HIR; use erg_compiler::hir::HIR;
use erg_compiler::lower::ASTLowerer; use erg_compiler::lower::ASTLowerer;
use erg_compiler::module::{SharedCompilerResource, SharedModuleGraph, SharedModuleIndex}; use erg_compiler::module::{ModuleEntry, SharedCompilerResource};
use erg_compiler::ty::HasType; use erg_compiler::ty::HasType;
pub use molc::RedirectableStdout; pub use molc::RedirectableStdout;
@ -141,95 +141,8 @@ macro_rules! _log {
}; };
} }
#[derive(Debug)]
pub struct AnalysisResult {
pub ast: Module,
pub artifact: IncompleteArtifact,
}
impl AnalysisResult {
pub fn new(ast: Module, artifact: IncompleteArtifact) -> Self {
Self { ast, artifact }
}
}
pub const TRIGGER_CHARS: [&str; 4] = [".", ":", "(", " "]; pub const TRIGGER_CHARS: [&str; 4] = [".", ":", "(", " "];
#[derive(Debug, Clone, Default)]
pub struct AnalysisResultCache(Shared<Dict<NormalizedUrl, AnalysisResult>>);
impl AnalysisResultCache {
pub fn new() -> Self {
Self(Shared::new(Dict::new()))
}
pub fn insert(&self, uri: NormalizedUrl, result: AnalysisResult) {
self.0.borrow_mut().insert(uri, result);
}
pub fn get(&self, uri: &NormalizedUrl) -> Option<MappedRwLockReadGuard<AnalysisResult>> {
if self.0.borrow().get(uri).is_none() {
None
} else {
Some(RwLockReadGuard::map(self.0.borrow(), |dict| {
dict.get(uri).unwrap()
}))
}
}
pub fn get_mut(&self, uri: &NormalizedUrl) -> Option<MappedRwLockWriteGuard<AnalysisResult>> {
if self.0.borrow().get(uri).is_none() {
None
} else {
Some(RwLockWriteGuard::map(self.0.borrow_mut(), |dict| {
dict.get_mut(uri).unwrap()
}))
}
}
pub fn get_ast(&self, uri: &NormalizedUrl) -> Option<MappedRwLockReadGuard<Module>> {
self.get(uri)
.map(|r| MappedRwLockReadGuard::map(r, |r| &r.ast))
}
pub fn get_mut_hir(&self, uri: &NormalizedUrl) -> Option<MappedRwLockWriteGuard<HIR>> {
self.get_mut(uri).and_then(|r| {
if r.artifact.object.is_none() {
None
} else {
Some(MappedRwLockWriteGuard::map(r, |r| {
r.artifact.object.as_mut().unwrap()
}))
}
})
}
#[allow(unused)]
pub fn get_artifact(
&self,
uri: &NormalizedUrl,
) -> Option<MappedRwLockReadGuard<IncompleteArtifact>> {
self.get(uri)
.map(|r| MappedRwLockReadGuard::map(r, |r| &r.artifact))
}
pub fn get_hir(&self, uri: &NormalizedUrl) -> Option<MappedRwLockReadGuard<HIR>> {
self.get(uri).and_then(|r| {
if r.artifact.object.is_none() {
None
} else {
Some(MappedRwLockReadGuard::map(r, |r| {
r.artifact.object.as_ref().unwrap()
}))
}
})
}
pub fn remove(&self, uri: &NormalizedUrl) -> Option<AnalysisResult> {
self.0.borrow_mut().remove(uri)
}
}
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct ModuleCache(Shared<Dict<NormalizedUrl, ModuleContext>>); pub struct ModuleCache(Shared<Dict<NormalizedUrl, ModuleContext>>);
@ -258,12 +171,6 @@ impl ModuleCache {
self.0.borrow_mut().remove(uri) self.0.borrow_mut().remove(uri)
} }
pub fn values(&self) -> std::collections::hash_map::Values<NormalizedUrl, ModuleContext> {
let _ref = self.0.borrow();
let ref_ = unsafe { self.0.as_ptr().as_ref() };
ref_.unwrap().values()
}
pub fn _iter(&self) -> std::collections::hash_map::Iter<NormalizedUrl, ModuleContext> { pub fn _iter(&self) -> std::collections::hash_map::Iter<NormalizedUrl, ModuleContext> {
let _ref = self.0.borrow(); let _ref = self.0.borrow();
let ref_ = unsafe { self.0.as_ptr().as_ref() }; let ref_ = unsafe { self.0.as_ptr().as_ref() };
@ -302,7 +209,7 @@ pub struct Server<Checker: BuildRunnable = HIRBuilder, Parser: Parsable = Simple
// TODO: remove modules, analysis_result, and add `shared: SharedCompilerResource` // TODO: remove modules, analysis_result, and add `shared: SharedCompilerResource`
pub(crate) modules: ModuleCache, pub(crate) modules: ModuleCache,
pub(crate) flags: Flags, pub(crate) flags: Flags,
pub(crate) analysis_result: AnalysisResultCache, pub(crate) shared: SharedCompilerResource,
pub(crate) channels: Option<SendChannels>, pub(crate) channels: Option<SendChannels>,
pub(crate) stdout_redirect: Option<mpsc::Sender<Value>>, pub(crate) stdout_redirect: Option<mpsc::Sender<Value>>,
pub(crate) _parser: std::marker::PhantomData<fn() -> Parser>, pub(crate) _parser: std::marker::PhantomData<fn() -> Parser>,
@ -342,7 +249,7 @@ impl<C: BuildRunnable, P: Parsable> Clone for Server<C, P> {
file_cache: self.file_cache.clone(), file_cache: self.file_cache.clone(),
comp_cache: self.comp_cache.clone(), comp_cache: self.comp_cache.clone(),
modules: self.modules.clone(), modules: self.modules.clone(),
analysis_result: self.analysis_result.clone(), shared: self.shared.clone(),
channels: self.channels.clone(), channels: self.channels.clone(),
flags: self.flags.clone(), flags: self.flags.clone(),
stdout_redirect: self.stdout_redirect.clone(), stdout_redirect: self.stdout_redirect.clone(),
@ -356,6 +263,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
pub fn new(cfg: ErgConfig, stdout_redirect: Option<mpsc::Sender<Value>>) -> Self { pub fn new(cfg: ErgConfig, stdout_redirect: Option<mpsc::Sender<Value>>) -> Self {
Self { Self {
comp_cache: CompletionCache::new(cfg.copy()), comp_cache: CompletionCache::new(cfg.copy()),
shared: SharedCompilerResource::new(cfg.copy()),
cfg, cfg,
home: normalize_path(std::env::current_dir().unwrap_or_default()), home: normalize_path(std::env::current_dir().unwrap_or_default()),
erg_path: erg_path().clone(), // already normalized erg_path: erg_path().clone(), // already normalized
@ -365,7 +273,6 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
opt_features: vec![], opt_features: vec![],
file_cache: FileCache::new(stdout_redirect.clone()), file_cache: FileCache::new(stdout_redirect.clone()),
modules: ModuleCache::new(), modules: ModuleCache::new(),
analysis_result: AnalysisResultCache::new(),
channels: None, channels: None,
flags: Flags::default(), flags: Flags::default(),
stdout_redirect, stdout_redirect,
@ -638,7 +545,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
self.file_cache.clear(); self.file_cache.clear();
self.comp_cache.clear(); self.comp_cache.clear();
self.modules = ModuleCache::new(); self.modules = ModuleCache::new();
self.analysis_result = AnalysisResultCache::new(); // self.analysis_result = AnalysisResultCache::new();
self.channels.as_ref().unwrap().close(); self.channels.as_ref().unwrap().close();
self.start_language_services(); self.start_language_services();
self.start_workspace_diagnostics(); self.start_workspace_diagnostics();
@ -877,13 +784,9 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
/// Because of the difficulty of caching "transitional types" such as assert casting and mutable dependent types, /// Because of the difficulty of caching "transitional types" such as assert casting and mutable dependent types,
/// the cache is deleted after each analysis. /// the cache is deleted after each analysis.
pub(crate) fn get_checker(&self, path: PathBuf) -> Checker { pub(crate) fn get_checker(&self, path: PathBuf) -> Checker {
if let Some(shared) = self.get_shared() { let shared = self.shared.clone();
let shared = shared.clone(); shared.clear(&path);
shared.clear(&path); Checker::inherit(self.cfg.inherit(path), shared)
Checker::inherit(self.cfg.inherit(path), shared)
} else {
Checker::new(self.cfg.inherit(path))
}
} }
pub(crate) fn steal_lowerer(&mut self, uri: &NormalizedUrl) -> Option<ASTLowerer> { pub(crate) fn steal_lowerer(&mut self, uri: &NormalizedUrl) -> Option<ASTLowerer> {
@ -901,34 +804,24 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
} }
pub(crate) fn get_visitor(&self, uri: &NormalizedUrl) -> Option<HIRVisitor> { pub(crate) fn get_visitor(&self, uri: &NormalizedUrl) -> Option<HIRVisitor> {
self.analysis_result let path = uri.to_file_path().ok()?;
.get_hir(uri) let ent = self.shared.mod_cache.get(&path)?;
.map(|hir| HIRVisitor::new(hir, &self.file_cache, uri.clone())) ent.hir.as_ref()?;
.or_else(|| { let hir = MappedRwLockReadGuard::map(ent, |ent| ent.hir.as_ref().unwrap());
let path = uri.to_file_path().ok()?; Some(HIRVisitor::new(hir, &self.file_cache, uri.clone()))
let ent = self.get_shared()?.mod_cache.get(&path)?;
ent.hir.as_ref()?;
let hir = MappedRwLockReadGuard::map(ent, |ent| ent.hir.as_ref().unwrap());
Some(HIRVisitor::new(hir, &self.file_cache, uri.clone()))
})
} }
pub(crate) fn get_searcher(&self, uri: &NormalizedUrl, kind: ExprKind) -> Option<HIRVisitor> { pub(crate) fn get_searcher(&self, uri: &NormalizedUrl, kind: ExprKind) -> Option<HIRVisitor> {
self.analysis_result let path = uri.to_file_path().ok()?;
.get_hir(uri) let ent = self.shared.mod_cache.get(&path)?;
.map(|hir| HIRVisitor::new_searcher(hir, &self.file_cache, uri.clone(), kind)) ent.hir.as_ref()?;
.or_else(|| { let hir = MappedRwLockReadGuard::map(ent, |ent| ent.hir.as_ref().unwrap());
let path = uri.to_file_path().ok()?; Some(HIRVisitor::new_searcher(
let ent = self.get_shared()?.mod_cache.get(&path)?; hir,
ent.hir.as_ref()?; &self.file_cache,
let hir = MappedRwLockReadGuard::map(ent, |ent| ent.hir.as_ref().unwrap()); uri.clone(),
Some(HIRVisitor::new_searcher( kind,
hir, ))
&self.file_cache,
uri.clone(),
kind,
))
})
} }
pub(crate) fn get_local_ctx(&self, uri: &NormalizedUrl, pos: Position) -> Vec<&Context> { pub(crate) fn get_local_ctx(&self, uri: &NormalizedUrl, pos: Position) -> Vec<&Context> {
@ -956,30 +849,32 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
pub(crate) fn _get_all_ctxs(&self) -> Vec<Arc<ModuleContext>> { pub(crate) fn _get_all_ctxs(&self) -> Vec<Arc<ModuleContext>> {
let mut ctxs = vec![]; let mut ctxs = vec![];
if let Some(shared) = self.get_shared() { ctxs.extend(
ctxs.extend(shared.mod_cache.raw_values().map(|ent| ent.module.clone())); self.shared
ctxs.extend( .mod_cache
shared .raw_values()
.py_mod_cache .map(|ent| ent.module.clone()),
.raw_values() );
.map(|ent| ent.module.clone()), ctxs.extend(
); self.shared
} .py_mod_cache
.raw_values()
.map(|ent| ent.module.clone()),
);
ctxs ctxs
} }
pub(crate) fn get_workspace_ctxs(&self) -> Vec<&Context> { 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_of(&self.home).unwrap_or(self.home.clone());
let mut ctxs = vec![]; let mut ctxs = vec![];
if let Some(shared) = self.get_shared() { for (path, ent) in self
for (path, ent) in shared .shared
.mod_cache .mod_cache
.raw_iter() .raw_iter()
.chain(shared.py_mod_cache.raw_iter()) .chain(self.shared.py_mod_cache.raw_iter())
{ {
if path.starts_with(&project_root) { if path.starts_with(&project_root) {
ctxs.push(&ent.module.context); ctxs.push(&ent.module.context);
}
} }
} }
ctxs ctxs
@ -1044,61 +939,64 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
} }
} }
pub(crate) fn get_index(&self) -> Option<&SharedModuleIndex> {
self.modules
.values()
.next()
.map(|module| module.context.index())
}
pub(crate) fn get_graph(&self) -> Option<&SharedModuleGraph> {
self.modules
.values()
.next()
.map(|module| module.context.graph())
}
pub(crate) fn get_shared(&self) -> Option<&SharedCompilerResource> {
self.modules
.values()
.next()
.map(|module| module.context.shared())
}
pub(crate) fn get_builtin_module(&self) -> Option<&Context> { pub(crate) fn get_builtin_module(&self) -> Option<&Context> {
self.get_shared() self.shared
.and_then(|mode| mode.mod_cache.raw_ref_ctx(Path::new("<builtins>"))) .mod_cache
.raw_ref_ctx(Path::new("<builtins>"))
.map(|mc| &mc.context) .map(|mc| &mc.context)
} }
pub(crate) fn clear_cache(&mut self, uri: &NormalizedUrl) { pub(crate) fn clear_cache(&mut self, uri: &NormalizedUrl) {
self.analysis_result.remove(uri); // self.analysis_result.remove(uri);
if let Some(module) = self.modules.remove(uri) { let path = util::uri_to_path(uri);
let shared = module.context.shared(); self.shared.clear(&path);
let path = util::uri_to_path(uri); self.modules.remove(uri);
shared.clear(&path); }
}
pub fn remove_module_entry(&mut self, uri: &NormalizedUrl) -> Option<ModuleEntry> {
let path = uri.to_file_path().ok()?;
self.shared.mod_cache.remove(&path)
}
pub fn insert_module_entry(&mut self, uri: NormalizedUrl, entry: ModuleEntry) {
let Ok(path) = uri.to_file_path() else {
return;
};
self.shared.mod_cache.insert(path.into(), entry);
} }
pub fn get_hir(&self, uri: &NormalizedUrl) -> Option<MappedRwLockReadGuard<HIR>> { pub fn get_hir(&self, uri: &NormalizedUrl) -> Option<MappedRwLockReadGuard<HIR>> {
self.analysis_result.get_hir(uri).or_else(|| { let path = uri.to_file_path().ok()?;
let path = uri.to_file_path().ok()?; let ent = self.shared.mod_cache.get(&path)?;
let ent = self.get_shared()?.mod_cache.get(&path)?; ent.hir.as_ref()?;
ent.hir.as_ref()?; Some(MappedRwLockReadGuard::map(ent, |ent| {
Some(MappedRwLockReadGuard::map(ent, |ent| { ent.hir.as_ref().unwrap()
ent.hir.as_ref().unwrap() }))
}))
})
} }
pub fn get_mut_hir(&self, uri: &NormalizedUrl) -> Option<MappedRwLockWriteGuard<HIR>> { pub fn steal_entry(&self, uri: &NormalizedUrl) -> Option<ModuleEntry> {
self.analysis_result.get_mut_hir(uri).or_else(|| { let path = uri.to_file_path().ok()?;
let path = uri.to_file_path().ok()?; self.shared.mod_cache.remove(&path)
let ent = self.get_shared()?.mod_cache.get_mut(&path)?; }
ent.hir.as_ref()?;
Some(MappedRwLockWriteGuard::map(ent, |ent| { pub fn restore_entry(&self, uri: NormalizedUrl, entry: ModuleEntry) {
ent.hir.as_mut().unwrap() let path = uri.to_file_path().unwrap();
})) self.shared.mod_cache.insert(path.into(), entry);
}) }
pub fn get_ast(&self, uri: &NormalizedUrl) -> Option<MappedRwLockReadGuard<Module>> {
let path = uri.to_file_path().ok()?;
let ent = self.shared.mod_cache.get(&path)?;
ent.ast.as_ref()?;
Some(MappedRwLockReadGuard::map(ent, |ent| {
ent.ast.as_ref().unwrap()
}))
}
pub fn get_warns(&self, uri: &NormalizedUrl) -> Option<Vec<&CompileWarning>> {
let path = NormalizedPathBuf::from(uri.to_file_path().ok()?);
let warns = self.shared.warns.raw_iter();
let warns = warns.filter(|warn| NormalizedPathBuf::from(warn.input.path()) == path);
Some(warns.collect())
} }
} }

View file

@ -17,6 +17,8 @@ use molc::{add_char, oneline_range};
fn test_open() -> Result<(), Box<dyn std::error::Error>> { fn test_open() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
client.wait_messages(3)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
client.wait_messages(3)?; client.wait_messages(3)?;
assert!(client.responses.iter().any(|val| val assert!(client.responses.iter().any(|val| val
@ -29,6 +31,7 @@ fn test_open() -> Result<(), Box<dyn std::error::Error>> {
fn test_completion() -> Result<(), Box<dyn std::error::Error>> { fn test_completion() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
client.notify_change(uri.clone().raw(), add_char(2, 0, "x"))?; client.notify_change(uri.clone().raw(), add_char(2, 0, "x"))?;
@ -47,6 +50,7 @@ fn test_completion() -> Result<(), Box<dyn std::error::Error>> {
fn test_neighbor_completion() -> Result<(), Box<dyn std::error::Error>> { fn test_neighbor_completion() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
client.notify_open(FILE_B)?; client.notify_open(FILE_B)?;
@ -66,6 +70,7 @@ fn test_neighbor_completion() -> Result<(), Box<dyn std::error::Error>> {
fn test_rename() -> Result<(), Box<dyn std::error::Error>> { fn test_rename() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
let edit = client let edit = client
@ -81,6 +86,7 @@ fn test_rename() -> Result<(), Box<dyn std::error::Error>> {
fn test_signature_help() -> Result<(), Box<dyn std::error::Error>> { fn test_signature_help() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
client.notify_change(uri.clone().raw(), add_char(2, 0, "assert"))?; client.notify_change(uri.clone().raw(), add_char(2, 0, "assert"))?;
@ -99,6 +105,7 @@ fn test_signature_help() -> Result<(), Box<dyn std::error::Error>> {
fn test_hover() -> Result<(), Box<dyn std::error::Error>> { fn test_hover() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
let hover = client.request_hover(uri.raw(), 1, 4)?.unwrap(); let hover = client.request_hover(uri.raw(), 1, 4)?.unwrap();
@ -124,6 +131,7 @@ fn test_hover() -> Result<(), Box<dyn std::error::Error>> {
fn test_references() -> Result<(), Box<dyn std::error::Error>> { fn test_references() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
let locations = client.request_references(uri.raw(), 1, 4)?.unwrap(); let locations = client.request_references(uri.raw(), 1, 4)?.unwrap();
@ -143,6 +151,7 @@ fn test_references() -> Result<(), Box<dyn std::error::Error>> {
fn test_goto_definition() -> Result<(), Box<dyn std::error::Error>> { fn test_goto_definition() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
let Some(GotoDefinitionResponse::Scalar(location)) = let Some(GotoDefinitionResponse::Scalar(location)) =
@ -159,6 +168,7 @@ fn test_goto_definition() -> Result<(), Box<dyn std::error::Error>> {
fn test_folding_range() -> Result<(), Box<dyn std::error::Error>> { fn test_folding_range() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_IMPORTS).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_IMPORTS).canonicalize()?)?;
client.notify_open(FILE_IMPORTS)?; client.notify_open(FILE_IMPORTS)?;
let ranges = client.request_folding_range(uri.raw())?.unwrap(); let ranges = client.request_folding_range(uri.raw())?.unwrap();
@ -180,6 +190,7 @@ fn test_folding_range() -> Result<(), Box<dyn std::error::Error>> {
fn test_document_symbol() -> Result<(), Box<dyn std::error::Error>> { fn test_document_symbol() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client(); let mut client = Server::bind_fake_client();
client.request_initialize()?; client.request_initialize()?;
client.notify_initialized()?;
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?; let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
client.notify_open(FILE_A)?; client.notify_open(FILE_A)?;
let Some(DocumentSymbolResponse::Nested(symbols)) = let Some(DocumentSymbolResponse::Nested(symbols)) =

View file

@ -255,6 +255,7 @@ pub trait Stream<T>: Sized {
self.ref_mut_payload().split_off(at) self.ref_mut_payload().split_off(at)
} }
/// Remove all elements that don't satisfy the predicate.
fn retain(&mut self, f: impl FnMut(&T) -> bool) { fn retain(&mut self, f: impl FnMut(&T) -> bool) {
self.ref_mut_payload().retain(f); self.ref_mut_payload().retain(f);
} }

View file

@ -269,6 +269,10 @@ impl SharedModuleCache {
self.0.borrow_mut().register(path.into(), ast, hir, ctx); self.0.borrow_mut().register(path.into(), ast, hir, ctx);
} }
pub fn insert(&self, path: NormalizedPathBuf, entry: ModuleEntry) {
self.0.borrow_mut().cache.insert(path, entry);
}
pub fn remove<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<ModuleEntry> pub fn remove<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<ModuleEntry>
where where
NormalizedPathBuf: Borrow<Q>, NormalizedPathBuf: Borrow<Q>,

View file

@ -1,3 +1,6 @@
use std::path::Path;
use erg_common::pathutil::NormalizedPathBuf;
use erg_common::shared::Shared; use erg_common::shared::Shared;
use erg_common::traits::Stream; use erg_common::traits::Stream;
@ -26,6 +29,19 @@ impl SharedCompileErrors {
pub fn clear(&self) { pub fn clear(&self) {
self.0.borrow_mut().clear(); self.0.borrow_mut().clear();
} }
pub fn remove(&self, path: &Path) {
let path = NormalizedPathBuf::from(path);
self.0
.borrow_mut()
.retain(|e| NormalizedPathBuf::from(e.input.path()) != path);
}
pub fn raw_iter(&self) -> impl Iterator<Item = &CompileError> {
let _ref = self.0.borrow();
let ref_ = unsafe { self.0.as_ptr().as_ref().unwrap() };
ref_.iter()
}
} }
pub type SharedCompileWarnings = SharedCompileErrors; pub type SharedCompileWarnings = SharedCompileErrors;

View file

@ -76,8 +76,8 @@ impl SharedCompilerResource {
self.index.remove_path(path); self.index.remove_path(path);
self.graph.remove(path); self.graph.remove(path);
self.promises.remove(path); self.promises.remove(path);
// self.errors.remove(path); self.errors.remove(path);
// self.warns.remove(path); self.warns.remove(path);
} }
pub fn rename_path(&self, old: &Path, new: PathBuf) { pub fn rename_path(&self, old: &Path, new: PathBuf) {