mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
chore(els): remove AnalysisResultCache
This commit is contained in:
parent
d92e3f5425
commit
94b5fc27e9
13 changed files with 198 additions and 282 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -186,9 +186,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
version = "0.2.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
|
@ -257,9 +257,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "molc"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9485212d67a88d2169ee683420e1a2fe763afb96a3901ebfabb5ba095d0d2eaa"
|
||||
checksum = "b266c0d03bfc46984d579c11d4fa2ea76f2cb4680477f4af7c97a306745e12d5"
|
||||
dependencies = [
|
||||
"lsp-types",
|
||||
"serde",
|
||||
|
@ -325,9 +325,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -385,14 +385,14 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.31",
|
||||
"syn 2.0.33",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.105"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
|
||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -407,7 +407,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.31",
|
||||
"syn 2.0.33",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -459,9 +459,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.31"
|
||||
version = "2.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
|
||||
checksum = "9caece70c63bfba29ec2fed841a09851b14a235c60010fa4de58089b6c025668"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -501,9 +501,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.11"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
|
|
|
@ -19,6 +19,7 @@ pretty = ["erg_common/pretty", "erg_compiler/pretty"]
|
|||
large_thread = ["erg_common/large_thread", "erg_compiler/large_thread"]
|
||||
py_compat = ["erg_compiler/py_compat"]
|
||||
experimental = ["erg_common/experimental", "erg_compiler/experimental"]
|
||||
backtrace = ["erg_common/backtrace"]
|
||||
|
||||
[dependencies]
|
||||
erg_common = { workspace = true, features = ["els"] }
|
||||
|
|
|
@ -42,10 +42,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
let Ok(loc) = AbsLocation::from_str(data) else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some(shared) = self.get_shared() else {
|
||||
return Ok(None);
|
||||
};
|
||||
if let Some(refs) = shared.index.get_refs(&loc) {
|
||||
if let Some(refs) = self.shared.index.get_refs(&loc) {
|
||||
for referrer_loc in refs.referrers.iter() {
|
||||
let Some(uri) = referrer_loc
|
||||
.module
|
||||
|
|
|
@ -32,13 +32,11 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
self.send_log("visitor not found")?;
|
||||
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")?;
|
||||
return Ok(None);
|
||||
};
|
||||
let warns = result
|
||||
.artifact
|
||||
.warns
|
||||
let warns = warns
|
||||
.iter()
|
||||
.filter(|warn| warn.core.main_message.ends_with("is not used"))
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -72,7 +70,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
}
|
||||
Some(";") => range.end.character += 1,
|
||||
Some(other) => {
|
||||
self.send_log(format!("? {other}"))?;
|
||||
crate::_log!(self, "? {other}");
|
||||
}
|
||||
}
|
||||
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 edit = TextEdit::new(util::loc_to_range(def_loc.loc)?, new_text.clone());
|
||||
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() {
|
||||
let url = Url::from_file_path(refer.module.as_ref()?).ok()?;
|
||||
let range = util::loc_to_range(refer.loc)?;
|
||||
|
@ -389,10 +387,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
code
|
||||
};
|
||||
changes.insert(uri.raw(), vec![delete]);
|
||||
if let Some(index) = self
|
||||
.get_index()
|
||||
.and_then(|index| index.get_refs(&def.sig.ident().vi.def_loc))
|
||||
{
|
||||
if let Some(index) = self.shared.index.get_refs(&def.sig.ident().vi.def_loc) {
|
||||
for ref_ in index.referrers.iter() {
|
||||
let Some(path) = ref_.module.as_ref() else {
|
||||
continue;
|
||||
|
|
|
@ -8,7 +8,6 @@ use std::time::Duration;
|
|||
|
||||
use erg_common::consts::PYTHON_MODE;
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::shared::MappedRwLockReadGuard;
|
||||
use erg_common::spawn::{safe_yield, spawn_new_thread};
|
||||
use erg_common::style::*;
|
||||
use erg_common::traits::Stream;
|
||||
|
@ -28,7 +27,7 @@ use serde_json::json;
|
|||
use crate::_log;
|
||||
use crate::channels::WorkerMessage;
|
||||
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::util::{self, project_root_of, NormalizedUrl};
|
||||
|
||||
|
@ -43,45 +42,40 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
uri: NormalizedUrl,
|
||||
code: S,
|
||||
) -> ELSResult<()> {
|
||||
self.send_log(format!("checking {uri}"))?;
|
||||
_log!(self, "checking {uri}");
|
||||
let path = util::uri_to_path(&uri);
|
||||
let mode = if path.to_string_lossy().ends_with(".d.er") {
|
||||
"declare"
|
||||
} else {
|
||||
"exec"
|
||||
};
|
||||
let old = self.analysis_result.get_ast(&uri).or_else(|| {
|
||||
let ent = self.get_shared()?.mod_cache.get(&path)?;
|
||||
ent.ast.as_ref()?;
|
||||
Some(MappedRwLockReadGuard::map(ent, |ent| {
|
||||
ent.ast.as_ref().unwrap()
|
||||
}))
|
||||
});
|
||||
let old = self.get_ast(&uri);
|
||||
if let Some((old, new)) = old.zip(self.build_ast(&uri)) {
|
||||
if ASTDiff::diff(old, &new).is_nop() {
|
||||
crate::_log!(self, "no changes: {uri}");
|
||||
_log!(self, "no changes: {uri}");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
let mut checker = self.get_checker(path.clone());
|
||||
let artifact = match checker.build(code.into(), mode) {
|
||||
Ok(artifact) => {
|
||||
self.send_log(format!(
|
||||
_log!(
|
||||
self,
|
||||
"checking {uri} passed, found warns: {}",
|
||||
artifact.warns.len()
|
||||
))?;
|
||||
);
|
||||
let uri_and_diags = self.make_uri_and_diags(artifact.warns.clone());
|
||||
// clear previous diagnostics
|
||||
self.send_diagnostics(uri.clone().raw(), vec![])?;
|
||||
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)?;
|
||||
}
|
||||
artifact.into()
|
||||
}
|
||||
Err(artifact) => {
|
||||
self.send_log(format!("found errors: {}", artifact.errors.len()))?;
|
||||
self.send_log(format!("found warns: {}", artifact.warns.len()))?;
|
||||
_log!(self, "found errors: {}", artifact.errors.len());
|
||||
_log!(self, "found warns: {}", artifact.warns.len());
|
||||
let diags = artifact
|
||||
.errors
|
||||
.clone()
|
||||
|
@ -93,36 +87,32 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
self.send_diagnostics(uri.clone().raw(), vec![])?;
|
||||
}
|
||||
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)?;
|
||||
}
|
||||
artifact
|
||||
}
|
||||
};
|
||||
if let Some(shared) = self.get_shared() {
|
||||
let ast = self.build_ast(&uri);
|
||||
if mode == "declare" {
|
||||
shared.py_mod_cache.register(
|
||||
path,
|
||||
ast,
|
||||
artifact.object.clone(),
|
||||
checker.get_context().unwrap().clone(),
|
||||
);
|
||||
} else {
|
||||
shared.mod_cache.register(
|
||||
path,
|
||||
ast,
|
||||
artifact.object.clone(),
|
||||
checker.get_context().unwrap().clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(module) = self.build_ast(&uri) {
|
||||
self.analysis_result
|
||||
.insert(uri.clone(), AnalysisResult::new(module, artifact));
|
||||
let ast = self.build_ast(&uri);
|
||||
if mode == "declare" {
|
||||
self.shared.py_mod_cache.register(
|
||||
path,
|
||||
ast,
|
||||
artifact.object,
|
||||
checker.get_context().unwrap().clone(),
|
||||
);
|
||||
} else {
|
||||
self.shared.mod_cache.register(
|
||||
path,
|
||||
ast,
|
||||
artifact.object,
|
||||
checker.get_context().unwrap().clone(),
|
||||
);
|
||||
}
|
||||
self.shared.errors.extend(artifact.errors);
|
||||
self.shared.warns.extend(artifact.warns);
|
||||
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);
|
||||
}
|
||||
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<()> {
|
||||
let Some(old) = self.analysis_result.get_ast(&uri) else {
|
||||
let Some(old) = self.get_ast(&uri) else {
|
||||
crate::_log!(self, "not found");
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -146,11 +136,16 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
let ast_diff = ASTDiff::diff(old, &new);
|
||||
crate::_log!(self, "diff: {ast_diff}");
|
||||
if let Some(mut lowerer) = self.steal_lowerer(&uri) {
|
||||
let hir = self.get_mut_hir(&uri);
|
||||
if let Some((hir_diff, hir)) = HIRDiff::new(ast_diff, &mut lowerer).zip(hir) {
|
||||
let mut ent = self.steal_entry(&uri);
|
||||
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}");
|
||||
hir_diff.update(hir);
|
||||
}
|
||||
if let Some(ent) = ent {
|
||||
self.restore_entry(uri.clone(), ent);
|
||||
}
|
||||
self.restore_lowerer(uri, lowerer);
|
||||
}
|
||||
// skip checking for dependents
|
||||
|
|
|
@ -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> {
|
||||
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() {
|
||||
return vec![];
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
return self.send_error_info(error_reason);
|
||||
}
|
||||
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:?}"))?;
|
||||
for referrer in value.referrers.iter() {
|
||||
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__
|
||||
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));
|
||||
graph.sort().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__
|
||||
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));
|
||||
graph
|
||||
.ref_inner()
|
||||
|
@ -304,19 +304,17 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
let new_uri = NormalizedUrl::new(new);
|
||||
edits.extend(self.collect_module_changes(&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;
|
||||
};
|
||||
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 {
|
||||
continue;
|
||||
};
|
||||
if let Some(shared) = self.get_shared() {
|
||||
shared.rename_path(
|
||||
&old_uri.to_file_path().unwrap(),
|
||||
new_uri.to_file_path().unwrap(),
|
||||
);
|
||||
}
|
||||
self.shared.rename_path(
|
||||
&old_uri.to_file_path().unwrap(),
|
||||
new_uri.to_file_path().unwrap(),
|
||||
);
|
||||
self.modules.insert(new_uri, entry);
|
||||
}
|
||||
self.file_cache.rename_files(¶ms)?;
|
||||
|
|
|
@ -11,20 +11,20 @@ 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::shared::{
|
||||
MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLockReadGuard, RwLockWriteGuard, Shared,
|
||||
};
|
||||
use erg_common::pathutil::NormalizedPathBuf;
|
||||
use erg_common::shared::{MappedRwLockReadGuard, Shared};
|
||||
use erg_common::spawn::{safe_yield, spawn_new_thread};
|
||||
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::context::{Context, ModuleContext};
|
||||
use erg_compiler::erg_parser::ast::Module;
|
||||
use erg_compiler::erg_parser::parse::{Parsable, SimpleParser};
|
||||
use erg_compiler::error::CompileWarning;
|
||||
use erg_compiler::hir::HIR;
|
||||
use erg_compiler::lower::ASTLowerer;
|
||||
use erg_compiler::module::{SharedCompilerResource, SharedModuleGraph, SharedModuleIndex};
|
||||
use erg_compiler::module::{ModuleEntry, SharedCompilerResource};
|
||||
use erg_compiler::ty::HasType;
|
||||
|
||||
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] = [".", ":", "(", " "];
|
||||
|
||||
#[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)]
|
||||
pub struct ModuleCache(Shared<Dict<NormalizedUrl, ModuleContext>>);
|
||||
|
||||
|
@ -258,12 +171,6 @@ impl ModuleCache {
|
|||
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> {
|
||||
let _ref = self.0.borrow();
|
||||
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`
|
||||
pub(crate) modules: ModuleCache,
|
||||
pub(crate) flags: Flags,
|
||||
pub(crate) analysis_result: AnalysisResultCache,
|
||||
pub(crate) shared: SharedCompilerResource,
|
||||
pub(crate) channels: Option<SendChannels>,
|
||||
pub(crate) stdout_redirect: Option<mpsc::Sender<Value>>,
|
||||
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(),
|
||||
comp_cache: self.comp_cache.clone(),
|
||||
modules: self.modules.clone(),
|
||||
analysis_result: self.analysis_result.clone(),
|
||||
shared: self.shared.clone(),
|
||||
channels: self.channels.clone(),
|
||||
flags: self.flags.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 {
|
||||
Self {
|
||||
comp_cache: CompletionCache::new(cfg.copy()),
|
||||
shared: SharedCompilerResource::new(cfg.copy()),
|
||||
cfg,
|
||||
home: normalize_path(std::env::current_dir().unwrap_or_default()),
|
||||
erg_path: erg_path().clone(), // already normalized
|
||||
|
@ -365,7 +273,6 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
opt_features: vec![],
|
||||
file_cache: FileCache::new(stdout_redirect.clone()),
|
||||
modules: ModuleCache::new(),
|
||||
analysis_result: AnalysisResultCache::new(),
|
||||
channels: None,
|
||||
flags: Flags::default(),
|
||||
stdout_redirect,
|
||||
|
@ -638,7 +545,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
self.file_cache.clear();
|
||||
self.comp_cache.clear();
|
||||
self.modules = ModuleCache::new();
|
||||
self.analysis_result = AnalysisResultCache::new();
|
||||
// self.analysis_result = AnalysisResultCache::new();
|
||||
self.channels.as_ref().unwrap().close();
|
||||
self.start_language_services();
|
||||
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,
|
||||
/// the cache is deleted after each analysis.
|
||||
pub(crate) fn get_checker(&self, path: PathBuf) -> Checker {
|
||||
if let Some(shared) = self.get_shared() {
|
||||
let shared = shared.clone();
|
||||
shared.clear(&path);
|
||||
Checker::inherit(self.cfg.inherit(path), shared)
|
||||
} else {
|
||||
Checker::new(self.cfg.inherit(path))
|
||||
}
|
||||
let shared = self.shared.clone();
|
||||
shared.clear(&path);
|
||||
Checker::inherit(self.cfg.inherit(path), shared)
|
||||
}
|
||||
|
||||
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> {
|
||||
self.analysis_result
|
||||
.get_hir(uri)
|
||||
.map(|hir| HIRVisitor::new(hir, &self.file_cache, uri.clone()))
|
||||
.or_else(|| {
|
||||
let path = uri.to_file_path().ok()?;
|
||||
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()))
|
||||
})
|
||||
let path = uri.to_file_path().ok()?;
|
||||
let ent = self.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> {
|
||||
self.analysis_result
|
||||
.get_hir(uri)
|
||||
.map(|hir| HIRVisitor::new_searcher(hir, &self.file_cache, uri.clone(), kind))
|
||||
.or_else(|| {
|
||||
let path = uri.to_file_path().ok()?;
|
||||
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_searcher(
|
||||
hir,
|
||||
&self.file_cache,
|
||||
uri.clone(),
|
||||
kind,
|
||||
))
|
||||
})
|
||||
let path = uri.to_file_path().ok()?;
|
||||
let ent = self.shared.mod_cache.get(&path)?;
|
||||
ent.hir.as_ref()?;
|
||||
let hir = MappedRwLockReadGuard::map(ent, |ent| ent.hir.as_ref().unwrap());
|
||||
Some(HIRVisitor::new_searcher(
|
||||
hir,
|
||||
&self.file_cache,
|
||||
uri.clone(),
|
||||
kind,
|
||||
))
|
||||
}
|
||||
|
||||
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>> {
|
||||
let mut ctxs = vec![];
|
||||
if let Some(shared) = self.get_shared() {
|
||||
ctxs.extend(shared.mod_cache.raw_values().map(|ent| ent.module.clone()));
|
||||
ctxs.extend(
|
||||
shared
|
||||
.py_mod_cache
|
||||
.raw_values()
|
||||
.map(|ent| ent.module.clone()),
|
||||
);
|
||||
}
|
||||
ctxs.extend(
|
||||
self.shared
|
||||
.mod_cache
|
||||
.raw_values()
|
||||
.map(|ent| ent.module.clone()),
|
||||
);
|
||||
ctxs.extend(
|
||||
self.shared
|
||||
.py_mod_cache
|
||||
.raw_values()
|
||||
.map(|ent| ent.module.clone()),
|
||||
);
|
||||
ctxs
|
||||
}
|
||||
|
||||
pub(crate) fn get_workspace_ctxs(&self) -> Vec<&Context> {
|
||||
let project_root = project_root_of(&self.home).unwrap_or(self.home.clone());
|
||||
let mut ctxs = vec![];
|
||||
if let Some(shared) = self.get_shared() {
|
||||
for (path, ent) in shared
|
||||
.mod_cache
|
||||
.raw_iter()
|
||||
.chain(shared.py_mod_cache.raw_iter())
|
||||
{
|
||||
if path.starts_with(&project_root) {
|
||||
ctxs.push(&ent.module.context);
|
||||
}
|
||||
for (path, ent) in self
|
||||
.shared
|
||||
.mod_cache
|
||||
.raw_iter()
|
||||
.chain(self.shared.py_mod_cache.raw_iter())
|
||||
{
|
||||
if path.starts_with(&project_root) {
|
||||
ctxs.push(&ent.module.context);
|
||||
}
|
||||
}
|
||||
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> {
|
||||
self.get_shared()
|
||||
.and_then(|mode| mode.mod_cache.raw_ref_ctx(Path::new("<builtins>")))
|
||||
self.shared
|
||||
.mod_cache
|
||||
.raw_ref_ctx(Path::new("<builtins>"))
|
||||
.map(|mc| &mc.context)
|
||||
}
|
||||
|
||||
pub(crate) fn clear_cache(&mut self, uri: &NormalizedUrl) {
|
||||
self.analysis_result.remove(uri);
|
||||
if let Some(module) = self.modules.remove(uri) {
|
||||
let shared = module.context.shared();
|
||||
let path = util::uri_to_path(uri);
|
||||
shared.clear(&path);
|
||||
}
|
||||
// self.analysis_result.remove(uri);
|
||||
let path = util::uri_to_path(uri);
|
||||
self.shared.clear(&path);
|
||||
self.modules.remove(uri);
|
||||
}
|
||||
|
||||
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>> {
|
||||
self.analysis_result.get_hir(uri).or_else(|| {
|
||||
let path = uri.to_file_path().ok()?;
|
||||
let ent = self.get_shared()?.mod_cache.get(&path)?;
|
||||
ent.hir.as_ref()?;
|
||||
Some(MappedRwLockReadGuard::map(ent, |ent| {
|
||||
ent.hir.as_ref().unwrap()
|
||||
}))
|
||||
})
|
||||
let path = uri.to_file_path().ok()?;
|
||||
let ent = self.shared.mod_cache.get(&path)?;
|
||||
ent.hir.as_ref()?;
|
||||
Some(MappedRwLockReadGuard::map(ent, |ent| {
|
||||
ent.hir.as_ref().unwrap()
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn get_mut_hir(&self, uri: &NormalizedUrl) -> Option<MappedRwLockWriteGuard<HIR>> {
|
||||
self.analysis_result.get_mut_hir(uri).or_else(|| {
|
||||
let path = uri.to_file_path().ok()?;
|
||||
let ent = self.get_shared()?.mod_cache.get_mut(&path)?;
|
||||
ent.hir.as_ref()?;
|
||||
Some(MappedRwLockWriteGuard::map(ent, |ent| {
|
||||
ent.hir.as_mut().unwrap()
|
||||
}))
|
||||
})
|
||||
pub fn steal_entry(&self, uri: &NormalizedUrl) -> Option<ModuleEntry> {
|
||||
let path = uri.to_file_path().ok()?;
|
||||
self.shared.mod_cache.remove(&path)
|
||||
}
|
||||
|
||||
pub fn restore_entry(&self, uri: NormalizedUrl, entry: ModuleEntry) {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ use molc::{add_char, oneline_range};
|
|||
fn test_open() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
client.wait_messages(3)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
client.wait_messages(3)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_IMPORTS).canonicalize()?)?;
|
||||
client.notify_open(FILE_IMPORTS)?;
|
||||
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>> {
|
||||
let mut client = Server::bind_fake_client();
|
||||
client.request_initialize()?;
|
||||
client.notify_initialized()?;
|
||||
let uri = NormalizedUrl::from_file_path(Path::new(FILE_A).canonicalize()?)?;
|
||||
client.notify_open(FILE_A)?;
|
||||
let Some(DocumentSymbolResponse::Nested(symbols)) =
|
||||
|
|
|
@ -255,6 +255,7 @@ pub trait Stream<T>: Sized {
|
|||
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) {
|
||||
self.ref_mut_payload().retain(f);
|
||||
}
|
||||
|
|
|
@ -269,6 +269,10 @@ impl SharedModuleCache {
|
|||
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>
|
||||
where
|
||||
NormalizedPathBuf: Borrow<Q>,
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use std::path::Path;
|
||||
|
||||
use erg_common::pathutil::NormalizedPathBuf;
|
||||
use erg_common::shared::Shared;
|
||||
use erg_common::traits::Stream;
|
||||
|
||||
|
@ -26,6 +29,19 @@ impl SharedCompileErrors {
|
|||
pub fn clear(&self) {
|
||||
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;
|
||||
|
|
|
@ -76,8 +76,8 @@ impl SharedCompilerResource {
|
|||
self.index.remove_path(path);
|
||||
self.graph.remove(path);
|
||||
self.promises.remove(path);
|
||||
// self.errors.remove(path);
|
||||
// self.warns.remove(path);
|
||||
self.errors.remove(path);
|
||||
self.warns.remove(path);
|
||||
}
|
||||
|
||||
pub fn rename_path(&self, old: &Path, new: PathBuf) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue