aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs19
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs31
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs132
-rw-r--r--crates/rust-analyzer/src/config.rs41
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs166
5 files changed, 307 insertions, 82 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 443b057ab..c69e0efea 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -60,13 +60,10 @@ pub(super) fn lower(
60 params: Option<ast::ParamList>, 60 params: Option<ast::ParamList>,
61 body: Option<ast::Expr>, 61 body: Option<ast::Expr>,
62) -> (Body, BodySourceMap) { 62) -> (Body, BodySourceMap) {
63 let ctx = LowerCtx::new(db, expander.current_file_id.clone());
64
65 ExprCollector { 63 ExprCollector {
66 db, 64 db,
67 def, 65 def,
68 expander, 66 expander,
69 ctx,
70 source_map: BodySourceMap::default(), 67 source_map: BodySourceMap::default(),
71 body: Body { 68 body: Body {
72 exprs: Arena::default(), 69 exprs: Arena::default(),
@@ -83,7 +80,6 @@ struct ExprCollector<'a> {
83 db: &'a dyn DefDatabase, 80 db: &'a dyn DefDatabase,
84 def: DefWithBodyId, 81 def: DefWithBodyId,
85 expander: Expander, 82 expander: Expander,
86 ctx: LowerCtx,
87 body: Body, 83 body: Body,
88 source_map: BodySourceMap, 84 source_map: BodySourceMap,
89} 85}
@@ -122,6 +118,10 @@ impl ExprCollector<'_> {
122 (self.body, self.source_map) 118 (self.body, self.source_map)
123 } 119 }
124 120
121 fn ctx(&self) -> LowerCtx {
122 LowerCtx::new(self.db, self.expander.current_file_id)
123 }
124
125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
126 let src = self.expander.to_source(ptr); 126 let src = self.expander.to_source(ptr);
127 let id = self.make_expr(expr, Ok(src.clone())); 127 let id = self.make_expr(expr, Ok(src.clone()));
@@ -268,7 +268,7 @@ impl ExprCollector<'_> {
268 }; 268 };
269 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 269 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
270 let generic_args = 270 let generic_args =
271 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it)); 271 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
272 self.alloc_expr( 272 self.alloc_expr(
273 Expr::MethodCall { receiver, method_name, args, generic_args }, 273 Expr::MethodCall { receiver, method_name, args, generic_args },
274 syntax_ptr, 274 syntax_ptr,
@@ -373,7 +373,7 @@ impl ExprCollector<'_> {
373 } 373 }
374 ast::Expr::CastExpr(e) => { 374 ast::Expr::CastExpr(e) => {
375 let expr = self.collect_expr_opt(e.expr()); 375 let expr = self.collect_expr_opt(e.expr());
376 let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref()); 376 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
377 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 377 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
378 } 378 }
379 ast::Expr::RefExpr(e) => { 379 ast::Expr::RefExpr(e) => {
@@ -396,7 +396,7 @@ impl ExprCollector<'_> {
396 for param in pl.params() { 396 for param in pl.params() {
397 let pat = self.collect_pat_opt(param.pat()); 397 let pat = self.collect_pat_opt(param.pat());
398 let type_ref = 398 let type_ref =
399 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); 399 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
400 args.push(pat); 400 args.push(pat);
401 arg_types.push(type_ref); 401 arg_types.push(type_ref);
402 } 402 }
@@ -404,7 +404,7 @@ impl ExprCollector<'_> {
404 let ret_type = e 404 let ret_type = e
405 .ret_type() 405 .ret_type()
406 .and_then(|r| r.type_ref()) 406 .and_then(|r| r.type_ref())
407 .map(|it| TypeRef::from_ast(&self.ctx, it)); 407 .map(|it| TypeRef::from_ast(&self.ctx(), it));
408 let body = self.collect_expr_opt(e.body()); 408 let body = self.collect_expr_opt(e.body());
409 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 409 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
410 } 410 }
@@ -507,7 +507,8 @@ impl ExprCollector<'_> {
507 .map(|s| match s { 507 .map(|s| match s {
508 ast::Stmt::LetStmt(stmt) => { 508 ast::Stmt::LetStmt(stmt) => {
509 let pat = self.collect_pat_opt(stmt.pat()); 509 let pat = self.collect_pat_opt(stmt.pat());
510 let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); 510 let type_ref =
511 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
511 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 512 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
512 Statement::Let { pat, type_ref, initializer } 513 Statement::Let { pat, type_ref, initializer }
513 } 514 }
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 115ad8328..c2168222e 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -564,6 +564,37 @@ fn main() {
564} 564}
565 565
566#[test] 566#[test]
567fn issue_4465_dollar_crate_at_type() {
568 assert_snapshot!(
569 infer(r#"
570pub struct Foo {}
571pub fn anything<T>() -> T {
572 loop {}
573}
574macro_rules! foo {
575 () => {{
576 let r: $crate::Foo = anything();
577 r
578 }};
579}
580fn main() {
581 let _a = foo!();
582}
583"#), @r###"
584 45..60 '{ loop {} }': T
585 51..58 'loop {}': !
586 56..58 '{}': ()
587 !0..31 '{letr:...g();r}': Foo
588 !4..5 'r': Foo
589 !18..26 'anything': fn anything<Foo>() -> Foo
590 !18..28 'anything()': Foo
591 !29..30 'r': Foo
592 164..188 '{ ...!(); }': ()
593 174..176 '_a': Foo
594"###);
595}
596
597#[test]
567fn issue_4053_diesel_where_clauses() { 598fn issue_4053_diesel_where_clauses() {
568 assert_snapshot!( 599 assert_snapshot!(
569 infer(r#" 600 infer(r#"
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 9d32cbc7a..c49aacf98 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1617,6 +1617,138 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
1617} 1617}
1618 1618
1619#[test] 1619#[test]
1620fn fn_ptr_and_item() {
1621 assert_snapshot!(
1622 infer(r#"
1623#[lang="fn_once"]
1624trait FnOnce<Args> {
1625 type Output;
1626
1627 fn call_once(self, args: Args) -> Self::Output;
1628}
1629
1630trait Foo<T> {
1631 fn foo(&self) -> T;
1632}
1633
1634struct Bar<T>(T);
1635
1636impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
1637 fn foo(&self) -> (A1, R) {}
1638}
1639
1640enum Opt<T> { None, Some(T) }
1641impl<T> Opt<T> {
1642 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {}
1643}
1644
1645fn test() {
1646 let bar: Bar<fn(u8) -> u32>;
1647 bar.foo();
1648
1649 let opt: Opt<u8>;
1650 let f: fn(u8) -> u32;
1651 opt.map(f);
1652}
1653"#),
1654 @r###"
165575..79 'self': Self
165681..85 'args': Args
1657140..144 'self': &Self
1658244..248 'self': &Bar<F>
1659261..263 '{}': ()
1660347..351 'self': Opt<T>
1661353..354 'f': F
1662369..371 '{}': ()
1663385..501 '{ ...(f); }': ()
1664395..398 'bar': Bar<fn(u8) -> u32>
1665424..427 'bar': Bar<fn(u8) -> u32>
1666424..433 'bar.foo()': {unknown}
1667444..447 'opt': Opt<u8>
1668466..467 'f': fn(u8) -> u32
1669488..491 'opt': Opt<u8>
1670488..498 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>>
1671496..497 'f': fn(u8) -> u32
1672"###
1673 );
1674}
1675
1676#[test]
1677fn fn_trait_deref_with_ty_default() {
1678 assert_snapshot!(
1679 infer(r#"
1680#[lang = "deref"]
1681trait Deref {
1682 type Target;
1683
1684 fn deref(&self) -> &Self::Target;
1685}
1686
1687#[lang="fn_once"]
1688trait FnOnce<Args> {
1689 type Output;
1690
1691 fn call_once(self, args: Args) -> Self::Output;
1692}
1693
1694struct Foo;
1695
1696impl Foo {
1697 fn foo(&self) -> usize {}
1698}
1699
1700struct Lazy<T, F = fn() -> T>(F);
1701
1702impl<T, F> Lazy<T, F> {
1703 pub fn new(f: F) -> Lazy<T, F> {}
1704}
1705
1706impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
1707 type Target = T;
1708}
1709
1710fn test() {
1711 let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
1712 let r1 = lazy1.foo();
1713
1714 fn make_foo_fn() -> Foo {}
1715 let make_foo_fn_ptr: fn() -> Foo = make_foo_fn;
1716 let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr);
1717 let r2 = lazy2.foo();
1718}
1719"#),
1720 @r###"
172165..69 'self': &Self
1722166..170 'self': Self
1723172..176 'args': Args
1724240..244 'self': &Foo
1725255..257 '{}': ()
1726335..336 'f': F
1727355..357 '{}': ()
1728444..690 '{ ...o(); }': ()
1729454..459 'lazy1': Lazy<Foo, fn() -> T>
1730476..485 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
1731476..493 'Lazy::...| Foo)': Lazy<Foo, fn() -> T>
1732486..492 '|| Foo': || -> T
1733489..492 'Foo': Foo
1734503..505 'r1': {unknown}
1735508..513 'lazy1': Lazy<Foo, fn() -> T>
1736508..519 'lazy1.foo()': {unknown}
1737561..576 'make_foo_fn_ptr': fn() -> Foo
1738592..603 'make_foo_fn': fn make_foo_fn() -> Foo
1739613..618 'lazy2': Lazy<Foo, fn() -> T>
1740635..644 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
1741635..661 'Lazy::...n_ptr)': Lazy<Foo, fn() -> T>
1742645..660 'make_foo_fn_ptr': fn() -> Foo
1743671..673 'r2': {unknown}
1744676..681 'lazy2': Lazy<Foo, fn() -> T>
1745676..687 'lazy2.foo()': {unknown}
1746550..552 '{}': ()
1747"###
1748 );
1749}
1750
1751#[test]
1620fn closure_1() { 1752fn closure_1() {
1621 assert_snapshot!( 1753 assert_snapshot!(
1622 infer(r#" 1754 infer(r#"
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 53aee833d..b5dc6f0fa 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -33,6 +33,36 @@ pub struct Config {
33 pub inlay_hints: InlayHintsConfig, 33 pub inlay_hints: InlayHintsConfig,
34 pub completion: CompletionConfig, 34 pub completion: CompletionConfig,
35 pub call_info_full: bool, 35 pub call_info_full: bool,
36 pub lens: LensConfig,
37}
38
39#[derive(Clone, Debug, PartialEq, Eq)]
40pub struct LensConfig {
41 pub run: bool,
42 pub debug: bool,
43 pub impementations: bool,
44}
45
46impl Default for LensConfig {
47 fn default() -> Self {
48 Self { run: true, debug: true, impementations: true }
49 }
50}
51
52impl LensConfig {
53 pub const NO_LENS: LensConfig = Self { run: false, debug: false, impementations: false };
54
55 pub fn any(&self) -> bool {
56 self.impementations || self.runnable()
57 }
58
59 pub fn none(&self) -> bool {
60 !self.any()
61 }
62
63 pub fn runnable(&self) -> bool {
64 self.run || self.debug
65 }
36} 66}
37 67
38#[derive(Debug, Clone)] 68#[derive(Debug, Clone)]
@@ -107,6 +137,7 @@ impl Default for Config {
107 ..CompletionConfig::default() 137 ..CompletionConfig::default()
108 }, 138 },
109 call_info_full: true, 139 call_info_full: true,
140 lens: LensConfig::default(),
110 } 141 }
111 } 142 }
112} 143}
@@ -196,6 +227,16 @@ impl Config {
196 set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets); 227 set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets);
197 set(value, "/callInfo/full", &mut self.call_info_full); 228 set(value, "/callInfo/full", &mut self.call_info_full);
198 229
230 let mut lens_enabled = true;
231 set(value, "/lens/enable", &mut lens_enabled);
232 if lens_enabled {
233 set(value, "/lens/run", &mut self.lens.run);
234 set(value, "/lens/debug", &mut self.lens.debug);
235 set(value, "/lens/implementations", &mut self.lens.impementations);
236 } else {
237 self.lens = LensConfig::NO_LENS;
238 }
239
199 log::info!("Config::update() = {:#?}", self); 240 log::info!("Config::update() = {:#?}", self);
200 241
201 fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> { 242 fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> {
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 6b14830b6..e67556752 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -812,88 +812,108 @@ pub fn handle_code_lens(
812 params: lsp_types::CodeLensParams, 812 params: lsp_types::CodeLensParams,
813) -> Result<Option<Vec<CodeLens>>> { 813) -> Result<Option<Vec<CodeLens>>> {
814 let _p = profile("handle_code_lens"); 814 let _p = profile("handle_code_lens");
815 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
816 let line_index = world.analysis().file_line_index(file_id)?;
817
818 let mut lenses: Vec<CodeLens> = Default::default(); 815 let mut lenses: Vec<CodeLens> = Default::default();
819 816
817 if world.config.lens.none() {
818 // early return before any db query!
819 return Ok(Some(lenses));
820 }
821
822 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
823 let line_index = world.analysis().file_line_index(file_id)?;
820 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?; 824 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?;
821 // Gather runnables 825
822 for runnable in world.analysis().runnables(file_id)? { 826 if world.config.lens.runnable() {
823 let title = match &runnable.kind { 827 // Gather runnables
824 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶\u{fe0e} Run Test", 828 for runnable in world.analysis().runnables(file_id)? {
825 RunnableKind::DocTest { .. } => "▶\u{fe0e} Run Doctest", 829 let (run_title, debugee) = match &runnable.kind {
826 RunnableKind::Bench { .. } => "Run Bench", 830 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => {
827 RunnableKind::Bin => { 831 ("▶️\u{fe0e}Run Test", true)
828 // Do not suggest binary run on other target than binary
829 match &cargo_spec {
830 Some(spec) => match spec.target_kind {
831 TargetKind::Bin => "Run",
832 _ => continue,
833 },
834 None => continue,
835 } 832 }
833 RunnableKind::DocTest { .. } => {
834 // cargo does not support -no-run for doctests
835 ("▶️\u{fe0e}Run Doctest", false)
836 }
837 RunnableKind::Bench { .. } => {
838 // Nothing wrong with bench debugging
839 ("Run Bench", true)
840 }
841 RunnableKind::Bin => {
842 // Do not suggest binary run on other target than binary
843 match &cargo_spec {
844 Some(spec) => match spec.target_kind {
845 TargetKind::Bin => ("Run", true),
846 _ => continue,
847 },
848 None => continue,
849 }
850 }
851 };
852
853 let mut r = to_lsp_runnable(&world, file_id, runnable)?;
854 if world.config.lens.run {
855 let lens = CodeLens {
856 range: r.range,
857 command: Some(Command {
858 title: run_title.to_string(),
859 command: "rust-analyzer.runSingle".into(),
860 arguments: Some(vec![to_value(&r).unwrap()]),
861 }),
862 data: None,
863 };
864 lenses.push(lens);
836 } 865 }
837 }
838 .to_string();
839 let mut r = to_lsp_runnable(&world, file_id, runnable)?;
840 let lens = CodeLens {
841 range: r.range,
842 command: Some(Command {
843 title,
844 command: "rust-analyzer.runSingle".into(),
845 arguments: Some(vec![to_value(&r).unwrap()]),
846 }),
847 data: None,
848 };
849 lenses.push(lens);
850 866
851 if r.args[0] == "run" { 867 if debugee && world.config.lens.debug {
852 r.args[0] = "build".into(); 868 if r.args[0] == "run" {
853 } else { 869 r.args[0] = "build".into();
854 r.args.push("--no-run".into()); 870 } else {
871 r.args.push("--no-run".into());
872 }
873 let debug_lens = CodeLens {
874 range: r.range,
875 command: Some(Command {
876 title: "Debug".into(),
877 command: "rust-analyzer.debugSingle".into(),
878 arguments: Some(vec![to_value(r).unwrap()]),
879 }),
880 data: None,
881 };
882 lenses.push(debug_lens);
883 }
855 } 884 }
856 let debug_lens = CodeLens {
857 range: r.range,
858 command: Some(Command {
859 title: "Debug".into(),
860 command: "rust-analyzer.debugSingle".into(),
861 arguments: Some(vec![to_value(r).unwrap()]),
862 }),
863 data: None,
864 };
865 lenses.push(debug_lens);
866 } 885 }
867 886
868 // Handle impls 887 if world.config.lens.impementations {
869 lenses.extend( 888 // Handle impls
870 world 889 lenses.extend(
871 .analysis() 890 world
872 .file_structure(file_id)? 891 .analysis()
873 .into_iter() 892 .file_structure(file_id)?
874 .filter(|it| match it.kind { 893 .into_iter()
875 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true, 894 .filter(|it| match it.kind {
876 _ => false, 895 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true,
877 }) 896 _ => false,
878 .map(|it| { 897 })
879 let range = to_proto::range(&line_index, it.node_range); 898 .map(|it| {
880 let pos = range.start; 899 let range = to_proto::range(&line_index, it.node_range);
881 let lens_params = lsp_types::request::GotoImplementationParams { 900 let pos = range.start;
882 text_document_position_params: lsp_types::TextDocumentPositionParams::new( 901 let lens_params = lsp_types::request::GotoImplementationParams {
883 params.text_document.clone(), 902 text_document_position_params: lsp_types::TextDocumentPositionParams::new(
884 pos, 903 params.text_document.clone(),
885 ), 904 pos,
886 work_done_progress_params: Default::default(), 905 ),
887 partial_result_params: Default::default(), 906 work_done_progress_params: Default::default(),
888 }; 907 partial_result_params: Default::default(),
889 CodeLens { 908 };
890 range, 909 CodeLens {
891 command: None, 910 range,
892 data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()), 911 command: None,
893 } 912 data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()),
894 }), 913 }
895 ); 914 }),
896 915 );
916 }
897 Ok(Some(lenses)) 917 Ok(Some(lenses))
898} 918}
899 919