mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-22 19:34:16 +00:00
Extract call_info and completion into separate crates
This commit is contained in:
parent
2067a410f3
commit
9e7c952bbd
34 changed files with 336 additions and 226 deletions
36
Cargo.lock
generated
36
Cargo.lock
generated
|
@ -127,6 +127,20 @@ version = "1.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "call_info"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"base_db",
|
||||||
|
"either",
|
||||||
|
"expect-test",
|
||||||
|
"hir",
|
||||||
|
"ide_db",
|
||||||
|
"stdx",
|
||||||
|
"syntax",
|
||||||
|
"test_utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cargo_metadata"
|
name = "cargo_metadata"
|
||||||
version = "0.11.4"
|
version = "0.11.4"
|
||||||
|
@ -249,6 +263,26 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "completion"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"assists",
|
||||||
|
"base_db",
|
||||||
|
"call_info",
|
||||||
|
"expect-test",
|
||||||
|
"hir",
|
||||||
|
"ide_db",
|
||||||
|
"itertools",
|
||||||
|
"log",
|
||||||
|
"profile",
|
||||||
|
"rustc-hash",
|
||||||
|
"stdx",
|
||||||
|
"syntax",
|
||||||
|
"test_utils",
|
||||||
|
"text_edit",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const_fn"
|
name = "const_fn"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
@ -609,7 +643,9 @@ version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assists",
|
"assists",
|
||||||
"base_db",
|
"base_db",
|
||||||
|
"call_info",
|
||||||
"cfg",
|
"cfg",
|
||||||
|
"completion",
|
||||||
"either",
|
"either",
|
||||||
"expect-test",
|
"expect-test",
|
||||||
"hir",
|
"hir",
|
||||||
|
|
26
crates/call_info/Cargo.toml
Normal file
26
crates/call_info/Cargo.toml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
[package]
|
||||||
|
name = "call_info"
|
||||||
|
version = "0.0.0"
|
||||||
|
description = "TBD"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
authors = ["rust-analyzer developers"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
either = "1.5.3"
|
||||||
|
|
||||||
|
stdx = { path = "../stdx", version = "0.0.0" }
|
||||||
|
syntax = { path = "../syntax", version = "0.0.0" }
|
||||||
|
base_db = { path = "../base_db", version = "0.0.0" }
|
||||||
|
ide_db = { path = "../ide_db", version = "0.0.0" }
|
||||||
|
test_utils = { path = "../test_utils", version = "0.0.0" }
|
||||||
|
|
||||||
|
# call_info crate should depend only on the top-level `hir` package. if you need
|
||||||
|
# something from some `hir_xxx` subpackage, reexport the API via `hir`.
|
||||||
|
hir = { path = "../hir", version = "0.0.0" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
expect-test = "1.0"
|
|
@ -1,4 +1,5 @@
|
||||||
//! FIXME: write short doc here
|
//! This crate provides primitives for tracking the information about a call site.
|
||||||
|
use base_db::FilePosition;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{HasAttrs, HirDisplay, Semantics, Type};
|
use hir::{HasAttrs, HirDisplay, Semantics, Type};
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
|
@ -9,8 +10,6 @@ use syntax::{
|
||||||
};
|
};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::FilePosition;
|
|
||||||
|
|
||||||
/// Contains information about a call site. Specifically the
|
/// Contains information about a call site. Specifically the
|
||||||
/// `FunctionSignature`and current parameter.
|
/// `FunctionSignature`and current parameter.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -40,7 +39,7 @@ impl CallInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes parameter information for the given call expression.
|
/// Computes parameter information for the given call expression.
|
||||||
pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
|
pub fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
|
||||||
let sema = Semantics::new(db);
|
let sema = Semantics::new(db);
|
||||||
let file = sema.parse(position.file_id);
|
let file = sema.parse(position.file_id);
|
||||||
let file = file.syntax();
|
let file = file.syntax();
|
||||||
|
@ -141,13 +140,13 @@ fn call_info_impl(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct ActiveParameter {
|
pub struct ActiveParameter {
|
||||||
pub(crate) ty: Type,
|
pub ty: Type,
|
||||||
pub(crate) name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveParameter {
|
impl ActiveParameter {
|
||||||
pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> {
|
pub fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> {
|
||||||
let sema = Semantics::new(db);
|
let sema = Semantics::new(db);
|
||||||
let file = sema.parse(position.file_id);
|
let file = sema.parse(position.file_id);
|
||||||
let file = file.syntax();
|
let file = file.syntax();
|
||||||
|
@ -156,7 +155,7 @@ impl ActiveParameter {
|
||||||
Self::at_token(&sema, token)
|
Self::at_token(&sema, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> {
|
pub fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> {
|
||||||
let (signature, active_parameter) = call_info_impl(&sema, token)?;
|
let (signature, active_parameter) = call_info_impl(&sema, token)?;
|
||||||
|
|
||||||
let idx = active_parameter?;
|
let idx = active_parameter?;
|
||||||
|
@ -172,7 +171,7 @@ impl ActiveParameter {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum FnCallNode {
|
pub enum FnCallNode {
|
||||||
CallExpr(ast::CallExpr),
|
CallExpr(ast::CallExpr),
|
||||||
MethodCallExpr(ast::MethodCallExpr),
|
MethodCallExpr(ast::MethodCallExpr),
|
||||||
}
|
}
|
||||||
|
@ -196,7 +195,7 @@ impl FnCallNode {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn with_node_exact(node: &SyntaxNode) -> Option<FnCallNode> {
|
pub fn with_node_exact(node: &SyntaxNode) -> Option<FnCallNode> {
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)),
|
ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)),
|
||||||
|
@ -206,7 +205,7 @@ impl FnCallNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn name_ref(&self) -> Option<ast::NameRef> {
|
pub fn name_ref(&self) -> Option<ast::NameRef> {
|
||||||
match self {
|
match self {
|
||||||
FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()? {
|
FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()? {
|
||||||
ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
|
ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
|
||||||
|
@ -229,14 +228,28 @@ impl FnCallNode {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use base_db::{fixture::ChangeFixture, FilePosition};
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
use test_utils::mark;
|
use ide_db::RootDatabase;
|
||||||
|
use test_utils::{mark, RangeOrOffset};
|
||||||
|
|
||||||
use crate::fixture;
|
/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
|
||||||
|
pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
|
||||||
|
let change_fixture = ChangeFixture::parse(ra_fixture);
|
||||||
|
let mut database = RootDatabase::default();
|
||||||
|
database.apply_change(change_fixture.change);
|
||||||
|
let (file_id, range_or_offset) =
|
||||||
|
change_fixture.file_position.expect("expected a marker (<|>)");
|
||||||
|
let offset = match range_or_offset {
|
||||||
|
RangeOrOffset::Range(_) => panic!(),
|
||||||
|
RangeOrOffset::Offset(it) => it,
|
||||||
|
};
|
||||||
|
(database, FilePosition { file_id, offset })
|
||||||
|
}
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let (analysis, position) = fixture::position(ra_fixture);
|
let (db, position) = position(ra_fixture);
|
||||||
let call_info = analysis.call_info(position).unwrap();
|
let call_info = crate::call_info(&db, position);
|
||||||
let actual = match call_info {
|
let actual = match call_info {
|
||||||
Some(call_info) => {
|
Some(call_info) => {
|
||||||
let docs = match &call_info.doc {
|
let docs = match &call_info.doc {
|
32
crates/completion/Cargo.toml
Normal file
32
crates/completion/Cargo.toml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
[package]
|
||||||
|
name = "completion"
|
||||||
|
version = "0.0.0"
|
||||||
|
description = "TBD"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
authors = ["rust-analyzer developers"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
itertools = "0.9.0"
|
||||||
|
log = "0.4.8"
|
||||||
|
rustc-hash = "1.1.0"
|
||||||
|
|
||||||
|
syntax = { path = "../syntax", version = "0.0.0" }
|
||||||
|
text_edit = { path = "../text_edit", version = "0.0.0" }
|
||||||
|
base_db = { path = "../base_db", version = "0.0.0" }
|
||||||
|
ide_db = { path = "../ide_db", version = "0.0.0" }
|
||||||
|
profile = { path = "../profile", version = "0.0.0" }
|
||||||
|
test_utils = { path = "../test_utils", version = "0.0.0" }
|
||||||
|
assists = { path = "../assists", version = "0.0.0" }
|
||||||
|
call_info = { path = "../call_info", version = "0.0.0" }
|
||||||
|
|
||||||
|
# completions crate should depend only on the top-level `hir` package. if you need
|
||||||
|
# something from some `hir_xxx` subpackage, reexport the API via `hir`.
|
||||||
|
hir = { path = "../hir", version = "0.0.0" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
expect-test = "1.0"
|
||||||
|
stdx = { path = "../stdx", version = "0.0.0" }
|
|
@ -6,7 +6,7 @@
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use syntax::{ast, AstNode, SyntaxKind};
|
use syntax::{ast, AstNode, SyntaxKind};
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{
|
||||||
completion_context::CompletionContext,
|
completion_context::CompletionContext,
|
||||||
completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions},
|
completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions},
|
||||||
generated_features::FEATURES,
|
generated_features::FEATURES,
|
||||||
|
@ -389,7 +389,7 @@ const DEFAULT_LINT_COMPLETIONS: &[LintCompletion] = &[
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{test_utils::completion_list, CompletionKind};
|
use crate::{test_utils::completion_list, CompletionKind};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let actual = completion_list(ra_fixture, CompletionKind::Attribute);
|
let actual = completion_list(ra_fixture, CompletionKind::Attribute);
|
|
@ -4,7 +4,7 @@ use hir::{HasVisibility, Type};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::completion::{completion_context::CompletionContext, completion_item::Completions};
|
use crate::{completion_context::CompletionContext, completion_item::Completions};
|
||||||
|
|
||||||
/// Complete dot accesses, i.e. fields or methods.
|
/// Complete dot accesses, i.e. fields or methods.
|
||||||
pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
|
@ -64,7 +64,7 @@ mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::completion::{test_utils::completion_list, CompletionKind};
|
use crate::{test_utils::completion_list, CompletionKind};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let actual = completion_list(ra_fixture, CompletionKind::Reference);
|
let actual = completion_list(ra_fixture, CompletionKind::Reference);
|
|
@ -6,7 +6,7 @@ use syntax::{
|
||||||
match_ast, AstNode,
|
match_ast, AstNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions};
|
use crate::{CompletionContext, CompletionItem, CompletionKind, Completions};
|
||||||
|
|
||||||
/// Complete repeated parameters, both name and type. For example, if all
|
/// Complete repeated parameters, both name and type. For example, if all
|
||||||
/// functions in a file have a `spam: &mut Spam` parameter, a completion with
|
/// functions in a file have a `spam: &mut Spam` parameter, a completion with
|
||||||
|
@ -68,7 +68,7 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{test_utils::completion_list, CompletionKind};
|
use crate::{test_utils::completion_list, CompletionKind};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let actual = completion_list(ra_fixture, CompletionKind::Magic);
|
let actual = completion_list(ra_fixture, CompletionKind::Magic);
|
|
@ -1,11 +1,9 @@
|
||||||
//! FIXME: write short doc here
|
//! Completes keywords.
|
||||||
|
|
||||||
use syntax::{ast, SyntaxKind};
|
use syntax::{ast, SyntaxKind};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};
|
||||||
CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
// complete keyword "crate" in use stmt
|
// complete keyword "crate" in use stmt
|
||||||
|
@ -177,7 +175,7 @@ fn complete_return(
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{
|
||||||
test_utils::{check_edit, completion_list},
|
test_utils::{check_edit, completion_list},
|
||||||
CompletionKind,
|
CompletionKind,
|
||||||
};
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
//! FIXME: write short doc here
|
//! Completes macro invocations used in item position.
|
||||||
|
|
||||||
use crate::completion::{CompletionContext, Completions};
|
use crate::{CompletionContext, Completions};
|
||||||
|
|
||||||
pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
// Show only macros in top level.
|
// Show only macros in top level.
|
||||||
|
@ -17,7 +17,7 @@ pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &Compl
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{test_utils::completion_list, CompletionKind};
|
use crate::{test_utils::completion_list, CompletionKind};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let actual = completion_list(ra_fixture, CompletionKind::Reference);
|
let actual = completion_list(ra_fixture, CompletionKind::Reference);
|
|
@ -150,7 +150,7 @@ fn module_chain_to_containing_module_file(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::completion::{test_utils::completion_list, CompletionKind};
|
use crate::{test_utils::completion_list, CompletionKind};
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
|
@ -1,6 +1,6 @@
|
||||||
//! FIXME: write short doc here
|
//! Completes constats and paths in patterns.
|
||||||
|
|
||||||
use crate::completion::{CompletionContext, Completions};
|
use crate::{CompletionContext, Completions};
|
||||||
|
|
||||||
/// Completes constats and paths in patterns.
|
/// Completes constats and paths in patterns.
|
||||||
pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
|
@ -35,7 +35,7 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{test_utils::completion_list, CompletionKind};
|
use crate::{test_utils::completion_list, CompletionKind};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let actual = completion_list(ra_fixture, CompletionKind::Reference);
|
let actual = completion_list(ra_fixture, CompletionKind::Reference);
|
|
@ -1,4 +1,4 @@
|
||||||
//! FIXME: write short doc here
|
//! Postfix completions, like `Ok(10).ifl<|>` => `if let Ok() = Ok(10) { <|> }`.
|
||||||
|
|
||||||
mod format_like;
|
mod format_like;
|
||||||
|
|
||||||
|
@ -11,11 +11,9 @@ use text_edit::TextEdit;
|
||||||
|
|
||||||
use self::format_like::add_format_like_completions;
|
use self::format_like::add_format_like_completions;
|
||||||
use crate::{
|
use crate::{
|
||||||
completion::{
|
|
||||||
completion_config::SnippetCap,
|
completion_config::SnippetCap,
|
||||||
completion_context::CompletionContext,
|
completion_context::CompletionContext,
|
||||||
completion_item::{Builder, CompletionKind, Completions},
|
completion_item::{Builder, CompletionKind, Completions},
|
||||||
},
|
|
||||||
CompletionItem, CompletionItemKind,
|
CompletionItem, CompletionItemKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -263,7 +261,7 @@ fn postfix_snippet(
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{
|
||||||
test_utils::{check_edit, completion_list},
|
test_utils::{check_edit, completion_list},
|
||||||
CompletionKind,
|
CompletionKind,
|
||||||
};
|
};
|
|
@ -14,7 +14,7 @@
|
||||||
// + `logw` -> `log::warn!(...)`
|
// + `logw` -> `log::warn!(...)`
|
||||||
// + `loge` -> `log::error!(...)`
|
// + `loge` -> `log::error!(...)`
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{
|
||||||
complete_postfix::postfix_snippet, completion_config::SnippetCap,
|
complete_postfix::postfix_snippet, completion_config::SnippetCap,
|
||||||
completion_context::CompletionContext, completion_item::Completions,
|
completion_context::CompletionContext, completion_item::Completions,
|
||||||
};
|
};
|
|
@ -5,7 +5,7 @@ use rustc_hash::FxHashSet;
|
||||||
use syntax::AstNode;
|
use syntax::AstNode;
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::completion::{CompletionContext, Completions};
|
use crate::{CompletionContext, Completions};
|
||||||
|
|
||||||
pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
let path = match &ctx.path_qual {
|
let path = match &ctx.path_qual {
|
||||||
|
@ -149,7 +149,7 @@ mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{
|
||||||
test_utils::{check_edit, completion_list},
|
test_utils::{check_edit, completion_list},
|
||||||
CompletionKind,
|
CompletionKind,
|
||||||
};
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
//! Complete fields in record literals and patterns.
|
//! Complete fields in record literals and patterns.
|
||||||
use crate::completion::{CompletionContext, Completions};
|
use crate::{CompletionContext, Completions};
|
||||||
|
|
||||||
pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
|
pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
|
||||||
let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
|
let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
|
||||||
|
@ -20,7 +20,7 @@ pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{test_utils::completion_list, CompletionKind};
|
use crate::{test_utils::completion_list, CompletionKind};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let actual = completion_list(ra_fixture, CompletionKind::Reference);
|
let actual = completion_list(ra_fixture, CompletionKind::Reference);
|
|
@ -1,6 +1,6 @@
|
||||||
//! FIXME: write short doc here
|
//! This file provides snippet completions, like `pd` => `eprintln!(...)`.
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{
|
||||||
completion_config::SnippetCap, completion_item::Builder, CompletionContext, CompletionItem,
|
completion_config::SnippetCap, completion_item::Builder, CompletionContext, CompletionItem,
|
||||||
CompletionItemKind, CompletionKind, Completions,
|
CompletionItemKind, CompletionKind, Completions,
|
||||||
};
|
};
|
||||||
|
@ -71,7 +71,7 @@ fn ${1:feature}() {
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{test_utils::completion_list, CompletionKind};
|
use crate::{test_utils::completion_list, CompletionKind};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let actual = completion_list(ra_fixture, CompletionKind::Snippet);
|
let actual = completion_list(ra_fixture, CompletionKind::Snippet);
|
|
@ -35,15 +35,18 @@ use assists::utils::get_missing_assoc_items;
|
||||||
use hir::{self, HasAttrs, HasSource};
|
use hir::{self, HasAttrs, HasSource};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, edit, Impl},
|
ast::{self, edit, Impl},
|
||||||
|
display::function_declaration,
|
||||||
AstNode, SyntaxKind, SyntaxNode, TextRange, T,
|
AstNode, SyntaxKind, SyntaxNode, TextRange, T,
|
||||||
};
|
};
|
||||||
use text_edit::TextEdit;
|
use text_edit::TextEdit;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
completion::{
|
CompletionContext,
|
||||||
CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
|
CompletionItem,
|
||||||
},
|
CompletionItemKind,
|
||||||
display::function_declaration,
|
CompletionKind,
|
||||||
|
Completions,
|
||||||
|
// display::function_declaration,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
@ -237,7 +240,7 @@ fn make_const_compl_syntax(const_: &ast::Const) -> String {
|
||||||
mod tests {
|
mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{
|
||||||
test_utils::{check_edit, completion_list},
|
test_utils::{check_edit, completion_list},
|
||||||
CompletionKind,
|
CompletionKind,
|
||||||
};
|
};
|
|
@ -4,7 +4,7 @@ use hir::{Adt, ModuleDef, ScopeDef, Type};
|
||||||
use syntax::AstNode;
|
use syntax::AstNode;
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::completion::{CompletionContext, Completions};
|
use crate::{CompletionContext, Completions};
|
||||||
|
|
||||||
pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) {
|
if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) {
|
||||||
|
@ -68,7 +68,7 @@ mod tests {
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::completion::{
|
use crate::{
|
||||||
test_utils::{check_edit, completion_list},
|
test_utils::{check_edit, completion_list},
|
||||||
CompletionKind,
|
CompletionKind,
|
||||||
};
|
};
|
|
@ -1,6 +1,7 @@
|
||||||
//! FIXME: write short doc here
|
//! See `CompletionContext` structure.
|
||||||
|
|
||||||
use base_db::SourceDatabase;
|
use base_db::{FilePosition, SourceDatabase};
|
||||||
|
use call_info::ActiveParameter;
|
||||||
use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type};
|
use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type};
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
|
@ -13,8 +14,6 @@ use test_utils::mark;
|
||||||
use text_edit::Indel;
|
use text_edit::Indel;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
call_info::ActiveParameter,
|
|
||||||
completion::{
|
|
||||||
patterns::{
|
patterns::{
|
||||||
fn_is_prev, for_is_prev2, has_bind_pat_parent, has_block_expr_parent,
|
fn_is_prev, for_is_prev2, has_bind_pat_parent, has_block_expr_parent,
|
||||||
has_field_list_parent, has_impl_as_prev_sibling, has_impl_parent,
|
has_field_list_parent, has_impl_as_prev_sibling, has_impl_parent,
|
||||||
|
@ -23,8 +22,6 @@ use crate::{
|
||||||
unsafe_is_prev,
|
unsafe_is_prev,
|
||||||
},
|
},
|
||||||
CompletionConfig,
|
CompletionConfig,
|
||||||
},
|
|
||||||
FilePosition,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// `CompletionContext` is created early during completion to figure out, where
|
/// `CompletionContext` is created early during completion to figure out, where
|
|
@ -1,4 +1,4 @@
|
||||||
//! FIXME: write short doc here
|
//! See `CompletionItem` structure.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use hir::Documentation;
|
||||||
use syntax::TextRange;
|
use syntax::TextRange;
|
||||||
use text_edit::TextEdit;
|
use text_edit::TextEdit;
|
||||||
|
|
||||||
use crate::completion::completion_config::SnippetCap;
|
use crate::completion_config::SnippetCap;
|
||||||
|
|
||||||
/// `CompletionItem` describes a single completion variant in the editor pop-up.
|
/// `CompletionItem` describes a single completion variant in the editor pop-up.
|
||||||
/// It is basically a POD with various properties. To construct a
|
/// It is basically a POD with various properties. To construct a
|
||||||
|
@ -360,15 +360,15 @@ impl<'a> Into<CompletionItem> for Builder {
|
||||||
|
|
||||||
/// Represents an in-progress set of completions being built.
|
/// Represents an in-progress set of completions being built.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct Completions {
|
pub struct Completions {
|
||||||
buf: Vec<CompletionItem>,
|
buf: Vec<CompletionItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completions {
|
impl Completions {
|
||||||
pub(crate) fn add(&mut self, item: impl Into<CompletionItem>) {
|
pub fn add(&mut self, item: impl Into<CompletionItem>) {
|
||||||
self.buf.push(item.into())
|
self.buf.push(item.into())
|
||||||
}
|
}
|
||||||
pub(crate) fn add_all<I>(&mut self, items: I)
|
pub fn add_all<I>(&mut self, items: I)
|
||||||
where
|
where
|
||||||
I: IntoIterator,
|
I: IntoIterator,
|
||||||
I::Item: Into<CompletionItem>,
|
I::Item: Into<CompletionItem>,
|
File diff suppressed because one or more lines are too long
|
@ -1,3 +1,5 @@
|
||||||
|
//! `completions` crate provides utilities for generating completions of user input.
|
||||||
|
|
||||||
mod completion_config;
|
mod completion_config;
|
||||||
mod completion_item;
|
mod completion_item;
|
||||||
mod completion_context;
|
mod completion_context;
|
||||||
|
@ -21,17 +23,15 @@ mod complete_macro_in_item_position;
|
||||||
mod complete_trait_impl;
|
mod complete_trait_impl;
|
||||||
mod complete_mod;
|
mod complete_mod;
|
||||||
|
|
||||||
|
use base_db::FilePosition;
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
completion::{
|
|
||||||
completion_context::CompletionContext,
|
completion_context::CompletionContext,
|
||||||
completion_item::{CompletionKind, Completions},
|
completion_item::{CompletionKind, Completions},
|
||||||
},
|
|
||||||
FilePosition,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::completion::{
|
pub use crate::{
|
||||||
completion_config::CompletionConfig,
|
completion_config::CompletionConfig,
|
||||||
completion_item::{CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat},
|
completion_item::{CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat},
|
||||||
};
|
};
|
||||||
|
@ -105,7 +105,7 @@ pub use crate::completion::{
|
||||||
/// `foo` *should* be present among the completion variants. Filtering by
|
/// `foo` *should* be present among the completion variants. Filtering by
|
||||||
/// identifier prefix/fuzzy match should be done higher in the stack, together
|
/// identifier prefix/fuzzy match should be done higher in the stack, together
|
||||||
/// with ordering of completions (currently this is done by the client).
|
/// with ordering of completions (currently this is done by the client).
|
||||||
pub(crate) fn completions(
|
pub fn completions(
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
config: &CompletionConfig,
|
config: &CompletionConfig,
|
||||||
position: FilePosition,
|
position: FilePosition,
|
||||||
|
@ -139,8 +139,8 @@ pub(crate) fn completions(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::completion::completion_config::CompletionConfig;
|
use crate::completion_config::CompletionConfig;
|
||||||
use crate::fixture;
|
use crate::test_utils;
|
||||||
|
|
||||||
struct DetailAndDocumentation<'a> {
|
struct DetailAndDocumentation<'a> {
|
||||||
detail: &'a str,
|
detail: &'a str,
|
||||||
|
@ -148,9 +148,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) {
|
fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) {
|
||||||
let (analysis, position) = fixture::position(ra_fixture);
|
let (db, position) = test_utils::position(ra_fixture);
|
||||||
let config = CompletionConfig::default();
|
let config = CompletionConfig::default();
|
||||||
let completions = analysis.completions(&config, position).unwrap().unwrap();
|
let completions: Vec<_> = crate::completions(&db, &config, position).unwrap().into();
|
||||||
for item in completions {
|
for item in completions {
|
||||||
if item.detail() == Some(expected.detail) {
|
if item.detail() == Some(expected.detail) {
|
||||||
let opt = item.documentation();
|
let opt = item.documentation();
|
||||||
|
@ -163,14 +163,18 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_no_completion(ra_fixture: &str) {
|
fn check_no_completion(ra_fixture: &str) {
|
||||||
let (analysis, position) = fixture::position(ra_fixture);
|
let (db, position) = test_utils::position(ra_fixture);
|
||||||
let config = CompletionConfig::default();
|
let config = CompletionConfig::default();
|
||||||
analysis.completions(&config, position).unwrap();
|
|
||||||
|
|
||||||
let completions: Option<Vec<String>> = analysis
|
let completions: Option<Vec<String>> = crate::completions(&db, &config, position)
|
||||||
.completions(&config, position)
|
.and_then(|completions| {
|
||||||
.unwrap()
|
let completions: Vec<_> = completions.into();
|
||||||
.and_then(|completions| if completions.is_empty() { None } else { Some(completions) })
|
if completions.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(completions)
|
||||||
|
}
|
||||||
|
})
|
||||||
.map(|completions| {
|
.map(|completions| {
|
||||||
completions.into_iter().map(|completion| format!("{:?}", completion)).collect()
|
completions.into_iter().map(|completion| format!("{:?}", completion)).collect()
|
||||||
});
|
});
|
|
@ -9,7 +9,7 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::completion::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable};
|
use crate::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable};
|
||||||
|
|
||||||
pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool {
|
pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool {
|
||||||
not_same_range_ancestor(element)
|
not_same_range_ancestor(element)
|
|
@ -3,16 +3,17 @@
|
||||||
|
|
||||||
use hir::{HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type};
|
use hir::{HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use syntax::ast::NameOwner;
|
use syntax::{ast::NameOwner, display::*};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
completion::{
|
// display::{const_label, function_declaration, macro_label, type_label},
|
||||||
|
CompletionScore,
|
||||||
|
RootDatabase,
|
||||||
|
{
|
||||||
completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
|
completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
|
||||||
CompletionKind, Completions,
|
CompletionKind, Completions,
|
||||||
},
|
},
|
||||||
display::{const_label, function_declaration, macro_label, type_label},
|
|
||||||
CompletionScore, RootDatabase,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Completions {
|
impl Completions {
|
||||||
|
@ -487,13 +488,8 @@ mod tests {
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
completion::{
|
test_utils::{check_edit, check_edit_with_config, do_completion, get_all_completion_items},
|
||||||
test_utils::{
|
CompletionConfig, CompletionKind, CompletionScore,
|
||||||
check_edit, check_edit_with_config, do_completion, get_all_completion_items,
|
|
||||||
},
|
|
||||||
CompletionConfig, CompletionKind,
|
|
||||||
},
|
|
||||||
CompletionScore,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
|
@ -1277,7 +1273,6 @@ fn go(world: &WorldSnapshot) { go(w<|>) }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn too_many_arguments() {
|
fn too_many_arguments() {
|
||||||
mark::check!(too_many_arguments);
|
|
||||||
check_scores(
|
check_scores(
|
||||||
r#"
|
r#"
|
||||||
struct Foo;
|
struct Foo;
|
|
@ -1,15 +1,27 @@
|
||||||
//! Runs completion for testing purposes.
|
//! Runs completion for testing purposes.
|
||||||
|
|
||||||
|
use base_db::{fixture::ChangeFixture, FileLoader, FilePosition};
|
||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
|
use ide_db::RootDatabase;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use stdx::{format_to, trim_indent};
|
use stdx::{format_to, trim_indent};
|
||||||
use syntax::{AstNode, NodeOrToken, SyntaxElement};
|
use syntax::{AstNode, NodeOrToken, SyntaxElement};
|
||||||
use test_utils::assert_eq_text;
|
use test_utils::{assert_eq_text, RangeOrOffset};
|
||||||
|
|
||||||
use crate::{
|
use crate::{completion_item::CompletionKind, CompletionConfig, CompletionItem};
|
||||||
completion::{completion_item::CompletionKind, CompletionConfig},
|
|
||||||
fixture, CompletionItem,
|
/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
|
||||||
};
|
pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
|
||||||
|
let change_fixture = ChangeFixture::parse(ra_fixture);
|
||||||
|
let mut database = RootDatabase::default();
|
||||||
|
database.apply_change(change_fixture.change);
|
||||||
|
let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)");
|
||||||
|
let offset = match range_or_offset {
|
||||||
|
RangeOrOffset::Range(_) => panic!(),
|
||||||
|
RangeOrOffset::Offset(it) => it,
|
||||||
|
};
|
||||||
|
(database, FilePosition { file_id, offset })
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
|
pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
|
||||||
do_completion_with_config(CompletionConfig::default(), code, kind)
|
do_completion_with_config(CompletionConfig::default(), code, kind)
|
||||||
|
@ -79,47 +91,40 @@ pub(crate) fn check_edit_with_config(
|
||||||
ra_fixture_after: &str,
|
ra_fixture_after: &str,
|
||||||
) {
|
) {
|
||||||
let ra_fixture_after = trim_indent(ra_fixture_after);
|
let ra_fixture_after = trim_indent(ra_fixture_after);
|
||||||
let (analysis, position) = fixture::position(ra_fixture_before);
|
let (db, position) = position(ra_fixture_before);
|
||||||
let completions: Vec<CompletionItem> =
|
let completions: Vec<CompletionItem> =
|
||||||
analysis.completions(&config, position).unwrap().unwrap().into();
|
crate::completions(&db, &config, position).unwrap().into();
|
||||||
let (completion,) = completions
|
let (completion,) = completions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|it| it.lookup() == what)
|
.filter(|it| it.lookup() == what)
|
||||||
.collect_tuple()
|
.collect_tuple()
|
||||||
.unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions));
|
.unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions));
|
||||||
let mut actual = analysis.file_text(position.file_id).unwrap().to_string();
|
let mut actual = db.file_text(position.file_id).to_string();
|
||||||
completion.text_edit().apply(&mut actual);
|
completion.text_edit().apply(&mut actual);
|
||||||
assert_eq_text!(&ra_fixture_after, &actual)
|
assert_eq_text!(&ra_fixture_after, &actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
|
pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
|
||||||
let (analysis, pos) = fixture::position(code);
|
let (db, pos) = position(code);
|
||||||
analysis
|
|
||||||
.with_db(|db| {
|
let sema = Semantics::new(&db);
|
||||||
let sema = Semantics::new(db);
|
|
||||||
let original_file = sema.parse(pos.file_id);
|
let original_file = sema.parse(pos.file_id);
|
||||||
let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
|
let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
|
||||||
assert!(check(NodeOrToken::Token(token)));
|
assert!(check(NodeOrToken::Token(token)));
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_pattern_is_not_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
|
pub(crate) fn check_pattern_is_not_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
|
||||||
let (analysis, pos) = fixture::position(code);
|
let (db, pos) = position(code);
|
||||||
analysis
|
let sema = Semantics::new(&db);
|
||||||
.with_db(|db| {
|
|
||||||
let sema = Semantics::new(db);
|
|
||||||
let original_file = sema.parse(pos.file_id);
|
let original_file = sema.parse(pos.file_id);
|
||||||
let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
|
let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
|
||||||
assert!(!check(NodeOrToken::Token(token)));
|
assert!(!check(NodeOrToken::Token(token)));
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_all_completion_items(
|
pub(crate) fn get_all_completion_items(
|
||||||
config: CompletionConfig,
|
config: CompletionConfig,
|
||||||
code: &str,
|
code: &str,
|
||||||
) -> Vec<CompletionItem> {
|
) -> Vec<CompletionItem> {
|
||||||
let (analysis, position) = fixture::position(code);
|
let (db, position) = position(code);
|
||||||
analysis.completions(&config, position).unwrap().unwrap().into()
|
crate::completions(&db, &config, position).unwrap().into()
|
||||||
}
|
}
|
|
@ -30,6 +30,8 @@ profile = { path = "../profile", version = "0.0.0" }
|
||||||
test_utils = { path = "../test_utils", version = "0.0.0" }
|
test_utils = { path = "../test_utils", version = "0.0.0" }
|
||||||
assists = { path = "../assists", version = "0.0.0" }
|
assists = { path = "../assists", version = "0.0.0" }
|
||||||
ssr = { path = "../ssr", version = "0.0.0" }
|
ssr = { path = "../ssr", version = "0.0.0" }
|
||||||
|
call_info = { path = "../call_info", version = "0.0.0" }
|
||||||
|
completion = { path = "../completion", version = "0.0.0" }
|
||||||
|
|
||||||
# ide should depend only on the top-level `hir` package. if you need
|
# 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`.
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
|
use call_info::FnCallNode;
|
||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
use ide_db::RootDatabase;
|
use ide_db::RootDatabase;
|
||||||
use syntax::{ast, match_ast, AstNode, TextRange};
|
use syntax::{ast, match_ast, AstNode, TextRange};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
call_info::FnCallNode, display::ToNav, goto_definition, references, FilePosition,
|
display::ToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo,
|
||||||
NavigationTarget, RangeInfo,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
@ -4,87 +4,8 @@
|
||||||
mod navigation_target;
|
mod navigation_target;
|
||||||
mod short_label;
|
mod short_label;
|
||||||
|
|
||||||
use syntax::{
|
|
||||||
ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner},
|
|
||||||
SyntaxKind::{ATTR, COMMENT},
|
|
||||||
};
|
|
||||||
|
|
||||||
use ast::VisibilityOwner;
|
|
||||||
use stdx::format_to;
|
|
||||||
|
|
||||||
pub use navigation_target::NavigationTarget;
|
pub use navigation_target::NavigationTarget;
|
||||||
pub(crate) use navigation_target::{ToNav, TryToNav};
|
pub(crate) use navigation_target::{ToNav, TryToNav};
|
||||||
pub(crate) use short_label::ShortLabel;
|
pub(crate) use short_label::ShortLabel;
|
||||||
|
|
||||||
pub(crate) fn function_declaration(node: &ast::Fn) -> String {
|
pub(crate) use syntax::display::{function_declaration, macro_label};
|
||||||
let mut buf = String::new();
|
|
||||||
if let Some(vis) = node.visibility() {
|
|
||||||
format_to!(buf, "{} ", vis);
|
|
||||||
}
|
|
||||||
if node.async_token().is_some() {
|
|
||||||
format_to!(buf, "async ");
|
|
||||||
}
|
|
||||||
if node.const_token().is_some() {
|
|
||||||
format_to!(buf, "const ");
|
|
||||||
}
|
|
||||||
if node.unsafe_token().is_some() {
|
|
||||||
format_to!(buf, "unsafe ");
|
|
||||||
}
|
|
||||||
if let Some(abi) = node.abi() {
|
|
||||||
// Keyword `extern` is included in the string.
|
|
||||||
format_to!(buf, "{} ", abi);
|
|
||||||
}
|
|
||||||
if let Some(name) = node.name() {
|
|
||||||
format_to!(buf, "fn {}", name)
|
|
||||||
}
|
|
||||||
if let Some(type_params) = node.generic_param_list() {
|
|
||||||
format_to!(buf, "{}", type_params);
|
|
||||||
}
|
|
||||||
if let Some(param_list) = node.param_list() {
|
|
||||||
let params: Vec<String> = param_list
|
|
||||||
.self_param()
|
|
||||||
.into_iter()
|
|
||||||
.map(|self_param| self_param.to_string())
|
|
||||||
.chain(param_list.params().map(|param| param.to_string()))
|
|
||||||
.collect();
|
|
||||||
// Useful to inline parameters
|
|
||||||
format_to!(buf, "({})", params.join(", "));
|
|
||||||
}
|
|
||||||
if let Some(ret_type) = node.ret_type() {
|
|
||||||
if ret_type.ty().is_some() {
|
|
||||||
format_to!(buf, " {}", ret_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(where_clause) = node.where_clause() {
|
|
||||||
format_to!(buf, "\n{}", where_clause);
|
|
||||||
}
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn const_label(node: &ast::Const) -> String {
|
|
||||||
let label: String = node
|
|
||||||
.syntax()
|
|
||||||
.children_with_tokens()
|
|
||||||
.filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
|
|
||||||
.map(|node| node.to_string())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
label.trim().to_owned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn type_label(node: &ast::TypeAlias) -> String {
|
|
||||||
let label: String = node
|
|
||||||
.syntax()
|
|
||||||
.children_with_tokens()
|
|
||||||
.filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
|
|
||||||
.map(|node| node.to_string())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
label.trim().to_owned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
|
|
||||||
let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default();
|
|
||||||
let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
|
|
||||||
format!("{}macro_rules! {}", vis, name)
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,8 +23,6 @@ mod prime_caches;
|
||||||
mod display;
|
mod display;
|
||||||
|
|
||||||
mod call_hierarchy;
|
mod call_hierarchy;
|
||||||
mod call_info;
|
|
||||||
mod completion;
|
|
||||||
mod diagnostics;
|
mod diagnostics;
|
||||||
mod expand_macro;
|
mod expand_macro;
|
||||||
mod extend_selection;
|
mod extend_selection;
|
||||||
|
@ -65,10 +63,6 @@ use crate::display::ToNav;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
call_hierarchy::CallItem,
|
call_hierarchy::CallItem,
|
||||||
call_info::CallInfo,
|
|
||||||
completion::{
|
|
||||||
CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat,
|
|
||||||
},
|
|
||||||
diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity},
|
diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity},
|
||||||
display::NavigationTarget,
|
display::NavigationTarget,
|
||||||
expand_macro::ExpandedMacro,
|
expand_macro::ExpandedMacro,
|
||||||
|
@ -86,6 +80,10 @@ pub use crate::{
|
||||||
Highlight, HighlightModifier, HighlightModifiers, HighlightTag, HighlightedRange,
|
Highlight, HighlightModifier, HighlightModifiers, HighlightTag, HighlightedRange,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
pub use call_info::CallInfo;
|
||||||
|
pub use completion::{
|
||||||
|
CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat,
|
||||||
|
};
|
||||||
|
|
||||||
pub use assists::{
|
pub use assists::{
|
||||||
utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist,
|
utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist,
|
||||||
|
|
|
@ -3,14 +3,12 @@
|
||||||
use std::{collections::BTreeMap, convert::TryFrom};
|
use std::{collections::BTreeMap, convert::TryFrom};
|
||||||
|
|
||||||
use ast::{HasQuotes, HasStringValue};
|
use ast::{HasQuotes, HasStringValue};
|
||||||
|
use call_info::ActiveParameter;
|
||||||
use hir::Semantics;
|
use hir::Semantics;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize};
|
use syntax::{ast, AstToken, SyntaxNode, SyntaxToken, TextRange, TextSize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{Analysis, Highlight, HighlightModifier, HighlightTag, HighlightedRange, RootDatabase};
|
||||||
call_info::ActiveParameter, Analysis, Highlight, HighlightModifier, HighlightTag,
|
|
||||||
HighlightedRange, RootDatabase,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::HighlightedRangeStack;
|
use super::HighlightedRangeStack;
|
||||||
|
|
||||||
|
|
83
crates/syntax/src/display.rs
Normal file
83
crates/syntax/src/display.rs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
//! This module contains utilities for turning SyntaxNodes and HIR types
|
||||||
|
//! into types that may be used to render in a UI.
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner},
|
||||||
|
SyntaxKind::{ATTR, COMMENT},
|
||||||
|
};
|
||||||
|
|
||||||
|
use ast::VisibilityOwner;
|
||||||
|
use stdx::format_to;
|
||||||
|
|
||||||
|
pub fn function_declaration(node: &ast::Fn) -> String {
|
||||||
|
let mut buf = String::new();
|
||||||
|
if let Some(vis) = node.visibility() {
|
||||||
|
format_to!(buf, "{} ", vis);
|
||||||
|
}
|
||||||
|
if node.async_token().is_some() {
|
||||||
|
format_to!(buf, "async ");
|
||||||
|
}
|
||||||
|
if node.const_token().is_some() {
|
||||||
|
format_to!(buf, "const ");
|
||||||
|
}
|
||||||
|
if node.unsafe_token().is_some() {
|
||||||
|
format_to!(buf, "unsafe ");
|
||||||
|
}
|
||||||
|
if let Some(abi) = node.abi() {
|
||||||
|
// Keyword `extern` is included in the string.
|
||||||
|
format_to!(buf, "{} ", abi);
|
||||||
|
}
|
||||||
|
if let Some(name) = node.name() {
|
||||||
|
format_to!(buf, "fn {}", name)
|
||||||
|
}
|
||||||
|
if let Some(type_params) = node.generic_param_list() {
|
||||||
|
format_to!(buf, "{}", type_params);
|
||||||
|
}
|
||||||
|
if let Some(param_list) = node.param_list() {
|
||||||
|
let params: Vec<String> = param_list
|
||||||
|
.self_param()
|
||||||
|
.into_iter()
|
||||||
|
.map(|self_param| self_param.to_string())
|
||||||
|
.chain(param_list.params().map(|param| param.to_string()))
|
||||||
|
.collect();
|
||||||
|
// Useful to inline parameters
|
||||||
|
format_to!(buf, "({})", params.join(", "));
|
||||||
|
}
|
||||||
|
if let Some(ret_type) = node.ret_type() {
|
||||||
|
if ret_type.ty().is_some() {
|
||||||
|
format_to!(buf, " {}", ret_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(where_clause) = node.where_clause() {
|
||||||
|
format_to!(buf, "\n{}", where_clause);
|
||||||
|
}
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn const_label(node: &ast::Const) -> String {
|
||||||
|
let label: String = node
|
||||||
|
.syntax()
|
||||||
|
.children_with_tokens()
|
||||||
|
.filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
|
||||||
|
.map(|node| node.to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
label.trim().to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_label(node: &ast::TypeAlias) -> String {
|
||||||
|
let label: String = node
|
||||||
|
.syntax()
|
||||||
|
.children_with_tokens()
|
||||||
|
.filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
|
||||||
|
.map(|node| node.to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
label.trim().to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn macro_label(node: &ast::MacroCall) -> String {
|
||||||
|
let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default();
|
||||||
|
let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
|
||||||
|
format!("{}macro_rules! {}", vis, name)
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ mod ptr;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
pub mod display;
|
||||||
pub mod algo;
|
pub mod algo;
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -213,7 +213,7 @@ fn check_todo(path: &Path, text: &str) {
|
||||||
// `ast::make`.
|
// `ast::make`.
|
||||||
"ast/make.rs",
|
"ast/make.rs",
|
||||||
// The documentation in string literals may contain anything for its own purposes
|
// The documentation in string literals may contain anything for its own purposes
|
||||||
"completion/generated_features.rs",
|
"completion/src/generated_features.rs",
|
||||||
];
|
];
|
||||||
if need_todo.iter().any(|p| path.ends_with(p)) {
|
if need_todo.iter().any(|p| path.ends_with(p)) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue