mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 05:38:46 +00:00
Merge #3029
3029: Docs r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
ff2d77bde6
39 changed files with 429 additions and 321 deletions
31
Cargo.lock
generated
31
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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)?;
|
||||
|
||||
|
|
|
@ -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>> {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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![];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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!();
|
||||
}
|
||||
"#,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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::*},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>()
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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);
|
||||
|
|
48
crates/ra_ide_db/Cargo.toml
Normal file
48
crates/ra_ide_db/Cargo.toml
Normal 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"]
|
|
@ -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 {
|
|
@ -1,4 +1,4 @@
|
|||
//! FIXME: write short doc here
|
||||
//! See docs for `FeatureFlags`.
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
|
@ -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>;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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,
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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;
|
Loading…
Reference in a new issue