mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
move db basics to ra_db
This should allow to move hir to a separate crate
This commit is contained in:
parent
b2de95879a
commit
11168c464c
22 changed files with 352 additions and 293 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -607,6 +607,7 @@ dependencies = [
|
||||||
"id-arena 1.0.2 (git+https://github.com/fitzgen/id-arena/?rev=43ecd67)",
|
"id-arena 1.0.2 (git+https://github.com/fitzgen/id-arena/?rev=43ecd67)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ra_db 0.1.0",
|
||||||
"ra_editor 0.1.0",
|
"ra_editor 0.1.0",
|
||||||
"ra_syntax 0.1.0",
|
"ra_syntax 0.1.0",
|
||||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -628,6 +629,21 @@ dependencies = [
|
||||||
"tools 0.1.0",
|
"tools 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ra_db"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"id-arena 1.0.2 (git+https://github.com/fitzgen/id-arena/?rev=43ecd67)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ra_editor 0.1.0",
|
||||||
|
"ra_syntax 0.1.0",
|
||||||
|
"relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"salsa 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"test_utils 0.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ra_editor"
|
name = "ra_editor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -15,4 +15,5 @@ parking_lot = "0.6.4"
|
||||||
id-arena = { git = "https://github.com/fitzgen/id-arena/", rev = "43ecd67" }
|
id-arena = { git = "https://github.com/fitzgen/id-arena/", rev = "43ecd67" }
|
||||||
ra_syntax = { path = "../ra_syntax" }
|
ra_syntax = { path = "../ra_syntax" }
|
||||||
ra_editor = { path = "../ra_editor" }
|
ra_editor = { path = "../ra_editor" }
|
||||||
|
ra_db = { path = "../ra_db" }
|
||||||
test_utils = { path = "../test_utils" }
|
test_utils = { path = "../test_utils" }
|
||||||
|
|
|
@ -7,10 +7,11 @@ use ra_syntax::{
|
||||||
AstNode, AtomEdit,
|
AstNode, AtomEdit,
|
||||||
SyntaxNodeRef,
|
SyntaxNodeRef,
|
||||||
};
|
};
|
||||||
|
use ra_db::SyntaxDatabase;
|
||||||
use rustc_hash::{FxHashMap};
|
use rustc_hash::{FxHashMap};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::{self, SyntaxDatabase},
|
db,
|
||||||
hir,
|
hir,
|
||||||
Cancelable, FilePosition
|
Cancelable, FilePosition
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use ra_editor::LineIndex;
|
|
||||||
use ra_syntax::{SourceFileNode};
|
|
||||||
use salsa::{self, Database};
|
use salsa::{self, Database};
|
||||||
|
use ra_db::{LocationIntener, BaseDatabase};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hir,
|
hir,
|
||||||
symbol_index,
|
symbol_index,
|
||||||
loc2id::{IdMaps, LocationIntener, DefId, DefLoc, FnId},
|
loc2id::{IdMaps, DefId, DefLoc, FnId},
|
||||||
Cancelable, Canceled, FileId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -47,11 +45,11 @@ impl Default for RootDatabase {
|
||||||
runtime: salsa::Runtime::default(),
|
runtime: salsa::Runtime::default(),
|
||||||
id_maps: Default::default(),
|
id_maps: Default::default(),
|
||||||
};
|
};
|
||||||
db.query_mut(crate::input::SourceRootQuery)
|
db.query_mut(ra_db::SourceRootQuery)
|
||||||
.set(crate::input::WORKSPACE, Default::default());
|
.set(ra_db::WORKSPACE, Default::default());
|
||||||
db.query_mut(crate::input::CrateGraphQuery)
|
db.query_mut(ra_db::CrateGraphQuery)
|
||||||
.set((), Default::default());
|
.set((), Default::default());
|
||||||
db.query_mut(crate::input::LibrariesQuery)
|
db.query_mut(ra_db::LibrariesQuery)
|
||||||
.set((), Default::default());
|
.set((), Default::default());
|
||||||
db
|
db
|
||||||
}
|
}
|
||||||
|
@ -67,22 +65,7 @@ impl salsa::ParallelDatabase for RootDatabase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait BaseDatabase: salsa::Database {
|
impl BaseDatabase for RootDatabase {}
|
||||||
fn id_maps(&self) -> &IdMaps;
|
|
||||||
fn check_canceled(&self) -> Cancelable<()> {
|
|
||||||
if self.salsa_runtime().is_current_revision_canceled() {
|
|
||||||
Err(Canceled)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BaseDatabase for RootDatabase {
|
|
||||||
fn id_maps(&self) -> &IdMaps {
|
|
||||||
&self.id_maps
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
|
impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
|
||||||
fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> {
|
fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> {
|
||||||
|
@ -121,16 +104,16 @@ impl RootDatabase {
|
||||||
|
|
||||||
salsa::database_storage! {
|
salsa::database_storage! {
|
||||||
pub(crate) struct RootDatabaseStorage for RootDatabase {
|
pub(crate) struct RootDatabaseStorage for RootDatabase {
|
||||||
impl crate::input::FilesDatabase {
|
impl ra_db::FilesDatabase {
|
||||||
fn file_text() for crate::input::FileTextQuery;
|
fn file_text() for ra_db::FileTextQuery;
|
||||||
fn file_source_root() for crate::input::FileSourceRootQuery;
|
fn file_source_root() for ra_db::FileSourceRootQuery;
|
||||||
fn source_root() for crate::input::SourceRootQuery;
|
fn source_root() for ra_db::SourceRootQuery;
|
||||||
fn libraries() for crate::input::LibrariesQuery;
|
fn libraries() for ra_db::LibrariesQuery;
|
||||||
fn crate_graph() for crate::input::CrateGraphQuery;
|
fn crate_graph() for ra_db::CrateGraphQuery;
|
||||||
}
|
}
|
||||||
impl SyntaxDatabase {
|
impl ra_db::SyntaxDatabase {
|
||||||
fn source_file() for SourceFileQuery;
|
fn source_file() for ra_db::SourceFileQuery;
|
||||||
fn file_lines() for FileLinesQuery;
|
fn file_lines() for ra_db::FileLinesQuery;
|
||||||
}
|
}
|
||||||
impl symbol_index::SymbolsDatabase {
|
impl symbol_index::SymbolsDatabase {
|
||||||
fn file_symbols() for symbol_index::FileSymbolsQuery;
|
fn file_symbols() for symbol_index::FileSymbolsQuery;
|
||||||
|
@ -148,23 +131,3 @@ salsa::database_storage! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_group! {
|
|
||||||
pub(crate) trait SyntaxDatabase: crate::input::FilesDatabase + BaseDatabase {
|
|
||||||
fn source_file(file_id: FileId) -> SourceFileNode {
|
|
||||||
type SourceFileQuery;
|
|
||||||
}
|
|
||||||
fn file_lines(file_id: FileId) -> Arc<LineIndex> {
|
|
||||||
type FileLinesQuery;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn source_file(db: &impl SyntaxDatabase, file_id: FileId) -> SourceFileNode {
|
|
||||||
let text = db.file_text(file_id);
|
|
||||||
SourceFileNode::parse(&*text)
|
|
||||||
}
|
|
||||||
fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> {
|
|
||||||
let text = db.file_text(file_id);
|
|
||||||
Arc::new(LineIndex::new(&*text))
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,10 +4,10 @@ use ra_syntax::{
|
||||||
SyntaxNode,
|
SyntaxNode,
|
||||||
ast::FnDefNode,
|
ast::FnDefNode,
|
||||||
};
|
};
|
||||||
|
use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
FileId,
|
FileId,
|
||||||
db::SyntaxDatabase,
|
|
||||||
hir::{
|
hir::{
|
||||||
SourceFileItems, SourceItemId,
|
SourceFileItems, SourceItemId,
|
||||||
query_definitions,
|
query_definitions,
|
||||||
|
@ -15,8 +15,7 @@ use crate::{
|
||||||
module::{ModuleId, ModuleTree, ModuleSource,
|
module::{ModuleId, ModuleTree, ModuleSource,
|
||||||
nameres::{ItemMap, InputModuleItems}},
|
nameres::{ItemMap, InputModuleItems}},
|
||||||
},
|
},
|
||||||
input::SourceRootId,
|
loc2id::{DefLoc, DefId, FnId},
|
||||||
loc2id::{DefLoc, DefId, FnId, LocationIntener},
|
|
||||||
Cancelable,
|
Cancelable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,10 @@ use ra_syntax::{
|
||||||
algo::generate,
|
algo::generate,
|
||||||
ast::{self, ArgListOwner, LoopBodyOwner, NameOwner},
|
ast::{self, ArgListOwner, LoopBodyOwner, NameOwner},
|
||||||
};
|
};
|
||||||
|
use ra_db::LocalSyntaxPtr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
syntax_ptr::LocalSyntaxPtr,
|
|
||||||
arena::{Arena, Id},
|
arena::{Arena, Id},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@ use ra_syntax::{
|
||||||
};
|
};
|
||||||
use relative_path::RelativePathBuf;
|
use relative_path::RelativePathBuf;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
use ra_db::{SourceRoot, SourceRootId, FileResolverImp};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hir::HirDatabase,
|
hir::HirDatabase,
|
||||||
input::{SourceRoot, SourceRootId},
|
Cancelable, FileId,
|
||||||
Cancelable, FileId, FileResolverImp,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
|
@ -10,12 +10,12 @@ use ra_syntax::{
|
||||||
ast::{self, AstNode, NameOwner},
|
ast::{self, AstNode, NameOwner},
|
||||||
SmolStr, SyntaxNode,
|
SmolStr, SyntaxNode,
|
||||||
};
|
};
|
||||||
|
use ra_db::SourceRootId;
|
||||||
use relative_path::RelativePathBuf;
|
use relative_path::RelativePathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
FileId, FilePosition, Cancelable,
|
FileId, FilePosition, Cancelable,
|
||||||
hir::{Path, PathKind, HirDatabase, SourceItemId},
|
hir::{Path, PathKind, HirDatabase, SourceItemId},
|
||||||
input::SourceRootId,
|
|
||||||
arena::{Arena, Id},
|
arena::{Arena, Id},
|
||||||
loc2id::{DefLoc, DefId},
|
loc2id::{DefLoc, DefId},
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,12 +19,12 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
TextRange,
|
TextRange,
|
||||||
SmolStr, SyntaxKind::{self, *},
|
SmolStr, SyntaxKind::{self, *},
|
||||||
ast::{self, AstNode}
|
ast::{self, AstNode}
|
||||||
};
|
};
|
||||||
|
use ra_db::SourceRootId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Cancelable, FileId,
|
Cancelable, FileId,
|
||||||
|
@ -35,7 +35,6 @@ use crate::{
|
||||||
HirDatabase,
|
HirDatabase,
|
||||||
module::{ModuleId, ModuleTree},
|
module::{ModuleId, ModuleTree},
|
||||||
},
|
},
|
||||||
input::SourceRootId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Item map is the result of the name resolution. Item map contains, for each
|
/// Item map is the result of the name resolution. Item map contains, for each
|
||||||
|
@ -342,11 +341,11 @@ where
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use ra_db::FilesDatabase;
|
||||||
use crate::{
|
use crate::{
|
||||||
AnalysisChange,
|
AnalysisChange,
|
||||||
mock_analysis::{MockAnalysis, analysis_and_position},
|
mock_analysis::{MockAnalysis, analysis_and_position},
|
||||||
hir::{self, HirDatabase},
|
hir::{self, HirDatabase},
|
||||||
input::FilesDatabase,
|
|
||||||
};
|
};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ use ra_syntax::{
|
||||||
AstNode, SyntaxNode, SmolStr,
|
AstNode, SyntaxNode, SmolStr,
|
||||||
ast::{self, FnDef, FnDefNode, NameOwner, ModuleItemOwner}
|
ast::{self, FnDef, FnDefNode, NameOwner, ModuleItemOwner}
|
||||||
};
|
};
|
||||||
|
use ra_db::SourceRootId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
FileId, Cancelable,
|
FileId, Cancelable,
|
||||||
|
@ -21,7 +22,6 @@ use crate::{
|
||||||
nameres::{InputModuleItems, ItemMap, Resolver},
|
nameres::{InputModuleItems, ItemMap, Resolver},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
input::SourceRootId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Resolve `FnId` to the corresponding `SyntaxNode`
|
/// Resolve `FnId` to the corresponding `SyntaxNode`
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
hash::{Hash, Hasher},
|
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,84 +10,24 @@ use ra_syntax::{
|
||||||
SyntaxKind::*,
|
SyntaxKind::*,
|
||||||
SyntaxNodeRef, TextRange, TextUnit,
|
SyntaxNodeRef, TextRange, TextUnit,
|
||||||
};
|
};
|
||||||
|
use ra_db::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE, SyntaxDatabase, SourceFileQuery};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use relative_path::RelativePath;
|
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use salsa::{Database, ParallelDatabase};
|
use salsa::{Database, ParallelDatabase};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
completion::{completions, CompletionItem},
|
completion::{completions, CompletionItem},
|
||||||
db::{self, SourceFileQuery, SyntaxDatabase},
|
db,
|
||||||
hir::{
|
hir::{
|
||||||
self,
|
self,
|
||||||
FnSignatureInfo,
|
FnSignatureInfo,
|
||||||
Problem,
|
Problem,
|
||||||
},
|
},
|
||||||
input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE},
|
|
||||||
symbol_index::{SymbolIndex, SymbolsDatabase},
|
symbol_index::{SymbolIndex, SymbolsDatabase},
|
||||||
AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver,
|
AnalysisChange, Cancelable, CrateId, Diagnostic, FileId,
|
||||||
FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit,
|
FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub(crate) struct FileResolverImp {
|
|
||||||
inner: Arc<FileResolver>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for FileResolverImp {
|
|
||||||
fn eq(&self, other: &FileResolverImp) -> bool {
|
|
||||||
self.inner() == other.inner()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for FileResolverImp {}
|
|
||||||
|
|
||||||
impl Hash for FileResolverImp {
|
|
||||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
||||||
self.inner().hash(hasher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FileResolverImp {
|
|
||||||
pub(crate) fn new(inner: Arc<FileResolver>) -> FileResolverImp {
|
|
||||||
FileResolverImp { inner }
|
|
||||||
}
|
|
||||||
pub(crate) fn file_stem(&self, file_id: FileId) -> String {
|
|
||||||
self.inner.file_stem(file_id)
|
|
||||||
}
|
|
||||||
pub(crate) fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId> {
|
|
||||||
self.inner.resolve(file_id, path)
|
|
||||||
}
|
|
||||||
pub(crate) fn debug_path(&self, file_id: FileId) -> Option<std::path::PathBuf> {
|
|
||||||
self.inner.debug_path(file_id)
|
|
||||||
}
|
|
||||||
fn inner(&self) -> *const FileResolver {
|
|
||||||
&*self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for FileResolverImp {
|
|
||||||
fn default() -> FileResolverImp {
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct DummyResolver;
|
|
||||||
impl FileResolver for DummyResolver {
|
|
||||||
fn file_stem(&self, _file_: FileId) -> String {
|
|
||||||
panic!("file resolver not set")
|
|
||||||
}
|
|
||||||
fn resolve(
|
|
||||||
&self,
|
|
||||||
_file_id: FileId,
|
|
||||||
_path: &::relative_path::RelativePath,
|
|
||||||
) -> Option<FileId> {
|
|
||||||
panic!("file resolver not set")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FileResolverImp {
|
|
||||||
inner: Arc::new(DummyResolver),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct AnalysisHostImpl {
|
pub(crate) struct AnalysisHostImpl {
|
||||||
db: db::RootDatabase,
|
db: db::RootDatabase,
|
||||||
|
@ -105,7 +44,7 @@ impl AnalysisHostImpl {
|
||||||
|
|
||||||
for (file_id, text) in change.files_changed {
|
for (file_id, text) in change.files_changed {
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::FileTextQuery)
|
.query_mut(ra_db::FileTextQuery)
|
||||||
.set(file_id, Arc::new(text))
|
.set(file_id, Arc::new(text))
|
||||||
}
|
}
|
||||||
if !(change.files_added.is_empty() && change.files_removed.is_empty()) {
|
if !(change.files_added.is_empty() && change.files_removed.is_empty()) {
|
||||||
|
@ -115,22 +54,22 @@ impl AnalysisHostImpl {
|
||||||
let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE));
|
let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE));
|
||||||
for (file_id, text) in change.files_added {
|
for (file_id, text) in change.files_added {
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::FileTextQuery)
|
.query_mut(ra_db::FileTextQuery)
|
||||||
.set(file_id, Arc::new(text));
|
.set(file_id, Arc::new(text));
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::FileSourceRootQuery)
|
.query_mut(ra_db::FileSourceRootQuery)
|
||||||
.set(file_id, crate::input::WORKSPACE);
|
.set(file_id, ra_db::WORKSPACE);
|
||||||
source_root.files.insert(file_id);
|
source_root.files.insert(file_id);
|
||||||
}
|
}
|
||||||
for file_id in change.files_removed {
|
for file_id in change.files_removed {
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::FileTextQuery)
|
.query_mut(ra_db::FileTextQuery)
|
||||||
.set(file_id, Arc::new(String::new()));
|
.set(file_id, Arc::new(String::new()));
|
||||||
source_root.files.remove(&file_id);
|
source_root.files.remove(&file_id);
|
||||||
}
|
}
|
||||||
source_root.file_resolver = file_resolver;
|
source_root.file_resolver = file_resolver;
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::SourceRootQuery)
|
.query_mut(ra_db::SourceRootQuery)
|
||||||
.set(WORKSPACE, Arc::new(source_root))
|
.set(WORKSPACE, Arc::new(source_root))
|
||||||
}
|
}
|
||||||
if !change.libraries_added.is_empty() {
|
if !change.libraries_added.is_empty() {
|
||||||
|
@ -147,10 +86,10 @@ impl AnalysisHostImpl {
|
||||||
library.file_resolver.debug_path(file_id)
|
library.file_resolver.debug_path(file_id)
|
||||||
);
|
);
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::FileSourceRootQuery)
|
.query_mut(ra_db::FileSourceRootQuery)
|
||||||
.set_constant(file_id, source_root_id);
|
.set_constant(file_id, source_root_id);
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::FileTextQuery)
|
.query_mut(ra_db::FileTextQuery)
|
||||||
.set_constant(file_id, Arc::new(text));
|
.set_constant(file_id, Arc::new(text));
|
||||||
}
|
}
|
||||||
let source_root = SourceRoot {
|
let source_root = SourceRoot {
|
||||||
|
@ -158,19 +97,19 @@ impl AnalysisHostImpl {
|
||||||
file_resolver: library.file_resolver,
|
file_resolver: library.file_resolver,
|
||||||
};
|
};
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::SourceRootQuery)
|
.query_mut(ra_db::SourceRootQuery)
|
||||||
.set(source_root_id, Arc::new(source_root));
|
.set(source_root_id, Arc::new(source_root));
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::symbol_index::LibrarySymbolsQuery)
|
.query_mut(crate::symbol_index::LibrarySymbolsQuery)
|
||||||
.set(source_root_id, Arc::new(library.symbol_index));
|
.set(source_root_id, Arc::new(library.symbol_index));
|
||||||
}
|
}
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::LibrariesQuery)
|
.query_mut(ra_db::LibrariesQuery)
|
||||||
.set((), Arc::new(libraries));
|
.set((), Arc::new(libraries));
|
||||||
}
|
}
|
||||||
if let Some(crate_graph) = change.crate_graph {
|
if let Some(crate_graph) = change.crate_graph {
|
||||||
self.db
|
self.db
|
||||||
.query_mut(crate::input::CrateGraphQuery)
|
.query_mut(ra_db::CrateGraphQuery)
|
||||||
.set((), Arc::new(crate_graph))
|
.set((), Arc::new(crate_graph))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,7 +200,7 @@ impl AnalysisImpl {
|
||||||
Ok(crate_id.into_iter().collect())
|
Ok(crate_id.into_iter().collect())
|
||||||
}
|
}
|
||||||
pub fn crate_root(&self, crate_id: CrateId) -> FileId {
|
pub fn crate_root(&self, crate_id: CrateId) -> FileId {
|
||||||
self.db.crate_graph().crate_roots[&crate_id]
|
self.db.crate_graph().crate_root(crate_id)
|
||||||
}
|
}
|
||||||
pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
|
pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
|
||||||
completions(&self.db, position)
|
completions(&self.db, position)
|
||||||
|
@ -546,16 +485,6 @@ impl SourceChange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateGraph {
|
|
||||||
fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
|
|
||||||
let (&crate_id, _) = self
|
|
||||||
.crate_roots
|
|
||||||
.iter()
|
|
||||||
.find(|(_crate_id, &root_id)| root_id == file_id)?;
|
|
||||||
Some(crate_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FnCallNode<'a> {
|
enum FnCallNode<'a> {
|
||||||
CallExpr(ast::CallExpr<'a>),
|
CallExpr(ast::CallExpr<'a>),
|
||||||
MethodCallExpr(ast::MethodCallExpr<'a>),
|
MethodCallExpr(ast::MethodCallExpr<'a>),
|
||||||
|
|
|
@ -19,8 +19,6 @@ macro_rules! ctry {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod arena;
|
mod arena;
|
||||||
mod syntax_ptr;
|
|
||||||
mod input;
|
|
||||||
mod db;
|
mod db;
|
||||||
mod loc2id;
|
mod loc2id;
|
||||||
mod imp;
|
mod imp;
|
||||||
|
@ -32,35 +30,27 @@ pub mod mock_analysis;
|
||||||
use std::{fmt, sync::Arc};
|
use std::{fmt, sync::Arc};
|
||||||
|
|
||||||
use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit};
|
use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit};
|
||||||
|
use ra_db::FileResolverImp;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use relative_path::RelativePathBuf;
|
use relative_path::RelativePathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp},
|
imp::{AnalysisHostImpl, AnalysisImpl},
|
||||||
symbol_index::SymbolIndex,
|
symbol_index::SymbolIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
completion::CompletionItem,
|
completion::CompletionItem,
|
||||||
hir::FnSignatureInfo,
|
hir::FnSignatureInfo,
|
||||||
input::{CrateGraph, CrateId, FileId, FileResolver},
|
|
||||||
};
|
};
|
||||||
pub use ra_editor::{
|
pub use ra_editor::{
|
||||||
FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode,
|
FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
pub use ra_db::{
|
||||||
pub struct Canceled;
|
Canceled, Cancelable,
|
||||||
|
CrateGraph, CrateId, FileId, FileResolver
|
||||||
pub type Cancelable<T> = Result<T, Canceled>;
|
};
|
||||||
|
|
||||||
impl std::fmt::Display for Canceled {
|
|
||||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
fmt.write_str("Canceled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for Canceled {}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct AnalysisChange {
|
pub struct AnalysisChange {
|
||||||
|
|
|
@ -1,74 +1,10 @@
|
||||||
use parking_lot::Mutex;
|
use ra_db::SourceRootId;
|
||||||
|
|
||||||
use std::hash::Hash;
|
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hir::{SourceItemId, ModuleId},
|
hir::{SourceItemId, ModuleId},
|
||||||
input::SourceRootId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// There are two principle ways to refer to things:
|
use ra_db::{NumericId, LocationIntener};
|
||||||
/// - by their locatinon (module in foo/bar/baz.rs at line 42)
|
|
||||||
/// - by their numeric id (module `ModuleId(42)`)
|
|
||||||
///
|
|
||||||
/// The first one is more powerful (you can actually find the thing in question
|
|
||||||
/// by id), but the second one is so much more compact.
|
|
||||||
///
|
|
||||||
/// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a
|
|
||||||
/// bidirectional mapping between positional and numeric ids, we can use compact
|
|
||||||
/// representation wich still allows us to get the actual item
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Loc2IdMap<LOC, ID>
|
|
||||||
where
|
|
||||||
ID: NumericId,
|
|
||||||
LOC: Clone + Eq + Hash,
|
|
||||||
{
|
|
||||||
loc2id: FxHashMap<LOC, ID>,
|
|
||||||
id2loc: FxHashMap<ID, LOC>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<LOC, ID> Default for Loc2IdMap<LOC, ID>
|
|
||||||
where
|
|
||||||
ID: NumericId,
|
|
||||||
LOC: Clone + Eq + Hash,
|
|
||||||
{
|
|
||||||
fn default() -> Self {
|
|
||||||
Loc2IdMap {
|
|
||||||
loc2id: FxHashMap::default(),
|
|
||||||
id2loc: FxHashMap::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<LOC, ID> Loc2IdMap<LOC, ID>
|
|
||||||
where
|
|
||||||
ID: NumericId,
|
|
||||||
LOC: Clone + Eq + Hash,
|
|
||||||
{
|
|
||||||
pub fn loc2id(&mut self, loc: &LOC) -> ID {
|
|
||||||
match self.loc2id.get(loc) {
|
|
||||||
Some(id) => return id.clone(),
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
let id = self.loc2id.len();
|
|
||||||
assert!(id < u32::max_value() as usize);
|
|
||||||
let id = ID::from_u32(id as u32);
|
|
||||||
self.loc2id.insert(loc.clone(), id.clone());
|
|
||||||
self.id2loc.insert(id.clone(), loc.clone());
|
|
||||||
id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id2loc(&self, id: ID) -> LOC {
|
|
||||||
self.id2loc[&id].clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait NumericId: Clone + Eq + Hash {
|
|
||||||
fn from_u32(id: u32) -> Self;
|
|
||||||
fn to_u32(self) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_numeric_id {
|
macro_rules! impl_numeric_id {
|
||||||
($id:ident) => {
|
($id:ident) => {
|
||||||
|
@ -131,37 +67,3 @@ pub(crate) struct IdMaps {
|
||||||
pub(crate) fns: LocationIntener<SourceItemId, FnId>,
|
pub(crate) fns: LocationIntener<SourceItemId, FnId>,
|
||||||
pub(crate) defs: LocationIntener<DefLoc, DefId>,
|
pub(crate) defs: LocationIntener<DefLoc, DefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) struct LocationIntener<LOC, ID>
|
|
||||||
where
|
|
||||||
ID: NumericId,
|
|
||||||
LOC: Clone + Eq + Hash,
|
|
||||||
{
|
|
||||||
map: Mutex<Loc2IdMap<LOC, ID>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<LOC, ID> Default for LocationIntener<LOC, ID>
|
|
||||||
where
|
|
||||||
ID: NumericId,
|
|
||||||
LOC: Clone + Eq + Hash,
|
|
||||||
{
|
|
||||||
fn default() -> Self {
|
|
||||||
LocationIntener {
|
|
||||||
map: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<LOC, ID> LocationIntener<LOC, ID>
|
|
||||||
where
|
|
||||||
ID: NumericId,
|
|
||||||
LOC: Clone + Eq + Hash,
|
|
||||||
{
|
|
||||||
fn loc2id(&self, loc: &LOC) -> ID {
|
|
||||||
self.map.lock().loc2id(loc)
|
|
||||||
}
|
|
||||||
fn id2loc(&self, id: ID) -> LOC {
|
|
||||||
self.map.lock().id2loc(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,13 +9,12 @@ use ra_syntax::{
|
||||||
SourceFileNode,
|
SourceFileNode,
|
||||||
SyntaxKind::{self, *},
|
SyntaxKind::{self, *},
|
||||||
};
|
};
|
||||||
|
use ra_db::{SyntaxDatabase, SourceRootId};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Cancelable,
|
Cancelable,
|
||||||
FileId, Query,
|
FileId, Query,
|
||||||
db::SyntaxDatabase,
|
|
||||||
input::SourceRootId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
salsa::query_group! {
|
salsa::query_group! {
|
||||||
|
|
|
@ -126,7 +126,7 @@ fn test_resolve_crate_root() {
|
||||||
let mut host = mock.analysis_host();
|
let mut host = mock.analysis_host();
|
||||||
assert!(host.analysis().crate_for(mod_file).unwrap().is_empty());
|
assert!(host.analysis().crate_for(mod_file).unwrap().is_empty());
|
||||||
|
|
||||||
let mut crate_graph = CrateGraph::new();
|
let mut crate_graph = CrateGraph::default();
|
||||||
let crate_id = crate_graph.add_crate_root(root_file);
|
let crate_id = crate_graph.add_crate_root(root_file);
|
||||||
let mut change = AnalysisChange::new();
|
let mut change = AnalysisChange::new();
|
||||||
change.set_crate_graph(crate_graph);
|
change.set_crate_graph(crate_graph);
|
||||||
|
|
16
crates/ra_db/Cargo.toml
Normal file
16
crates/ra_db/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[package]
|
||||||
|
edition = "2018"
|
||||||
|
name = "ra_db"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.4.5"
|
||||||
|
relative-path = "0.4.0"
|
||||||
|
salsa = "0.8.0"
|
||||||
|
rustc-hash = "1.0"
|
||||||
|
parking_lot = "0.6.4"
|
||||||
|
id-arena = { git = "https://github.com/fitzgen/id-arena/", rev = "43ecd67" }
|
||||||
|
ra_syntax = { path = "../ra_syntax" }
|
||||||
|
ra_editor = { path = "../ra_editor" }
|
||||||
|
test_utils = { path = "../test_utils" }
|
76
crates/ra_db/src/file_resolver.rs
Normal file
76
crates/ra_db/src/file_resolver.rs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
use std::{
|
||||||
|
sync::Arc,
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
fmt,
|
||||||
|
};
|
||||||
|
|
||||||
|
use relative_path::RelativePath;
|
||||||
|
|
||||||
|
use crate::input::FileId;
|
||||||
|
|
||||||
|
pub trait FileResolver: fmt::Debug + Send + Sync + 'static {
|
||||||
|
fn file_stem(&self, file_id: FileId) -> String;
|
||||||
|
fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId>;
|
||||||
|
fn debug_path(&self, _1file_id: FileId) -> Option<std::path::PathBuf> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct FileResolverImp {
|
||||||
|
inner: Arc<FileResolver>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for FileResolverImp {
|
||||||
|
fn eq(&self, other: &FileResolverImp) -> bool {
|
||||||
|
self.inner() == other.inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for FileResolverImp {}
|
||||||
|
|
||||||
|
impl Hash for FileResolverImp {
|
||||||
|
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||||
|
self.inner().hash(hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileResolverImp {
|
||||||
|
pub fn new(inner: Arc<FileResolver>) -> FileResolverImp {
|
||||||
|
FileResolverImp { inner }
|
||||||
|
}
|
||||||
|
pub fn file_stem(&self, file_id: FileId) -> String {
|
||||||
|
self.inner.file_stem(file_id)
|
||||||
|
}
|
||||||
|
pub fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId> {
|
||||||
|
self.inner.resolve(file_id, path)
|
||||||
|
}
|
||||||
|
pub fn debug_path(&self, file_id: FileId) -> Option<std::path::PathBuf> {
|
||||||
|
self.inner.debug_path(file_id)
|
||||||
|
}
|
||||||
|
fn inner(&self) -> *const FileResolver {
|
||||||
|
&*self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FileResolverImp {
|
||||||
|
fn default() -> FileResolverImp {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct DummyResolver;
|
||||||
|
impl FileResolver for DummyResolver {
|
||||||
|
fn file_stem(&self, _file_: FileId) -> String {
|
||||||
|
panic!("file resolver not set")
|
||||||
|
}
|
||||||
|
fn resolve(
|
||||||
|
&self,
|
||||||
|
_file_id: FileId,
|
||||||
|
_path: &::relative_path::RelativePath,
|
||||||
|
) -> Option<FileId> {
|
||||||
|
panic!("file resolver not set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FileResolverImp {
|
||||||
|
inner: Arc::new(DummyResolver),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
use std::{fmt, sync::Arc};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use relative_path::RelativePath;
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use salsa;
|
use salsa;
|
||||||
|
|
||||||
use crate::FileResolverImp;
|
use crate::file_resolver::FileResolverImp;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct FileId(pub u32);
|
pub struct FileId(pub u32);
|
||||||
|
@ -19,8 +18,8 @@ pub struct CrateGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateGraph {
|
impl CrateGraph {
|
||||||
pub fn new() -> CrateGraph {
|
pub fn crate_root(&self, crate_id: CrateId) -> FileId {
|
||||||
CrateGraph::default()
|
self.crate_roots[&crate_id]
|
||||||
}
|
}
|
||||||
pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
|
pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
|
||||||
let crate_id = CrateId(self.crate_roots.len() as u32);
|
let crate_id = CrateId(self.crate_roots.len() as u32);
|
||||||
|
@ -28,18 +27,17 @@ impl CrateGraph {
|
||||||
assert!(prev.is_none());
|
assert!(prev.is_none());
|
||||||
crate_id
|
crate_id
|
||||||
}
|
}
|
||||||
}
|
pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
|
||||||
|
let (&crate_id, _) = self
|
||||||
pub trait FileResolver: fmt::Debug + Send + Sync + 'static {
|
.crate_roots
|
||||||
fn file_stem(&self, file_id: FileId) -> String;
|
.iter()
|
||||||
fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId>;
|
.find(|(_crate_id, &root_id)| root_id == file_id)?;
|
||||||
fn debug_path(&self, _1file_id: FileId) -> Option<std::path::PathBuf> {
|
Some(crate_id)
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
salsa::query_group! {
|
salsa::query_group! {
|
||||||
pub(crate) trait FilesDatabase: salsa::Database {
|
pub trait FilesDatabase: salsa::Database {
|
||||||
fn file_text(file_id: FileId) -> Arc<String> {
|
fn file_text(file_id: FileId) -> Arc<String> {
|
||||||
type FileTextQuery;
|
type FileTextQuery;
|
||||||
storage input;
|
storage input;
|
||||||
|
@ -64,12 +62,12 @@ salsa::query_group! {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub(crate) struct SourceRootId(pub(crate) u32);
|
pub struct SourceRootId(pub u32);
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||||
pub(crate) struct SourceRoot {
|
pub struct SourceRoot {
|
||||||
pub(crate) file_resolver: FileResolverImp,
|
pub file_resolver: FileResolverImp,
|
||||||
pub(crate) files: FxHashSet<FileId>,
|
pub files: FxHashSet<FileId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const WORKSPACE: SourceRootId = SourceRootId(0);
|
pub const WORKSPACE: SourceRootId = SourceRootId(0);
|
69
crates/ra_db/src/lib.rs
Normal file
69
crates/ra_db/src/lib.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
//! ra_db defines basic database traits. Concrete DB is defined by ra_analysis.
|
||||||
|
|
||||||
|
extern crate ra_editor;
|
||||||
|
extern crate ra_syntax;
|
||||||
|
extern crate relative_path;
|
||||||
|
extern crate rustc_hash;
|
||||||
|
extern crate salsa;
|
||||||
|
|
||||||
|
mod syntax_ptr;
|
||||||
|
mod file_resolver;
|
||||||
|
mod input;
|
||||||
|
mod loc2id;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use ra_editor::LineIndex;
|
||||||
|
use ra_syntax::SourceFileNode;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
pub struct Canceled;
|
||||||
|
|
||||||
|
pub type Cancelable<T> = Result<T, Canceled>;
|
||||||
|
|
||||||
|
impl std::fmt::Display for Canceled {
|
||||||
|
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
fmt.write_str("Canceled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for Canceled {}
|
||||||
|
|
||||||
|
pub use crate::{
|
||||||
|
syntax_ptr::LocalSyntaxPtr,
|
||||||
|
file_resolver::{FileResolver, FileResolverImp},
|
||||||
|
input::{
|
||||||
|
FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, WORKSPACE,
|
||||||
|
FileTextQuery, FileSourceRootQuery, SourceRootQuery, LibrariesQuery, CrateGraphQuery,
|
||||||
|
},
|
||||||
|
loc2id::{LocationIntener, NumericId},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait BaseDatabase: salsa::Database {
|
||||||
|
fn check_canceled(&self) -> Cancelable<()> {
|
||||||
|
if self.salsa_runtime().is_current_revision_canceled() {
|
||||||
|
Err(Canceled)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
salsa::query_group! {
|
||||||
|
pub trait SyntaxDatabase: crate::input::FilesDatabase + BaseDatabase {
|
||||||
|
fn source_file(file_id: FileId) -> SourceFileNode {
|
||||||
|
type SourceFileQuery;
|
||||||
|
}
|
||||||
|
fn file_lines(file_id: FileId) -> Arc<LineIndex> {
|
||||||
|
type FileLinesQuery;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source_file(db: &impl SyntaxDatabase, file_id: FileId) -> SourceFileNode {
|
||||||
|
let text = db.file_text(file_id);
|
||||||
|
SourceFileNode::parse(&*text)
|
||||||
|
}
|
||||||
|
fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> {
|
||||||
|
let text = db.file_text(file_id);
|
||||||
|
Arc::new(LineIndex::new(&*text))
|
||||||
|
}
|
100
crates/ra_db/src/loc2id.rs
Normal file
100
crates/ra_db/src/loc2id.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
/// There are two principle ways to refer to things:
|
||||||
|
/// - by their locatinon (module in foo/bar/baz.rs at line 42)
|
||||||
|
/// - by their numeric id (module `ModuleId(42)`)
|
||||||
|
///
|
||||||
|
/// The first one is more powerful (you can actually find the thing in question
|
||||||
|
/// by id), but the second one is so much more compact.
|
||||||
|
///
|
||||||
|
/// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a
|
||||||
|
/// bidirectional mapping between positional and numeric ids, we can use compact
|
||||||
|
/// representation wich still allows us to get the actual item
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Loc2IdMap<LOC, ID>
|
||||||
|
where
|
||||||
|
ID: NumericId,
|
||||||
|
LOC: Clone + Eq + Hash,
|
||||||
|
{
|
||||||
|
loc2id: FxHashMap<LOC, ID>,
|
||||||
|
id2loc: FxHashMap<ID, LOC>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<LOC, ID> Default for Loc2IdMap<LOC, ID>
|
||||||
|
where
|
||||||
|
ID: NumericId,
|
||||||
|
LOC: Clone + Eq + Hash,
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
Loc2IdMap {
|
||||||
|
loc2id: FxHashMap::default(),
|
||||||
|
id2loc: FxHashMap::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<LOC, ID> Loc2IdMap<LOC, ID>
|
||||||
|
where
|
||||||
|
ID: NumericId,
|
||||||
|
LOC: Clone + Eq + Hash,
|
||||||
|
{
|
||||||
|
pub fn loc2id(&mut self, loc: &LOC) -> ID {
|
||||||
|
match self.loc2id.get(loc) {
|
||||||
|
Some(id) => return id.clone(),
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
let id = self.loc2id.len();
|
||||||
|
assert!(id < u32::max_value() as usize);
|
||||||
|
let id = ID::from_u32(id as u32);
|
||||||
|
self.loc2id.insert(loc.clone(), id.clone());
|
||||||
|
self.id2loc.insert(id.clone(), loc.clone());
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id2loc(&self, id: ID) -> LOC {
|
||||||
|
self.id2loc[&id].clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait NumericId: Clone + Eq + Hash {
|
||||||
|
fn from_u32(id: u32) -> Self;
|
||||||
|
fn to_u32(self) -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LocationIntener<LOC, ID>
|
||||||
|
where
|
||||||
|
ID: NumericId,
|
||||||
|
LOC: Clone + Eq + Hash,
|
||||||
|
{
|
||||||
|
map: Mutex<Loc2IdMap<LOC, ID>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<LOC, ID> Default for LocationIntener<LOC, ID>
|
||||||
|
where
|
||||||
|
ID: NumericId,
|
||||||
|
LOC: Clone + Eq + Hash,
|
||||||
|
{
|
||||||
|
fn default() -> Self {
|
||||||
|
LocationIntener {
|
||||||
|
map: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<LOC, ID> LocationIntener<LOC, ID>
|
||||||
|
where
|
||||||
|
ID: NumericId,
|
||||||
|
LOC: Clone + Eq + Hash,
|
||||||
|
{
|
||||||
|
pub fn loc2id(&self, loc: &LOC) -> ID {
|
||||||
|
self.map.lock().loc2id(loc)
|
||||||
|
}
|
||||||
|
pub fn id2loc(&self, id: ID) -> LOC {
|
||||||
|
self.map.lock().id2loc(id)
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,20 +2,20 @@ use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange
|
||||||
|
|
||||||
/// A pionter to a syntax node inside a file.
|
/// A pionter to a syntax node inside a file.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub(crate) struct LocalSyntaxPtr {
|
pub struct LocalSyntaxPtr {
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
kind: SyntaxKind,
|
kind: SyntaxKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalSyntaxPtr {
|
impl LocalSyntaxPtr {
|
||||||
pub(crate) fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
|
pub fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
|
||||||
LocalSyntaxPtr {
|
LocalSyntaxPtr {
|
||||||
range: node.range(),
|
range: node.range(),
|
||||||
kind: node.kind(),
|
kind: node.kind(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve(self, file: &SourceFileNode) -> SyntaxNode {
|
pub fn resolve(self, file: &SourceFileNode) -> SyntaxNode {
|
||||||
let mut curr = file.syntax();
|
let mut curr = file.syntax();
|
||||||
loop {
|
loop {
|
||||||
if curr.range() == self.range && curr.kind() == self.kind {
|
if curr.range() == self.range && curr.kind() == self.kind {
|
||||||
|
@ -28,7 +28,7 @@ impl LocalSyntaxPtr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn range(self) -> TextRange {
|
pub fn range(self) -> TextRange {
|
||||||
self.range
|
self.range
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -140,7 +140,7 @@ impl ServerWorldState {
|
||||||
Ok(file_id)
|
Ok(file_id)
|
||||||
}
|
}
|
||||||
pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) {
|
pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) {
|
||||||
let mut crate_graph = CrateGraph::new();
|
let mut crate_graph = CrateGraph::default();
|
||||||
ws.iter()
|
ws.iter()
|
||||||
.flat_map(|ws| {
|
.flat_map(|ws| {
|
||||||
ws.packages()
|
ws.packages()
|
||||||
|
|
Loading…
Reference in a new issue