mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Merge #3034
3034: Remove ImportLocator hack r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
895cdb5883
35 changed files with 132 additions and 350 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -963,6 +963,7 @@ dependencies = [
|
|||
"ra_db",
|
||||
"ra_fmt",
|
||||
"ra_hir",
|
||||
"ra_ide_db",
|
||||
"ra_prof",
|
||||
"ra_syntax",
|
||||
"ra_text_edit",
|
||||
|
@ -1165,7 +1166,6 @@ dependencies = [
|
|||
"log",
|
||||
"once_cell",
|
||||
"proptest",
|
||||
"ra_assists",
|
||||
"ra_cfg",
|
||||
"ra_db",
|
||||
"ra_fmt",
|
||||
|
|
|
@ -18,5 +18,6 @@ ra_text_edit = { path = "../ra_text_edit" }
|
|||
ra_fmt = { path = "../ra_fmt" }
|
||||
ra_prof = { path = "../ra_prof" }
|
||||
ra_db = { path = "../ra_db" }
|
||||
ra_ide_db = { path = "../ra_ide_db" }
|
||||
hir = { path = "../ra_hir", package = "ra_hir" }
|
||||
test_utils = { path = "../test_utils" }
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
//! This module defines `AssistCtx` -- the API surface that is exposed to assists.
|
||||
use either::Either;
|
||||
use hir::{db::HirDatabase, InFile, SourceAnalyzer, SourceBinder};
|
||||
use ra_db::FileRange;
|
||||
use hir::{InFile, SourceAnalyzer, SourceBinder};
|
||||
use ra_db::{FileRange, SourceDatabase};
|
||||
use ra_fmt::{leading_indent, reindent};
|
||||
use ra_ide_db::RootDatabase;
|
||||
use ra_syntax::{
|
||||
algo::{self, find_covering_element, find_node_at_offset},
|
||||
AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextUnit,
|
||||
|
@ -49,14 +50,14 @@ pub(crate) enum Assist {
|
|||
/// moment, because the LSP API is pretty awkward in this place, and it's much
|
||||
/// easier to just compute the edit eagerly :-)
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct AssistCtx<'a, DB> {
|
||||
pub(crate) db: &'a DB,
|
||||
pub(crate) struct AssistCtx<'a> {
|
||||
pub(crate) db: &'a RootDatabase,
|
||||
pub(crate) frange: FileRange,
|
||||
source_file: SourceFile,
|
||||
should_compute_edit: bool,
|
||||
}
|
||||
|
||||
impl<'a, DB> Clone for AssistCtx<'a, DB> {
|
||||
impl<'a> Clone for AssistCtx<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
AssistCtx {
|
||||
db: self.db,
|
||||
|
@ -67,17 +68,24 @@ impl<'a, DB> Clone for AssistCtx<'a, DB> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
|
||||
pub(crate) fn with_ctx<F, T>(db: &DB, frange: FileRange, should_compute_edit: bool, f: F) -> T
|
||||
impl<'a> AssistCtx<'a> {
|
||||
pub(crate) fn with_ctx<F, T>(
|
||||
db: &RootDatabase,
|
||||
frange: FileRange,
|
||||
should_compute_edit: bool,
|
||||
f: F,
|
||||
) -> T
|
||||
where
|
||||
F: FnOnce(AssistCtx<DB>) -> T,
|
||||
F: FnOnce(AssistCtx) -> T,
|
||||
{
|
||||
let parse = db.parse(frange.file_id);
|
||||
|
||||
let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit };
|
||||
f(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AssistCtx<'a> {
|
||||
pub(crate) fn add_assist(
|
||||
self,
|
||||
id: AssistId,
|
||||
|
@ -141,7 +149,7 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
|
|||
pub(crate) fn covering_element(&self) -> SyntaxElement {
|
||||
find_covering_element(self.source_file.syntax(), self.frange.range)
|
||||
}
|
||||
pub(crate) fn source_binder(&self) -> SourceBinder<'a, DB> {
|
||||
pub(crate) fn source_binder(&self) -> SourceBinder<'a, RootDatabase> {
|
||||
SourceBinder::new(self.db)
|
||||
}
|
||||
pub(crate) fn source_analyzer(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! FIXME: write short doc here
|
||||
|
||||
use crate::{Assist, AssistCtx, AssistId};
|
||||
use hir::db::HirDatabase;
|
||||
|
||||
use join_to_string::join;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode},
|
||||
|
@ -29,7 +29,7 @@ const DERIVE_TRAIT: &str = "derive";
|
|||
//
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn add_custom_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
|
||||
let input = ctx.find_node_at_offset::<ast::AttrInput>()?;
|
||||
let attr = input.syntax().parent().and_then(ast::Attr::cast)?;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode, AttrsOwner},
|
||||
SyntaxKind::{COMMENT, WHITESPACE},
|
||||
|
@ -25,7 +24,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// y: u32,
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn add_derive(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> {
|
||||
let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
|
||||
let node_start = derive_insertion_offset(&nominal)?;
|
||||
ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", |edit| {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use hir::{db::HirDatabase, HirDisplay};
|
||||
use hir::HirDisplay;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner},
|
||||
TextRange,
|
||||
|
@ -21,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// let x: i32 = 92;
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn add_explicit_type(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> {
|
||||
let stmt = ctx.find_node_at_offset::<LetStmt>()?;
|
||||
let expr = stmt.initializer()?;
|
||||
let pat = stmt.pat()?;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use format_buf::format;
|
||||
use hir::db::HirDatabase;
|
||||
|
||||
use join_to_string::join;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode, NameOwner, TypeParamsOwner},
|
||||
|
@ -27,7 +27,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
//
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn add_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> {
|
||||
let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
|
||||
let name = nominal.name()?;
|
||||
ctx.add_assist(AssistId("add_impl"), format!("Implement {}", name.text().as_str()), |edit| {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use hir::{self, db::HirDatabase, ModPath};
|
||||
use hir::{self, ModPath};
|
||||
use ra_syntax::{
|
||||
ast::{self, NameOwner},
|
||||
AstNode, Direction, SmolStr,
|
||||
|
@ -50,7 +50,7 @@ pub fn auto_import_text_edit(
|
|||
//
|
||||
// fn process(map: HashMap<String, String>) {}
|
||||
// ```
|
||||
pub(crate) fn add_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_import(ctx: AssistCtx) -> Option<Assist> {
|
||||
let path: ast::Path = ctx.find_node_at_offset()?;
|
||||
// We don't want to mess with use statements
|
||||
if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
|
||||
|
|
|
@ -43,7 +43,7 @@ enum AddMissingImplMembersMode {
|
|||
//
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_missing_impl_members(ctx: AssistCtx) -> Option<Assist> {
|
||||
add_missing_impl_members_inner(
|
||||
ctx,
|
||||
AddMissingImplMembersMode::NoDefaultMethods,
|
||||
|
@ -84,7 +84,7 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti
|
|||
//
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_missing_default_members(ctx: AssistCtx) -> Option<Assist> {
|
||||
add_missing_impl_members_inner(
|
||||
ctx,
|
||||
AddMissingImplMembersMode::DefaultMethodsOnly,
|
||||
|
@ -94,7 +94,7 @@ pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> O
|
|||
}
|
||||
|
||||
fn add_missing_impl_members_inner(
|
||||
ctx: AssistCtx<impl HirDatabase>,
|
||||
ctx: AssistCtx,
|
||||
mode: AddMissingImplMembersMode,
|
||||
assist_id: &'static str,
|
||||
label: &'static str,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use format_buf::format;
|
||||
use hir::{db::HirDatabase, InFile};
|
||||
use hir::InFile;
|
||||
use join_to_string::join;
|
||||
use ra_syntax::{
|
||||
ast::{
|
||||
|
@ -31,7 +31,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// }
|
||||
//
|
||||
// ```
|
||||
pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_new(ctx: AssistCtx) -> Option<Assist> {
|
||||
let strukt = ctx.find_node_at_offset::<ast::StructDef>()?;
|
||||
|
||||
// We want to only apply this to non-union structs with named fields
|
||||
|
@ -128,10 +128,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
|
|||
//
|
||||
// FIXME: change the new fn checking to a more semantic approach when that's more
|
||||
// viable (e.g. we process proc macros, etc)
|
||||
fn find_struct_impl(
|
||||
ctx: &AssistCtx<impl HirDatabase>,
|
||||
strukt: &ast::StructDef,
|
||||
) -> Option<Option<ast::ImplBlock>> {
|
||||
fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option<Option<ast::ImplBlock>> {
|
||||
let db = ctx.db;
|
||||
let module = strukt.syntax().ancestors().find(|node| {
|
||||
ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use super::invert_if::invert_boolean_expression;
|
||||
use hir::db::HirDatabase;
|
||||
use ra_syntax::ast::{self, AstNode};
|
||||
|
||||
use crate::{Assist, AssistCtx, AssistId};
|
||||
|
@ -23,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// if !(x == 4 && y) {}
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn apply_demorgan(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn apply_demorgan(ctx: AssistCtx) -> Option<Assist> {
|
||||
let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
|
||||
let op = expr.op_kind()?;
|
||||
let op_range = expr.op_token()?.text_range();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use hir::{db::HirDatabase, ModPath};
|
||||
use hir::ModPath;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode},
|
||||
SyntaxNode,
|
||||
|
@ -6,8 +6,9 @@ use ra_syntax::{
|
|||
|
||||
use crate::{
|
||||
assist_ctx::{ActionBuilder, Assist, AssistCtx},
|
||||
auto_import_text_edit, AssistId, ImportsLocator,
|
||||
auto_import_text_edit, AssistId,
|
||||
};
|
||||
use ra_ide_db::imports_locator::ImportsLocatorIde;
|
||||
|
||||
// Assist: auto_import
|
||||
//
|
||||
|
@ -26,10 +27,7 @@ use crate::{
|
|||
// let map = HashMap<|>::new();
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn auto_import<F: ImportsLocator>(
|
||||
ctx: AssistCtx<impl HirDatabase>,
|
||||
imports_locator: &mut F,
|
||||
) -> Option<Assist> {
|
||||
pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
|
||||
let path_to_import: ast::Path = ctx.find_node_at_offset()?;
|
||||
let path_to_import_syntax = path_to_import.syntax();
|
||||
if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() {
|
||||
|
@ -52,6 +50,8 @@ pub(crate) fn auto_import<F: ImportsLocator>(
|
|||
return None;
|
||||
}
|
||||
|
||||
let mut imports_locator = ImportsLocatorIde::new(ctx.db);
|
||||
|
||||
let proposed_imports = imports_locator
|
||||
.find_imports(&name_to_import)
|
||||
.into_iter()
|
||||
|
@ -81,16 +81,12 @@ fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode)
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::helpers::{
|
||||
check_assist_with_imports_locator, check_assist_with_imports_locator_not_applicable,
|
||||
TestImportsLocator,
|
||||
};
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
|
||||
#[test]
|
||||
fn applicable_when_found_an_import() {
|
||||
check_assist_with_imports_locator(
|
||||
check_assist(
|
||||
auto_import,
|
||||
TestImportsLocator::new,
|
||||
r"
|
||||
<|>PubStruct
|
||||
|
||||
|
@ -112,9 +108,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn auto_imports_are_merged() {
|
||||
check_assist_with_imports_locator(
|
||||
check_assist(
|
||||
auto_import,
|
||||
TestImportsLocator::new,
|
||||
r"
|
||||
use PubMod::PubStruct1;
|
||||
|
||||
|
@ -148,9 +143,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn applicable_when_found_multiple_imports() {
|
||||
check_assist_with_imports_locator(
|
||||
check_assist(
|
||||
auto_import,
|
||||
TestImportsLocator::new,
|
||||
r"
|
||||
PubSt<|>ruct
|
||||
|
||||
|
@ -184,9 +178,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn not_applicable_for_already_imported_types() {
|
||||
check_assist_with_imports_locator_not_applicable(
|
||||
check_assist_not_applicable(
|
||||
auto_import,
|
||||
TestImportsLocator::new,
|
||||
r"
|
||||
use PubMod::PubStruct;
|
||||
|
||||
|
@ -201,9 +194,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn not_applicable_for_types_with_private_paths() {
|
||||
check_assist_with_imports_locator_not_applicable(
|
||||
check_assist_not_applicable(
|
||||
auto_import,
|
||||
TestImportsLocator::new,
|
||||
r"
|
||||
PrivateStruct<|>
|
||||
|
||||
|
@ -216,9 +208,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn not_applicable_when_no_imports_found() {
|
||||
check_assist_with_imports_locator_not_applicable(
|
||||
check_assist_not_applicable(
|
||||
auto_import,
|
||||
TestImportsLocator::new,
|
||||
"
|
||||
PubStruct<|>",
|
||||
);
|
||||
|
@ -226,9 +217,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn not_applicable_in_import_statements() {
|
||||
check_assist_with_imports_locator_not_applicable(
|
||||
check_assist_not_applicable(
|
||||
auto_import,
|
||||
TestImportsLocator::new,
|
||||
r"
|
||||
use PubStruct<|>;
|
||||
|
||||
|
@ -240,9 +230,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn function_import() {
|
||||
check_assist_with_imports_locator(
|
||||
check_assist(
|
||||
auto_import,
|
||||
TestImportsLocator::new,
|
||||
r"
|
||||
test_function<|>
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast::{self, NameOwner, VisibilityOwner},
|
||||
AstNode,
|
||||
|
@ -22,14 +21,14 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// ```
|
||||
// pub(crate) fn frobnicate() {}
|
||||
// ```
|
||||
pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn change_visibility(ctx: AssistCtx) -> Option<Assist> {
|
||||
if let Some(vis) = ctx.find_node_at_offset::<ast::Visibility>() {
|
||||
return change_vis(ctx, vis);
|
||||
}
|
||||
add_vis(ctx)
|
||||
}
|
||||
|
||||
fn add_vis(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
fn add_vis(ctx: AssistCtx) -> Option<Assist> {
|
||||
let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() {
|
||||
T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true,
|
||||
_ => false,
|
||||
|
@ -75,7 +74,7 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
|
|||
.unwrap_or_else(|| node.text_range().start())
|
||||
}
|
||||
|
||||
fn change_vis(ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> {
|
||||
fn change_vis(ctx: AssistCtx, vis: ast::Visibility) -> Option<Assist> {
|
||||
if vis.syntax().text() == "pub" {
|
||||
return ctx.add_assist(
|
||||
AssistId("change_visibility"),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::{iter::once, ops::RangeInclusive};
|
||||
|
||||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
algo::replace_children,
|
||||
ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat},
|
||||
|
@ -36,7 +35,7 @@ use crate::{
|
|||
// bar();
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn convert_to_guarded_return(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
|
||||
let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
|
||||
if if_expr.else_branch().is_some() {
|
||||
return None;
|
||||
|
|
|
@ -31,7 +31,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// }
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option<Assist> {
|
||||
let match_expr = ctx.find_node_at_offset::<ast::MatchExpr>()?;
|
||||
let match_arm_list = match_expr.match_arm_list()?;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::ast::{AstNode, BinExpr, BinOp};
|
||||
|
||||
use crate::{Assist, AssistCtx, AssistId};
|
||||
|
@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// let _ = 2 + 90;
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn flip_binexpr(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn flip_binexpr(ctx: AssistCtx) -> Option<Assist> {
|
||||
let expr = ctx.find_node_at_offset::<BinExpr>()?;
|
||||
let lhs = expr.lhs()?.syntax().clone();
|
||||
let rhs = expr.rhs()?.syntax().clone();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{algo::non_trivia_sibling, Direction, T};
|
||||
|
||||
use crate::{Assist, AssistCtx, AssistId};
|
||||
|
@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// ((3, 4), (1, 2));
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn flip_comma(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn flip_comma(ctx: AssistCtx) -> Option<Assist> {
|
||||
let comma = ctx.find_token_at_offset(T![,])?;
|
||||
let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
|
||||
let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
algo::non_trivia_sibling,
|
||||
ast::{self, AstNode},
|
||||
|
@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// ```
|
||||
// fn foo<T: Copy + Clone>() { }
|
||||
// ```
|
||||
pub(crate) fn flip_trait_bound(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option<Assist> {
|
||||
// We want to replicate the behavior of `flip_binexpr` by only suggesting
|
||||
// the assist when the cursor is on a `+`
|
||||
let plus = ctx.find_token_at_offset(T![+])?;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode, AstToken},
|
||||
TextRange,
|
||||
|
@ -23,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// (1 + 2) * 4;
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn inline_local_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> {
|
||||
let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?;
|
||||
let bind_pat = match let_stmt.pat()? {
|
||||
ast::Pat::BindPat(pat) => pat,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use format_buf::format;
|
||||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode},
|
||||
SyntaxKind::{
|
||||
|
@ -28,7 +27,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// var_name * 4;
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> {
|
||||
if ctx.frange.range.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::ast::{self, AstNode};
|
||||
use ra_syntax::T;
|
||||
|
||||
|
@ -23,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// }
|
||||
// ```
|
||||
|
||||
pub(crate) fn invert_if(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
|
||||
let if_keyword = ctx.find_token_at_offset(T![if])?;
|
||||
let expr = ast::IfExpr::cast(if_keyword.parent())?;
|
||||
let if_range = if_keyword.text_range();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::iter::successors;
|
||||
|
||||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode},
|
||||
Direction, TextUnit,
|
||||
|
@ -32,7 +31,7 @@ use crate::{Assist, AssistCtx, AssistId, TextRange};
|
|||
// }
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn merge_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> {
|
||||
let current_arm = ctx.find_node_at_offset::<ast::MatchArm>()?;
|
||||
// Don't try to handle arms with guards for now - can add support for this later
|
||||
if current_arm.guard().is_some() {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast::{self, edit, make, AstNode, NameOwner, TypeBoundsOwner},
|
||||
SyntaxElement,
|
||||
|
@ -22,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// f(x)
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> {
|
||||
let type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?;
|
||||
|
||||
let mut type_params = type_param_list.type_params();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast,
|
||||
ast::{AstNode, AstToken, IfExpr, MatchArm},
|
||||
|
@ -32,7 +31,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// }
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option<Assist> {
|
||||
let match_arm = ctx.find_node_at_offset::<MatchArm>()?;
|
||||
let guard = match_arm.guard()?;
|
||||
let space_before_guard = guard.syntax().prev_sibling_or_token();
|
||||
|
@ -89,7 +88,7 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx<impl HirDatabase>) -> Option
|
|||
// }
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> {
|
||||
let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
|
||||
let last_match_pat = match_arm.pats().last()?;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast, AstToken,
|
||||
SyntaxKind::{RAW_STRING, STRING},
|
||||
|
@ -22,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// r#"Hello, World!"#;
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn make_raw_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option<Assist> {
|
||||
let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?;
|
||||
let value = token.value()?;
|
||||
ctx.add_assist(AssistId("make_raw_string"), "Rewrite as raw string", |edit| {
|
||||
|
@ -51,7 +50,7 @@ pub(crate) fn make_raw_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
|
|||
// "Hello, \"World!\"";
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn make_usual_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option<Assist> {
|
||||
let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?;
|
||||
let value = token.value()?;
|
||||
ctx.add_assist(AssistId("make_usual_string"), "Rewrite as regular string", |edit| {
|
||||
|
@ -77,7 +76,7 @@ pub(crate) fn make_usual_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi
|
|||
// r##"Hello, World!"##;
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn add_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn add_hash(ctx: AssistCtx) -> Option<Assist> {
|
||||
let token = ctx.find_token_at_offset(RAW_STRING)?;
|
||||
ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| {
|
||||
edit.target(token.text_range());
|
||||
|
@ -101,7 +100,7 @@ pub(crate) fn add_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
|||
// r"Hello, World!";
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn remove_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn remove_hash(ctx: AssistCtx) -> Option<Assist> {
|
||||
let token = ctx.find_token_at_offset(RAW_STRING)?;
|
||||
let text = token.text().as_str();
|
||||
if text.starts_with("r\"") {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode},
|
||||
TextUnit, T,
|
||||
|
@ -21,7 +20,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// 92;
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn remove_dbg(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option<Assist> {
|
||||
let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
|
||||
|
||||
if !is_valid_macrocall(¯o_call, "dbg")? {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use hir::db::HirDatabase;
|
||||
use ra_fmt::unwrap_trivial_block;
|
||||
use ra_syntax::{
|
||||
ast::{self, make},
|
||||
|
@ -34,7 +33,7 @@ use ast::edit::IndentLevel;
|
|||
// }
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn replace_if_let_with_match(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> {
|
||||
let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
|
||||
let cond = if_expr.condition()?;
|
||||
let pat = cond.pat()?;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::iter::successors;
|
||||
|
||||
use hir::db::HirDatabase;
|
||||
use ra_syntax::{ast, AstNode, TextUnit, T};
|
||||
|
||||
use crate::{Assist, AssistCtx, AssistId};
|
||||
|
@ -16,7 +15,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
|||
// ```
|
||||
// use std::{collections::HashMap};
|
||||
// ```
|
||||
pub(crate) fn split_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> {
|
||||
let colon_colon = ctx.find_token_at_offset(T![::])?;
|
||||
let path = ast::Path::cast(colon_colon.parent())?;
|
||||
let top_path = successors(Some(path), |it| it.parent_path()).last()?;
|
||||
|
|
|
@ -8,7 +8,7 @@ mod generated;
|
|||
use ra_db::{fixture::WithFixture, FileRange};
|
||||
use test_utils::{assert_eq_text, extract_range_or_offset};
|
||||
|
||||
use crate::test_db::TestDB;
|
||||
use ra_ide_db::RootDatabase;
|
||||
|
||||
fn check(assist_id: &str, before: &str, after: &str) {
|
||||
// FIXME we cannot get the imports search functionality here yet, but still need to generate a test and a doc for an assist
|
||||
|
@ -16,7 +16,7 @@ fn check(assist_id: &str, before: &str, after: &str) {
|
|||
return;
|
||||
}
|
||||
let (selection, before) = extract_range_or_offset(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = RootDatabase::with_single_file(&before);
|
||||
let frange = FileRange { file_id, range: selection.into() };
|
||||
|
||||
let assist = crate::assists(&db, frange)
|
||||
|
|
|
@ -9,13 +9,11 @@ mod assist_ctx;
|
|||
mod marks;
|
||||
#[cfg(test)]
|
||||
mod doc_tests;
|
||||
#[cfg(test)]
|
||||
mod test_db;
|
||||
pub mod ast_transform;
|
||||
|
||||
use either::Either;
|
||||
use hir::{db::HirDatabase, ModuleDef};
|
||||
use ra_db::FileRange;
|
||||
use ra_ide_db::RootDatabase;
|
||||
use ra_syntax::{TextRange, TextUnit};
|
||||
use ra_text_edit::TextEdit;
|
||||
|
||||
|
@ -61,10 +59,7 @@ impl ResolvedAssist {
|
|||
///
|
||||
/// Assists are returned in the "unresolved" state, that is only labels are
|
||||
/// returned, without actual edits.
|
||||
pub fn applicable_assists<H>(db: &H, range: FileRange) -> Vec<AssistLabel>
|
||||
where
|
||||
H: HirDatabase + 'static,
|
||||
{
|
||||
pub fn applicable_assists(db: &RootDatabase, range: FileRange) -> Vec<AssistLabel> {
|
||||
AssistCtx::with_ctx(db, range, false, |ctx| {
|
||||
assists::all()
|
||||
.iter()
|
||||
|
@ -77,59 +72,11 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
/// A functionality for locating imports for the given name.
|
||||
///
|
||||
/// Currently has to be a trait with the real implementation provided by the ra_ide_api crate,
|
||||
/// due to the search functionality located there.
|
||||
/// Later, this trait should be removed completely and the search functionality moved to a separate crate,
|
||||
/// accessible from the ra_assists crate.
|
||||
pub trait ImportsLocator {
|
||||
/// Finds all imports for the given name and the module that contains this name.
|
||||
fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef>;
|
||||
}
|
||||
|
||||
/// Return all the assists applicable at the given position
|
||||
/// and additional assists that need the imports locator functionality to work.
|
||||
///
|
||||
/// Assists are returned in the "resolved" state, that is with edit fully
|
||||
/// computed.
|
||||
pub fn assists_with_imports_locator<H, F>(
|
||||
db: &H,
|
||||
range: FileRange,
|
||||
mut imports_locator: F,
|
||||
) -> Vec<ResolvedAssist>
|
||||
where
|
||||
H: HirDatabase + 'static,
|
||||
F: ImportsLocator,
|
||||
{
|
||||
AssistCtx::with_ctx(db, range, true, |ctx| {
|
||||
let mut assists = assists::all()
|
||||
.iter()
|
||||
.map(|f| f(ctx.clone()))
|
||||
.chain(
|
||||
assists::all_with_imports_locator()
|
||||
.iter()
|
||||
.map(|f| f(ctx.clone(), &mut imports_locator)),
|
||||
)
|
||||
.filter_map(std::convert::identity)
|
||||
.map(|a| match a {
|
||||
Assist::Resolved { assist } => assist,
|
||||
Assist::Unresolved { .. } => unreachable!(),
|
||||
})
|
||||
.collect();
|
||||
sort_assists(&mut assists);
|
||||
assists
|
||||
})
|
||||
}
|
||||
|
||||
/// Return all the assists applicable at the given position.
|
||||
///
|
||||
/// Assists are returned in the "resolved" state, that is with edit fully
|
||||
/// computed.
|
||||
pub fn assists<H>(db: &H, range: FileRange) -> Vec<ResolvedAssist>
|
||||
where
|
||||
H: HirDatabase + 'static,
|
||||
{
|
||||
pub fn assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssist> {
|
||||
AssistCtx::with_ctx(db, range, true, |ctx| {
|
||||
let mut a = assists::all()
|
||||
.iter()
|
||||
|
@ -155,8 +102,7 @@ fn sort_assists(assists: &mut Vec<ResolvedAssist>) {
|
|||
}
|
||||
|
||||
mod assists {
|
||||
use crate::{Assist, AssistCtx, ImportsLocator};
|
||||
use hir::db::HirDatabase;
|
||||
use crate::{Assist, AssistCtx};
|
||||
|
||||
mod add_derive;
|
||||
mod add_explicit_type;
|
||||
|
@ -184,7 +130,7 @@ mod assists {
|
|||
mod move_bounds;
|
||||
mod early_return;
|
||||
|
||||
pub(crate) fn all<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assist>] {
|
||||
pub(crate) fn all() -> &'static [fn(AssistCtx) -> Option<Assist>] {
|
||||
&[
|
||||
add_derive::add_derive,
|
||||
add_explicit_type::add_explicit_type,
|
||||
|
@ -215,79 +161,34 @@ mod assists {
|
|||
raw_string::make_usual_string,
|
||||
raw_string::remove_hash,
|
||||
early_return::convert_to_guarded_return,
|
||||
auto_import::auto_import,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn all_with_imports_locator<'a, DB: HirDatabase, F: ImportsLocator>(
|
||||
) -> &'a [fn(AssistCtx<DB>, &mut F) -> Option<Assist>] {
|
||||
&[auto_import::auto_import]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod helpers {
|
||||
use hir::db::DefDatabase;
|
||||
use ra_db::{fixture::WithFixture, FileId, FileRange};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
|
||||
use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
|
||||
use ra_syntax::TextRange;
|
||||
use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range};
|
||||
|
||||
use crate::{test_db::TestDB, Assist, AssistCtx, ImportsLocator};
|
||||
use std::sync::Arc;
|
||||
use crate::{Assist, AssistCtx};
|
||||
|
||||
// FIXME remove the `ModuleDefId` reexport from `ra_hir` when this gets removed.
|
||||
pub(crate) struct TestImportsLocator {
|
||||
db: Arc<TestDB>,
|
||||
test_file_id: FileId,
|
||||
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
|
||||
let (mut db, file_id) = RootDatabase::with_single_file(text);
|
||||
// FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`,
|
||||
// but it looks like this might need specialization? :(
|
||||
let local_roots = vec![db.file_source_root(file_id)];
|
||||
db.set_local_roots(Arc::new(local_roots));
|
||||
(db, file_id)
|
||||
}
|
||||
|
||||
impl TestImportsLocator {
|
||||
pub(crate) fn new(db: Arc<TestDB>, test_file_id: FileId) -> Self {
|
||||
TestImportsLocator { db, test_file_id }
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportsLocator for TestImportsLocator {
|
||||
fn find_imports(&mut self, name_to_import: &str) -> Vec<hir::ModuleDef> {
|
||||
let crate_def_map = self.db.crate_def_map(self.db.test_crate());
|
||||
let mut findings = Vec::new();
|
||||
|
||||
let mut module_ids_to_process =
|
||||
crate_def_map.modules_for_file(self.test_file_id).collect::<Vec<_>>();
|
||||
|
||||
while !module_ids_to_process.is_empty() {
|
||||
let mut more_ids_to_process = Vec::new();
|
||||
for local_module_id in module_ids_to_process.drain(..) {
|
||||
for (name, namespace_data) in
|
||||
crate_def_map[local_module_id].scope.entries_without_primitives()
|
||||
{
|
||||
let found_a_match = &name.to_string() == name_to_import;
|
||||
vec![namespace_data.types, namespace_data.values]
|
||||
.into_iter()
|
||||
.filter_map(std::convert::identity)
|
||||
.for_each(|(module_def_id, _)| {
|
||||
if found_a_match {
|
||||
findings.push(module_def_id.into());
|
||||
}
|
||||
if let hir::ModuleDefId::ModuleId(module_id) = module_def_id {
|
||||
more_ids_to_process.push(module_id.local_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
module_ids_to_process = more_ids_to_process;
|
||||
}
|
||||
|
||||
findings
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist(
|
||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
||||
before: &str,
|
||||
after: &str,
|
||||
) {
|
||||
pub(crate) fn check_assist(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) {
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = with_single_file(&before);
|
||||
let frange =
|
||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||
let assist =
|
||||
|
@ -309,45 +210,13 @@ mod helpers {
|
|||
assert_eq_text!(after, &actual);
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_with_imports_locator<F: ImportsLocator>(
|
||||
assist: fn(AssistCtx<TestDB>, &mut F) -> Option<Assist>,
|
||||
imports_locator_provider: fn(db: Arc<TestDB>, file_id: FileId) -> F,
|
||||
before: &str,
|
||||
after: &str,
|
||||
) {
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let db = Arc::new(db);
|
||||
let mut imports_locator = imports_locator_provider(Arc::clone(&db), file_id);
|
||||
let frange =
|
||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||
let assist =
|
||||
AssistCtx::with_ctx(db.as_ref(), frange, true, |ctx| assist(ctx, &mut imports_locator))
|
||||
.expect("code action is not applicable");
|
||||
let action = match assist {
|
||||
Assist::Unresolved { .. } => unreachable!(),
|
||||
Assist::Resolved { assist } => assist.get_first_action(),
|
||||
};
|
||||
|
||||
let actual = action.edit.apply(&before);
|
||||
let actual_cursor_pos = match action.cursor_position {
|
||||
None => action
|
||||
.edit
|
||||
.apply_to_offset(before_cursor_pos)
|
||||
.expect("cursor position is affected by the edit"),
|
||||
Some(off) => off,
|
||||
};
|
||||
let actual = add_cursor(&actual, actual_cursor_pos);
|
||||
assert_eq_text!(after, &actual);
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_range(
|
||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
||||
assist: fn(AssistCtx) -> Option<Assist>,
|
||||
before: &str,
|
||||
after: &str,
|
||||
) {
|
||||
let (range, before) = extract_range(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = with_single_file(&before);
|
||||
let frange = FileRange { file_id, range };
|
||||
let assist =
|
||||
AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
|
||||
|
@ -364,12 +233,12 @@ mod helpers {
|
|||
}
|
||||
|
||||
pub(crate) fn check_assist_target(
|
||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
||||
assist: fn(AssistCtx) -> Option<Assist>,
|
||||
before: &str,
|
||||
target: &str,
|
||||
) {
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = with_single_file(&before);
|
||||
let frange =
|
||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||
let assist =
|
||||
|
@ -384,12 +253,12 @@ mod helpers {
|
|||
}
|
||||
|
||||
pub(crate) fn check_assist_range_target(
|
||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
||||
assist: fn(AssistCtx) -> Option<Assist>,
|
||||
before: &str,
|
||||
target: &str,
|
||||
) {
|
||||
let (range, before) = extract_range(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = with_single_file(&before);
|
||||
let frange = FileRange { file_id, range };
|
||||
let assist =
|
||||
AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
|
||||
|
@ -403,39 +272,23 @@ mod helpers {
|
|||
}
|
||||
|
||||
pub(crate) fn check_assist_not_applicable(
|
||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
||||
assist: fn(AssistCtx) -> Option<Assist>,
|
||||
before: &str,
|
||||
) {
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = with_single_file(&before);
|
||||
let frange =
|
||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||
let assist = AssistCtx::with_ctx(&db, frange, true, assist);
|
||||
assert!(assist.is_none());
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_with_imports_locator_not_applicable<F: ImportsLocator>(
|
||||
assist: fn(AssistCtx<TestDB>, &mut F) -> Option<Assist>,
|
||||
imports_locator_provider: fn(db: Arc<TestDB>, file_id: FileId) -> F,
|
||||
before: &str,
|
||||
) {
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let db = Arc::new(db);
|
||||
let mut imports_locator = imports_locator_provider(Arc::clone(&db), file_id);
|
||||
let frange =
|
||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||
let assist =
|
||||
AssistCtx::with_ctx(db.as_ref(), frange, true, |ctx| assist(ctx, &mut imports_locator));
|
||||
assert!(assist.is_none());
|
||||
}
|
||||
|
||||
pub(crate) fn check_assist_range_not_applicable(
|
||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
||||
assist: fn(AssistCtx) -> Option<Assist>,
|
||||
before: &str,
|
||||
) {
|
||||
let (range, before) = extract_range(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = with_single_file(&before);
|
||||
let frange = FileRange { file_id, range };
|
||||
let assist = AssistCtx::with_ctx(&db, frange, true, assist);
|
||||
assert!(assist.is_none());
|
||||
|
@ -444,17 +297,17 @@ mod helpers {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ra_db::{fixture::WithFixture, FileRange};
|
||||
use ra_db::FileRange;
|
||||
use ra_syntax::TextRange;
|
||||
use test_utils::{extract_offset, extract_range};
|
||||
|
||||
use crate::test_db::TestDB;
|
||||
use crate::helpers;
|
||||
|
||||
#[test]
|
||||
fn assist_order_field_struct() {
|
||||
let before = "struct Foo { <|>bar: u32 }";
|
||||
let (before_cursor_pos, before) = extract_offset(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = helpers::with_single_file(&before);
|
||||
let frange =
|
||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||
let assists = super::assists(&db, frange);
|
||||
|
@ -478,7 +331,7 @@ mod tests {
|
|||
}
|
||||
}";
|
||||
let (range, before) = extract_range(before);
|
||||
let (db, file_id) = TestDB::with_single_file(&before);
|
||||
let (db, file_id) = helpers::with_single_file(&before);
|
||||
let frange = FileRange { file_id, range };
|
||||
let assists = super::assists(&db, frange);
|
||||
let mut assists = assists.iter();
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
//! Database used for testing `ra_assists`.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath};
|
||||
|
||||
#[salsa::database(
|
||||
ra_db::SourceDatabaseExtStorage,
|
||||
ra_db::SourceDatabaseStorage,
|
||||
hir::db::InternDatabaseStorage,
|
||||
hir::db::AstDatabaseStorage,
|
||||
hir::db::DefDatabaseStorage,
|
||||
hir::db::HirDatabaseStorage
|
||||
)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TestDB {
|
||||
runtime: salsa::Runtime<TestDB>,
|
||||
}
|
||||
|
||||
impl salsa::Database for TestDB {
|
||||
fn salsa_runtime(&self) -> &salsa::Runtime<Self> {
|
||||
&self.runtime
|
||||
}
|
||||
fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
|
||||
&mut self.runtime
|
||||
}
|
||||
}
|
||||
|
||||
impl std::panic::RefUnwindSafe for TestDB {}
|
||||
|
||||
impl FileLoader for TestDB {
|
||||
fn file_text(&self, file_id: FileId) -> Arc<String> {
|
||||
FileLoaderDelegate(self).file_text(file_id)
|
||||
}
|
||||
fn resolve_relative_path(
|
||||
&self,
|
||||
anchor: FileId,
|
||||
relative_path: &RelativePath,
|
||||
) -> Option<FileId> {
|
||||
FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
|
||||
}
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
|
||||
FileLoaderDelegate(self).relevant_crates(file_id)
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
use either::Either;
|
||||
use ra_assists::{AssistAction, AssistLabel};
|
||||
use ra_db::{FilePosition, FileRange};
|
||||
use ra_ide_db::{imports_locator::ImportsLocatorIde, RootDatabase};
|
||||
use ra_ide_db::RootDatabase;
|
||||
|
||||
use crate::{FileId, SourceChange, SourceFileEdit};
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub struct Assist {
|
|||
}
|
||||
|
||||
pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> {
|
||||
ra_assists::assists_with_imports_locator(db, frange, ImportsLocatorIde::new(db))
|
||||
ra_assists::assists(db, frange)
|
||||
.into_iter()
|
||||
.map(|assist| {
|
||||
let file_id = frange.file_id;
|
||||
|
|
|
@ -32,7 +32,6 @@ 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`.
|
||||
|
|
|
@ -92,7 +92,7 @@ pub fn classify_name(
|
|||
ast::FnDef(it) => {
|
||||
let src = name.with_value(it);
|
||||
let def: hir::Function = sb.to_def(src)?;
|
||||
if parent.parent().and_then(ast::ItemList::cast).is_some() {
|
||||
if parent.parent().and_then(ast::ItemList::cast).map_or(false, |it| it.syntax().parent().and_then(ast::Module::cast).is_none()) {
|
||||
Some(from_assoc_item(sb.db, def.into()))
|
||||
} else {
|
||||
Some(from_module_def(sb.db, def.into(), None))
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
//! Later, this should be moved away to a separate crate that is accessible from the ra_assists module.
|
||||
|
||||
use hir::{db::HirDatabase, ModuleDef, SourceBinder};
|
||||
use ra_assists::ImportsLocator;
|
||||
use ra_prof::profile;
|
||||
use ra_syntax::{ast, AstNode, SyntaxKind::NAME};
|
||||
|
||||
|
@ -22,29 +21,7 @@ impl<'a> ImportsLocatorIde<'a> {
|
|||
Self { source_binder: SourceBinder::new(db) }
|
||||
}
|
||||
|
||||
fn get_name_definition(
|
||||
&mut self,
|
||||
db: &impl HirDatabase,
|
||||
import_candidate: &FileSymbol,
|
||||
) -> Option<NameKind> {
|
||||
let _p = profile("get_name_definition");
|
||||
let file_id = import_candidate.file_id.into();
|
||||
let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
|
||||
let candidate_name_node = if candidate_node.kind() != NAME {
|
||||
candidate_node.children().find(|it| it.kind() == NAME)?
|
||||
} else {
|
||||
candidate_node
|
||||
};
|
||||
classify_name(
|
||||
&mut self.source_binder,
|
||||
hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
|
||||
)
|
||||
.map(|it| it.kind)
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportsLocator for ImportsLocatorIde<'_> {
|
||||
fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
|
||||
pub fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
|
||||
let _p = profile("search_for_imports");
|
||||
let db = self.source_binder.db;
|
||||
|
||||
|
@ -72,4 +49,24 @@ impl ImportsLocator for ImportsLocatorIde<'_> {
|
|||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_name_definition(
|
||||
&mut self,
|
||||
db: &impl HirDatabase,
|
||||
import_candidate: &FileSymbol,
|
||||
) -> Option<NameKind> {
|
||||
let _p = profile("get_name_definition");
|
||||
let file_id = import_candidate.file_id.into();
|
||||
let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
|
||||
let candidate_name_node = if candidate_node.kind() != NAME {
|
||||
candidate_node.children().find(|it| it.kind() == NAME)?
|
||||
} else {
|
||||
candidate_node
|
||||
};
|
||||
classify_name(
|
||||
&mut self.source_binder,
|
||||
hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
|
||||
)
|
||||
.map(|it| it.kind)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue