mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 20:14:45 +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]]
|
[[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"
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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![];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(¶ms)?;
|
self.file_cache.rename_files(¶ms)?;
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)) =
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue