mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +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_db",
|
||||||
"ra_fmt",
|
"ra_fmt",
|
||||||
"ra_hir",
|
"ra_hir",
|
||||||
|
"ra_ide_db",
|
||||||
"ra_prof",
|
"ra_prof",
|
||||||
"ra_syntax",
|
"ra_syntax",
|
||||||
"ra_text_edit",
|
"ra_text_edit",
|
||||||
|
@ -1165,7 +1166,6 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proptest",
|
"proptest",
|
||||||
"ra_assists",
|
|
||||||
"ra_cfg",
|
"ra_cfg",
|
||||||
"ra_db",
|
"ra_db",
|
||||||
"ra_fmt",
|
"ra_fmt",
|
||||||
|
|
|
@ -18,5 +18,6 @@ ra_text_edit = { path = "../ra_text_edit" }
|
||||||
ra_fmt = { path = "../ra_fmt" }
|
ra_fmt = { path = "../ra_fmt" }
|
||||||
ra_prof = { path = "../ra_prof" }
|
ra_prof = { path = "../ra_prof" }
|
||||||
ra_db = { path = "../ra_db" }
|
ra_db = { path = "../ra_db" }
|
||||||
|
ra_ide_db = { path = "../ra_ide_db" }
|
||||||
hir = { path = "../ra_hir", package = "ra_hir" }
|
hir = { path = "../ra_hir", package = "ra_hir" }
|
||||||
test_utils = { path = "../test_utils" }
|
test_utils = { path = "../test_utils" }
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
//! This module defines `AssistCtx` -- the API surface that is exposed to assists.
|
//! This module defines `AssistCtx` -- the API surface that is exposed to assists.
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{db::HirDatabase, InFile, SourceAnalyzer, SourceBinder};
|
use hir::{InFile, SourceAnalyzer, SourceBinder};
|
||||||
use ra_db::FileRange;
|
use ra_db::{FileRange, SourceDatabase};
|
||||||
use ra_fmt::{leading_indent, reindent};
|
use ra_fmt::{leading_indent, reindent};
|
||||||
|
use ra_ide_db::RootDatabase;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::{self, find_covering_element, find_node_at_offset},
|
algo::{self, find_covering_element, find_node_at_offset},
|
||||||
AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextUnit,
|
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
|
/// moment, because the LSP API is pretty awkward in this place, and it's much
|
||||||
/// easier to just compute the edit eagerly :-)
|
/// easier to just compute the edit eagerly :-)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct AssistCtx<'a, DB> {
|
pub(crate) struct AssistCtx<'a> {
|
||||||
pub(crate) db: &'a DB,
|
pub(crate) db: &'a RootDatabase,
|
||||||
pub(crate) frange: FileRange,
|
pub(crate) frange: FileRange,
|
||||||
source_file: SourceFile,
|
source_file: SourceFile,
|
||||||
should_compute_edit: bool,
|
should_compute_edit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, DB> Clone for AssistCtx<'a, DB> {
|
impl<'a> Clone for AssistCtx<'a> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
AssistCtx {
|
AssistCtx {
|
||||||
db: self.db,
|
db: self.db,
|
||||||
|
@ -67,17 +68,24 @@ impl<'a, DB> Clone for AssistCtx<'a, DB> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
|
impl<'a> AssistCtx<'a> {
|
||||||
pub(crate) fn with_ctx<F, T>(db: &DB, frange: FileRange, should_compute_edit: bool, f: F) -> T
|
pub(crate) fn with_ctx<F, T>(
|
||||||
|
db: &RootDatabase,
|
||||||
|
frange: FileRange,
|
||||||
|
should_compute_edit: bool,
|
||||||
|
f: F,
|
||||||
|
) -> T
|
||||||
where
|
where
|
||||||
F: FnOnce(AssistCtx<DB>) -> T,
|
F: FnOnce(AssistCtx) -> T,
|
||||||
{
|
{
|
||||||
let parse = db.parse(frange.file_id);
|
let parse = db.parse(frange.file_id);
|
||||||
|
|
||||||
let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit };
|
let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit };
|
||||||
f(ctx)
|
f(ctx)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> AssistCtx<'a> {
|
||||||
pub(crate) fn add_assist(
|
pub(crate) fn add_assist(
|
||||||
self,
|
self,
|
||||||
id: AssistId,
|
id: AssistId,
|
||||||
|
@ -141,7 +149,7 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
|
||||||
pub(crate) fn covering_element(&self) -> SyntaxElement {
|
pub(crate) fn covering_element(&self) -> SyntaxElement {
|
||||||
find_covering_element(self.source_file.syntax(), self.frange.range)
|
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)
|
SourceBinder::new(self.db)
|
||||||
}
|
}
|
||||||
pub(crate) fn source_analyzer(
|
pub(crate) fn source_analyzer(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use crate::{Assist, AssistCtx, AssistId};
|
use crate::{Assist, AssistCtx, AssistId};
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use join_to_string::join;
|
use join_to_string::join;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode},
|
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 input = ctx.find_node_at_offset::<ast::AttrInput>()?;
|
||||||
let attr = input.syntax().parent().and_then(ast::Attr::cast)?;
|
let attr = input.syntax().parent().and_then(ast::Attr::cast)?;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode, AttrsOwner},
|
ast::{self, AstNode, AttrsOwner},
|
||||||
SyntaxKind::{COMMENT, WHITESPACE},
|
SyntaxKind::{COMMENT, WHITESPACE},
|
||||||
|
@ -25,7 +24,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// y: u32,
|
// 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 nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
|
||||||
let node_start = derive_insertion_offset(&nominal)?;
|
let node_start = derive_insertion_offset(&nominal)?;
|
||||||
ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", |edit| {
|
ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", |edit| {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use hir::{db::HirDatabase, HirDisplay};
|
use hir::HirDisplay;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner},
|
ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner},
|
||||||
TextRange,
|
TextRange,
|
||||||
|
@ -21,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// let x: i32 = 92;
|
// 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 stmt = ctx.find_node_at_offset::<LetStmt>()?;
|
||||||
let expr = stmt.initializer()?;
|
let expr = stmt.initializer()?;
|
||||||
let pat = stmt.pat()?;
|
let pat = stmt.pat()?;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use format_buf::format;
|
use format_buf::format;
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use join_to_string::join;
|
use join_to_string::join;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode, NameOwner, TypeParamsOwner},
|
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 nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
|
||||||
let name = nominal.name()?;
|
let name = nominal.name()?;
|
||||||
ctx.add_assist(AssistId("add_impl"), format!("Implement {}", name.text().as_str()), |edit| {
|
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::{
|
use ra_syntax::{
|
||||||
ast::{self, NameOwner},
|
ast::{self, NameOwner},
|
||||||
AstNode, Direction, SmolStr,
|
AstNode, Direction, SmolStr,
|
||||||
|
@ -50,7 +50,7 @@ pub fn auto_import_text_edit(
|
||||||
//
|
//
|
||||||
// fn process(map: HashMap<String, String>) {}
|
// 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()?;
|
let path: ast::Path = ctx.find_node_at_offset()?;
|
||||||
// We don't want to mess with use statements
|
// We don't want to mess with use statements
|
||||||
if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
|
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(
|
add_missing_impl_members_inner(
|
||||||
ctx,
|
ctx,
|
||||||
AddMissingImplMembersMode::NoDefaultMethods,
|
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(
|
add_missing_impl_members_inner(
|
||||||
ctx,
|
ctx,
|
||||||
AddMissingImplMembersMode::DefaultMethodsOnly,
|
AddMissingImplMembersMode::DefaultMethodsOnly,
|
||||||
|
@ -94,7 +94,7 @@ pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> O
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_missing_impl_members_inner(
|
fn add_missing_impl_members_inner(
|
||||||
ctx: AssistCtx<impl HirDatabase>,
|
ctx: AssistCtx,
|
||||||
mode: AddMissingImplMembersMode,
|
mode: AddMissingImplMembersMode,
|
||||||
assist_id: &'static str,
|
assist_id: &'static str,
|
||||||
label: &'static str,
|
label: &'static str,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use format_buf::format;
|
use format_buf::format;
|
||||||
use hir::{db::HirDatabase, InFile};
|
use hir::InFile;
|
||||||
use join_to_string::join;
|
use join_to_string::join;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{
|
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>()?;
|
let strukt = ctx.find_node_at_offset::<ast::StructDef>()?;
|
||||||
|
|
||||||
// We want to only apply this to non-union structs with named fields
|
// 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
|
// FIXME: change the new fn checking to a more semantic approach when that's more
|
||||||
// viable (e.g. we process proc macros, etc)
|
// viable (e.g. we process proc macros, etc)
|
||||||
fn find_struct_impl(
|
fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option<Option<ast::ImplBlock>> {
|
||||||
ctx: &AssistCtx<impl HirDatabase>,
|
|
||||||
strukt: &ast::StructDef,
|
|
||||||
) -> Option<Option<ast::ImplBlock>> {
|
|
||||||
let db = ctx.db;
|
let db = ctx.db;
|
||||||
let module = strukt.syntax().ancestors().find(|node| {
|
let module = strukt.syntax().ancestors().find(|node| {
|
||||||
ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
|
ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use super::invert_if::invert_boolean_expression;
|
use super::invert_if::invert_boolean_expression;
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::ast::{self, AstNode};
|
use ra_syntax::ast::{self, AstNode};
|
||||||
|
|
||||||
use crate::{Assist, AssistCtx, AssistId};
|
use crate::{Assist, AssistCtx, AssistId};
|
||||||
|
@ -23,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// if !(x == 4 && y) {}
|
// 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 expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
|
||||||
let op = expr.op_kind()?;
|
let op = expr.op_kind()?;
|
||||||
let op_range = expr.op_token()?.text_range();
|
let op_range = expr.op_token()?.text_range();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use hir::{db::HirDatabase, ModPath};
|
use hir::ModPath;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
SyntaxNode,
|
SyntaxNode,
|
||||||
|
@ -6,8 +6,9 @@ use ra_syntax::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assist_ctx::{ActionBuilder, Assist, AssistCtx},
|
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
|
// Assist: auto_import
|
||||||
//
|
//
|
||||||
|
@ -26,10 +27,7 @@ use crate::{
|
||||||
// let map = HashMap<|>::new();
|
// let map = HashMap<|>::new();
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
pub(crate) fn auto_import<F: ImportsLocator>(
|
pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
|
||||||
ctx: AssistCtx<impl HirDatabase>,
|
|
||||||
imports_locator: &mut F,
|
|
||||||
) -> Option<Assist> {
|
|
||||||
let path_to_import: ast::Path = ctx.find_node_at_offset()?;
|
let path_to_import: ast::Path = ctx.find_node_at_offset()?;
|
||||||
let path_to_import_syntax = path_to_import.syntax();
|
let path_to_import_syntax = path_to_import.syntax();
|
||||||
if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() {
|
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;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut imports_locator = ImportsLocatorIde::new(ctx.db);
|
||||||
|
|
||||||
let proposed_imports = imports_locator
|
let proposed_imports = imports_locator
|
||||||
.find_imports(&name_to_import)
|
.find_imports(&name_to_import)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -81,16 +81,12 @@ fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode)
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::helpers::{
|
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||||
check_assist_with_imports_locator, check_assist_with_imports_locator_not_applicable,
|
|
||||||
TestImportsLocator,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn applicable_when_found_an_import() {
|
fn applicable_when_found_an_import() {
|
||||||
check_assist_with_imports_locator(
|
check_assist(
|
||||||
auto_import,
|
auto_import,
|
||||||
TestImportsLocator::new,
|
|
||||||
r"
|
r"
|
||||||
<|>PubStruct
|
<|>PubStruct
|
||||||
|
|
||||||
|
@ -112,9 +108,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn auto_imports_are_merged() {
|
fn auto_imports_are_merged() {
|
||||||
check_assist_with_imports_locator(
|
check_assist(
|
||||||
auto_import,
|
auto_import,
|
||||||
TestImportsLocator::new,
|
|
||||||
r"
|
r"
|
||||||
use PubMod::PubStruct1;
|
use PubMod::PubStruct1;
|
||||||
|
|
||||||
|
@ -148,9 +143,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn applicable_when_found_multiple_imports() {
|
fn applicable_when_found_multiple_imports() {
|
||||||
check_assist_with_imports_locator(
|
check_assist(
|
||||||
auto_import,
|
auto_import,
|
||||||
TestImportsLocator::new,
|
|
||||||
r"
|
r"
|
||||||
PubSt<|>ruct
|
PubSt<|>ruct
|
||||||
|
|
||||||
|
@ -184,9 +178,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn not_applicable_for_already_imported_types() {
|
fn not_applicable_for_already_imported_types() {
|
||||||
check_assist_with_imports_locator_not_applicable(
|
check_assist_not_applicable(
|
||||||
auto_import,
|
auto_import,
|
||||||
TestImportsLocator::new,
|
|
||||||
r"
|
r"
|
||||||
use PubMod::PubStruct;
|
use PubMod::PubStruct;
|
||||||
|
|
||||||
|
@ -201,9 +194,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn not_applicable_for_types_with_private_paths() {
|
fn not_applicable_for_types_with_private_paths() {
|
||||||
check_assist_with_imports_locator_not_applicable(
|
check_assist_not_applicable(
|
||||||
auto_import,
|
auto_import,
|
||||||
TestImportsLocator::new,
|
|
||||||
r"
|
r"
|
||||||
PrivateStruct<|>
|
PrivateStruct<|>
|
||||||
|
|
||||||
|
@ -216,9 +208,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn not_applicable_when_no_imports_found() {
|
fn not_applicable_when_no_imports_found() {
|
||||||
check_assist_with_imports_locator_not_applicable(
|
check_assist_not_applicable(
|
||||||
auto_import,
|
auto_import,
|
||||||
TestImportsLocator::new,
|
|
||||||
"
|
"
|
||||||
PubStruct<|>",
|
PubStruct<|>",
|
||||||
);
|
);
|
||||||
|
@ -226,9 +217,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn not_applicable_in_import_statements() {
|
fn not_applicable_in_import_statements() {
|
||||||
check_assist_with_imports_locator_not_applicable(
|
check_assist_not_applicable(
|
||||||
auto_import,
|
auto_import,
|
||||||
TestImportsLocator::new,
|
|
||||||
r"
|
r"
|
||||||
use PubStruct<|>;
|
use PubStruct<|>;
|
||||||
|
|
||||||
|
@ -240,9 +230,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_import() {
|
fn function_import() {
|
||||||
check_assist_with_imports_locator(
|
check_assist(
|
||||||
auto_import,
|
auto_import,
|
||||||
TestImportsLocator::new,
|
|
||||||
r"
|
r"
|
||||||
test_function<|>
|
test_function<|>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, NameOwner, VisibilityOwner},
|
ast::{self, NameOwner, VisibilityOwner},
|
||||||
AstNode,
|
AstNode,
|
||||||
|
@ -22,14 +21,14 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// ```
|
// ```
|
||||||
// pub(crate) fn frobnicate() {}
|
// 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>() {
|
if let Some(vis) = ctx.find_node_at_offset::<ast::Visibility>() {
|
||||||
return change_vis(ctx, vis);
|
return change_vis(ctx, vis);
|
||||||
}
|
}
|
||||||
add_vis(ctx)
|
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() {
|
let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() {
|
||||||
T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true,
|
T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -75,7 +74,7 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
|
||||||
.unwrap_or_else(|| node.text_range().start())
|
.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" {
|
if vis.syntax().text() == "pub" {
|
||||||
return ctx.add_assist(
|
return ctx.add_assist(
|
||||||
AssistId("change_visibility"),
|
AssistId("change_visibility"),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::{iter::once, ops::RangeInclusive};
|
use std::{iter::once, ops::RangeInclusive};
|
||||||
|
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::replace_children,
|
algo::replace_children,
|
||||||
ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat},
|
ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat},
|
||||||
|
@ -36,7 +35,7 @@ use crate::{
|
||||||
// bar();
|
// 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()?;
|
let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
|
||||||
if if_expr.else_branch().is_some() {
|
if if_expr.else_branch().is_some() {
|
||||||
return None;
|
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_expr = ctx.find_node_at_offset::<ast::MatchExpr>()?;
|
||||||
let match_arm_list = match_expr.match_arm_list()?;
|
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 ra_syntax::ast::{AstNode, BinExpr, BinOp};
|
||||||
|
|
||||||
use crate::{Assist, AssistCtx, AssistId};
|
use crate::{Assist, AssistCtx, AssistId};
|
||||||
|
@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// let _ = 2 + 90;
|
// 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 expr = ctx.find_node_at_offset::<BinExpr>()?;
|
||||||
let lhs = expr.lhs()?.syntax().clone();
|
let lhs = expr.lhs()?.syntax().clone();
|
||||||
let rhs = expr.rhs()?.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 ra_syntax::{algo::non_trivia_sibling, Direction, T};
|
||||||
|
|
||||||
use crate::{Assist, AssistCtx, AssistId};
|
use crate::{Assist, AssistCtx, AssistId};
|
||||||
|
@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// ((3, 4), (1, 2));
|
// ((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 comma = ctx.find_token_at_offset(T![,])?;
|
||||||
let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
|
let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
|
||||||
let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
|
let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::non_trivia_sibling,
|
algo::non_trivia_sibling,
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
|
@ -18,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// ```
|
// ```
|
||||||
// fn foo<T: Copy + Clone>() { }
|
// 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
|
// We want to replicate the behavior of `flip_binexpr` by only suggesting
|
||||||
// the assist when the cursor is on a `+`
|
// the assist when the cursor is on a `+`
|
||||||
let plus = ctx.find_token_at_offset(T![+])?;
|
let plus = ctx.find_token_at_offset(T![+])?;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode, AstToken},
|
ast::{self, AstNode, AstToken},
|
||||||
TextRange,
|
TextRange,
|
||||||
|
@ -23,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// (1 + 2) * 4;
|
// (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 let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?;
|
||||||
let bind_pat = match let_stmt.pat()? {
|
let bind_pat = match let_stmt.pat()? {
|
||||||
ast::Pat::BindPat(pat) => pat,
|
ast::Pat::BindPat(pat) => pat,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use format_buf::format;
|
use format_buf::format;
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
SyntaxKind::{
|
SyntaxKind::{
|
||||||
|
@ -28,7 +27,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// var_name * 4;
|
// 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() {
|
if ctx.frange.range.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::ast::{self, AstNode};
|
use ra_syntax::ast::{self, AstNode};
|
||||||
use ra_syntax::T;
|
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 if_keyword = ctx.find_token_at_offset(T![if])?;
|
||||||
let expr = ast::IfExpr::cast(if_keyword.parent())?;
|
let expr = ast::IfExpr::cast(if_keyword.parent())?;
|
||||||
let if_range = if_keyword.text_range();
|
let if_range = if_keyword.text_range();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::iter::successors;
|
use std::iter::successors;
|
||||||
|
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
Direction, TextUnit,
|
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>()?;
|
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
|
// Don't try to handle arms with guards for now - can add support for this later
|
||||||
if current_arm.guard().is_some() {
|
if current_arm.guard().is_some() {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, edit, make, AstNode, NameOwner, TypeBoundsOwner},
|
ast::{self, edit, make, AstNode, NameOwner, TypeBoundsOwner},
|
||||||
SyntaxElement,
|
SyntaxElement,
|
||||||
|
@ -22,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// f(x)
|
// 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 type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?;
|
||||||
|
|
||||||
let mut type_params = type_param_list.type_params();
|
let mut type_params = type_param_list.type_params();
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast,
|
ast,
|
||||||
ast::{AstNode, AstToken, IfExpr, MatchArm},
|
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 match_arm = ctx.find_node_at_offset::<MatchArm>()?;
|
||||||
let guard = match_arm.guard()?;
|
let guard = match_arm.guard()?;
|
||||||
let space_before_guard = guard.syntax().prev_sibling_or_token();
|
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 match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
|
||||||
let last_match_pat = match_arm.pats().last()?;
|
let last_match_pat = match_arm.pats().last()?;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast, AstToken,
|
ast, AstToken,
|
||||||
SyntaxKind::{RAW_STRING, STRING},
|
SyntaxKind::{RAW_STRING, STRING},
|
||||||
|
@ -22,7 +21,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// r#"Hello, World!"#;
|
// 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 token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?;
|
||||||
let value = token.value()?;
|
let value = token.value()?;
|
||||||
ctx.add_assist(AssistId("make_raw_string"), "Rewrite as raw string", |edit| {
|
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!\"";
|
// "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 token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?;
|
||||||
let value = token.value()?;
|
let value = token.value()?;
|
||||||
ctx.add_assist(AssistId("make_usual_string"), "Rewrite as regular string", |edit| {
|
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!"##;
|
// 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)?;
|
let token = ctx.find_token_at_offset(RAW_STRING)?;
|
||||||
ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| {
|
ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| {
|
||||||
edit.target(token.text_range());
|
edit.target(token.text_range());
|
||||||
|
@ -101,7 +100,7 @@ pub(crate) fn add_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||||
// r"Hello, World!";
|
// 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 token = ctx.find_token_at_offset(RAW_STRING)?;
|
||||||
let text = token.text().as_str();
|
let text = token.text().as_str();
|
||||||
if text.starts_with("r\"") {
|
if text.starts_with("r\"") {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
TextUnit, T,
|
TextUnit, T,
|
||||||
|
@ -21,7 +20,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// 92;
|
// 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>()?;
|
let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
|
||||||
|
|
||||||
if !is_valid_macrocall(¯o_call, "dbg")? {
|
if !is_valid_macrocall(¯o_call, "dbg")? {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_fmt::unwrap_trivial_block;
|
use ra_fmt::unwrap_trivial_block;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, make},
|
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 if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
|
||||||
let cond = if_expr.condition()?;
|
let cond = if_expr.condition()?;
|
||||||
let pat = cond.pat()?;
|
let pat = cond.pat()?;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::iter::successors;
|
use std::iter::successors;
|
||||||
|
|
||||||
use hir::db::HirDatabase;
|
|
||||||
use ra_syntax::{ast, AstNode, TextUnit, T};
|
use ra_syntax::{ast, AstNode, TextUnit, T};
|
||||||
|
|
||||||
use crate::{Assist, AssistCtx, AssistId};
|
use crate::{Assist, AssistCtx, AssistId};
|
||||||
|
@ -16,7 +15,7 @@ use crate::{Assist, AssistCtx, AssistId};
|
||||||
// ```
|
// ```
|
||||||
// use std::{collections::HashMap};
|
// 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 colon_colon = ctx.find_token_at_offset(T![::])?;
|
||||||
let path = ast::Path::cast(colon_colon.parent())?;
|
let path = ast::Path::cast(colon_colon.parent())?;
|
||||||
let top_path = successors(Some(path), |it| it.parent_path()).last()?;
|
let top_path = successors(Some(path), |it| it.parent_path()).last()?;
|
||||||
|
|
|
@ -8,7 +8,7 @@ mod generated;
|
||||||
use ra_db::{fixture::WithFixture, FileRange};
|
use ra_db::{fixture::WithFixture, FileRange};
|
||||||
use test_utils::{assert_eq_text, extract_range_or_offset};
|
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) {
|
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
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
let (selection, before) = extract_range_or_offset(before);
|
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 frange = FileRange { file_id, range: selection.into() };
|
||||||
|
|
||||||
let assist = crate::assists(&db, frange)
|
let assist = crate::assists(&db, frange)
|
||||||
|
|
|
@ -9,13 +9,11 @@ mod assist_ctx;
|
||||||
mod marks;
|
mod marks;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod doc_tests;
|
mod doc_tests;
|
||||||
#[cfg(test)]
|
|
||||||
mod test_db;
|
|
||||||
pub mod ast_transform;
|
pub mod ast_transform;
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{db::HirDatabase, ModuleDef};
|
|
||||||
use ra_db::FileRange;
|
use ra_db::FileRange;
|
||||||
|
use ra_ide_db::RootDatabase;
|
||||||
use ra_syntax::{TextRange, TextUnit};
|
use ra_syntax::{TextRange, TextUnit};
|
||||||
use ra_text_edit::TextEdit;
|
use ra_text_edit::TextEdit;
|
||||||
|
|
||||||
|
@ -61,10 +59,7 @@ impl ResolvedAssist {
|
||||||
///
|
///
|
||||||
/// Assists are returned in the "unresolved" state, that is only labels are
|
/// Assists are returned in the "unresolved" state, that is only labels are
|
||||||
/// returned, without actual edits.
|
/// returned, without actual edits.
|
||||||
pub fn applicable_assists<H>(db: &H, range: FileRange) -> Vec<AssistLabel>
|
pub fn applicable_assists(db: &RootDatabase, range: FileRange) -> Vec<AssistLabel> {
|
||||||
where
|
|
||||||
H: HirDatabase + 'static,
|
|
||||||
{
|
|
||||||
AssistCtx::with_ctx(db, range, false, |ctx| {
|
AssistCtx::with_ctx(db, range, false, |ctx| {
|
||||||
assists::all()
|
assists::all()
|
||||||
.iter()
|
.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.
|
/// Return all the assists applicable at the given position.
|
||||||
///
|
///
|
||||||
/// Assists are returned in the "resolved" state, that is with edit fully
|
/// Assists are returned in the "resolved" state, that is with edit fully
|
||||||
/// computed.
|
/// computed.
|
||||||
pub fn assists<H>(db: &H, range: FileRange) -> Vec<ResolvedAssist>
|
pub fn assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssist> {
|
||||||
where
|
|
||||||
H: HirDatabase + 'static,
|
|
||||||
{
|
|
||||||
AssistCtx::with_ctx(db, range, true, |ctx| {
|
AssistCtx::with_ctx(db, range, true, |ctx| {
|
||||||
let mut a = assists::all()
|
let mut a = assists::all()
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -155,8 +102,7 @@ fn sort_assists(assists: &mut Vec<ResolvedAssist>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod assists {
|
mod assists {
|
||||||
use crate::{Assist, AssistCtx, ImportsLocator};
|
use crate::{Assist, AssistCtx};
|
||||||
use hir::db::HirDatabase;
|
|
||||||
|
|
||||||
mod add_derive;
|
mod add_derive;
|
||||||
mod add_explicit_type;
|
mod add_explicit_type;
|
||||||
|
@ -184,7 +130,7 @@ mod assists {
|
||||||
mod move_bounds;
|
mod move_bounds;
|
||||||
mod early_return;
|
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_derive::add_derive,
|
||||||
add_explicit_type::add_explicit_type,
|
add_explicit_type::add_explicit_type,
|
||||||
|
@ -215,79 +161,34 @@ mod assists {
|
||||||
raw_string::make_usual_string,
|
raw_string::make_usual_string,
|
||||||
raw_string::remove_hash,
|
raw_string::remove_hash,
|
||||||
early_return::convert_to_guarded_return,
|
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)]
|
#[cfg(test)]
|
||||||
mod helpers {
|
mod helpers {
|
||||||
use hir::db::DefDatabase;
|
use std::sync::Arc;
|
||||||
use ra_db::{fixture::WithFixture, FileId, FileRange};
|
|
||||||
|
use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
|
||||||
|
use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
|
||||||
use ra_syntax::TextRange;
|
use ra_syntax::TextRange;
|
||||||
use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range};
|
use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range};
|
||||||
|
|
||||||
use crate::{test_db::TestDB, Assist, AssistCtx, ImportsLocator};
|
use crate::{Assist, AssistCtx};
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
// FIXME remove the `ModuleDefId` reexport from `ra_hir` when this gets removed.
|
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
|
||||||
pub(crate) struct TestImportsLocator {
|
let (mut db, file_id) = RootDatabase::with_single_file(text);
|
||||||
db: Arc<TestDB>,
|
// FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`,
|
||||||
test_file_id: FileId,
|
// 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 check_assist(assist: fn(AssistCtx) -> Option<Assist>, before: &str, after: &str) {
|
||||||
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,
|
|
||||||
) {
|
|
||||||
let (before_cursor_pos, before) = extract_offset(before);
|
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 =
|
let frange =
|
||||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||||
let assist =
|
let assist =
|
||||||
|
@ -309,45 +210,13 @@ mod helpers {
|
||||||
assert_eq_text!(after, &actual);
|
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(
|
pub(crate) fn check_assist_range(
|
||||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
assist: fn(AssistCtx) -> Option<Assist>,
|
||||||
before: &str,
|
before: &str,
|
||||||
after: &str,
|
after: &str,
|
||||||
) {
|
) {
|
||||||
let (range, before) = extract_range(before);
|
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 frange = FileRange { file_id, range };
|
||||||
let assist =
|
let assist =
|
||||||
AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
|
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(
|
pub(crate) fn check_assist_target(
|
||||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
assist: fn(AssistCtx) -> Option<Assist>,
|
||||||
before: &str,
|
before: &str,
|
||||||
target: &str,
|
target: &str,
|
||||||
) {
|
) {
|
||||||
let (before_cursor_pos, before) = extract_offset(before);
|
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 =
|
let frange =
|
||||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||||
let assist =
|
let assist =
|
||||||
|
@ -384,12 +253,12 @@ mod helpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_assist_range_target(
|
pub(crate) fn check_assist_range_target(
|
||||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
assist: fn(AssistCtx) -> Option<Assist>,
|
||||||
before: &str,
|
before: &str,
|
||||||
target: &str,
|
target: &str,
|
||||||
) {
|
) {
|
||||||
let (range, before) = extract_range(before);
|
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 frange = FileRange { file_id, range };
|
||||||
let assist =
|
let assist =
|
||||||
AssistCtx::with_ctx(&db, frange, true, assist).expect("code action is not applicable");
|
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(
|
pub(crate) fn check_assist_not_applicable(
|
||||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
assist: fn(AssistCtx) -> Option<Assist>,
|
||||||
before: &str,
|
before: &str,
|
||||||
) {
|
) {
|
||||||
let (before_cursor_pos, before) = extract_offset(before);
|
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 =
|
let frange =
|
||||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||||
let assist = AssistCtx::with_ctx(&db, frange, true, assist);
|
let assist = AssistCtx::with_ctx(&db, frange, true, assist);
|
||||||
assert!(assist.is_none());
|
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(
|
pub(crate) fn check_assist_range_not_applicable(
|
||||||
assist: fn(AssistCtx<TestDB>) -> Option<Assist>,
|
assist: fn(AssistCtx) -> Option<Assist>,
|
||||||
before: &str,
|
before: &str,
|
||||||
) {
|
) {
|
||||||
let (range, before) = extract_range(before);
|
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 frange = FileRange { file_id, range };
|
||||||
let assist = AssistCtx::with_ctx(&db, frange, true, assist);
|
let assist = AssistCtx::with_ctx(&db, frange, true, assist);
|
||||||
assert!(assist.is_none());
|
assert!(assist.is_none());
|
||||||
|
@ -444,17 +297,17 @@ mod helpers {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ra_db::{fixture::WithFixture, FileRange};
|
use ra_db::FileRange;
|
||||||
use ra_syntax::TextRange;
|
use ra_syntax::TextRange;
|
||||||
use test_utils::{extract_offset, extract_range};
|
use test_utils::{extract_offset, extract_range};
|
||||||
|
|
||||||
use crate::test_db::TestDB;
|
use crate::helpers;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn assist_order_field_struct() {
|
fn assist_order_field_struct() {
|
||||||
let before = "struct Foo { <|>bar: u32 }";
|
let before = "struct Foo { <|>bar: u32 }";
|
||||||
let (before_cursor_pos, before) = extract_offset(before);
|
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 =
|
let frange =
|
||||||
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
|
||||||
let assists = super::assists(&db, frange);
|
let assists = super::assists(&db, frange);
|
||||||
|
@ -478,7 +331,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
}";
|
}";
|
||||||
let (range, before) = extract_range(before);
|
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 frange = FileRange { file_id, range };
|
||||||
let assists = super::assists(&db, frange);
|
let assists = super::assists(&db, frange);
|
||||||
let mut assists = assists.iter();
|
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 either::Either;
|
||||||
use ra_assists::{AssistAction, AssistLabel};
|
use ra_assists::{AssistAction, AssistLabel};
|
||||||
use ra_db::{FilePosition, FileRange};
|
use ra_db::{FilePosition, FileRange};
|
||||||
use ra_ide_db::{imports_locator::ImportsLocatorIde, RootDatabase};
|
use ra_ide_db::RootDatabase;
|
||||||
|
|
||||||
use crate::{FileId, SourceChange, SourceFileEdit};
|
use crate::{FileId, SourceChange, SourceFileEdit};
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ pub struct Assist {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<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()
|
.into_iter()
|
||||||
.map(|assist| {
|
.map(|assist| {
|
||||||
let file_id = frange.file_id;
|
let file_id = frange.file_id;
|
||||||
|
|
|
@ -32,7 +32,6 @@ ra_cfg = { path = "../ra_cfg" }
|
||||||
ra_fmt = { path = "../ra_fmt" }
|
ra_fmt = { path = "../ra_fmt" }
|
||||||
ra_prof = { path = "../ra_prof" }
|
ra_prof = { path = "../ra_prof" }
|
||||||
test_utils = { path = "../test_utils" }
|
test_utils = { path = "../test_utils" }
|
||||||
ra_assists = { path = "../ra_assists" }
|
|
||||||
|
|
||||||
# ra_ide should depend only on the top-level `hir` package. if you need
|
# 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`.
|
# something from some `hir_xxx` subpackage, reexport the API via `hir`.
|
||||||
|
|
|
@ -92,7 +92,7 @@ pub fn classify_name(
|
||||||
ast::FnDef(it) => {
|
ast::FnDef(it) => {
|
||||||
let src = name.with_value(it);
|
let src = name.with_value(it);
|
||||||
let def: hir::Function = sb.to_def(src)?;
|
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()))
|
Some(from_assoc_item(sb.db, def.into()))
|
||||||
} else {
|
} else {
|
||||||
Some(from_module_def(sb.db, def.into(), None))
|
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.
|
//! 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 hir::{db::HirDatabase, ModuleDef, SourceBinder};
|
||||||
use ra_assists::ImportsLocator;
|
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use ra_syntax::{ast, AstNode, SyntaxKind::NAME};
|
use ra_syntax::{ast, AstNode, SyntaxKind::NAME};
|
||||||
|
|
||||||
|
@ -22,29 +21,7 @@ impl<'a> ImportsLocatorIde<'a> {
|
||||||
Self { source_binder: SourceBinder::new(db) }
|
Self { source_binder: SourceBinder::new(db) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_name_definition(
|
pub fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
|
||||||
&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> {
|
|
||||||
let _p = profile("search_for_imports");
|
let _p = profile("search_for_imports");
|
||||||
let db = self.source_binder.db;
|
let db = self.source_binder.db;
|
||||||
|
|
||||||
|
@ -72,4 +49,24 @@ impl ImportsLocator for ImportsLocatorIde<'_> {
|
||||||
})
|
})
|
||||||
.collect()
|
.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