fix: don't remove path mapping when invalidating vfs cache (#1316) (#1333)

* fix: don't remove path mapping when invalidating vfs cache (#1316)

* fix: don't clean path mapping when invalidate vfs cache

* fix: remove duplicated insert

* refactor: name

* fix: use correct path to ecow
This commit is contained in:
Myriad-Dreamin 2025-02-20 00:52:39 +08:00 committed by GitHub
parent 9904189910
commit 5a05d12fdd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 40 additions and 11 deletions

View file

@ -16,6 +16,7 @@ parking_lot.workspace = true
nohash-hasher.workspace = true
indexmap.workspace = true
comemo.workspace = true
ecow.workspace = true
log.workspace = true
rpds = "1"

View file

@ -46,6 +46,7 @@ use std::num::NonZeroUsize;
use std::sync::OnceLock;
use std::{path::Path, sync::Arc};
use ecow::EcoVec;
use parking_lot::{Mutex, RwLock};
use rpds::RedBlackTreeMapSync;
use typst::diag::{FileError, FileResult};
@ -426,7 +427,7 @@ impl<M: PathAccessModel + Sized> Vfs<M> {
.get_or_init(|| {
let (path, content) = self.access_model.content(fid);
if let Some(path) = path.as_ref() {
self.paths.lock().insert(path, fid);
self.paths.lock().insert(path, fid, self.revision);
}
(path, self.revision.get(), content)
@ -478,9 +479,13 @@ impl<M: PathAccessModel + Sized> RevisingVfs<'_, M> {
}
fn invalidate_path(&mut self, path: &Path) {
if let Some(fids) = self.paths.remove(path) {
if let Some(fids) = self.paths.get(path) {
if fids.is_empty() {
return;
}
self.view_changed = true;
for fid in fids {
for fid in fids.clone() {
self.invalidate_file_id(fid);
}
}
@ -617,20 +622,42 @@ impl fmt::Debug for DisplayEntryMap<'_> {
#[derive(Debug, Clone, Default)]
struct PathMap {
paths: FxHashMap<ImmutPath, Vec<TypstFileId>>,
paths: FxHashMap<ImmutPath, EcoVec<TypstFileId>>,
file_ids: FxHashMap<TypstFileId, (ImmutPath, NonZeroUsize)>,
}
impl PathMap {
fn insert(&mut self, path: &ImmutPath, fid: TypstFileId) {
if let Some(fids) = self.paths.get_mut(path) {
fids.push(fid);
} else {
self.paths.insert(path.clone(), vec![fid]);
fn insert(&mut self, next: &ImmutPath, fid: TypstFileId, rev: NonZeroUsize) {
use std::collections::hash_map::Entry;
let rev_entry = self.file_ids.entry(fid);
match rev_entry {
Entry::Occupied(mut entry) => {
let (prev, prev_rev) = entry.get_mut();
if prev != next {
if *prev_rev == rev {
log::warn!("Vfs: {fid:?} is changed in rev({rev:?}), {prev:?} -> {next:?}");
}
if let Some(fids) = self.paths.get_mut(prev) {
fids.retain(|f| *f != fid);
}
*prev = next.clone();
*prev_rev = rev;
self.paths.entry(next.clone()).or_default().push(fid);
}
}
Entry::Vacant(entry) => {
entry.insert((next.clone(), rev));
self.paths.entry(next.clone()).or_default().push(fid);
}
}
}
fn remove(&mut self, path: &Path) -> Option<Vec<TypstFileId>> {
self.paths.remove(path)
fn get(&mut self, path: &Path) -> Option<&EcoVec<TypstFileId>> {
self.paths.get(path)
}
fn display(&self) -> DisplayPathMap {