mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
simpler update
This commit is contained in:
parent
b937262c9b
commit
ecc9df5f00
4 changed files with 149 additions and 73 deletions
|
@ -2,17 +2,38 @@ use std::{
|
|||
path::{PathBuf},
|
||||
};
|
||||
|
||||
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use libsyntax2::{
|
||||
ast::{self, AstNode, NameOwner},
|
||||
SyntaxNode, ParsedFile, SmolStr,
|
||||
ast::{self, AstNode, NameOwner, ParsedFile},
|
||||
SyntaxNode, SmolStr,
|
||||
};
|
||||
use {FileId, FileResolver};
|
||||
|
||||
type SyntaxProvider<'a> = dyn Fn(FileId) -> ParsedFile + 'a;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct ModuleId(FileId);
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ModuleMap {
|
||||
state: RwLock<State>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ChangeKind {
|
||||
Delete, Insert, Update
|
||||
}
|
||||
|
||||
impl Clone for ModuleMap {
|
||||
fn clone(&self) -> ModuleMap {
|
||||
let state = self.state.read().clone();
|
||||
ModuleMap { state: RwLock::new(state) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct State {
|
||||
changes: Vec<(FileId, ChangeKind)>,
|
||||
links: Vec<Link>,
|
||||
}
|
||||
|
||||
|
@ -24,31 +45,8 @@ struct Link {
|
|||
}
|
||||
|
||||
impl ModuleMap {
|
||||
pub fn update_file(
|
||||
&mut self,
|
||||
file_id: FileId,
|
||||
syntax: Option<&ParsedFile>,
|
||||
file_resolver: &FileResolver,
|
||||
) {
|
||||
let mod_id = ModuleId(file_id);
|
||||
self.links.retain(|link| link.owner != mod_id);
|
||||
match syntax {
|
||||
None => {
|
||||
for link in self.links.iter_mut() {
|
||||
link.points_to.retain(|&x| x != mod_id);
|
||||
}
|
||||
}
|
||||
Some(syntax) => {
|
||||
self.links.extend(
|
||||
syntax.ast().modules().filter_map(|it| {
|
||||
Link::new(mod_id, it)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
self.links.iter_mut().for_each(|link| {
|
||||
link.resolve(file_resolver)
|
||||
})
|
||||
pub fn update_file(&mut self, file: FileId, change_kind: ChangeKind) {
|
||||
self.state.get_mut().changes.push((file, change_kind));
|
||||
}
|
||||
|
||||
pub fn module2file(&self, m: ModuleId) -> FileId {
|
||||
|
@ -59,8 +57,15 @@ impl ModuleMap {
|
|||
ModuleId(file_id)
|
||||
}
|
||||
|
||||
pub fn child_module_by_name(&self, parent_mod: ModuleId, child_mod: &str) -> Vec<ModuleId> {
|
||||
self.links
|
||||
pub fn child_module_by_name<'a>(
|
||||
&self,
|
||||
parent_mod: ModuleId,
|
||||
child_mod: &str,
|
||||
file_resolver: &FileResolver,
|
||||
syntax_provider: &SyntaxProvider,
|
||||
) -> Vec<ModuleId> {
|
||||
self.links(file_resolver, syntax_provider)
|
||||
.links
|
||||
.iter()
|
||||
.filter(|link| link.owner == parent_mod)
|
||||
.filter(|link| link.name() == child_mod)
|
||||
|
@ -69,13 +74,90 @@ impl ModuleMap {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn parent_modules<'a>(&'a self, m: ModuleId) -> impl Iterator<Item=(ModuleId, ast::Module<'a>)> + 'a {
|
||||
self.links
|
||||
pub fn parent_modules(
|
||||
&self,
|
||||
m: ModuleId,
|
||||
file_resolver: &FileResolver,
|
||||
syntax_provider: &SyntaxProvider,
|
||||
) -> Vec<(ModuleId, SmolStr, SyntaxNode)> {
|
||||
let links = self.links(file_resolver, syntax_provider);
|
||||
let res = links
|
||||
.links
|
||||
.iter()
|
||||
.filter(move |link| link.points_to.iter().any(|&it| it == m))
|
||||
.map(|link| {
|
||||
(link.owner, link.ast())
|
||||
(link.owner, link.name().clone(), link.syntax.clone())
|
||||
})
|
||||
.collect();
|
||||
res
|
||||
}
|
||||
|
||||
fn links(
|
||||
&self,
|
||||
file_resolver: &FileResolver,
|
||||
syntax_provider: &SyntaxProvider,
|
||||
) -> RwLockReadGuard<State> {
|
||||
{
|
||||
let guard = self.state.read();
|
||||
if guard.changes.is_empty() {
|
||||
return guard;
|
||||
}
|
||||
}
|
||||
let mut guard = self.state.write();
|
||||
if !guard.changes.is_empty() {
|
||||
guard.apply_changes(file_resolver, syntax_provider);
|
||||
}
|
||||
assert!(guard.changes.is_empty());
|
||||
RwLockWriteGuard::downgrade(guard)
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn apply_changes(
|
||||
&mut self,
|
||||
file_resolver: &FileResolver,
|
||||
syntax_provider: &SyntaxProvider,
|
||||
) {
|
||||
let mut reresolve = false;
|
||||
for (file_id, kind) in self.changes.drain(..) {
|
||||
let mod_id = ModuleId(file_id);
|
||||
self.links.retain(|link| link.owner != mod_id);
|
||||
match kind {
|
||||
ChangeKind::Delete => {
|
||||
for link in self.links.iter_mut() {
|
||||
link.points_to.retain(|&x| x != mod_id);
|
||||
}
|
||||
}
|
||||
ChangeKind::Insert => {
|
||||
let file = syntax_provider(file_id);
|
||||
self.links.extend(
|
||||
file
|
||||
.ast()
|
||||
.modules()
|
||||
.filter_map(|it| Link::new(mod_id, it))
|
||||
);
|
||||
reresolve = true;
|
||||
}
|
||||
ChangeKind::Update => {
|
||||
let file = syntax_provider(file_id);
|
||||
self.links.extend(
|
||||
file
|
||||
.ast()
|
||||
.modules()
|
||||
.filter_map(|it| Link::new(mod_id, it))
|
||||
.map(|mut link| {
|
||||
link.resolve(file_resolver);
|
||||
link
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if reresolve {
|
||||
for link in self.links.iter_mut() {
|
||||
link.resolve(file_resolver)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue