diff --git a/Cargo.lock b/Cargo.lock index f39cd01c37..9346edc968 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1123,6 +1123,37 @@ dependencies = [ [[package]] name = "ra_ide" version = "0.1.0" +dependencies = [ + "either", + "format-buf", + "fst", + "indexmap", + "insta", + "itertools", + "join_to_string", + "log", + "once_cell", + "proptest", + "ra_assists", + "ra_cfg", + "ra_db", + "ra_fmt", + "ra_hir", + "ra_ide_db", + "ra_prof", + "ra_syntax", + "ra_text_edit", + "rand 0.7.3", + "rayon", + "rustc-hash", + "superslice", + "test_utils", + "unicase", +] + +[[package]] +name = "ra_ide_db" +version = "0.1.0" dependencies = [ "either", "format-buf", diff --git a/crates/ra_ide/Cargo.toml b/crates/ra_ide/Cargo.toml index 53817d1f76..9ace35229d 100644 --- a/crates/ra_ide/Cargo.toml +++ b/crates/ra_ide/Cargo.toml @@ -28,6 +28,7 @@ once_cell = "1.2.0" ra_syntax = { path = "../ra_syntax" } ra_text_edit = { path = "../ra_text_edit" } ra_db = { path = "../ra_db" } +ra_ide_db = { path = "../ra_ide_db" } ra_cfg = { path = "../ra_cfg" } ra_fmt = { path = "../ra_fmt" } ra_prof = { path = "../ra_prof" } diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs index c43c45c654..f26047570f 100644 --- a/crates/ra_ide/src/assists.rs +++ b/crates/ra_ide/src/assists.rs @@ -1,13 +1,13 @@ //! FIXME: write short doc here -use ra_db::{FilePosition, FileRange}; - -use crate::{ - db::RootDatabase, imports_locator::ImportsLocatorIde, FileId, SourceChange, SourceFileEdit, -}; use either::Either; -pub use ra_assists::AssistId; use ra_assists::{AssistAction, AssistLabel}; +use ra_db::{FilePosition, FileRange}; +use ra_ide_db::RootDatabase; + +use crate::{imports_locator::ImportsLocatorIde, FileId, SourceChange, SourceFileEdit}; + +pub use ra_assists::AssistId; #[derive(Debug)] pub struct Assist { diff --git a/crates/ra_ide/src/call_hierarchy.rs b/crates/ra_ide/src/call_hierarchy.rs index aa5d60c7b5..f984f40ad7 100644 --- a/crates/ra_ide/src/call_hierarchy.rs +++ b/crates/ra_ide/src/call_hierarchy.rs @@ -3,6 +3,7 @@ use indexmap::IndexMap; use hir::db::AstDatabase; +use ra_ide_db::RootDatabase; use ra_syntax::{ ast::{self, DocCommentsOwner}, match_ast, AstNode, TextRange, @@ -10,7 +11,6 @@ use ra_syntax::{ use crate::{ call_info::FnCallNode, - db::RootDatabase, display::{ShortLabel, ToNav}, expand::descend_into_macros, goto_definition, references, FilePosition, NavigationTarget, RangeInfo, diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 72a68522e5..f2b29306e6 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -1,15 +1,13 @@ //! FIXME: write short doc here use hir::db::AstDatabase; +use ra_ide_db::RootDatabase; use ra_syntax::{ ast::{self, ArgListOwner}, match_ast, AstNode, SyntaxNode, }; - use test_utils::tested_by; -use crate::{ - db::RootDatabase, expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature, -}; +use crate::{expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature}; /// Computes parameter information for the given call expression. pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option { diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index abe1f36cec..fedc02e14b 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs @@ -17,6 +17,7 @@ mod complete_postfix; mod complete_macro_in_item_position; use ra_db::SourceDatabase; +use ra_ide_db::RootDatabase; #[cfg(test)] use crate::completion::completion_item::do_completion; @@ -25,7 +26,7 @@ use crate::{ completion_context::CompletionContext, completion_item::{CompletionKind, Completions}, }, - db, FilePosition, + FilePosition, }; pub use crate::completion::completion_item::{ @@ -54,7 +55,7 @@ pub use crate::completion::completion_item::{ /// `foo` *should* be present among the completion variants. Filtering by /// identifier prefix/fuzzy match should be done higher in the stack, together /// with ordering of completions (currently this is done by the client). -pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Option { +pub(crate) fn completions(db: &RootDatabase, position: FilePosition) -> Option { let original_parse = db.parse(position.file_id); let ctx = CompletionContext::new(db, &original_parse, position)?; diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index deaacda6cf..5a0407fd7b 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -1,5 +1,6 @@ //! FIXME: write short doc here +use ra_ide_db::RootDatabase; use ra_syntax::{ algo::{find_covering_element, find_node_at_offset}, ast, AstNode, Parse, SourceFile, @@ -8,13 +9,13 @@ use ra_syntax::{ }; use ra_text_edit::AtomTextEdit; -use crate::{db, FilePosition}; +use crate::FilePosition; /// `CompletionContext` is created early during completion to figure out, where /// exactly is the cursor, syntax-wise. #[derive(Debug)] pub(crate) struct CompletionContext<'a> { - pub(super) db: &'a db::RootDatabase, + pub(super) db: &'a RootDatabase, pub(super) analyzer: hir::SourceAnalyzer, pub(super) offset: TextUnit, pub(super) token: SyntaxToken, @@ -48,7 +49,7 @@ pub(crate) struct CompletionContext<'a> { impl<'a> CompletionContext<'a> { pub(super) fn new( - db: &'a db::RootDatabase, + db: &'a RootDatabase, original_parse: &'a Parse, position: FilePosition, ) -> Option> { diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index f403b3bcf2..22bd497231 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs @@ -5,6 +5,7 @@ use std::cell::RefCell; use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}; use itertools::Itertools; use ra_db::{RelativePath, SourceDatabase, SourceDatabaseExt}; +use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ algo, @@ -13,7 +14,7 @@ use ra_syntax::{ }; use ra_text_edit::{TextEdit, TextEditBuilder}; -use crate::{db::RootDatabase, Diagnostic, FileId, FileSystemEdit, SourceChange, SourceFileEdit}; +use crate::{Diagnostic, FileId, FileSystemEdit, SourceChange, SourceFileEdit}; #[derive(Debug, Copy, Clone)] pub enum Severity { diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index 1e4a472b44..c23e08e9a3 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs @@ -4,13 +4,11 @@ use std::fmt::{self, Display}; use hir::{Docs, Documentation, HasSource, HirDisplay}; use join_to_string::join; +use ra_ide_db::RootDatabase; use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; use std::convert::From; -use crate::{ - db, - display::{generic_parameters, where_predicates}, -}; +use crate::display::{generic_parameters, where_predicates}; #[derive(Debug)] pub enum CallableKind { @@ -48,13 +46,13 @@ impl FunctionSignature { self } - pub(crate) fn from_hir(db: &db::RootDatabase, function: hir::Function) -> Self { + pub(crate) fn from_hir(db: &RootDatabase, function: hir::Function) -> Self { let doc = function.docs(db); let ast_node = function.source(db).value; FunctionSignature::from(&ast_node).with_doc_opt(doc) } - pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option { + pub(crate) fn from_struct(db: &RootDatabase, st: hir::Struct) -> Option { let node: ast::StructDef = st.source(db).value; match node.kind() { ast::StructKind::Record(_) => return None, @@ -86,10 +84,7 @@ impl FunctionSignature { ) } - pub(crate) fn from_enum_variant( - db: &db::RootDatabase, - variant: hir::EnumVariant, - ) -> Option { + pub(crate) fn from_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option { let node: ast::EnumVariant = variant.source(db).value; match node.kind() { ast::StructKind::Record(_) | ast::StructKind::Unit => return None, @@ -126,7 +121,7 @@ impl FunctionSignature { ) } - pub(crate) fn from_macro(db: &db::RootDatabase, macro_def: hir::MacroDef) -> Option { + pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option { let node: ast::MacroCall = macro_def.source(db).value; let params = vec![]; diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index b2af3479cd..906aab1eba 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -3,6 +3,7 @@ use either::Either; use hir::{AssocItem, FieldSource, HasSource, InFile, ModuleSource}; use ra_db::{FileId, SourceDatabase}; +use ra_ide_db::RootDatabase; use ra_syntax::{ ast::{self, DocCommentsOwner, NameOwner}, match_ast, AstNode, SmolStr, @@ -10,7 +11,7 @@ use ra_syntax::{ TextRange, }; -use crate::{db::RootDatabase, expand::original_range, FileSymbol}; +use crate::{expand::original_range, FileSymbol}; use super::short_label::ShortLabel; diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs index 831438c09b..9f3aaa3a3f 100644 --- a/crates/ra_ide/src/expand.rs +++ b/crates/ra_ide/src/expand.rs @@ -3,9 +3,10 @@ use std::iter::successors; use hir::{InFile, Origin}; use ra_db::FileId; +use ra_ide_db::RootDatabase; use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange}; -use crate::{db::RootDatabase, FileRange}; +use crate::FileRange; pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> FileRange { if let Some((range, Origin::Call)) = original_range_and_origin(db, node) { diff --git a/crates/ra_ide/src/expand_macro.rs b/crates/ra_ide/src/expand_macro.rs index 0f7b6e875f..af2783befb 100644 --- a/crates/ra_ide/src/expand_macro.rs +++ b/crates/ra_ide/src/expand_macro.rs @@ -1,14 +1,15 @@ //! This modules implements "expand macro" functionality in the IDE -use crate::{db::RootDatabase, FilePosition}; use hir::db::AstDatabase; use ra_db::SourceDatabase; -use rustc_hash::FxHashMap; - +use ra_ide_db::RootDatabase; use ra_syntax::{ algo::{find_node_at_offset, replace_descendants}, ast, AstNode, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, WalkEvent, T, }; +use rustc_hash::FxHashMap; + +use crate::FilePosition; pub struct ExpandedMacro { pub name: String, @@ -185,7 +186,7 @@ fn some_thing() -> u32 { //- /lib.rs macro_rules! match_ast { (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; - + (match ($node:expr) { $( ast::$ast:ident($it:ident) => $res:block, )* _ => $catch_all:expr $(,)? @@ -193,7 +194,7 @@ fn some_thing() -> u32 { $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* { $catch_all } }}; - } + } fn main() { mat<|>ch_ast! { @@ -227,11 +228,11 @@ fn some_thing() -> u32 { r#" //- /lib.rs macro_rules! match_ast { - (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; + (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; (match ($node:expr) {}) => {{}}; - } + } - fn main() { + fn main() { let p = f(|it| { let res = mat<|>ch_ast! { match c {}}; Some(res) @@ -254,9 +255,9 @@ fn some_thing() -> u32 { } macro_rules! foo { () => {bar!()}; - } + } - fn main() { + fn main() { let res = fo<|>o!(); } "#, @@ -277,9 +278,9 @@ fn some_thing() -> u32 { } macro_rules! foo { () => {$crate::bar!()}; - } + } - fn main() { + fn main() { let res = fo<|>o!(); } "#, diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs index 930e0c4c24..726963a33e 100644 --- a/crates/ra_ide/src/extend_selection.rs +++ b/crates/ra_ide/src/extend_selection.rs @@ -1,6 +1,10 @@ //! FIXME: write short doc here +use std::iter::successors; + +use hir::db::AstDatabase; use ra_db::SourceDatabase; +use ra_ide_db::RootDatabase; use ra_syntax::{ algo::find_covering_element, ast::{self, AstNode, AstToken}, @@ -9,9 +13,7 @@ use ra_syntax::{ SyntaxNode, SyntaxToken, TextRange, TextUnit, TokenAtOffset, T, }; -use crate::{db::RootDatabase, expand::descend_into_macros, FileId, FileRange}; -use hir::db::AstDatabase; -use std::iter::successors; +use crate::{expand::descend_into_macros, FileId, FileRange}; pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange { let src = db.parse(frange.file_id).tree(); @@ -512,8 +514,8 @@ fn bar(){} fn test_extend_trait_bounds_list_in_where_clause() { do_check( r#" -fn foo() - where +fn foo() + where R: req::Request + 'static, R::Params: DeserializeOwned<|> + panic::UnwindSafe + 'static, R::Result: Serialize + 'static, diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 5a12a619c4..e9329a72c9 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -1,6 +1,7 @@ //! FIXME: write short doc here use hir::{db::AstDatabase, InFile, SourceBinder}; +use ra_ide_db::{symbol_index, RootDatabase}; use ra_syntax::{ ast::{self, DocCommentsOwner}, match_ast, AstNode, @@ -9,7 +10,6 @@ use ra_syntax::{ }; use crate::{ - db::RootDatabase, display::{ShortLabel, ToNav}, expand::descend_into_macros, references::{classify_name_ref, NameKind::*}, @@ -94,7 +94,7 @@ pub(crate) fn reference_definition( }; // Fallback index based approach: - let navs = crate::symbol_index::index_resolve(sb.db, name_ref.value) + let navs = symbol_index::index_resolve(sb.db, name_ref.value) .into_iter() .map(|s| s.to_nav(sb.db)) .collect(); diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index ce8b6c72a1..11ad6d1372 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -1,11 +1,11 @@ //! FIXME: write short doc here use hir::db::AstDatabase; +use ra_ide_db::RootDatabase; use ra_syntax::{ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; use crate::{ - db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, - RangeInfo, + display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, RangeInfo, }; pub(crate) fn goto_type_definition( diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 6661e5cb22..315b881904 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -2,6 +2,7 @@ use hir::{db::AstDatabase, Adt, HasSource, HirDisplay, SourceBinder}; use ra_db::SourceDatabase; +use ra_ide_db::RootDatabase; use ra_syntax::{ algo::find_covering_element, ast::{self, DocCommentsOwner}, @@ -11,7 +12,6 @@ use ra_syntax::{ }; use crate::{ - db::RootDatabase, display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, expand::descend_into_macros, references::{classify_name, classify_name_ref, NameKind, NameKind::*}, diff --git a/crates/ra_ide/src/impls.rs b/crates/ra_ide/src/impls.rs index 9834025d30..64a2dadc85 100644 --- a/crates/ra_ide/src/impls.rs +++ b/crates/ra_ide/src/impls.rs @@ -2,9 +2,10 @@ use hir::{Crate, ImplBlock, SourceBinder}; use ra_db::SourceDatabase; +use ra_ide_db::RootDatabase; use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; -use crate::{db::RootDatabase, display::ToNav, FilePosition, NavigationTarget, RangeInfo}; +use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; pub(crate) fn goto_implementation( db: &RootDatabase, diff --git a/crates/ra_ide/src/imports_locator.rs b/crates/ra_ide/src/imports_locator.rs index 9e1a1c1ecf..cfd58aafeb 100644 --- a/crates/ra_ide/src/imports_locator.rs +++ b/crates/ra_ide/src/imports_locator.rs @@ -1,17 +1,20 @@ //! This module contains an import search funcionality that is provided to the ra_assists module. //! Later, this should be moved away to a separate crate that is accessible from the ra_assists module. -use crate::{ - db::RootDatabase, - references::{classify_name, NameDefinition, NameKind}, - symbol_index::{self, FileSymbol}, - Query, -}; use hir::{db::HirDatabase, ModuleDef, SourceBinder}; use ra_assists::ImportsLocator; +use ra_ide_db::{ + symbol_index::{self, FileSymbol}, + RootDatabase, +}; use ra_prof::profile; use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; +use crate::{ + references::{classify_name, NameDefinition, NameKind}, + Query, +}; + pub(crate) struct ImportsLocatorIde<'a> { source_binder: SourceBinder<'a, RootDatabase>, } diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index de447a5aa1..6b0d3d996f 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -2,13 +2,14 @@ use hir::{HirDisplay, SourceAnalyzer, SourceBinder}; use once_cell::unsync::Lazy; +use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, }; -use crate::{db::RootDatabase, FileId, FunctionSignature}; +use crate::{FileId, FunctionSignature}; #[derive(Debug, PartialEq, Eq)] pub enum InlayKind { diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 03ad6b2c13..5fb111a90d 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -10,12 +10,8 @@ // For proving that RootDatabase is RefUnwindSafe. #![recursion_limit = "128"] -mod db; pub mod mock_analysis; -mod symbol_index; -mod change; mod source_change; -mod feature_flags; mod status; mod completion; @@ -35,14 +31,11 @@ mod assists; mod diagnostics; mod syntax_tree; mod folding_ranges; -mod line_index; -mod line_index_utils; mod join_lines; mod typing; mod matching_brace; mod display; mod inlay_hints; -mod wasm_shims; mod expand; mod expand_macro; @@ -58,24 +51,24 @@ use ra_db::{ salsa::{self, ParallelDatabase}, CheckCanceled, Env, FileLoader, SourceDatabase, }; +use ra_ide_db::{ + symbol_index::{self, FileSymbol}, + LineIndexDatabase, +}; use ra_syntax::{SourceFile, TextRange, TextUnit}; -use crate::{db::LineIndexDatabase, display::ToNav, symbol_index::FileSymbol}; +use crate::display::ToNav; pub use crate::{ assists::{Assist, AssistId}, call_hierarchy::CallItem, - change::{AnalysisChange, LibraryData}, completion::{CompletionItem, CompletionItemKind, InsertTextFormat}, diagnostics::Severity, display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, expand_macro::ExpandedMacro, - feature_flags::FeatureFlags, folding_ranges::{Fold, FoldKind}, hover::HoverResult, inlay_hints::{InlayHint, InlayKind}, - line_index::{LineCol, LineIndex}, - line_index_utils::translate_offset_with_edit, references::{ Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope, }, @@ -88,6 +81,14 @@ pub use hir::Documentation; pub use ra_db::{ Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId, }; +pub use ra_ide_db::{ + change::{AnalysisChange, LibraryData}, + feature_flags::FeatureFlags, + line_index::{LineCol, LineIndex}, + line_index_utils::translate_offset_with_edit, + symbol_index::Query, + RootDatabase, +}; pub type Cancelable = Result; @@ -99,46 +100,6 @@ pub struct Diagnostic { pub severity: Severity, } -#[derive(Debug)] -pub struct Query { - query: String, - lowercased: String, - only_types: bool, - libs: bool, - exact: bool, - limit: usize, -} - -impl Query { - pub fn new(query: String) -> Query { - let lowercased = query.to_lowercase(); - Query { - query, - lowercased, - only_types: false, - libs: false, - exact: false, - limit: usize::max_value(), - } - } - - pub fn only_types(&mut self) { - self.only_types = true; - } - - pub fn libs(&mut self) { - self.libs = true; - } - - pub fn exact(&mut self) { - self.exact = true; - } - - pub fn limit(&mut self, limit: usize) { - self.limit = limit - } -} - /// Info associated with a text range. #[derive(Debug)] pub struct RangeInfo { @@ -163,7 +124,7 @@ pub struct CallInfo { /// `AnalysisHost` stores the current state of the world. #[derive(Debug)] pub struct AnalysisHost { - db: db::RootDatabase, + db: RootDatabase, } impl Default for AnalysisHost { @@ -174,7 +135,7 @@ impl Default for AnalysisHost { impl AnalysisHost { pub fn new(lru_capcity: Option, feature_flags: FeatureFlags) -> AnalysisHost { - AnalysisHost { db: db::RootDatabase::new(lru_capcity, feature_flags) } + AnalysisHost { db: RootDatabase::new(lru_capcity, feature_flags) } } /// Returns a snapshot of the current state, which you can query for /// semantic information. @@ -224,7 +185,7 @@ impl AnalysisHost { /// `Analysis` are canceled (most method return `Err(Canceled)`). #[derive(Debug)] pub struct Analysis { - db: salsa::Snapshot, + db: salsa::Snapshot, } // As a general design guideline, `Analysis` API are intended to be independent @@ -505,7 +466,7 @@ impl Analysis { } /// Performs an operation on that may be Canceled. - fn with_db T + std::panic::UnwindSafe, T>( + fn with_db T + std::panic::UnwindSafe, T>( &self, f: F, ) -> Cancelable { @@ -518,3 +479,77 @@ fn analysis_is_send() { fn is_send() {} is_send::(); } + +#[cfg(test)] +mod tests { + use crate::{display::NavigationTarget, mock_analysis::single_file, Query}; + use ra_syntax::{ + SmolStr, + SyntaxKind::{FN_DEF, STRUCT_DEF}, + }; + + #[test] + fn test_world_symbols_with_no_container() { + let code = r#" + enum FooInner { } + "#; + + let mut symbols = get_symbols_matching(code, "FooInner"); + + let s = symbols.pop().unwrap(); + + assert_eq!(s.name(), "FooInner"); + assert!(s.container_name().is_none()); + } + + #[test] + fn test_world_symbols_include_container_name() { + let code = r#" +fn foo() { + enum FooInner { } +} + "#; + + let mut symbols = get_symbols_matching(code, "FooInner"); + + let s = symbols.pop().unwrap(); + + assert_eq!(s.name(), "FooInner"); + assert_eq!(s.container_name(), Some(&SmolStr::new("foo"))); + + let code = r#" +mod foo { + struct FooInner; +} + "#; + + let mut symbols = get_symbols_matching(code, "FooInner"); + + let s = symbols.pop().unwrap(); + + assert_eq!(s.name(), "FooInner"); + assert_eq!(s.container_name(), Some(&SmolStr::new("foo"))); + } + + #[test] + fn test_world_symbols_are_case_sensitive() { + let code = r#" +fn foo() {} + +struct Foo; + "#; + + let symbols = get_symbols_matching(code, "Foo"); + + let fn_match = symbols.iter().find(|s| s.name() == "foo").map(|s| s.kind()); + let struct_match = symbols.iter().find(|s| s.name() == "Foo").map(|s| s.kind()); + + assert_eq!(fn_match, Some(FN_DEF)); + assert_eq!(struct_match, Some(STRUCT_DEF)); + } + + fn get_symbols_matching(text: &str, query: &str) -> Vec { + let (analysis, _) = single_file(text); + analysis.symbol_search(Query::new(query.into())).unwrap() + } +} diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs index 2dbccfc3b5..e0332da88f 100644 --- a/crates/ra_ide/src/parent_module.rs +++ b/crates/ra_ide/src/parent_module.rs @@ -1,12 +1,13 @@ //! FIXME: write short doc here use ra_db::{CrateId, FileId, FilePosition, SourceDatabase}; +use ra_ide_db::RootDatabase; use ra_syntax::{ algo::find_node_at_offset, ast::{self, AstNode}, }; -use crate::{db::RootDatabase, NavigationTarget}; +use crate::NavigationTarget; /// This returns `Vec` because a module may be included from several places. We /// don't handle this case yet though, so the Vec has length at most one. diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index ebded715d6..b47f8bcd9e 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs @@ -17,6 +17,7 @@ mod search_scope; use hir::{InFile, SourceBinder}; use once_cell::unsync::Lazy; use ra_db::{SourceDatabase, SourceDatabaseExt}; +use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ algo::find_node_at_offset, @@ -24,9 +25,7 @@ use ra_syntax::{ match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, TextUnit, TokenAtOffset, }; -use crate::{ - db::RootDatabase, display::ToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, -}; +use crate::{display::ToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; pub(crate) use self::{ classify::{classify_name, classify_name_ref}, diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index 46cba30a38..758ea4e8b7 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs @@ -9,7 +9,7 @@ use super::{ name_definition::{from_assoc_item, from_module_def, from_struct_field}, NameDefinition, NameKind, }; -use crate::db::RootDatabase; +use ra_ide_db::RootDatabase; pub(crate) fn classify_name( sb: &mut SourceBinder, diff --git a/crates/ra_ide/src/references/name_definition.rs b/crates/ra_ide/src/references/name_definition.rs index 1e4226ab9a..71565e6d39 100644 --- a/crates/ra_ide/src/references/name_definition.rs +++ b/crates/ra_ide/src/references/name_definition.rs @@ -9,7 +9,7 @@ use hir::{ }; use ra_syntax::{ast, ast::VisibilityOwner}; -use crate::db::RootDatabase; +use ra_ide_db::RootDatabase; #[derive(Debug, PartialEq, Eq)] pub enum NameKind { diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 9a84c1c887..08e77c01fb 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -2,14 +2,14 @@ use hir::ModuleSource; use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt}; +use ra_ide_db::RootDatabase; use ra_syntax::{ algo::find_node_at_offset, ast, lex_single_valid_syntax_kind, AstNode, SyntaxKind, SyntaxNode, }; use ra_text_edit::TextEdit; use crate::{ - db::RootDatabase, FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange, - SourceFileEdit, TextRange, + FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange, SourceFileEdit, TextRange, }; use super::find_all_refs; diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs index f8211a7469..97c65c2cd4 100644 --- a/crates/ra_ide/src/references/search_scope.rs +++ b/crates/ra_ide/src/references/search_scope.rs @@ -10,7 +10,7 @@ use ra_prof::profile; use ra_syntax::{AstNode, TextRange}; use rustc_hash::FxHashMap; -use crate::db::RootDatabase; +use ra_ide_db::RootDatabase; use super::{NameDefinition, NameKind}; diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 8622dd9560..b6b0c70f9d 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs @@ -3,12 +3,13 @@ use hir::InFile; use itertools::Itertools; use ra_db::SourceDatabase; +use ra_ide_db::RootDatabase; use ra_syntax::{ ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner}, match_ast, SyntaxNode, TextRange, }; -use crate::{db::RootDatabase, FileId}; +use crate::FileId; #[derive(Debug)] pub struct Runnable { diff --git a/crates/ra_ide/src/status.rs b/crates/ra_ide/src/status.rs index 1bb27eb851..30eb5c995e 100644 --- a/crates/ra_ide/src/status.rs +++ b/crates/ra_ide/src/status.rs @@ -10,14 +10,14 @@ use ra_db::{ }, FileTextQuery, SourceRootId, }; +use ra_ide_db::{ + symbol_index::{LibrarySymbolsQuery, SymbolIndex}, + RootDatabase, +}; use ra_prof::{memory_usage, Bytes}; use ra_syntax::{ast, Parse, SyntaxNode}; -use crate::{ - db::RootDatabase, - symbol_index::{LibrarySymbolsQuery, SymbolIndex}, - FileId, -}; +use crate::FileId; fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { db.query(ra_db::ParseQuery).entries::() diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 530b984fc5..c5d249fe8e 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -4,6 +4,7 @@ use rustc_hash::FxHashMap; use hir::{HirFileId, InFile, Name, SourceAnalyzer, SourceBinder}; use ra_db::SourceDatabase; +use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxToken, TextRange, @@ -11,7 +12,6 @@ use ra_syntax::{ }; use crate::{ - db::RootDatabase, expand::descend_into_macros_with_analyzer, references::{ classify_name, classify_name_ref, diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs index 4d0f0fc47d..55966daf3b 100644 --- a/crates/ra_ide/src/syntax_tree.rs +++ b/crates/ra_ide/src/syntax_tree.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here -use crate::db::RootDatabase; use ra_db::SourceDatabase; +use ra_ide_db::RootDatabase; use ra_syntax::{ algo, AstNode, NodeOrToken, SourceFile, SyntaxKind::{RAW_STRING, STRING}, diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs index 21e5be9b38..e5d1779fdc 100644 --- a/crates/ra_ide/src/typing.rs +++ b/crates/ra_ide/src/typing.rs @@ -15,6 +15,7 @@ use ra_db::{FilePosition, SourceDatabase}; use ra_fmt::leading_indent; +use ra_ide_db::RootDatabase; use ra_syntax::{ algo::find_node_at_offset, ast::{self, AstToken}, @@ -24,7 +25,7 @@ use ra_syntax::{ }; use ra_text_edit::TextEdit; -use crate::{db::RootDatabase, source_change::SingleFileChange, SourceChange, SourceFileEdit}; +use crate::{source_change::SingleFileChange, SourceChange, SourceFileEdit}; pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option { let parse = db.parse(position.file_id); diff --git a/crates/ra_ide_db/Cargo.toml b/crates/ra_ide_db/Cargo.toml new file mode 100644 index 0000000000..1b7905eb3d --- /dev/null +++ b/crates/ra_ide_db/Cargo.toml @@ -0,0 +1,48 @@ +[package] +edition = "2018" +name = "ra_ide_db" +version = "0.1.0" +authors = ["rust-analyzer developers"] + +[lib] +doctest = false + +[features] +wasm = [] + +[dependencies] +either = "1.5" +format-buf = "1.0.0" +indexmap = "1.3.0" +itertools = "0.8.0" +join_to_string = "0.1.3" +log = "0.4.5" +rayon = "1.0.2" +fst = { version = "0.3.1", default-features = false } +rustc-hash = "1.0" +unicase = "2.2.0" +superslice = "1.0.0" +rand = { version = "0.7.0", features = ["small_rng"] } +once_cell = "1.2.0" + +ra_syntax = { path = "../ra_syntax" } +ra_text_edit = { path = "../ra_text_edit" } +ra_db = { path = "../ra_db" } +ra_cfg = { path = "../ra_cfg" } +ra_fmt = { path = "../ra_fmt" } +ra_prof = { path = "../ra_prof" } +test_utils = { path = "../test_utils" } +ra_assists = { path = "../ra_assists" } + +# ra_ide should depend only on the top-level `hir` package. if you need +# something from some `hir_xxx` subpackage, reexport the API via `hir`. +hir = { path = "../ra_hir", package = "ra_hir" } + +[dev-dependencies] +insta = "0.13.0" + +[dev-dependencies.proptest] +version = "0.9.0" +# Disable `fork` feature to allow compiling on webassembly +default-features = false +features = ["std", "bit-set", "break-dead-code"] diff --git a/crates/ra_ide/src/change.rs b/crates/ra_ide_db/src/change.rs similarity index 96% rename from crates/ra_ide/src/change.rs rename to crates/ra_ide_db/src/change.rs index 18dad2ea31..4668784d3f 100644 --- a/crates/ra_ide/src/change.rs +++ b/crates/ra_ide_db/src/change.rs @@ -1,4 +1,5 @@ -//! FIXME: write short doc here +//! Defines a unit of change that can applied to a state of IDE to get the next +//! state. Changes are transactional. use std::{fmt, sync::Arc, time}; @@ -14,8 +15,8 @@ use rayon::prelude::*; use rustc_hash::FxHashMap; use crate::{ - db::{DebugData, RootDatabase}, symbol_index::{SymbolIndex, SymbolsDatabase}, + DebugData, RootDatabase, }; #[derive(Default)] @@ -168,12 +169,12 @@ impl LibraryData { const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100); impl RootDatabase { - pub(crate) fn request_cancellation(&mut self) { + pub fn request_cancellation(&mut self) { let _p = profile("RootDatabase::request_cancellation"); self.salsa_runtime_mut().synthetic_write(Durability::LOW); } - pub(crate) fn apply_change(&mut self, change: AnalysisChange) { + pub fn apply_change(&mut self, change: AnalysisChange) { let _p = profile("RootDatabase::apply_change"); self.request_cancellation(); log::info!("apply_change {:?}", change); @@ -245,7 +246,7 @@ impl RootDatabase { self.set_source_root_with_durability(root_id, Arc::new(source_root), durability); } - pub(crate) fn maybe_collect_garbage(&mut self) { + pub fn maybe_collect_garbage(&mut self) { if cfg!(feature = "wasm") { return; } @@ -255,7 +256,7 @@ impl RootDatabase { } } - pub(crate) fn collect_garbage(&mut self) { + pub fn collect_garbage(&mut self) { if cfg!(feature = "wasm") { return; } @@ -282,7 +283,7 @@ impl RootDatabase { self.query(hir::db::BodyQuery).sweep(sweep); } - pub(crate) fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> { + pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> { let mut acc: Vec<(String, Bytes)> = vec![]; let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); macro_rules! sweep_each_query { diff --git a/crates/ra_ide/src/feature_flags.rs b/crates/ra_ide_db/src/feature_flags.rs similarity index 98% rename from crates/ra_ide/src/feature_flags.rs rename to crates/ra_ide_db/src/feature_flags.rs index 85617640d6..1b3cabf4d9 100644 --- a/crates/ra_ide/src/feature_flags.rs +++ b/crates/ra_ide_db/src/feature_flags.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! See docs for `FeatureFlags`. use rustc_hash::FxHashMap; diff --git a/crates/ra_ide/src/db.rs b/crates/ra_ide_db/src/lib.rs similarity index 86% rename from crates/ra_ide/src/db.rs rename to crates/ra_ide_db/src/lib.rs index 47d0aed6fb..e922d1e5f9 100644 --- a/crates/ra_ide/src/db.rs +++ b/crates/ra_ide_db/src/lib.rs @@ -1,4 +1,13 @@ -//! FIXME: write short doc here +//! This crate defines the core datastructure representing IDE state -- `RootDatabase`. +//! +//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search. + +pub mod line_index; +pub mod line_index_utils; +pub mod feature_flags; +pub mod symbol_index; +pub mod change; +mod wasm_shims; use std::sync::Arc; @@ -9,10 +18,7 @@ use ra_db::{ }; use rustc_hash::FxHashMap; -use crate::{ - symbol_index::{self, SymbolsDatabase}, - FeatureFlags, LineIndex, -}; +use crate::{feature_flags::FeatureFlags, line_index::LineIndex, symbol_index::SymbolsDatabase}; #[salsa::database( ra_db::SourceDatabaseStorage, @@ -25,12 +31,12 @@ use crate::{ hir::db::HirDatabaseStorage )] #[derive(Debug)] -pub(crate) struct RootDatabase { +pub struct RootDatabase { runtime: salsa::Runtime, - pub(crate) feature_flags: Arc, + pub feature_flags: Arc, pub(crate) debug_data: Arc, - pub(crate) last_gc: crate::wasm_shims::Instant, - pub(crate) last_gc_check: crate::wasm_shims::Instant, + pub last_gc: crate::wasm_shims::Instant, + pub last_gc_check: crate::wasm_shims::Instant, } impl FileLoader for RootDatabase { @@ -109,7 +115,7 @@ impl salsa::ParallelDatabase for RootDatabase { } #[salsa::query_group(LineIndexDatabaseStorage)] -pub(crate) trait LineIndexDatabase: ra_db::SourceDatabase + CheckCanceled { +pub trait LineIndexDatabase: ra_db::SourceDatabase + CheckCanceled { fn line_index(&self, file_id: FileId) -> Arc; } diff --git a/crates/ra_ide/src/line_index.rs b/crates/ra_ide_db/src/line_index.rs similarity index 98% rename from crates/ra_ide/src/line_index.rs rename to crates/ra_ide_db/src/line_index.rs index 710890d27d..452c87ac51 100644 --- a/crates/ra_ide/src/line_index.rs +++ b/crates/ra_ide_db/src/line_index.rs @@ -1,6 +1,7 @@ -//! FIXME: write short doc here +//! `LineIndex` maps flat `TextUnit` offsets into `(Line, Column)` +//! representation. -use crate::TextUnit; +use ra_syntax::TextUnit; use rustc_hash::FxHashMap; use superslice::Ext; diff --git a/crates/ra_ide/src/line_index_utils.rs b/crates/ra_ide_db/src/line_index_utils.rs similarity index 95% rename from crates/ra_ide/src/line_index_utils.rs rename to crates/ra_ide_db/src/line_index_utils.rs index bd1e08feba..435b065116 100644 --- a/crates/ra_ide/src/line_index_utils.rs +++ b/crates/ra_ide_db/src/line_index_utils.rs @@ -1,9 +1,87 @@ -//! FIXME: write short doc here +//! Code actions can specify desirable final position of the cursor. +//! +//! The position is specified as a `TextUnit` in the final file. We need to send +//! it in `(Line, Column)` coordinate though. However, we only have a LineIndex +//! for a file pre-edit! +//! +//! Code in this module applies this "to (Line, Column) after edit" +//! transformation. -use crate::{line_index::Utf16Char, LineCol, LineIndex}; use ra_syntax::{TextRange, TextUnit}; use ra_text_edit::{AtomTextEdit, TextEdit}; +use crate::line_index::{LineCol, LineIndex, Utf16Char}; + +pub fn translate_offset_with_edit( + line_index: &LineIndex, + offset: TextUnit, + text_edit: &TextEdit, +) -> LineCol { + let mut state = Edits::from_text_edit(&text_edit); + + let mut res = RunningLineCol::new(); + + macro_rules! test_step { + ($x:ident) => { + match &$x { + Step::Newline(n) => { + if offset < *n { + return res.to_line_col(offset); + } else { + res.add_line(*n); + } + } + Step::Utf16Char(x) => { + if offset < x.end() { + // if the offset is inside a multibyte char it's invalid + // clamp it to the start of the char + let clamp = offset.min(x.start()); + return res.to_line_col(clamp); + } else { + res.adjust_col(*x); + } + } + } + }; + } + + for orig_step in LineIndexStepIter::from(line_index) { + loop { + let translated_step = state.translate_step(&orig_step); + match state.next_steps(&translated_step) { + NextSteps::Use => { + test_step!(translated_step); + break; + } + NextSteps::ReplaceMany(ns) => { + for n in ns { + test_step!(n); + } + break; + } + NextSteps::AddMany(ns) => { + for n in ns { + test_step!(n); + } + } + } + } + } + + loop { + match state.next_inserted_steps() { + None => break, + Some(ns) => { + for n in ns { + test_step!(n); + } + } + } + } + + res.to_line_col(offset) +} + #[derive(Debug, Clone)] enum Step { Newline(TextUnit), @@ -17,7 +95,7 @@ struct LineIndexStepIter<'a> { utf16_chars: Option<(TextUnit, std::slice::Iter<'a, Utf16Char>)>, } -impl<'a> LineIndexStepIter<'a> { +impl LineIndexStepIter<'_> { fn from(line_index: &LineIndex) -> LineIndexStepIter { let mut x = LineIndexStepIter { line_index, next_newline_idx: 0, utf16_chars: None }; // skip first newline since it's not real @@ -26,7 +104,7 @@ impl<'a> LineIndexStepIter<'a> { } } -impl<'a> Iterator for LineIndexStepIter<'a> { +impl Iterator for LineIndexStepIter<'_> { type Item = Step; fn next(&mut self) -> Option { self.utf16_chars @@ -54,7 +132,7 @@ struct OffsetStepIter<'a> { offset: TextUnit, } -impl<'a> Iterator for OffsetStepIter<'a> { +impl Iterator for OffsetStepIter<'_> { type Item = Step; fn next(&mut self) -> Option { let (next, next_offset) = self @@ -220,84 +298,16 @@ impl RunningLineCol { } } -pub fn translate_offset_with_edit( - line_index: &LineIndex, - offset: TextUnit, - text_edit: &TextEdit, -) -> LineCol { - let mut state = Edits::from_text_edit(&text_edit); - - let mut res = RunningLineCol::new(); - - macro_rules! test_step { - ($x:ident) => { - match &$x { - Step::Newline(n) => { - if offset < *n { - return res.to_line_col(offset); - } else { - res.add_line(*n); - } - } - Step::Utf16Char(x) => { - if offset < x.end() { - // if the offset is inside a multibyte char it's invalid - // clamp it to the start of the char - let clamp = offset.min(x.start()); - return res.to_line_col(clamp); - } else { - res.adjust_col(*x); - } - } - } - }; - } - - for orig_step in LineIndexStepIter::from(line_index) { - loop { - let translated_step = state.translate_step(&orig_step); - match state.next_steps(&translated_step) { - NextSteps::Use => { - test_step!(translated_step); - break; - } - NextSteps::ReplaceMany(ns) => { - for n in ns { - test_step!(n); - } - break; - } - NextSteps::AddMany(ns) => { - for n in ns { - test_step!(n); - } - } - } - } - } - - loop { - match state.next_inserted_steps() { - None => break, - Some(ns) => { - for n in ns { - test_step!(n); - } - } - } - } - - res.to_line_col(offset) -} - #[cfg(test)] mod test { - use super::*; - use crate::line_index; use proptest::{prelude::*, proptest}; use ra_text_edit::test_utils::{arb_offset, arb_text_with_edit}; use ra_text_edit::TextEdit; + use crate::line_index; + + use super::*; + #[derive(Debug)] struct ArbTextWithEditAndOffset { text: String, diff --git a/crates/ra_ide/src/symbol_index.rs b/crates/ra_ide_db/src/symbol_index.rs similarity index 80% rename from crates/ra_ide/src/symbol_index.rs rename to crates/ra_ide_db/src/symbol_index.rs index 5729eb5b3d..64ddf2f95e 100644 --- a/crates/ra_ide/src/symbol_index.rs +++ b/crates/ra_ide_db/src/symbol_index.rs @@ -19,6 +19,7 @@ //! for each library (which is assumed to never change) and an FST for each Rust //! file in the current workspace, and run a query against the union of all //! those FSTs. + use std::{ fmt, hash::{Hash, Hasher}, @@ -29,7 +30,7 @@ use std::{ use fst::{self, Streamer}; use ra_db::{ salsa::{self, ParallelDatabase}, - SourceDatabaseExt, SourceRootId, + FileId, SourceDatabaseExt, SourceRootId, }; use ra_syntax::{ ast::{self, NameOwner}, @@ -40,10 +41,50 @@ use ra_syntax::{ #[cfg(not(feature = "wasm"))] use rayon::prelude::*; -use crate::{db::RootDatabase, FileId, Query}; +use crate::RootDatabase; + +#[derive(Debug)] +pub struct Query { + query: String, + lowercased: String, + only_types: bool, + libs: bool, + exact: bool, + limit: usize, +} + +impl Query { + pub fn new(query: String) -> Query { + let lowercased = query.to_lowercase(); + Query { + query, + lowercased, + only_types: false, + libs: false, + exact: false, + limit: usize::max_value(), + } + } + + pub fn only_types(&mut self) { + self.only_types = true; + } + + pub fn libs(&mut self) { + self.libs = true; + } + + pub fn exact(&mut self) { + self.exact = true; + } + + pub fn limit(&mut self, limit: usize) { + self.limit = limit + } +} #[salsa::query_group(SymbolsDatabaseStorage)] -pub(crate) trait SymbolsDatabase: hir::db::HirDatabase { +pub trait SymbolsDatabase: hir::db::HirDatabase { fn file_symbols(&self, file_id: FileId) -> Arc; #[salsa::input] fn library_symbols(&self, id: SourceRootId) -> Arc; @@ -68,7 +109,7 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc Arc::new(SymbolIndex::new(symbols)) } -pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Vec { +pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec { /// Need to wrap Snapshot to provide `Clone` impl for `map_with` struct Snap(salsa::Snapshot); impl Clone for Snap { @@ -110,16 +151,16 @@ pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Vec query.search(&buf) } -pub(crate) fn index_resolve(db: &RootDatabase, name_ref: &ast::NameRef) -> Vec { +pub fn index_resolve(db: &RootDatabase, name_ref: &ast::NameRef) -> Vec { let name = name_ref.text(); let mut query = Query::new(name.to_string()); query.exact(); query.limit(4); - crate::symbol_index::world_symbols(db, query) + world_symbols(db, query) } #[derive(Default)] -pub(crate) struct SymbolIndex { +pub struct SymbolIndex { symbols: Vec, map: fst::Map, } @@ -178,11 +219,11 @@ impl SymbolIndex { SymbolIndex { symbols, map } } - pub(crate) fn len(&self) -> usize { + pub fn len(&self) -> usize { self.symbols.len() } - pub(crate) fn memory_size(&self) -> usize { + pub fn memory_size(&self) -> usize { self.map.as_fst().size() + self.symbols.len() * mem::size_of::() } @@ -262,12 +303,12 @@ fn is_type(kind: SyntaxKind) -> bool { /// The actual data that is stored in the index. It should be as compact as /// possible. #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) struct FileSymbol { - pub(crate) file_id: FileId, - pub(crate) name: SmolStr, - pub(crate) ptr: SyntaxNodePtr, - pub(crate) name_range: Option, - pub(crate) container_name: Option, +pub struct FileSymbol { + pub file_id: FileId, + pub name: SmolStr, + pub ptr: SyntaxNodePtr, + pub name_range: Option, + pub container_name: Option, } fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec { @@ -329,77 +370,3 @@ fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option { container_name: None, }) } - -#[cfg(test)] -mod tests { - use crate::{display::NavigationTarget, mock_analysis::single_file, Query}; - use ra_syntax::{ - SmolStr, - SyntaxKind::{FN_DEF, STRUCT_DEF}, - }; - - #[test] - fn test_world_symbols_with_no_container() { - let code = r#" - enum FooInner { } - "#; - - let mut symbols = get_symbols_matching(code, "FooInner"); - - let s = symbols.pop().unwrap(); - - assert_eq!(s.name(), "FooInner"); - assert!(s.container_name().is_none()); - } - - #[test] - fn test_world_symbols_include_container_name() { - let code = r#" -fn foo() { - enum FooInner { } -} - "#; - - let mut symbols = get_symbols_matching(code, "FooInner"); - - let s = symbols.pop().unwrap(); - - assert_eq!(s.name(), "FooInner"); - assert_eq!(s.container_name(), Some(&SmolStr::new("foo"))); - - let code = r#" -mod foo { - struct FooInner; -} - "#; - - let mut symbols = get_symbols_matching(code, "FooInner"); - - let s = symbols.pop().unwrap(); - - assert_eq!(s.name(), "FooInner"); - assert_eq!(s.container_name(), Some(&SmolStr::new("foo"))); - } - - #[test] - fn test_world_symbols_are_case_sensitive() { - let code = r#" -fn foo() {} - -struct Foo; - "#; - - let symbols = get_symbols_matching(code, "Foo"); - - let fn_match = symbols.iter().find(|s| s.name() == "foo").map(|s| s.kind()); - let struct_match = symbols.iter().find(|s| s.name() == "Foo").map(|s| s.kind()); - - assert_eq!(fn_match, Some(FN_DEF)); - assert_eq!(struct_match, Some(STRUCT_DEF)); - } - - fn get_symbols_matching(text: &str, query: &str) -> Vec { - let (analysis, _) = single_file(text); - analysis.symbol_search(Query::new(query.into())).unwrap() - } -} diff --git a/crates/ra_ide/src/wasm_shims.rs b/crates/ra_ide_db/src/wasm_shims.rs similarity index 82% rename from crates/ra_ide/src/wasm_shims.rs rename to crates/ra_ide_db/src/wasm_shims.rs index 088cc9be40..7af9f9d9bb 100644 --- a/crates/ra_ide/src/wasm_shims.rs +++ b/crates/ra_ide_db/src/wasm_shims.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! A version of `std::time::Instant` that doesn't panic in WASM. #[cfg(not(feature = "wasm"))] pub use std::time::Instant;