mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-24 12:03:31 +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)",
|
||||
"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_db 0.1.0",
|
||||
"ra_editor 0.1.0",
|
||||
"ra_syntax 0.1.0",
|
||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -628,6 +629,21 @@ dependencies = [
|
|||
"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]]
|
||||
name = "ra_editor"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -15,4 +15,5 @@ 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" }
|
||||
ra_db = { path = "../ra_db" }
|
||||
test_utils = { path = "../test_utils" }
|
||||
|
|
|
@ -7,10 +7,11 @@ use ra_syntax::{
|
|||
AstNode, AtomEdit,
|
||||
SyntaxNodeRef,
|
||||
};
|
||||
use ra_db::SyntaxDatabase;
|
||||
use rustc_hash::{FxHashMap};
|
||||
|
||||
use crate::{
|
||||
db::{self, SyntaxDatabase},
|
||||
db,
|
||||
hir,
|
||||
Cancelable, FilePosition
|
||||
};
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
use std::sync::Arc;
|
||||
#[cfg(test)]
|
||||
use parking_lot::Mutex;
|
||||
use ra_editor::LineIndex;
|
||||
use ra_syntax::{SourceFileNode};
|
||||
use salsa::{self, Database};
|
||||
use ra_db::{LocationIntener, BaseDatabase};
|
||||
|
||||
use crate::{
|
||||
hir,
|
||||
symbol_index,
|
||||
loc2id::{IdMaps, LocationIntener, DefId, DefLoc, FnId},
|
||||
Cancelable, Canceled, FileId,
|
||||
loc2id::{IdMaps, DefId, DefLoc, FnId},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -47,11 +45,11 @@ impl Default for RootDatabase {
|
|||
runtime: salsa::Runtime::default(),
|
||||
id_maps: Default::default(),
|
||||
};
|
||||
db.query_mut(crate::input::SourceRootQuery)
|
||||
.set(crate::input::WORKSPACE, Default::default());
|
||||
db.query_mut(crate::input::CrateGraphQuery)
|
||||
db.query_mut(ra_db::SourceRootQuery)
|
||||
.set(ra_db::WORKSPACE, Default::default());
|
||||
db.query_mut(ra_db::CrateGraphQuery)
|
||||
.set((), Default::default());
|
||||
db.query_mut(crate::input::LibrariesQuery)
|
||||
db.query_mut(ra_db::LibrariesQuery)
|
||||
.set((), Default::default());
|
||||
db
|
||||
}
|
||||
|
@ -67,22 +65,7 @@ impl salsa::ParallelDatabase for RootDatabase {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) trait BaseDatabase: salsa::Database {
|
||||
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 BaseDatabase for RootDatabase {}
|
||||
|
||||
impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
|
||||
fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> {
|
||||
|
@ -121,16 +104,16 @@ impl RootDatabase {
|
|||
|
||||
salsa::database_storage! {
|
||||
pub(crate) struct RootDatabaseStorage for RootDatabase {
|
||||
impl crate::input::FilesDatabase {
|
||||
fn file_text() for crate::input::FileTextQuery;
|
||||
fn file_source_root() for crate::input::FileSourceRootQuery;
|
||||
fn source_root() for crate::input::SourceRootQuery;
|
||||
fn libraries() for crate::input::LibrariesQuery;
|
||||
fn crate_graph() for crate::input::CrateGraphQuery;
|
||||
impl ra_db::FilesDatabase {
|
||||
fn file_text() for ra_db::FileTextQuery;
|
||||
fn file_source_root() for ra_db::FileSourceRootQuery;
|
||||
fn source_root() for ra_db::SourceRootQuery;
|
||||
fn libraries() for ra_db::LibrariesQuery;
|
||||
fn crate_graph() for ra_db::CrateGraphQuery;
|
||||
}
|
||||
impl SyntaxDatabase {
|
||||
fn source_file() for SourceFileQuery;
|
||||
fn file_lines() for FileLinesQuery;
|
||||
impl ra_db::SyntaxDatabase {
|
||||
fn source_file() for ra_db::SourceFileQuery;
|
||||
fn file_lines() for ra_db::FileLinesQuery;
|
||||
}
|
||||
impl symbol_index::SymbolsDatabase {
|
||||
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,
|
||||
ast::FnDefNode,
|
||||
};
|
||||
use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase};
|
||||
|
||||
use crate::{
|
||||
FileId,
|
||||
db::SyntaxDatabase,
|
||||
hir::{
|
||||
SourceFileItems, SourceItemId,
|
||||
query_definitions,
|
||||
|
@ -15,8 +15,7 @@ use crate::{
|
|||
module::{ModuleId, ModuleTree, ModuleSource,
|
||||
nameres::{ItemMap, InputModuleItems}},
|
||||
},
|
||||
input::SourceRootId,
|
||||
loc2id::{DefLoc, DefId, FnId, LocationIntener},
|
||||
loc2id::{DefLoc, DefId, FnId},
|
||||
Cancelable,
|
||||
};
|
||||
|
||||
|
|
|
@ -5,9 +5,10 @@ use ra_syntax::{
|
|||
algo::generate,
|
||||
ast::{self, ArgListOwner, LoopBodyOwner, NameOwner},
|
||||
};
|
||||
use ra_db::LocalSyntaxPtr;
|
||||
|
||||
use crate::{
|
||||
syntax_ptr::LocalSyntaxPtr,
|
||||
|
||||
arena::{Arena, Id},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@ use ra_syntax::{
|
|||
};
|
||||
use relative_path::RelativePathBuf;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use ra_db::{SourceRoot, SourceRootId, FileResolverImp};
|
||||
|
||||
use crate::{
|
||||
hir::HirDatabase,
|
||||
input::{SourceRoot, SourceRootId},
|
||||
Cancelable, FileId, FileResolverImp,
|
||||
Cancelable, FileId,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
|
|
@ -10,12 +10,12 @@ use ra_syntax::{
|
|||
ast::{self, AstNode, NameOwner},
|
||||
SmolStr, SyntaxNode,
|
||||
};
|
||||
use ra_db::SourceRootId;
|
||||
use relative_path::RelativePathBuf;
|
||||
|
||||
use crate::{
|
||||
FileId, FilePosition, Cancelable,
|
||||
hir::{Path, PathKind, HirDatabase, SourceItemId},
|
||||
input::SourceRootId,
|
||||
arena::{Arena, Id},
|
||||
loc2id::{DefLoc, DefId},
|
||||
};
|
||||
|
|
|
@ -19,12 +19,12 @@ use std::{
|
|||
};
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ra_syntax::{
|
||||
TextRange,
|
||||
SmolStr, SyntaxKind::{self, *},
|
||||
ast::{self, AstNode}
|
||||
};
|
||||
use ra_db::SourceRootId;
|
||||
|
||||
use crate::{
|
||||
Cancelable, FileId,
|
||||
|
@ -35,7 +35,6 @@ use crate::{
|
|||
HirDatabase,
|
||||
module::{ModuleId, ModuleTree},
|
||||
},
|
||||
input::SourceRootId,
|
||||
};
|
||||
|
||||
/// Item map is the result of the name resolution. Item map contains, for each
|
||||
|
@ -342,11 +341,11 @@ where
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ra_db::FilesDatabase;
|
||||
use crate::{
|
||||
AnalysisChange,
|
||||
mock_analysis::{MockAnalysis, analysis_and_position},
|
||||
hir::{self, HirDatabase},
|
||||
input::FilesDatabase,
|
||||
};
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use ra_syntax::{
|
|||
AstNode, SyntaxNode, SmolStr,
|
||||
ast::{self, FnDef, FnDefNode, NameOwner, ModuleItemOwner}
|
||||
};
|
||||
use ra_db::SourceRootId;
|
||||
|
||||
use crate::{
|
||||
FileId, Cancelable,
|
||||
|
@ -21,7 +22,6 @@ use crate::{
|
|||
nameres::{InputModuleItems, ItemMap, Resolver},
|
||||
},
|
||||
},
|
||||
input::SourceRootId,
|
||||
};
|
||||
|
||||
/// Resolve `FnId` to the corresponding `SyntaxNode`
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::{
|
||||
fmt,
|
||||
hash::{Hash, Hasher},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
|
@ -11,84 +10,24 @@ use ra_syntax::{
|
|||
SyntaxKind::*,
|
||||
SyntaxNodeRef, TextRange, TextUnit,
|
||||
};
|
||||
use ra_db::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE, SyntaxDatabase, SourceFileQuery};
|
||||
use rayon::prelude::*;
|
||||
use relative_path::RelativePath;
|
||||
use rustc_hash::FxHashSet;
|
||||
use salsa::{Database, ParallelDatabase};
|
||||
|
||||
use crate::{
|
||||
completion::{completions, CompletionItem},
|
||||
db::{self, SourceFileQuery, SyntaxDatabase},
|
||||
db,
|
||||
hir::{
|
||||
self,
|
||||
FnSignatureInfo,
|
||||
Problem,
|
||||
},
|
||||
input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE},
|
||||
symbol_index::{SymbolIndex, SymbolsDatabase},
|
||||
AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver,
|
||||
AnalysisChange, Cancelable, CrateId, Diagnostic, FileId,
|
||||
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)]
|
||||
pub(crate) struct AnalysisHostImpl {
|
||||
db: db::RootDatabase,
|
||||
|
@ -105,7 +44,7 @@ impl AnalysisHostImpl {
|
|||
|
||||
for (file_id, text) in change.files_changed {
|
||||
self.db
|
||||
.query_mut(crate::input::FileTextQuery)
|
||||
.query_mut(ra_db::FileTextQuery)
|
||||
.set(file_id, Arc::new(text))
|
||||
}
|
||||
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));
|
||||
for (file_id, text) in change.files_added {
|
||||
self.db
|
||||
.query_mut(crate::input::FileTextQuery)
|
||||
.query_mut(ra_db::FileTextQuery)
|
||||
.set(file_id, Arc::new(text));
|
||||
self.db
|
||||
.query_mut(crate::input::FileSourceRootQuery)
|
||||
.set(file_id, crate::input::WORKSPACE);
|
||||
.query_mut(ra_db::FileSourceRootQuery)
|
||||
.set(file_id, ra_db::WORKSPACE);
|
||||
source_root.files.insert(file_id);
|
||||
}
|
||||
for file_id in change.files_removed {
|
||||
self.db
|
||||
.query_mut(crate::input::FileTextQuery)
|
||||
.query_mut(ra_db::FileTextQuery)
|
||||
.set(file_id, Arc::new(String::new()));
|
||||
source_root.files.remove(&file_id);
|
||||
}
|
||||
source_root.file_resolver = file_resolver;
|
||||
self.db
|
||||
.query_mut(crate::input::SourceRootQuery)
|
||||
.query_mut(ra_db::SourceRootQuery)
|
||||
.set(WORKSPACE, Arc::new(source_root))
|
||||
}
|
||||
if !change.libraries_added.is_empty() {
|
||||
|
@ -147,10 +86,10 @@ impl AnalysisHostImpl {
|
|||
library.file_resolver.debug_path(file_id)
|
||||
);
|
||||
self.db
|
||||
.query_mut(crate::input::FileSourceRootQuery)
|
||||
.query_mut(ra_db::FileSourceRootQuery)
|
||||
.set_constant(file_id, source_root_id);
|
||||
self.db
|
||||
.query_mut(crate::input::FileTextQuery)
|
||||
.query_mut(ra_db::FileTextQuery)
|
||||
.set_constant(file_id, Arc::new(text));
|
||||
}
|
||||
let source_root = SourceRoot {
|
||||
|
@ -158,19 +97,19 @@ impl AnalysisHostImpl {
|
|||
file_resolver: library.file_resolver,
|
||||
};
|
||||
self.db
|
||||
.query_mut(crate::input::SourceRootQuery)
|
||||
.query_mut(ra_db::SourceRootQuery)
|
||||
.set(source_root_id, Arc::new(source_root));
|
||||
self.db
|
||||
.query_mut(crate::symbol_index::LibrarySymbolsQuery)
|
||||
.set(source_root_id, Arc::new(library.symbol_index));
|
||||
}
|
||||
self.db
|
||||
.query_mut(crate::input::LibrariesQuery)
|
||||
.query_mut(ra_db::LibrariesQuery)
|
||||
.set((), Arc::new(libraries));
|
||||
}
|
||||
if let Some(crate_graph) = change.crate_graph {
|
||||
self.db
|
||||
.query_mut(crate::input::CrateGraphQuery)
|
||||
.query_mut(ra_db::CrateGraphQuery)
|
||||
.set((), Arc::new(crate_graph))
|
||||
}
|
||||
}
|
||||
|
@ -261,7 +200,7 @@ impl AnalysisImpl {
|
|||
Ok(crate_id.into_iter().collect())
|
||||
}
|
||||
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>>> {
|
||||
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> {
|
||||
CallExpr(ast::CallExpr<'a>),
|
||||
MethodCallExpr(ast::MethodCallExpr<'a>),
|
||||
|
|
|
@ -19,8 +19,6 @@ macro_rules! ctry {
|
|||
}
|
||||
|
||||
mod arena;
|
||||
mod syntax_ptr;
|
||||
mod input;
|
||||
mod db;
|
||||
mod loc2id;
|
||||
mod imp;
|
||||
|
@ -32,35 +30,27 @@ pub mod mock_analysis;
|
|||
use std::{fmt, sync::Arc};
|
||||
|
||||
use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit};
|
||||
use ra_db::FileResolverImp;
|
||||
use rayon::prelude::*;
|
||||
use relative_path::RelativePathBuf;
|
||||
|
||||
use crate::{
|
||||
imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp},
|
||||
imp::{AnalysisHostImpl, AnalysisImpl},
|
||||
symbol_index::SymbolIndex,
|
||||
};
|
||||
|
||||
pub use crate::{
|
||||
completion::CompletionItem,
|
||||
hir::FnSignatureInfo,
|
||||
input::{CrateGraph, CrateId, FileId, FileResolver},
|
||||
};
|
||||
pub use ra_editor::{
|
||||
FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode,
|
||||
};
|
||||
|
||||
#[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 ra_db::{
|
||||
Canceled, Cancelable,
|
||||
CrateGraph, CrateId, FileId, FileResolver
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct AnalysisChange {
|
||||
|
|
|
@ -1,74 +1,10 @@
|
|||
use parking_lot::Mutex;
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
use ra_db::SourceRootId;
|
||||
|
||||
use crate::{
|
||||
hir::{SourceItemId, ModuleId},
|
||||
input::SourceRootId,
|
||||
};
|
||||
|
||||
/// 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(crate) trait NumericId: Clone + Eq + Hash {
|
||||
fn from_u32(id: u32) -> Self;
|
||||
fn to_u32(self) -> u32;
|
||||
}
|
||||
use ra_db::{NumericId, LocationIntener};
|
||||
|
||||
macro_rules! impl_numeric_id {
|
||||
($id:ident) => {
|
||||
|
@ -131,37 +67,3 @@ pub(crate) struct IdMaps {
|
|||
pub(crate) fns: LocationIntener<SourceItemId, FnId>,
|
||||
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,
|
||||
SyntaxKind::{self, *},
|
||||
};
|
||||
use ra_db::{SyntaxDatabase, SourceRootId};
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::{
|
||||
Cancelable,
|
||||
FileId, Query,
|
||||
db::SyntaxDatabase,
|
||||
input::SourceRootId,
|
||||
};
|
||||
|
||||
salsa::query_group! {
|
||||
|
|
|
@ -126,7 +126,7 @@ fn test_resolve_crate_root() {
|
|||
let mut host = mock.analysis_host();
|
||||
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 mut change = AnalysisChange::new();
|
||||
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::FxHashSet;
|
||||
use salsa;
|
||||
|
||||
use crate::FileResolverImp;
|
||||
use crate::file_resolver::FileResolverImp;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FileId(pub u32);
|
||||
|
@ -19,8 +18,8 @@ pub struct CrateGraph {
|
|||
}
|
||||
|
||||
impl CrateGraph {
|
||||
pub fn new() -> CrateGraph {
|
||||
CrateGraph::default()
|
||||
pub fn crate_root(&self, crate_id: CrateId) -> FileId {
|
||||
self.crate_roots[&crate_id]
|
||||
}
|
||||
pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
|
||||
let crate_id = CrateId(self.crate_roots.len() as u32);
|
||||
|
@ -28,18 +27,17 @@ impl CrateGraph {
|
|||
assert!(prev.is_none());
|
||||
crate_id
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
pub 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)
|
||||
}
|
||||
}
|
||||
|
||||
salsa::query_group! {
|
||||
pub(crate) trait FilesDatabase: salsa::Database {
|
||||
pub trait FilesDatabase: salsa::Database {
|
||||
fn file_text(file_id: FileId) -> Arc<String> {
|
||||
type FileTextQuery;
|
||||
storage input;
|
||||
|
@ -64,12 +62,12 @@ salsa::query_group! {
|
|||
}
|
||||
|
||||
#[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)]
|
||||
pub(crate) struct SourceRoot {
|
||||
pub(crate) file_resolver: FileResolverImp,
|
||||
pub(crate) files: FxHashSet<FileId>,
|
||||
pub struct SourceRoot {
|
||||
pub file_resolver: FileResolverImp,
|
||||
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.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct LocalSyntaxPtr {
|
||||
pub struct LocalSyntaxPtr {
|
||||
range: TextRange,
|
||||
kind: SyntaxKind,
|
||||
}
|
||||
|
||||
impl LocalSyntaxPtr {
|
||||
pub(crate) fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
|
||||
pub fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
|
||||
LocalSyntaxPtr {
|
||||
range: node.range(),
|
||||
kind: node.kind(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn resolve(self, file: &SourceFileNode) -> SyntaxNode {
|
||||
pub fn resolve(self, file: &SourceFileNode) -> SyntaxNode {
|
||||
let mut curr = file.syntax();
|
||||
loop {
|
||||
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
|
||||
}
|
||||
}
|
|
@ -140,7 +140,7 @@ impl ServerWorldState {
|
|||
Ok(file_id)
|
||||
}
|
||||
pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) {
|
||||
let mut crate_graph = CrateGraph::new();
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
ws.iter()
|
||||
.flat_map(|ws| {
|
||||
ws.packages()
|
||||
|
|
Loading…
Reference in a new issue