3029: Docs r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-02-06 14:14:47 +00:00 committed by GitHub
commit ff2d77bde6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 429 additions and 321 deletions

31
Cargo.lock generated
View file

@ -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",

View file

@ -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" }

View file

@ -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 {

View file

@ -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,

View file

@ -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<CallInfo> {

View file

@ -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<Completions> {
pub(crate) fn completions(db: &RootDatabase, position: FilePosition) -> Option<Completions> {
let original_parse = db.parse(position.file_id);
let ctx = CompletionContext::new(db, &original_parse, position)?;

View file

@ -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<ast::SourceFile>,
position: FilePosition,
) -> Option<CompletionContext<'a>> {

View file

@ -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 {

View file

@ -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<Self> {
pub(crate) fn from_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
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<Self> {
pub(crate) fn from_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
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<Self> {
pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
let node: ast::MacroCall = macro_def.source(db).value;
let params = vec![];

View file

@ -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;

View file

@ -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) {

View file

@ -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!();
}
"#,

View file

@ -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<R>()
where
fn foo<R>()
where
R: req::Request + 'static,
R::Params: DeserializeOwned<|> + panic::UnwindSafe + 'static,
R::Result: Serialize + 'static,

View file

@ -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();

View file

@ -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(

View file

@ -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::*},

View file

@ -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,

View file

@ -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>,
}

View file

@ -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 {

View file

@ -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<T> = Result<T, Canceled>;
@ -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<T> {
@ -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<usize>, 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::RootDatabase>,
db: salsa::Snapshot<RootDatabase>,
}
// 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<F: FnOnce(&db::RootDatabase) -> T + std::panic::UnwindSafe, T>(
fn with_db<F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, T>(
&self,
f: F,
) -> Cancelable<T> {
@ -518,3 +479,77 @@ fn analysis_is_send() {
fn is_send<T: Send>() {}
is_send::<Analysis>();
}
#[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<NavigationTarget> {
let (analysis, _) = single_file(text);
analysis.symbol_search(Query::new(query.into())).unwrap()
}
}

View file

@ -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.

View file

@ -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},

View file

@ -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<RootDatabase>,

View file

@ -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 {

View file

@ -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;

View file

@ -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};

View file

@ -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 {

View file

@ -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::<SyntaxTreeStats>()

View file

@ -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,

View file

@ -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},

View file

@ -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<SourceChange> {
let parse = db.parse(position.file_id);

View file

@ -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"]

View file

@ -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 {

View file

@ -1,4 +1,4 @@
//! FIXME: write short doc here
//! See docs for `FeatureFlags`.
use rustc_hash::FxHashMap;

View file

@ -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<RootDatabase>,
pub(crate) feature_flags: Arc<FeatureFlags>,
pub feature_flags: Arc<FeatureFlags>,
pub(crate) debug_data: Arc<DebugData>,
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<LineIndex>;
}

View file

@ -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;

View file

@ -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<Step> {
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<Step> {
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,

View file

@ -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<SymbolIndex>;
#[salsa::input]
fn library_symbols(&self, id: SourceRootId) -> Arc<SymbolIndex>;
@ -68,7 +109,7 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex>
Arc::new(SymbolIndex::new(symbols))
}
pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
struct Snap(salsa::Snapshot<RootDatabase>);
impl Clone for Snap {
@ -110,16 +151,16 @@ pub(crate) fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol>
query.search(&buf)
}
pub(crate) fn index_resolve(db: &RootDatabase, name_ref: &ast::NameRef) -> Vec<FileSymbol> {
pub fn index_resolve(db: &RootDatabase, name_ref: &ast::NameRef) -> Vec<FileSymbol> {
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<FileSymbol>,
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::<FileSymbol>()
}
@ -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<TextRange>,
pub(crate) container_name: Option<SmolStr>,
pub struct FileSymbol {
pub file_id: FileId,
pub name: SmolStr,
pub ptr: SyntaxNodePtr,
pub name_range: Option<TextRange>,
pub container_name: Option<SmolStr>,
}
fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> {
@ -329,77 +370,3 @@ fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
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<NavigationTarget> {
let (analysis, _) = single_file(text);
analysis.symbol_search(Query::new(query.into())).unwrap()
}
}

View file

@ -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;