aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model.rs86
-rw-r--r--crates/ra_hir/src/lib.rs13
-rw-r--r--crates/ra_hir/src/semantics.rs25
-rw-r--r--crates/ra_hir/src/source_analyzer.rs6
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs10
-rw-r--r--crates/ra_ide/src/call_hierarchy.rs10
-rw-r--r--crates/ra_ide/src/call_info.rs361
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs2
-rw-r--r--crates/ra_ide/src/completion/presentation.rs9
-rw-r--r--crates/ra_ide/src/display.rs11
-rw-r--r--crates/ra_ide/src/display/function_signature.rs61
-rw-r--r--crates/ra_ide/src/file_structure.rs (renamed from crates/ra_ide/src/display/structure.rs)0
-rw-r--r--crates/ra_ide/src/inlay_hints.rs14
-rw-r--r--crates/ra_ide/src/lib.rs37
-rw-r--r--crates/ra_proc_macro_srv/src/proc_macro/bridge/client.rs14
-rw-r--r--crates/ra_proc_macro_srv/src/proc_macro/bridge/closure.rs3
-rw-r--r--crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs8
-rw-r--r--crates/ra_proc_macro_srv/src/rustc_server.rs13
-rw-r--r--crates/rust-analyzer/src/cli.rs8
-rw-r--r--crates/rust-analyzer/src/config.rs10
-rw-r--r--crates/rust-analyzer/src/handlers.rs19
-rw-r--r--crates/rust-analyzer/src/to_proto.rs83
-rw-r--r--docs/user/manual.adoc8
23 files changed, 487 insertions, 324 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 9891b0785..eb6a14eda 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,5 +1,5 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2use std::sync::Arc; 2use std::{iter, sync::Arc};
3 3
4use arrayvec::ArrayVec; 4use arrayvec::ArrayVec;
5use either::Either; 5use either::Either;
@@ -12,6 +12,7 @@ use hir_def::{
12 import_map, 12 import_map,
13 per_ns::PerNs, 13 per_ns::PerNs,
14 resolver::{HasResolver, Resolver}, 14 resolver::{HasResolver, Resolver},
15 src::HasSource as _,
15 type_ref::{Mutability, TypeRef}, 16 type_ref::{Mutability, TypeRef},
16 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, 17 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule,
17 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, 18 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId,
@@ -25,8 +26,8 @@ use hir_expand::{
25use hir_ty::{ 26use hir_ty::{
26 autoderef, 27 autoderef,
27 display::{HirDisplayError, HirFormatter}, 28 display::{HirDisplayError, HirFormatter},
28 method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, 29 method_resolution, ApplicationTy, CallableDefId, Canonical, FnSig, GenericPredicate,
29 TraitEnvironment, Ty, TyDefId, TypeCtor, 30 InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor,
30}; 31};
31use ra_db::{CrateId, Edition, FileId}; 32use ra_db::{CrateId, Edition, FileId};
32use ra_prof::profile; 33use ra_prof::profile;
@@ -40,7 +41,7 @@ use stdx::impl_from;
40use crate::{ 41use crate::{
41 db::{DefDatabase, HirDatabase}, 42 db::{DefDatabase, HirDatabase},
42 has_source::HasSource, 43 has_source::HasSource,
43 CallableDefId, HirDisplay, InFile, Name, 44 HirDisplay, InFile, Name,
44}; 45};
45 46
46/// hir::Crate describes a single crate. It's the main interface with which 47/// hir::Crate describes a single crate. It's the main interface with which
@@ -1168,6 +1169,12 @@ impl Type {
1168 Type::new(db, krate, def, ty) 1169 Type::new(db, krate, def, ty)
1169 } 1170 }
1170 1171
1172 pub fn is_unit(&self) -> bool {
1173 matches!(
1174 self.ty.value,
1175 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { cardinality: 0 }, .. })
1176 )
1177 }
1171 pub fn is_bool(&self) -> bool { 1178 pub fn is_bool(&self) -> bool {
1172 matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) 1179 matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }))
1173 } 1180 }
@@ -1225,9 +1232,10 @@ impl Type {
1225 db.trait_solve(self.krate, goal).is_some() 1232 db.trait_solve(self.krate, goal).is_some()
1226 } 1233 }
1227 1234
1228 // FIXME: this method is broken, as it doesn't take closures into account. 1235 pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
1229 pub fn as_callable(&self) -> Option<CallableDefId> { 1236 let (id, substs) = self.ty.value.as_callable()?;
1230 Some(self.ty.value.as_callable()?.0) 1237 let sig = db.callable_item_signature(id).subst(substs);
1238 Some(Callable { ty: self.clone(), sig, id, is_bound_method: false })
1231 } 1239 }
1232 1240
1233 pub fn is_closure(&self) -> bool { 1241 pub fn is_closure(&self) -> bool {
@@ -1512,6 +1520,70 @@ impl HirDisplay for Type {
1512 } 1520 }
1513} 1521}
1514 1522
1523// FIXME: closures
1524#[derive(Debug)]
1525pub struct Callable {
1526 ty: Type,
1527 sig: FnSig,
1528 id: CallableDefId,
1529 pub(crate) is_bound_method: bool,
1530}
1531
1532pub enum CallableKind {
1533 Function(Function),
1534 TupleStruct(Struct),
1535 TupleEnumVariant(EnumVariant),
1536}
1537
1538impl Callable {
1539 pub fn kind(&self) -> CallableKind {
1540 match self.id {
1541 CallableDefId::FunctionId(it) => CallableKind::Function(it.into()),
1542 CallableDefId::StructId(it) => CallableKind::TupleStruct(it.into()),
1543 CallableDefId::EnumVariantId(it) => CallableKind::TupleEnumVariant(it.into()),
1544 }
1545 }
1546 pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
1547 let func = match self.id {
1548 CallableDefId::FunctionId(it) if self.is_bound_method => it,
1549 _ => return None,
1550 };
1551 let src = func.lookup(db.upcast()).source(db.upcast());
1552 let param_list = src.value.param_list()?;
1553 param_list.self_param()
1554 }
1555 pub fn params(
1556 &self,
1557 db: &dyn HirDatabase,
1558 ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
1559 let types = self
1560 .sig
1561 .params()
1562 .iter()
1563 .skip(if self.is_bound_method { 1 } else { 0 })
1564 .map(|ty| self.ty.derived(ty.clone()));
1565 let patterns = match self.id {
1566 CallableDefId::FunctionId(func) => {
1567 let src = func.lookup(db.upcast()).source(db.upcast());
1568 src.value.param_list().map(|param_list| {
1569 param_list
1570 .self_param()
1571 .map(|it| Some(Either::Left(it)))
1572 .filter(|_| !self.is_bound_method)
1573 .into_iter()
1574 .chain(param_list.params().map(|it| it.pat().map(Either::Right)))
1575 })
1576 }
1577 CallableDefId::StructId(_) => None,
1578 CallableDefId::EnumVariantId(_) => None,
1579 };
1580 patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
1581 }
1582 pub fn return_type(&self) -> Type {
1583 self.ty.derived(self.sig.ret().clone())
1584 }
1585}
1586
1515/// For IDE only 1587/// For IDE only
1516#[derive(Debug)] 1588#[derive(Debug)]
1517pub enum ScopeDef { 1589pub enum ScopeDef {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index cf7134923..31f3241c9 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -32,10 +32,10 @@ mod has_source;
32 32
33pub use crate::{ 33pub use crate::{
34 code_model::{ 34 code_model::{
35 Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency, 35 Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind, Const,
36 DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, GenericDef, HasAttrs, 36 Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function,
37 HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, 37 GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef,
38 Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, 38 Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
39 }, 39 },
40 has_source::HasSource, 40 has_source::HasSource,
41 semantics::{original_range, PathResolution, Semantics, SemanticsScope}, 41 semantics::{original_range, PathResolution, Semantics, SemanticsScope},
@@ -52,7 +52,8 @@ pub use hir_def::{
52 type_ref::Mutability, 52 type_ref::Mutability,
53}; 53};
54pub use hir_expand::{ 54pub use hir_expand::{
55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, 55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc,
56 MacroDefId, /* FIXME */
56 MacroFile, Origin, 57 MacroFile, Origin,
57}; 58};
58pub use hir_ty::{display::HirDisplay, CallableDefId}; 59pub use hir_ty::display::HirDisplay;
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 155b666d7..f5283ab22 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -6,7 +6,7 @@ use std::{cell::RefCell, fmt, iter::successors};
6 6
7use hir_def::{ 7use hir_def::{
8 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
9 AsMacroCall, TraitId, VariantId, 9 AsMacroCall, FunctionId, TraitId, VariantId,
10}; 10};
11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; 11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
@@ -24,8 +24,8 @@ use crate::{
24 diagnostics::Diagnostic, 24 diagnostics::Diagnostic,
25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, 26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer},
27 AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, 27 AssocItem, Callable, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module,
28 Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, 28 ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef,
29}; 29};
30use resolver::TypeNs; 30use resolver::TypeNs;
31 31
@@ -197,7 +197,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
197 } 197 }
198 198
199 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 199 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
200 self.imp.resolve_method_call(call) 200 self.imp.resolve_method_call(call).map(Function::from)
201 }
202
203 pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
204 self.imp.resolve_method_call_as_callable(call)
201 } 205 }
202 206
203 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { 207 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
@@ -385,10 +389,21 @@ impl<'db> SemanticsImpl<'db> {
385 self.analyze(param.syntax()).type_of_self(self.db, &param) 389 self.analyze(param.syntax()).type_of_self(self.db, &param)
386 } 390 }
387 391
388 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 392 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
389 self.analyze(call.syntax()).resolve_method_call(self.db, call) 393 self.analyze(call.syntax()).resolve_method_call(self.db, call)
390 } 394 }
391 395
396 fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
397 // FIXME: this erases Substs
398 let func = self.resolve_method_call(call)?;
399 let ty = self.db.value_ty(func.into());
400 let resolver = self.analyze(call.syntax()).resolver;
401 let ty = Type::new_with_resolver(self.db, &resolver, ty.value)?;
402 let mut res = ty.as_callable(self.db)?;
403 res.is_bound_method = true;
404 Some(res)
405 }
406
392 fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { 407 fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
393 self.analyze(field.syntax()).resolve_field(self.db, field) 408 self.analyze(field.syntax()).resolve_field(self.db, field)
394 } 409 }
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index ecb54f653..86a47a9e5 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -14,7 +14,7 @@ use hir_def::{
14 }, 14 },
15 expr::{ExprId, Pat, PatId}, 15 expr::{ExprId, Pat, PatId},
16 resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, 16 resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
17 AsMacroCall, DefWithBodyId, FieldId, LocalFieldId, VariantId, 17 AsMacroCall, DefWithBodyId, FieldId, FunctionId, LocalFieldId, VariantId,
18}; 18};
19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
20use hir_ty::{ 20use hir_ty::{
@@ -142,9 +142,9 @@ impl SourceAnalyzer {
142 &self, 142 &self,
143 db: &dyn HirDatabase, 143 db: &dyn HirDatabase,
144 call: &ast::MethodCallExpr, 144 call: &ast::MethodCallExpr,
145 ) -> Option<Function> { 145 ) -> Option<FunctionId> {
146 let expr_id = self.expr_id(db, &call.clone().into())?; 146 let expr_id = self.expr_id(db, &call.clone().into())?;
147 self.infer.as_ref()?.method_resolution(expr_id).map(Function::from) 147 self.infer.as_ref()?.method_resolution(expr_id)
148 } 148 }
149 149
150 pub(crate) fn resolve_field( 150 pub(crate) fn resolve_field(
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 19692e70c..dbfa7fccb 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -226,7 +226,15 @@ impl CrateDefMap {
226 match enum_data.variant(&segment) { 226 match enum_data.variant(&segment) {
227 Some(local_id) => { 227 Some(local_id) => {
228 let variant = EnumVariantId { parent: e, local_id }; 228 let variant = EnumVariantId { parent: e, local_id };
229 PerNs::both(variant.into(), variant.into(), Visibility::Public) 229 match &*enum_data.variants[local_id].variant_data {
230 crate::adt::VariantData::Record(_) => {
231 PerNs::types(variant.into(), Visibility::Public)
232 }
233 crate::adt::VariantData::Tuple(_)
234 | crate::adt::VariantData::Unit => {
235 PerNs::both(variant.into(), variant.into(), Visibility::Public)
236 }
237 }
230 } 238 }
231 None => { 239 None => {
232 return ResolvePathResult::with( 240 return ResolvePathResult::with(
diff --git a/crates/ra_ide/src/call_hierarchy.rs b/crates/ra_ide/src/call_hierarchy.rs
index cb7e62cd6..6af251d23 100644
--- a/crates/ra_ide/src/call_hierarchy.rs
+++ b/crates/ra_ide/src/call_hierarchy.rs
@@ -95,9 +95,9 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
95 if let Some(func_target) = match &call_node { 95 if let Some(func_target) = match &call_node {
96 FnCallNode::CallExpr(expr) => { 96 FnCallNode::CallExpr(expr) => {
97 //FIXME: Type::as_callable is broken 97 //FIXME: Type::as_callable is broken
98 let callable_def = sema.type_of_expr(&expr.expr()?)?.as_callable()?; 98 let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(db)?;
99 match callable_def { 99 match callable.kind() {
100 hir::CallableDefId::FunctionId(it) => { 100 hir::CallableKind::Function(it) => {
101 let fn_def: hir::Function = it.into(); 101 let fn_def: hir::Function = it.into();
102 let nav = fn_def.to_nav(db); 102 let nav = fn_def.to_nav(db);
103 Some(nav) 103 Some(nav)
@@ -109,10 +109,6 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
109 let function = sema.resolve_method_call(&expr)?; 109 let function = sema.resolve_method_call(&expr)?;
110 Some(function.to_nav(db)) 110 Some(function.to_nav(db))
111 } 111 }
112 FnCallNode::MacroCallExpr(macro_call) => {
113 let macro_def = sema.resolve_macro_call(&macro_call)?;
114 Some(macro_def.to_nav(db))
115 }
116 } { 112 } {
117 Some((func_target, name_ref.syntax().text_range())) 113 Some((func_target, name_ref.syntax().text_range()))
118 } else { 114 } else {
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs
index 1fe1c21de..35a8a0dc5 100644
--- a/crates/ra_ide/src/call_info.rs
+++ b/crates/ra_ide/src/call_info.rs
@@ -1,20 +1,42 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2use hir::Semantics; 2use either::Either;
3use hir::{Docs, HirDisplay, Semantics, Type};
3use ra_ide_db::RootDatabase; 4use ra_ide_db::RootDatabase;
4use ra_syntax::{ 5use ra_syntax::{
5 ast::{self, ArgListOwner}, 6 ast::{self, ArgListOwner},
6 match_ast, AstNode, SyntaxNode, SyntaxToken, 7 match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize,
7}; 8};
9use stdx::format_to;
8use test_utils::mark; 10use test_utils::mark;
9 11
10use crate::{FilePosition, FunctionSignature}; 12use crate::FilePosition;
11 13
12/// Contains information about a call site. Specifically the 14/// Contains information about a call site. Specifically the
13/// `FunctionSignature`and current parameter. 15/// `FunctionSignature`and current parameter.
14#[derive(Debug)] 16#[derive(Debug)]
15pub struct CallInfo { 17pub struct CallInfo {
16 pub signature: FunctionSignature, 18 pub doc: Option<String>,
19 pub signature: String,
17 pub active_parameter: Option<usize>, 20 pub active_parameter: Option<usize>,
21 parameters: Vec<TextRange>,
22}
23
24impl CallInfo {
25 pub fn parameter_labels(&self) -> impl Iterator<Item = &str> + '_ {
26 self.parameters.iter().map(move |&it| &self.signature[it])
27 }
28 pub fn parameter_ranges(&self) -> &[TextRange] {
29 &self.parameters
30 }
31 fn push_param(&mut self, param: &str) {
32 if !self.signature.ends_with('(') {
33 self.signature.push_str(", ");
34 }
35 let start = TextSize::of(&self.signature);
36 self.signature.push_str(param);
37 let end = TextSize::of(&self.signature);
38 self.parameters.push(TextRange::new(start, end))
39 }
18} 40}
19 41
20/// Computes parameter information for the given call expression. 42/// Computes parameter information for the given call expression.
@@ -24,105 +46,130 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
24 let file = file.syntax(); 46 let file = file.syntax();
25 let token = file.token_at_offset(position.offset).next()?; 47 let token = file.token_at_offset(position.offset).next()?;
26 let token = sema.descend_into_macros(token); 48 let token = sema.descend_into_macros(token);
27 call_info_for_token(&sema, token)
28}
29 49
30#[derive(Debug)] 50 let (callable, active_parameter) = call_info_impl(&sema, token)?;
31pub(crate) struct ActiveParameter {
32 /// FIXME: should be `Type` and `Name
33 pub(crate) ty: String,
34 pub(crate) name: String,
35}
36 51
37impl ActiveParameter { 52 let mut res =
38 pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> { 53 CallInfo { doc: None, signature: String::new(), parameters: vec![], active_parameter };
39 call_info(db, position)?.into_active_parameter() 54
55 match callable.kind() {
56 hir::CallableKind::Function(func) => {
57 res.doc = func.docs(db).map(|it| it.as_str().to_string());
58 format_to!(res.signature, "fn {}", func.name(db));
59 }
60 hir::CallableKind::TupleStruct(strukt) => {
61 res.doc = strukt.docs(db).map(|it| it.as_str().to_string());
62 format_to!(res.signature, "struct {}", strukt.name(db));
63 }
64 hir::CallableKind::TupleEnumVariant(variant) => {
65 res.doc = variant.docs(db).map(|it| it.as_str().to_string());
66 format_to!(
67 res.signature,
68 "enum {}::{}",
69 variant.parent_enum(db).name(db),
70 variant.name(db)
71 );
72 }
40 } 73 }
41 74
42 pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> { 75 res.signature.push('(');
43 call_info_for_token(sema, token)?.into_active_parameter() 76 {
77 if let Some(self_param) = callable.receiver_param(db) {
78 format_to!(res.signature, "{}", self_param)
79 }
80 let mut buf = String::new();
81 for (pat, ty) in callable.params(db) {
82 buf.clear();
83 if let Some(pat) = pat {
84 match pat {
85 Either::Left(_self) => format_to!(buf, "self: "),
86 Either::Right(pat) => format_to!(buf, "{}: ", pat),
87 }
88 }
89 format_to!(buf, "{}", ty.display(db));
90 res.push_param(&buf);
91 }
44 } 92 }
93 res.signature.push(')');
94
95 match callable.kind() {
96 hir::CallableKind::Function(_) => {
97 let ret_type = callable.return_type();
98 if !ret_type.is_unit() {
99 format_to!(res.signature, " -> {}", ret_type.display(db));
100 }
101 }
102 hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
103 }
104 Some(res)
45} 105}
46 106
47fn call_info_for_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<CallInfo> { 107fn call_info_impl(
108 sema: &Semantics<RootDatabase>,
109 token: SyntaxToken,
110) -> Option<(hir::Callable, Option<usize>)> {
48 // Find the calling expression and it's NameRef 111 // Find the calling expression and it's NameRef
49 let calling_node = FnCallNode::with_node(&token.parent())?; 112 let calling_node = FnCallNode::with_node(&token.parent())?;
50 113
51 let signature = match &calling_node { 114 let callable = match &calling_node {
52 FnCallNode::CallExpr(call) => { 115 FnCallNode::CallExpr(call) => sema.type_of_expr(&call.expr()?)?.as_callable(sema.db)?,
53 //FIXME: Type::as_callable is broken 116 FnCallNode::MethodCallExpr(call) => sema.resolve_method_call_as_callable(call)?,
54 let callable_def = sema.type_of_expr(&call.expr()?)?.as_callable()?; 117 };
55 match callable_def { 118 let active_param = if let Some(arg_list) = calling_node.arg_list() {
56 hir::CallableDefId::FunctionId(it) => { 119 // Number of arguments specified at the call site
57 let fn_def = it.into(); 120 let num_args_at_callsite = arg_list.args().count();
58 FunctionSignature::from_hir(sema.db, fn_def) 121
59 } 122 let arg_list_range = arg_list.syntax().text_range();
60 hir::CallableDefId::StructId(it) => { 123 if !arg_list_range.contains_inclusive(token.text_range().start()) {
61 FunctionSignature::from_struct(sema.db, it.into())? 124 mark::hit!(call_info_bad_offset);
62 } 125 return None;
63 hir::CallableDefId::EnumVariantId(it) => {
64 FunctionSignature::from_enum_variant(sema.db, it.into())?
65 }
66 }
67 }
68 FnCallNode::MethodCallExpr(method_call) => {
69 let function = sema.resolve_method_call(&method_call)?;
70 FunctionSignature::from_hir(sema.db, function)
71 }
72 FnCallNode::MacroCallExpr(macro_call) => {
73 let macro_def = sema.resolve_macro_call(&macro_call)?;
74 FunctionSignature::from_macro(sema.db, macro_def)?
75 } 126 }
127 let param = std::cmp::min(
128 num_args_at_callsite,
129 arg_list
130 .args()
131 .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
132 .count(),
133 );
134
135 Some(param)
136 } else {
137 None
76 }; 138 };
139 Some((callable, active_param))
140}
77 141
78 // If we have a calling expression let's find which argument we are on 142#[derive(Debug)]
79 let num_params = signature.parameters.len(); 143pub(crate) struct ActiveParameter {
80 144 pub(crate) ty: Type,
81 let active_parameter = match num_params { 145 pub(crate) name: String,
82 0 => None, 146}
83 1 if signature.has_self_param => None,
84 1 => Some(0),
85 _ => {
86 if let Some(arg_list) = calling_node.arg_list() {
87 // Number of arguments specified at the call site
88 let num_args_at_callsite = arg_list.args().count();
89
90 let arg_list_range = arg_list.syntax().text_range();
91 if !arg_list_range.contains_inclusive(token.text_range().start()) {
92 mark::hit!(call_info_bad_offset);
93 return None;
94 }
95 147
96 let mut param = std::cmp::min( 148impl ActiveParameter {
97 num_args_at_callsite, 149 pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> {
98 arg_list 150 let sema = Semantics::new(db);
99 .args() 151 let file = sema.parse(position.file_id);
100 .take_while(|arg| { 152 let file = file.syntax();
101 arg.syntax().text_range().end() <= token.text_range().start() 153 let token = file.token_at_offset(position.offset).next()?;
102 }) 154 let token = sema.descend_into_macros(token);
103 .count(), 155 Self::at_token(&sema, token)
104 ); 156 }
105
106 // If we are in a method account for `self`
107 if signature.has_self_param {
108 param += 1;
109 }
110 157
111 Some(param) 158 pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> {
112 } else { 159 let (signature, active_parameter) = call_info_impl(&sema, token)?;
113 None
114 }
115 }
116 };
117 160
118 Some(CallInfo { signature, active_parameter }) 161 let idx = active_parameter?;
162 let mut params = signature.params(sema.db);
163 let (pat, ty) = params.swap_remove(idx);
164 let name = pat?.to_string();
165 Some(ActiveParameter { ty, name })
166 }
119} 167}
120 168
121#[derive(Debug)] 169#[derive(Debug)]
122pub(crate) enum FnCallNode { 170pub(crate) enum FnCallNode {
123 CallExpr(ast::CallExpr), 171 CallExpr(ast::CallExpr),
124 MethodCallExpr(ast::MethodCallExpr), 172 MethodCallExpr(ast::MethodCallExpr),
125 MacroCallExpr(ast::MacroCall),
126} 173}
127 174
128impl FnCallNode { 175impl FnCallNode {
@@ -138,7 +185,6 @@ impl FnCallNode {
138 } 185 }
139 Some(FnCallNode::MethodCallExpr(it)) 186 Some(FnCallNode::MethodCallExpr(it))
140 }, 187 },
141 ast::MacroCall(it) => Some(FnCallNode::MacroCallExpr(it)),
142 _ => None, 188 _ => None,
143 } 189 }
144 } 190 }
@@ -150,7 +196,6 @@ impl FnCallNode {
150 match node { 196 match node {
151 ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), 197 ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)),
152 ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)), 198 ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)),
153 ast::MacroCall(it) => Some(FnCallNode::MacroCallExpr(it)),
154 _ => None, 199 _ => None,
155 } 200 }
156 } 201 }
@@ -166,8 +211,6 @@ impl FnCallNode {
166 FnCallNode::MethodCallExpr(call_expr) => { 211 FnCallNode::MethodCallExpr(call_expr) => {
167 call_expr.syntax().children().filter_map(ast::NameRef::cast).next() 212 call_expr.syntax().children().filter_map(ast::NameRef::cast).next()
168 } 213 }
169
170 FnCallNode::MacroCallExpr(call_expr) => call_expr.path()?.segment()?.name_ref(),
171 } 214 }
172 } 215 }
173 216
@@ -175,21 +218,10 @@ impl FnCallNode {
175 match self { 218 match self {
176 FnCallNode::CallExpr(expr) => expr.arg_list(), 219 FnCallNode::CallExpr(expr) => expr.arg_list(),
177 FnCallNode::MethodCallExpr(expr) => expr.arg_list(), 220 FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
178 FnCallNode::MacroCallExpr(_) => None,
179 } 221 }
180 } 222 }
181} 223}
182 224
183impl CallInfo {
184 fn into_active_parameter(self) -> Option<ActiveParameter> {
185 let idx = self.active_parameter?;
186 let ty = self.signature.parameter_types.get(idx)?.clone();
187 let name = self.signature.parameter_names.get(idx)?.clone();
188 let res = ActiveParameter { ty, name };
189 Some(res)
190 }
191}
192
193#[cfg(test)] 225#[cfg(test)]
194mod tests { 226mod tests {
195 use expect::{expect, Expect}; 227 use expect::{expect, Expect};
@@ -202,20 +234,18 @@ mod tests {
202 let call_info = analysis.call_info(position).unwrap(); 234 let call_info = analysis.call_info(position).unwrap();
203 let actual = match call_info { 235 let actual = match call_info {
204 Some(call_info) => { 236 Some(call_info) => {
205 let docs = match &call_info.signature.doc { 237 let docs = match &call_info.doc {
206 None => "".to_string(), 238 None => "".to_string(),
207 Some(docs) => format!("{}\n------\n", docs.as_str()), 239 Some(docs) => format!("{}\n------\n", docs.as_str()),
208 }; 240 };
209 let params = call_info 241 let params = call_info
210 .signature 242 .parameter_labels()
211 .parameters
212 .iter()
213 .enumerate() 243 .enumerate()
214 .map(|(i, param)| { 244 .map(|(i, param)| {
215 if Some(i) == call_info.active_parameter { 245 if Some(i) == call_info.active_parameter {
216 format!("<{}>", param) 246 format!("<{}>", param)
217 } else { 247 } else {
218 param.clone() 248 param.to_string()
219 } 249 }
220 }) 250 })
221 .collect::<Vec<_>>() 251 .collect::<Vec<_>>()
@@ -296,10 +326,8 @@ fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
296fn bar() { foo(<|>3, ); } 326fn bar() { foo(<|>3, ); }
297"#, 327"#,
298 expect![[r#" 328 expect![[r#"
299 fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 329 fn foo(x: i32, y: {unknown}) -> u32
300 where T: Copy + Display, 330 (<x: i32>, y: {unknown})
301 U: Debug
302 (<x: T>, y: U)
303 "#]], 331 "#]],
304 ); 332 );
305 } 333 }
@@ -312,8 +340,7 @@ fn foo<T>() -> T where T: Copy + Display {}
312fn bar() { foo(<|>); } 340fn bar() { foo(<|>); }
313"#, 341"#,
314 expect![[r#" 342 expect![[r#"
315 fn foo<T>() -> T 343 fn foo() -> {unknown}
316 where T: Copy + Display
317 () 344 ()
318 "#]], 345 "#]],
319 ); 346 );
@@ -323,11 +350,14 @@ fn bar() { foo(<|>); }
323 fn test_fn_signature_for_impl() { 350 fn test_fn_signature_for_impl() {
324 check( 351 check(
325 r#" 352 r#"
326struct F; impl F { pub fn new() { F{}} } 353struct F;
327fn bar() {let _ : F = F::new(<|>);} 354impl F { pub fn new() { } }
355fn bar() {
356 let _ : F = F::new(<|>);
357}
328"#, 358"#,
329 expect![[r#" 359 expect![[r#"
330 pub fn new() 360 fn new()
331 () 361 ()
332 "#]], 362 "#]],
333 ); 363 );
@@ -346,8 +376,8 @@ fn bar() {
346} 376}
347"#, 377"#,
348 expect![[r#" 378 expect![[r#"
349 pub fn do_it(&self) 379 fn do_it(&self)
350 (&self) 380 ()
351 "#]], 381 "#]],
352 ); 382 );
353 } 383 }
@@ -357,16 +387,33 @@ fn bar() {
357 check( 387 check(
358 r#" 388 r#"
359struct S; 389struct S;
360impl S { pub fn do_it(&self, x: i32) {} } 390impl S {
391 fn foo(&self, x: i32) {}
392}
361 393
362fn bar() { 394fn main() { S.foo(<|>); }
363 let s: S = S; 395"#,
364 s.do_it(<|>); 396 expect![[r#"
397 fn foo(&self, x: i32)
398 (<x: i32>)
399 "#]],
400 );
401 }
402
403 #[test]
404 fn test_fn_signature_for_method_with_arg_as_assoc_fn() {
405 check(
406 r#"
407struct S;
408impl S {
409 fn foo(&self, x: i32) {}
365} 410}
411
412fn main() { S::foo(<|>); }
366"#, 413"#,
367 expect![[r#" 414 expect![[r#"
368 pub fn do_it(&self, x: i32) 415 fn foo(self: &S, x: i32)
369 (&self, <x: i32>) 416 (<self: &S>, x: i32)
370 "#]], 417 "#]],
371 ); 418 );
372 } 419 }
@@ -425,7 +472,7 @@ pub fn do() {
425 assert_eq!(6, my_crate::add_one(5)); 472 assert_eq!(6, my_crate::add_one(5));
426 ``` 473 ```
427 ------ 474 ------
428 pub fn add_one(x: i32) -> i32 475 fn add_one(x: i32) -> i32
429 (<x: i32>) 476 (<x: i32>)
430 "##]], 477 "##]],
431 ); 478 );
@@ -467,7 +514,7 @@ pub fn do_it() {
467 assert_eq!(6, my_crate::add_one(5)); 514 assert_eq!(6, my_crate::add_one(5));
468 ``` 515 ```
469 ------ 516 ------
470 pub fn add_one(x: i32) -> i32 517 fn add_one(x: i32) -> i32
471 (<x: i32>) 518 (<x: i32>)
472 "##]], 519 "##]],
473 ); 520 );
@@ -505,8 +552,8 @@ pub fn foo(mut r: WriteHandler<()>) {
505 552
506 By default this method stops actor's `Context`. 553 By default this method stops actor's `Context`.
507 ------ 554 ------
508 fn finished(&mut self, ctx: &mut Self::Context) 555 fn finished(&mut self, ctx: &mut {unknown})
509 (&mut self, <ctx: &mut Self::Context>) 556 (<ctx: &mut {unknown}>)
510 "#]], 557 "#]],
511 ); 558 );
512 } 559 }
@@ -539,7 +586,7 @@ fn main() {
539"#, 586"#,
540 expect![[r#" 587 expect![[r#"
541 fn bar(&self, _: u32) 588 fn bar(&self, _: u32)
542 (&self, <_: u32>) 589 (<_: u32>)
543 "#]], 590 "#]],
544 ); 591 );
545 } 592 }
@@ -549,15 +596,15 @@ fn main() {
549 check( 596 check(
550 r#" 597 r#"
551/// A cool tuple struct 598/// A cool tuple struct
552struct TS(u32, i32); 599struct S(u32, i32);
553fn main() { 600fn main() {
554 let s = TS(0, <|>); 601 let s = S(0, <|>);
555} 602}
556"#, 603"#,
557 expect![[r#" 604 expect![[r#"
558 A cool tuple struct 605 A cool tuple struct
559 ------ 606 ------
560 struct TS(u32, i32) -> TS 607 struct S(u32, i32)
561 (u32, <i32>) 608 (u32, <i32>)
562 "#]], 609 "#]],
563 ); 610 );
@@ -567,32 +614,19 @@ fn main() {
567 fn generic_struct() { 614 fn generic_struct() {
568 check( 615 check(
569 r#" 616 r#"
570struct TS<T>(T); 617struct S<T>(T);
571fn main() { 618fn main() {
572 let s = TS(<|>); 619 let s = S(<|>);
573} 620}
574"#, 621"#,
575 expect![[r#" 622 expect![[r#"
576 struct TS<T>(T) -> TS 623 struct S({unknown})
577 (<T>) 624 (<{unknown}>)
578 "#]], 625 "#]],
579 ); 626 );
580 } 627 }
581 628
582 #[test] 629 #[test]
583 fn cant_call_named_structs() {
584 check(
585 r#"
586struct TS { x: u32, y: i32 }
587fn main() {
588 let s = TS(<|>);
589}
590"#,
591 expect![[""]],
592 );
593 }
594
595 #[test]
596 fn works_for_enum_variants() { 630 fn works_for_enum_variants() {
597 check( 631 check(
598 r#" 632 r#"
@@ -612,27 +646,19 @@ fn main() {
612 expect![[r#" 646 expect![[r#"
613 A Variant 647 A Variant
614 ------ 648 ------
615 E::A(0: i32) 649 enum E::A(i32)
616 (<0: i32>) 650 (<i32>)
617 "#]], 651 "#]],
618 ); 652 );
619 } 653 }
620 654
621 #[test] 655 #[test]
622 fn cant_call_enum_records() { 656 fn cant_call_struct_record() {
623 check( 657 check(
624 r#" 658 r#"
625enum E { 659struct S { x: u32, y: i32 }
626 /// A Variant
627 A(i32),
628 /// Another
629 B,
630 /// And C
631 C { a: i32, b: i32 }
632}
633
634fn main() { 660fn main() {
635 let a = E::C(<|>); 661 let s = S(<|>);
636} 662}
637"#, 663"#,
638 expect![[""]], 664 expect![[""]],
@@ -640,24 +666,23 @@ fn main() {
640 } 666 }
641 667
642 #[test] 668 #[test]
643 fn fn_signature_for_macro() { 669 fn cant_call_enum_record() {
644 check( 670 check(
645 r#" 671 r#"
646/// empty macro 672enum E {
647macro_rules! foo { 673 /// A Variant
648 () => {} 674 A(i32),
675 /// Another
676 B,
677 /// And C
678 C { a: i32, b: i32 }
649} 679}
650 680
651fn f() { 681fn main() {
652 foo!(<|>); 682 let a = E::C(<|>);
653} 683}
654"#, 684"#,
655 expect![[r#" 685 expect![[""]],
656 empty macro
657 ------
658 foo!()
659 ()
660 "#]],
661 ); 686 );
662 } 687 }
663 688
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs
index a610fd6d1..90f5b1c25 100644
--- a/crates/ra_ide/src/completion/complete_trait_impl.rs
+++ b/crates/ra_ide/src/completion/complete_trait_impl.rs
@@ -43,7 +43,7 @@ use crate::{
43 completion::{ 43 completion::{
44 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, 44 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
45 }, 45 },
46 display::FunctionSignature, 46 display::function_signature::FunctionSignature,
47}; 47};
48 48
49pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { 49pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 64349dcb8..e29b82017 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -11,7 +11,7 @@ use crate::{
11 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, 11 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
12 CompletionKind, Completions, 12 CompletionKind, Completions,
13 }, 13 },
14 display::{const_label, macro_label, type_label, FunctionSignature}, 14 display::{const_label, function_signature::FunctionSignature, macro_label, type_label},
15 CompletionScore, RootDatabase, 15 CompletionScore, RootDatabase,
16}; 16};
17 17
@@ -329,15 +329,10 @@ pub(crate) fn compute_score(
329 ty: &Type, 329 ty: &Type,
330 name: &str, 330 name: &str,
331) -> Option<CompletionScore> { 331) -> Option<CompletionScore> {
332 // FIXME: this should not fall back to string equality.
333 let ty = &ty.display(ctx.db).to_string();
334 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { 332 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
335 mark::hit!(record_field_type_match); 333 mark::hit!(record_field_type_match);
336 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; 334 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?;
337 ( 335 (struct_field.name(ctx.db).to_string(), struct_field.signature_ty(ctx.db))
338 struct_field.name(ctx.db).to_string(),
339 struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
340 )
341 } else if let Some(active_parameter) = &ctx.active_parameter { 336 } else if let Some(active_parameter) = &ctx.active_parameter {
342 mark::hit!(active_param_type_match); 337 mark::hit!(active_param_type_match);
343 (active_parameter.name.clone(), active_parameter.ty.clone()) 338 (active_parameter.name.clone(), active_parameter.ty.clone())
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs
index 70d2a2dd1..1ec946369 100644
--- a/crates/ra_ide/src/display.rs
+++ b/crates/ra_ide/src/display.rs
@@ -1,9 +1,8 @@
1//! This module contains utilities for turning SyntaxNodes and HIR types 1//! This module contains utilities for turning SyntaxNodes and HIR types
2//! into types that may be used to render in a UI. 2//! into types that may be used to render in a UI.
3 3
4mod function_signature; 4pub(crate) mod function_signature;
5mod navigation_target; 5mod navigation_target;
6mod structure;
7mod short_label; 6mod short_label;
8 7
9use ra_syntax::{ 8use ra_syntax::{
@@ -11,15 +10,13 @@ use ra_syntax::{
11 SyntaxKind::{ATTR, COMMENT}, 10 SyntaxKind::{ATTR, COMMENT},
12}; 11};
13 12
14pub use function_signature::FunctionSignature;
15pub use navigation_target::NavigationTarget;
16pub use structure::{file_structure, StructureNode};
17
18pub(crate) use navigation_target::{ToNav, TryToNav}; 13pub(crate) use navigation_target::{ToNav, TryToNav};
19pub(crate) use short_label::ShortLabel; 14pub(crate) use short_label::ShortLabel;
20 15
16pub use navigation_target::NavigationTarget;
17
21pub(crate) fn function_label(node: &ast::FnDef) -> String { 18pub(crate) fn function_label(node: &ast::FnDef) -> String {
22 FunctionSignature::from(node).to_string() 19 function_signature::FunctionSignature::from(node).to_string()
23} 20}
24 21
25pub(crate) fn const_label(node: &ast::ConstDef) -> String { 22pub(crate) fn const_label(node: &ast::ConstDef) -> String {
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs
index 1d39544d3..9b7220d1f 100644
--- a/crates/ra_ide/src/display/function_signature.rs
+++ b/crates/ra_ide/src/display/function_signature.rs
@@ -15,49 +15,48 @@ use stdx::{split_delim, SepBy};
15use crate::display::{generic_parameters, where_predicates}; 15use crate::display::{generic_parameters, where_predicates};
16 16
17#[derive(Debug)] 17#[derive(Debug)]
18pub enum CallableKind { 18pub(crate) enum CallableKind {
19 Function, 19 Function,
20 StructConstructor, 20 StructConstructor,
21 VariantConstructor, 21 VariantConstructor,
22 Macro,
23} 22}
24 23
25/// Contains information about a function signature 24/// Contains information about a function signature
26#[derive(Debug)] 25#[derive(Debug)]
27pub struct FunctionSignature { 26pub(crate) struct FunctionSignature {
28 pub kind: CallableKind, 27 pub(crate) kind: CallableKind,
29 /// Optional visibility 28 /// Optional visibility
30 pub visibility: Option<String>, 29 pub(crate) visibility: Option<String>,
31 /// Qualifiers like `async`, `unsafe`, ... 30 /// Qualifiers like `async`, `unsafe`, ...
32 pub qualifier: FunctionQualifier, 31 pub(crate) qualifier: FunctionQualifier,
33 /// Name of the function 32 /// Name of the function
34 pub name: Option<String>, 33 pub(crate) name: Option<String>,
35 /// Documentation for the function 34 /// Documentation for the function
36 pub doc: Option<Documentation>, 35 pub(crate) doc: Option<Documentation>,
37 /// Generic parameters 36 /// Generic parameters
38 pub generic_parameters: Vec<String>, 37 pub(crate) generic_parameters: Vec<String>,
39 /// Parameters of the function 38 /// Parameters of the function
40 pub parameters: Vec<String>, 39 pub(crate) parameters: Vec<String>,
41 /// Parameter names of the function 40 /// Parameter names of the function
42 pub parameter_names: Vec<String>, 41 pub(crate) parameter_names: Vec<String>,
43 /// Parameter types of the function 42 /// Parameter types of the function
44 pub parameter_types: Vec<String>, 43 pub(crate) parameter_types: Vec<String>,
45 /// Optional return type 44 /// Optional return type
46 pub ret_type: Option<String>, 45 pub(crate) ret_type: Option<String>,
47 /// Where predicates 46 /// Where predicates
48 pub where_predicates: Vec<String>, 47 pub(crate) where_predicates: Vec<String>,
49 /// Self param presence 48 /// Self param presence
50 pub has_self_param: bool, 49 pub(crate) has_self_param: bool,
51} 50}
52 51
53#[derive(Debug, Default)] 52#[derive(Debug, Default)]
54pub struct FunctionQualifier { 53pub(crate) struct FunctionQualifier {
55 // `async` and `const` are mutually exclusive. Do we need to enforcing it here? 54 // `async` and `const` are mutually exclusive. Do we need to enforcing it here?
56 pub is_async: bool, 55 pub(crate) is_async: bool,
57 pub is_const: bool, 56 pub(crate) is_const: bool,
58 pub is_unsafe: bool, 57 pub(crate) is_unsafe: bool,
59 /// The string `extern ".."` 58 /// The string `extern ".."`
60 pub extern_abi: Option<String>, 59 pub(crate) extern_abi: Option<String>,
61} 60}
62 61
63impl FunctionSignature { 62impl FunctionSignature {
@@ -149,27 +148,6 @@ impl FunctionSignature {
149 has_self_param: false, 148 has_self_param: false,
150 }) 149 })
151 } 150 }
152
153 pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
154 let node: ast::MacroCall = macro_def.source(db).value;
155
156 let params = vec![];
157
158 Some(FunctionSignature {
159 kind: CallableKind::Macro,
160 visibility: None,
161 qualifier: Default::default(),
162 name: node.name().map(|n| n.text().to_string()),
163 ret_type: None,
164 parameters: params,
165 parameter_names: vec![],
166 parameter_types: vec![],
167 generic_parameters: vec![],
168 where_predicates: vec![],
169 doc: macro_def.docs(db),
170 has_self_param: false,
171 })
172 }
173} 151}
174 152
175impl From<&'_ ast::FnDef> for FunctionSignature { 153impl From<&'_ ast::FnDef> for FunctionSignature {
@@ -298,7 +276,6 @@ impl Display for FunctionSignature {
298 CallableKind::Function => write!(f, "fn {}", name)?, 276 CallableKind::Function => write!(f, "fn {}", name)?,
299 CallableKind::StructConstructor => write!(f, "struct {}", name)?, 277 CallableKind::StructConstructor => write!(f, "struct {}", name)?,
300 CallableKind::VariantConstructor => write!(f, "{}", name)?, 278 CallableKind::VariantConstructor => write!(f, "{}", name)?,
301 CallableKind::Macro => write!(f, "{}!", name)?,
302 } 279 }
303 } 280 }
304 281
diff --git a/crates/ra_ide/src/display/structure.rs b/crates/ra_ide/src/file_structure.rs
index 1f6a3febf..1f6a3febf 100644
--- a/crates/ra_ide/src/display/structure.rs
+++ b/crates/ra_ide/src/file_structure.rs
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 3cbae8a45..ae5695f61 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -5,10 +5,10 @@ use ra_syntax::{
5 ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, 5 ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner},
6 match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T, 6 match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T,
7}; 7};
8
9use crate::{FileId, FunctionSignature};
10use stdx::to_lower_snake_case; 8use stdx::to_lower_snake_case;
11 9
10use crate::{display::function_signature::FunctionSignature, FileId};
11
12#[derive(Clone, Debug, PartialEq, Eq)] 12#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct InlayHintsConfig { 13pub struct InlayHintsConfig {
14 pub type_hints: bool, 14 pub type_hints: bool,
@@ -322,15 +322,15 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<
322 match expr { 322 match expr {
323 ast::Expr::CallExpr(expr) => { 323 ast::Expr::CallExpr(expr) => {
324 // FIXME: Type::as_callable is broken for closures 324 // FIXME: Type::as_callable is broken for closures
325 let callable_def = sema.type_of_expr(&expr.expr()?)?.as_callable()?; 325 let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(sema.db)?;
326 match callable_def { 326 match callable.kind() {
327 hir::CallableDefId::FunctionId(it) => { 327 hir::CallableKind::Function(it) => {
328 Some(FunctionSignature::from_hir(sema.db, it.into())) 328 Some(FunctionSignature::from_hir(sema.db, it.into()))
329 } 329 }
330 hir::CallableDefId::StructId(it) => { 330 hir::CallableKind::TupleStruct(it) => {
331 FunctionSignature::from_struct(sema.db, it.into()) 331 FunctionSignature::from_struct(sema.db, it.into())
332 } 332 }
333 hir::CallableDefId::EnumVariantId(it) => { 333 hir::CallableKind::TupleEnumVariant(it) => {
334 FunctionSignature::from_enum_variant(sema.db, it.into()) 334 FunctionSignature::from_enum_variant(sema.db, it.into())
335 } 335 }
336 } 336 }
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 5d1f64e19..d3b20f371 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -19,29 +19,31 @@ pub mod mock_analysis;
19 19
20mod markup; 20mod markup;
21mod prime_caches; 21mod prime_caches;
22mod status; 22mod display;
23
24mod call_hierarchy;
25mod call_info;
23mod completion; 26mod completion;
24mod runnables; 27mod diagnostics;
28mod expand_macro;
29mod extend_selection;
30mod file_structure;
31mod folding_ranges;
25mod goto_definition; 32mod goto_definition;
26mod goto_type_definition;
27mod goto_implementation; 33mod goto_implementation;
28mod extend_selection; 34mod goto_type_definition;
29mod hover; 35mod hover;
30mod call_hierarchy; 36mod inlay_hints;
31mod call_info; 37mod join_lines;
32mod syntax_highlighting; 38mod matching_brace;
33mod parent_module; 39mod parent_module;
34mod references; 40mod references;
35mod diagnostics; 41mod runnables;
42mod ssr;
43mod status;
44mod syntax_highlighting;
36mod syntax_tree; 45mod syntax_tree;
37mod folding_ranges;
38mod join_lines;
39mod typing; 46mod typing;
40mod matching_brace;
41mod display;
42mod inlay_hints;
43mod expand_macro;
44mod ssr;
45 47
46use std::sync::Arc; 48use std::sync::Arc;
47 49
@@ -65,8 +67,9 @@ pub use crate::{
65 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, 67 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat,
66 }, 68 },
67 diagnostics::Severity, 69 diagnostics::Severity,
68 display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, 70 display::NavigationTarget,
69 expand_macro::ExpandedMacro, 71 expand_macro::ExpandedMacro,
72 file_structure::StructureNode,
70 folding_ranges::{Fold, FoldKind}, 73 folding_ranges::{Fold, FoldKind},
71 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, 74 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
72 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, 75 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
@@ -323,7 +326,7 @@ impl Analysis {
323 /// Returns a tree representation of symbols in the file. Useful to draw a 326 /// Returns a tree representation of symbols in the file. Useful to draw a
324 /// file outline. 327 /// file outline.
325 pub fn file_structure(&self, file_id: FileId) -> Cancelable<Vec<StructureNode>> { 328 pub fn file_structure(&self, file_id: FileId) -> Cancelable<Vec<StructureNode>> {
326 self.with_db(|db| file_structure(&db.parse(file_id).tree())) 329 self.with_db(|db| file_structure::file_structure(&db.parse(file_id).tree()))
327 } 330 }
328 331
329 /// Returns a list of the places in the file where type hints can be displayed. 332 /// Returns a list of the places in the file where type hints can be displayed.
diff --git a/crates/ra_proc_macro_srv/src/proc_macro/bridge/client.rs b/crates/ra_proc_macro_srv/src/proc_macro/bridge/client.rs
index 4b5dc7fd0..cb4b3bdb0 100644
--- a/crates/ra_proc_macro_srv/src/proc_macro/bridge/client.rs
+++ b/crates/ra_proc_macro_srv/src/proc_macro/bridge/client.rs
@@ -18,7 +18,7 @@ macro_rules! define_handles {
18 } 18 }
19 19
20 impl HandleCounters { 20 impl HandleCounters {
21 // FIXME(eddyb) use a reference to the `static COUNTERS`, intead of 21 // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
22 // a wrapper `fn` pointer, once `const fn` can reference `static`s. 22 // a wrapper `fn` pointer, once `const fn` can reference `static`s.
23 extern "C" fn get() -> &'static Self { 23 extern "C" fn get() -> &'static Self {
24 static COUNTERS: HandleCounters = HandleCounters { 24 static COUNTERS: HandleCounters = HandleCounters {
@@ -205,10 +205,16 @@ impl Clone for Literal {
205 } 205 }
206} 206}
207 207
208// FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
209impl fmt::Debug for Literal { 208impl fmt::Debug for Literal {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 f.write_str(&self.debug()) 210 f.debug_struct("Literal")
211 // format the kind without quotes, as in `kind: Float`
212 // .field("kind", &format_args!("{}", &self.debug_kind()))
213 .field("symbol", &self.symbol())
214 // format `Some("...")` on one line even in {:#?} mode
215 // .field("suffix", &format_args!("{:?}", &self.suffix()))
216 .field("span", &self.span())
217 .finish()
212 } 218 }
213} 219}
214 220
@@ -339,7 +345,7 @@ impl Bridge<'_> {
339#[repr(C)] 345#[repr(C)]
340#[derive(Copy, Clone)] 346#[derive(Copy, Clone)]
341pub struct Client<F> { 347pub struct Client<F> {
342 // FIXME(eddyb) use a reference to the `static COUNTERS`, intead of 348 // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
343 // a wrapper `fn` pointer, once `const fn` can reference `static`s. 349 // a wrapper `fn` pointer, once `const fn` can reference `static`s.
344 pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters, 350 pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
345 pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer<u8>, 351 pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer<u8>,
diff --git a/crates/ra_proc_macro_srv/src/proc_macro/bridge/closure.rs b/crates/ra_proc_macro_srv/src/proc_macro/bridge/closure.rs
index b8addff4a..273a97715 100644
--- a/crates/ra_proc_macro_srv/src/proc_macro/bridge/closure.rs
+++ b/crates/ra_proc_macro_srv/src/proc_macro/bridge/closure.rs
@@ -11,6 +11,9 @@ pub struct Closure<'a, A, R> {
11 11
12struct Env; 12struct Env;
13 13
14// impl<'a, A, R> !Sync for Closure<'a, A, R> {}
15// impl<'a, A, R> !Send for Closure<'a, A, R> {}
16
14impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> { 17impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> {
15 fn from(f: &'a mut F) -> Self { 18 fn from(f: &'a mut F) -> Self {
16 unsafe extern "C" fn call<A, R, F: FnMut(A) -> R>(env: &mut Env, arg: A) -> R { 19 unsafe extern "C" fn call<A, R, F: FnMut(A) -> R>(env: &mut Env, arg: A) -> R {
diff --git a/crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs b/crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs
index 6ae3926b2..aeb05aad4 100644
--- a/crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs
+++ b/crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs
@@ -108,8 +108,9 @@ macro_rules! with_api {
108 Literal { 108 Literal {
109 fn drop($self: $S::Literal); 109 fn drop($self: $S::Literal);
110 fn clone($self: &$S::Literal) -> $S::Literal; 110 fn clone($self: &$S::Literal) -> $S::Literal;
111 // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. 111 fn debug_kind($self: &$S::Literal) -> String;
112 fn debug($self: &$S::Literal) -> String; 112 fn symbol($self: &$S::Literal) -> String;
113 fn suffix($self: &$S::Literal) -> Option<String>;
113 fn integer(n: &str) -> $S::Literal; 114 fn integer(n: &str) -> $S::Literal;
114 fn typed_integer(n: &str, kind: &str) -> $S::Literal; 115 fn typed_integer(n: &str, kind: &str) -> $S::Literal;
115 fn float(n: &str) -> $S::Literal; 116 fn float(n: &str) -> $S::Literal;
@@ -222,6 +223,9 @@ pub struct Bridge<'a> {
222 dispatch: closure::Closure<'a, Buffer<u8>, Buffer<u8>>, 223 dispatch: closure::Closure<'a, Buffer<u8>, Buffer<u8>>,
223} 224}
224 225
226// impl<'a> !Sync for Bridge<'a> {}
227// impl<'a> !Send for Bridge<'a> {}
228
225#[forbid(unsafe_code)] 229#[forbid(unsafe_code)]
226#[allow(non_camel_case_types)] 230#[allow(non_camel_case_types)]
227mod api_tags { 231mod api_tags {
diff --git a/crates/ra_proc_macro_srv/src/rustc_server.rs b/crates/ra_proc_macro_srv/src/rustc_server.rs
index f481d70b2..cc32d5a6d 100644
--- a/crates/ra_proc_macro_srv/src/rustc_server.rs
+++ b/crates/ra_proc_macro_srv/src/rustc_server.rs
@@ -463,9 +463,16 @@ impl server::Ident for Rustc {
463} 463}
464 464
465impl server::Literal for Rustc { 465impl server::Literal for Rustc {
466 // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. 466 fn debug_kind(&mut self, _literal: &Self::Literal) -> String {
467 fn debug(&mut self, literal: &Self::Literal) -> String { 467 // r-a: debug_kind and suffix are unsupported; corresponding client code has been changed to not call these.
468 format!("{:?}", literal) 468 // They must still be present to be ABI-compatible and work with upstream proc_macro.
469 "".to_owned()
470 }
471 fn symbol(&mut self, literal: &Self::Literal) -> String {
472 literal.text.to_string()
473 }
474 fn suffix(&mut self, _literal: &Self::Literal) -> Option<String> {
475 None
469 } 476 }
470 477
471 fn integer(&mut self, n: &str) -> Self::Literal { 478 fn integer(&mut self, n: &str) -> Self::Literal {
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs
index 6863f100b..753001949 100644
--- a/crates/rust-analyzer/src/cli.rs
+++ b/crates/rust-analyzer/src/cli.rs
@@ -10,7 +10,7 @@ mod ssr;
10use std::io::Read; 10use std::io::Read;
11 11
12use anyhow::Result; 12use anyhow::Result;
13use ra_ide::{file_structure, Analysis}; 13use ra_ide::Analysis;
14use ra_prof::profile; 14use ra_prof::profile;
15use ra_syntax::{AstNode, SourceFile}; 15use ra_syntax::{AstNode, SourceFile};
16 16
@@ -48,8 +48,10 @@ pub fn parse(no_dump: bool) -> Result<()> {
48} 48}
49 49
50pub fn symbols() -> Result<()> { 50pub fn symbols() -> Result<()> {
51 let file = file()?; 51 let text = read_stdin()?;
52 for s in file_structure(&file) { 52 let (analysis, file_id) = Analysis::from_single_file(text);
53 let structure = analysis.file_structure(file_id).unwrap();
54 for s in structure {
53 println!("{:?}", s); 55 println!("{:?}", s);
54 } 56 }
55 Ok(()) 57 Ok(())
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index ed5e52871..68b2a2abd 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -127,6 +127,7 @@ pub struct ClientCapsConfig {
127 pub resolve_code_action: bool, 127 pub resolve_code_action: bool,
128 pub hover_actions: bool, 128 pub hover_actions: bool,
129 pub status_notification: bool, 129 pub status_notification: bool,
130 pub signature_help_label_offsets: bool,
130} 131}
131 132
132impl Config { 133impl Config {
@@ -302,6 +303,15 @@ impl Config {
302 { 303 {
303 self.client_caps.code_action_literals = value; 304 self.client_caps.code_action_literals = value;
304 } 305 }
306 if let Some(value) = doc_caps
307 .signature_help
308 .as_ref()
309 .and_then(|it| it.signature_information.as_ref())
310 .and_then(|it| it.parameter_information.as_ref())
311 .and_then(|it| it.label_offset_support)
312 {
313 self.client_caps.signature_help_label_offsets = value;
314 }
305 315
306 self.completion.allow_snippets(false); 316 self.completion.allow_snippets(false);
307 if let Some(completion) = &doc_caps.completion { 317 if let Some(completion) = &doc_caps.completion {
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index d28c700f1..18d660f42 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -553,21 +553,16 @@ pub(crate) fn handle_signature_help(
553 let _p = profile("handle_signature_help"); 553 let _p = profile("handle_signature_help");
554 let position = from_proto::file_position(&snap, params.text_document_position_params)?; 554 let position = from_proto::file_position(&snap, params.text_document_position_params)?;
555 let call_info = match snap.analysis.call_info(position)? { 555 let call_info = match snap.analysis.call_info(position)? {
556 None => return Ok(None),
557 Some(it) => it, 556 Some(it) => it,
557 None => return Ok(None),
558 }; 558 };
559 let concise = !snap.config.call_info_full; 559 let concise = !snap.config.call_info_full;
560 let mut active_parameter = call_info.active_parameter.map(|it| it as i64); 560 let res = to_proto::signature_help(
561 if concise && call_info.signature.has_self_param { 561 call_info,
562 active_parameter = active_parameter.map(|it| it.saturating_sub(1)); 562 concise,
563 } 563 snap.config.client_caps.signature_help_label_offsets,
564 let sig_info = to_proto::signature_information(call_info.signature, concise); 564 );
565 565 Ok(Some(res))
566 Ok(Some(lsp_types::SignatureHelp {
567 signatures: vec![sig_info],
568 active_signature: Some(0),
569 active_parameter,
570 }))
571} 566}
572 567
573pub(crate) fn handle_hover( 568pub(crate) fn handle_hover(
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 2fcae9ca3..7fcb43a4f 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -4,8 +4,8 @@ use std::path::{self, Path};
4use itertools::Itertools; 4use itertools::Itertools;
5use ra_db::{FileId, FileRange}; 5use ra_db::{FileId, FileRange};
6use ra_ide::{ 6use ra_ide::{
7 Assist, AssistKind, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, 7 Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation,
8 FoldKind, FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, 8 FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange,
9 Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget, 9 Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget,
10 ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, 10 ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit,
11}; 11};
@@ -219,29 +219,72 @@ pub(crate) fn completion_item(
219 res 219 res
220} 220}
221 221
222pub(crate) fn signature_information( 222pub(crate) fn signature_help(
223 signature: FunctionSignature, 223 call_info: CallInfo,
224 concise: bool, 224 concise: bool,
225) -> lsp_types::SignatureInformation { 225 label_offsets: bool,
226 let (label, documentation, params) = if concise { 226) -> lsp_types::SignatureHelp {
227 let mut params = signature.parameters; 227 let (label, parameters) = match (concise, label_offsets) {
228 if signature.has_self_param { 228 (_, false) => {
229 params.remove(0); 229 let params = call_info
230 .parameter_labels()
231 .map(|label| lsp_types::ParameterInformation {
232 label: lsp_types::ParameterLabel::Simple(label.to_string()),
233 documentation: None,
234 })
235 .collect::<Vec<_>>();
236 let label =
237 if concise { call_info.parameter_labels().join(", ") } else { call_info.signature };
238 (label, params)
239 }
240 (false, true) => {
241 let params = call_info
242 .parameter_ranges()
243 .iter()
244 .map(|it| [u32::from(it.start()).into(), u32::from(it.end()).into()])
245 .map(|label_offsets| lsp_types::ParameterInformation {
246 label: lsp_types::ParameterLabel::LabelOffsets(label_offsets),
247 documentation: None,
248 })
249 .collect::<Vec<_>>();
250 (call_info.signature, params)
251 }
252 (true, true) => {
253 let mut params = Vec::new();
254 let mut label = String::new();
255 let mut first = true;
256 for param in call_info.parameter_labels() {
257 if !first {
258 label.push_str(", ");
259 }
260 first = false;
261 let start = label.len() as u64;
262 label.push_str(param);
263 let end = label.len() as u64;
264 params.push(lsp_types::ParameterInformation {
265 label: lsp_types::ParameterLabel::LabelOffsets([start, end]),
266 documentation: None,
267 });
268 }
269
270 (label, params)
230 } 271 }
231 (params.join(", "), None, params)
232 } else {
233 (signature.to_string(), signature.doc.map(documentation), signature.parameters)
234 }; 272 };
235 273
236 let parameters: Vec<lsp_types::ParameterInformation> = params 274 let documentation = call_info.doc.map(|doc| {
237 .into_iter() 275 lsp_types::Documentation::MarkupContent(lsp_types::MarkupContent {
238 .map(|param| lsp_types::ParameterInformation { 276 kind: lsp_types::MarkupKind::Markdown,
239 label: lsp_types::ParameterLabel::Simple(param), 277 value: doc,
240 documentation: None,
241 }) 278 })
242 .collect(); 279 });
243 280
244 lsp_types::SignatureInformation { label, documentation, parameters: Some(parameters) } 281 let signature =
282 lsp_types::SignatureInformation { label, documentation, parameters: Some(parameters) };
283 lsp_types::SignatureHelp {
284 signatures: vec![signature],
285 active_signature: None,
286 active_parameter: call_info.active_parameter.map(|it| it as i64),
287 }
245} 288}
246 289
247pub(crate) fn inlay_int(line_index: &LineIndex, inlay_hint: InlayHint) -> lsp_ext::InlayHint { 290pub(crate) fn inlay_int(line_index: &LineIndex, inlay_hint: InlayHint) -> lsp_ext::InlayHint {
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index f16b4ed8d..978b463d5 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -13,8 +13,12 @@ This manual focuses on a specific usage of the library -- running it as part of
13https://microsoft.github.io/language-server-protocol/[Language Server Protocol] (LSP). 13https://microsoft.github.io/language-server-protocol/[Language Server Protocol] (LSP).
14The LSP allows various code editors, like VS Code, Emacs or Vim, to implement semantic features like completion or goto definition by talking to an external language server process. 14The LSP allows various code editors, like VS Code, Emacs or Vim, to implement semantic features like completion or goto definition by talking to an external language server process.
15 15
16To improve this document, send a pull request against 16[TIP]
17https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc[this file]. 17====
18[.lead]
19To improve this document, send a pull request: +
20https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc[https://github.com/rust-analyzer/.../manual.adoc]
21====
18 22
19If you have questions about using rust-analyzer, please ask them in the https://users.rust-lang.org/c/ide/14["`IDEs and Editors`"] topic of Rust users forum. 23If you have questions about using rust-analyzer, please ask them in the https://users.rust-lang.org/c/ide/14["`IDEs and Editors`"] topic of Rust users forum.
20 24