From b7edffe244581b428a4b4da4ff6a08ab461b018f Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Mon, 27 Apr 2020 00:11:04 +0200 Subject: Started rust-analyzer.cargo.defaultTarget implementation --- crates/ra_project_model/src/cargo_workspace.rs | 12 ++++++++++++ crates/rust-analyzer/src/config.rs | 1 + editors/code/package.json | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 362ee30fe..810833b64 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -42,6 +42,11 @@ impl ops::Index for CargoWorkspace { } } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct RustcConfig { + pub default_target: Option, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct CargoConfig { /// Do not activate the `default` feature. @@ -56,6 +61,9 @@ pub struct CargoConfig { /// Runs cargo check on launch to figure out the correct values of OUT_DIR pub load_out_dirs_from_check: bool, + + /// rustc config + pub rustc: RustcConfig, } impl Default for CargoConfig { @@ -65,6 +73,7 @@ impl Default for CargoConfig { all_features: true, features: Vec::new(), load_out_dirs_from_check: false, + rustc: RustcConfig { default_target: None }, } } } @@ -160,6 +169,9 @@ impl CargoWorkspace { if let Some(parent) = cargo_toml.parent() { meta.current_dir(parent); } + if let Some(target) = cargo_features.rustc.default_target.as_ref() { + meta.other_options(&[String::from("--filter-platform"), target.clone()]); + } let meta = meta.exec().with_context(|| { format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) })?; diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 715eddadb..908208ece 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -134,6 +134,7 @@ impl Config { set(value, "/cargo/allFeatures", &mut self.cargo.all_features); set(value, "/cargo/features", &mut self.cargo.features); set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); + set(value, "/cargo/rustc/defaultTarget", &mut self.cargo.rustc.default_target); match get(value, "/procMacro/enable") { Some(true) => { diff --git a/editors/code/package.json b/editors/code/package.json index b8aaa07d8..fe330fb43 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -237,6 +237,14 @@ "default": false, "markdownDescription": "Run `cargo check` on startup to get the correct value for package OUT_DIRs" }, + "rust-analyzer.cargo.rustc.defaultTarget": { + "type": [ + "null", + "string" + ], + "default": null, + "description": "Specify the default target" + }, "rust-analyzer.rustfmt.extraArgs": { "type": "array", "items": { -- cgit v1.2.3 From ed5af989f431b9bfabf6f67350587add05a1942c Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Tue, 28 Apr 2020 00:15:54 +0200 Subject: [config] rename cargo.defaultTarget --- crates/ra_project_model/src/cargo_workspace.rs | 8 ++++---- crates/rust-analyzer/src/config.rs | 2 +- editors/code/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 810833b64..1dfee6b47 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -62,8 +62,8 @@ pub struct CargoConfig { /// Runs cargo check on launch to figure out the correct values of OUT_DIR pub load_out_dirs_from_check: bool, - /// rustc config - pub rustc: RustcConfig, + /// rustc target + pub default_target: Option, } impl Default for CargoConfig { @@ -73,7 +73,7 @@ impl Default for CargoConfig { all_features: true, features: Vec::new(), load_out_dirs_from_check: false, - rustc: RustcConfig { default_target: None }, + default_target: None, } } } @@ -169,7 +169,7 @@ impl CargoWorkspace { if let Some(parent) = cargo_toml.parent() { meta.current_dir(parent); } - if let Some(target) = cargo_features.rustc.default_target.as_ref() { + if let Some(target) = cargo_features.default_target.as_ref() { meta.other_options(&[String::from("--filter-platform"), target.clone()]); } let meta = meta.exec().with_context(|| { diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 908208ece..25404ef90 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -134,7 +134,7 @@ impl Config { set(value, "/cargo/allFeatures", &mut self.cargo.all_features); set(value, "/cargo/features", &mut self.cargo.features); set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); - set(value, "/cargo/rustc/defaultTarget", &mut self.cargo.rustc.default_target); + set(value, "/cargo/defaultTarget", &mut self.cargo.default_target); match get(value, "/procMacro/enable") { Some(true) => { diff --git a/editors/code/package.json b/editors/code/package.json index fe330fb43..775bdaf17 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -237,7 +237,7 @@ "default": false, "markdownDescription": "Run `cargo check` on startup to get the correct value for package OUT_DIRs" }, - "rust-analyzer.cargo.rustc.defaultTarget": { + "rust-analyzer.cargo.defaultTarget": { "type": [ "null", "string" -- cgit v1.2.3 From e7523511ce201763e093d5f5563c20d0e0fc5d54 Mon Sep 17 00:00:00 2001 From: Christophe MASSOLIN Date: Tue, 28 Apr 2020 00:17:23 +0200 Subject: [config] remove RustcConfig --- crates/ra_project_model/src/cargo_workspace.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 1dfee6b47..31499b468 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -42,11 +42,6 @@ impl ops::Index for CargoWorkspace { } } -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct RustcConfig { - pub default_target: Option, -} - #[derive(Clone, Debug, PartialEq, Eq)] pub struct CargoConfig { /// Do not activate the `default` feature. -- cgit v1.2.3 From 76733f0cd456005295e60da8c45d74c8c48f177c Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Wed, 29 Apr 2020 13:52:55 +0200 Subject: Add unwrap block assist #4156 Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_assists/src/doc_tests/generated.rs | 19 ++ crates/ra_assists/src/handlers/unwrap_block.rs | 435 +++++++++++++++++++++++++ crates/ra_assists/src/lib.rs | 2 + crates/ra_syntax/src/ast/expr_extensions.rs | 2 +- docs/user/assists.md | 18 + 5 files changed, 475 insertions(+), 1 deletion(-) create mode 100644 crates/ra_assists/src/handlers/unwrap_block.rs diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index e4fa9ee36..6fe95da6a 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs @@ -726,3 +726,22 @@ use std::{collections::HashMap}; "#####, ) } + +#[test] +fn doctest_unwrap_block() { + check( + "unwrap_block", + r#####" +fn foo() { + if true {<|> + println!("foo"); + } +} +"#####, + r#####" +fn foo() { + <|>println!("foo"); +} +"#####, + ) +} diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs new file mode 100644 index 000000000..b98601f1c --- /dev/null +++ b/crates/ra_assists/src/handlers/unwrap_block.rs @@ -0,0 +1,435 @@ +use crate::{Assist, AssistCtx, AssistId}; + +use ast::LoopBodyOwner; +use ra_fmt::unwrap_trivial_block; +use ra_syntax::{ast, AstNode}; + +// Assist: unwrap_block +// +// Removes the `mut` keyword. +// +// ``` +// fn foo() { +// if true {<|> +// println!("foo"); +// } +// } +// ``` +// -> +// ``` +// fn foo() { +// <|>println!("foo"); +// } +// ``` +pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option { + let res = if let Some(if_expr) = ctx.find_node_at_offset::() { + // if expression + let mut expr_to_unwrap: Option = None; + for block_expr in if_expr.blocks() { + if let Some(block) = block_expr.block() { + let cursor_in_range = + block.l_curly_token()?.text_range().contains_range(ctx.frange.range); + + if cursor_in_range { + let exprto = unwrap_trivial_block(block_expr); + expr_to_unwrap = Some(exprto); + break; + } + } + } + let expr_to_unwrap = expr_to_unwrap?; + // Find if we are in a else if block + let ancestor = ctx + .sema + .ancestors_with_macros(if_expr.syntax().clone()) + .skip(1) + .find_map(ast::IfExpr::cast); + + if let Some(ancestor) = ancestor { + Some((ast::Expr::IfExpr(ancestor), expr_to_unwrap)) + } else { + Some((ast::Expr::IfExpr(if_expr), expr_to_unwrap)) + } + } else if let Some(for_expr) = ctx.find_node_at_offset::() { + // for expression + let block_expr = for_expr.loop_body()?; + let block = block_expr.block()?; + let cursor_in_range = block.l_curly_token()?.text_range().contains_range(ctx.frange.range); + + if cursor_in_range { + let expr_to_unwrap = unwrap_trivial_block(block_expr); + + Some((ast::Expr::ForExpr(for_expr), expr_to_unwrap)) + } else { + None + } + } else if let Some(while_expr) = ctx.find_node_at_offset::() { + // while expression + let block_expr = while_expr.loop_body()?; + let block = block_expr.block()?; + let cursor_in_range = block.l_curly_token()?.text_range().contains_range(ctx.frange.range); + + if cursor_in_range { + let expr_to_unwrap = unwrap_trivial_block(block_expr); + + Some((ast::Expr::WhileExpr(while_expr), expr_to_unwrap)) + } else { + None + } + } else if let Some(loop_expr) = ctx.find_node_at_offset::() { + // loop expression + let block_expr = loop_expr.loop_body()?; + let block = block_expr.block()?; + let cursor_in_range = block.l_curly_token()?.text_range().contains_range(ctx.frange.range); + + if cursor_in_range { + let expr_to_unwrap = unwrap_trivial_block(block_expr); + + Some((ast::Expr::LoopExpr(loop_expr), expr_to_unwrap)) + } else { + None + } + } else { + None + }; + + let (expr, expr_to_unwrap) = res?; + ctx.add_assist(AssistId("unwrap_block"), "Unwrap block", |edit| { + edit.set_cursor(expr.syntax().text_range().start()); + edit.target(expr_to_unwrap.syntax().text_range()); + + let pat_start: &[_] = &[' ', '{', '\n']; + let expr_to_unwrap = expr_to_unwrap.to_string(); + let expr_string = expr_to_unwrap.trim_start_matches(pat_start); + let mut expr_string_lines: Vec<&str> = expr_string.lines().collect(); + expr_string_lines.pop(); // Delete last line + + let expr_string = expr_string_lines + .into_iter() + .map(|line| line.replacen(" ", "", 1)) // Delete indentation + .collect::>() + .join("\n"); + + edit.replace(expr.syntax().text_range(), expr_string); + }) +} + +#[cfg(test)] +mod tests { + use crate::helpers::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn simple_if() { + check_assist( + unwrap_block, + r#" + fn main() { + bar(); + if true {<|> + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + "#, + r#" + fn main() { + bar(); + <|>foo(); + + //comment + bar(); + } + "#, + ); + } + + #[test] + fn simple_if_else() { + check_assist( + unwrap_block, + r#" + fn main() { + bar(); + if true { + foo(); + + //comment + bar(); + } else {<|> + println!("bar"); + } + } + "#, + r#" + fn main() { + bar(); + <|>println!("bar"); + } + "#, + ); + } + + #[test] + fn simple_if_else_if() { + check_assist( + unwrap_block, + r#" + fn main() { + //bar(); + if true { + println!("true"); + + //comment + //bar(); + } else if false {<|> + println!("bar"); + } else { + println!("foo"); + } + } + "#, + r#" + fn main() { + //bar(); + <|>println!("bar"); + } + "#, + ); + } + + #[test] + fn simple_if_bad_cursor_position() { + check_assist_not_applicable( + unwrap_block, + r#" + fn main() { + bar();<|> + if true { + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + "#, + ); + } + + #[test] + fn issue_example_with_if() { + check_assist( + unwrap_block, + r#" + fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { + if let Some(ty) = &ctx.expected_type {<|> + if let Some(Adt::Enum(enum_data)) = ty.as_adt() { + let variants = enum_data.variants(ctx.db); + + let module = if let Some(module) = ctx.scope().module() { + // Compute path from the completion site if available. + module + } else { + // Otherwise fall back to the enum's definition site. + enum_data.module(ctx.db) + }; + + for variant in variants { + if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) { + // Variants with trivial paths are already added by the existing completion logic, + // so we should avoid adding these twice + if path.segments.len() > 1 { + acc.add_enum_variant(ctx, variant, Some(path.to_string())); + } + } + } + } + } + } + "#, + r#" + fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { + <|>if let Some(Adt::Enum(enum_data)) = ty.as_adt() { + let variants = enum_data.variants(ctx.db); + + let module = if let Some(module) = ctx.scope().module() { + // Compute path from the completion site if available. + module + } else { + // Otherwise fall back to the enum's definition site. + enum_data.module(ctx.db) + }; + + for variant in variants { + if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) { + // Variants with trivial paths are already added by the existing completion logic, + // so we should avoid adding these twice + if path.segments.len() > 1 { + acc.add_enum_variant(ctx, variant, Some(path.to_string())); + } + } + } + } + } + "#, + ); + } + + #[test] + fn simple_for() { + check_assist( + unwrap_block, + r#" + fn main() { + for i in 0..5 {<|> + if true { + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + } + "#, + r#" + fn main() { + <|>if true { + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + "#, + ); + } + + #[test] + fn simple_if_in_for() { + check_assist( + unwrap_block, + r#" + fn main() { + for i in 0..5 { + if true {<|> + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + } + "#, + r#" + fn main() { + for i in 0..5 { + <|>foo(); + + //comment + bar(); + } + } + "#, + ); + } + + #[test] + fn simple_loop() { + check_assist( + unwrap_block, + r#" + fn main() { + loop {<|> + if true { + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + } + "#, + r#" + fn main() { + <|>if true { + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + "#, + ); + } + + #[test] + fn simple_while() { + check_assist( + unwrap_block, + r#" + fn main() { + while true {<|> + if true { + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + } + "#, + r#" + fn main() { + <|>if true { + foo(); + + //comment + bar(); + } else { + println!("bar"); + } + } + "#, + ); + } + + #[test] + fn simple_if_in_while_bad_cursor_position() { + check_assist_not_applicable( + unwrap_block, + r#" + fn main() { + while true { + if true { + foo();<|> + + //comment + bar(); + } else { + println!("bar"); + } + } + } + "#, + ); + } +} diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 64bd87afb..c5df86600 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -143,6 +143,7 @@ mod handlers { mod split_import; mod add_from_impl_for_enum; mod reorder_fields; + mod unwrap_block; pub(crate) fn all() -> &'static [AssistHandler] { &[ @@ -181,6 +182,7 @@ mod handlers { replace_unwrap_with_match::replace_unwrap_with_match, split_import::split_import, add_from_impl_for_enum::add_from_impl_for_enum, + unwrap_block::unwrap_block, // These are manually sorted for better priorities add_missing_impl_members::add_missing_impl_members, add_missing_impl_members::add_missing_default_members, diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs index 93aa3d45f..1c1134bc5 100644 --- a/crates/ra_syntax/src/ast/expr_extensions.rs +++ b/crates/ra_syntax/src/ast/expr_extensions.rs @@ -43,7 +43,7 @@ impl ast::IfExpr { Some(res) } - fn blocks(&self) -> AstChildren { + pub fn blocks(&self) -> AstChildren { support::children(self.syntax()) } } diff --git a/docs/user/assists.md b/docs/user/assists.md index 6c6943622..02323772c 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md @@ -695,3 +695,21 @@ use std::┃collections::HashMap; // AFTER use std::{collections::HashMap}; ``` + +## `unwrap_block` + +Removes the `mut` keyword. + +```rust +// BEFORE +fn foo() { + if true {┃ + println!("foo"); + } +} + +// AFTER +fn foo() { + ┃println!("foo"); +} +``` -- cgit v1.2.3 From bbe22640b8d52354c3de3e126c9fcda5b1b174fd Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Wed, 29 Apr 2020 14:53:47 +0200 Subject: Add unwrap block assist #4156 Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_assists/src/doc_tests/generated.rs | 2 +- crates/ra_assists/src/handlers/unwrap_block.rs | 4 ++-- docs/user/assists.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 6fe95da6a..b53b97e89 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs @@ -740,7 +740,7 @@ fn foo() { "#####, r#####" fn foo() { - <|>println!("foo"); + println!("foo"); } "#####, ) diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs index b98601f1c..35d87bc9e 100644 --- a/crates/ra_assists/src/handlers/unwrap_block.rs +++ b/crates/ra_assists/src/handlers/unwrap_block.rs @@ -6,7 +6,7 @@ use ra_syntax::{ast, AstNode}; // Assist: unwrap_block // -// Removes the `mut` keyword. +// This assist removes if...else, for, while and loop control statements to just keep the body. // // ``` // fn foo() { @@ -18,7 +18,7 @@ use ra_syntax::{ast, AstNode}; // -> // ``` // fn foo() { -// <|>println!("foo"); +// println!("foo"); // } // ``` pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option { diff --git a/docs/user/assists.md b/docs/user/assists.md index 02323772c..a421aa0c3 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md @@ -698,7 +698,7 @@ use std::{collections::HashMap}; ## `unwrap_block` -Removes the `mut` keyword. +This assist removes if...else, for, while and loop control statements to just keep the body. ```rust // BEFORE @@ -710,6 +710,6 @@ fn foo() { // AFTER fn foo() { - ┃println!("foo"); + println!("foo"); } ``` -- cgit v1.2.3 From e4267967a8ee3b35d902931cecf06bb4e19f86c5 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 1 May 2020 11:23:03 +0800 Subject: Support local_inner_macros --- crates/ra_hir/src/semantics/source_to_def.rs | 2 +- crates/ra_hir_def/src/body/lower.rs | 1 + crates/ra_hir_def/src/nameres/collector.rs | 2 ++ crates/ra_hir_def/src/nameres/raw.rs | 27 ++++++++++++++++++------ crates/ra_hir_def/src/path/lower.rs | 19 ++++++++++++++++- crates/ra_hir_expand/src/builtin_derive.rs | 2 +- crates/ra_hir_expand/src/builtin_macro.rs | 4 ++++ crates/ra_hir_expand/src/hygiene.rs | 31 +++++++++++++++++++--------- crates/ra_hir_expand/src/lib.rs | 2 ++ crates/ra_hir_ty/src/tests/macros.rs | 26 +++++++++++++++++++++++ 10 files changed, 97 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir/src/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs index 6f3b5b2da..8af64fdc1 100644 --- a/crates/ra_hir/src/semantics/source_to_def.rs +++ b/crates/ra_hir/src/semantics/source_to_def.rs @@ -151,7 +151,7 @@ impl SourceToDefCtx<'_, '_> { let krate = self.file_to_def(file_id)?.krate; let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); let ast_id = Some(AstId::new(src.file_id, file_ast_id)); - Some(MacroDefId { krate: Some(krate), ast_id, kind }) + Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false }) } pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index f467ed3fe..8c1aefbf5 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -430,6 +430,7 @@ impl ExprCollector<'_> { krate: Some(self.expander.module.krate), ast_id: Some(self.expander.ast_id(&e)), kind: MacroDefKind::Declarative, + local_inner: false, }; self.body.item_scope.define_legacy_macro(name, mac); diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 98c74fe25..bf3968bd6 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -204,6 +204,7 @@ impl DefCollector<'_> { ast_id: None, krate: Some(krate), kind: MacroDefKind::CustomDerive(expander), + local_inner: false, }; self.define_proc_macro(name.clone(), macro_id); @@ -941,6 +942,7 @@ impl ModCollector<'_, '_> { ast_id: Some(ast_id.ast_id), krate: Some(self.def_collector.def_map.krate), kind: MacroDefKind::Declarative, + local_inner: mac.local_inner, }; self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); } diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 39b011ad7..aed9dcc72 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -188,6 +188,7 @@ pub(super) struct MacroData { pub(super) path: ModPath, pub(super) name: Option, pub(super) export: bool, + pub(super) local_inner: bool, pub(super) builtin: bool, } @@ -401,14 +402,28 @@ impl RawItemsCollector { let name = m.name().map(|it| it.as_name()); let ast_id = self.source_ast_id_map.ast_id(&m); - // FIXME: cfg_attr - let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export"); // FIXME: cfg_attr - let builtin = - m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "rustc_builtin_macro"); - - let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export, builtin }); + let export = attrs.by_key("macro_export").exists(); + let local_inner = + attrs.by_key("macro_export").tt_values().map(|it| &it.token_trees).flatten().any( + |it| match it { + tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { + ident.text.contains("local_inner_macros") + } + _ => false, + }, + ); + let builtin = attrs.by_key("rustc_builtin_macro").exists(); + + let m = self.raw_items.macros.alloc(MacroData { + ast_id, + path, + name, + export, + local_inner, + builtin, + }); self.push_item(current_module, attrs, RawItemKind::Macro(m)); } diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index 9ec2e0dcd..e632f1afb 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs @@ -9,7 +9,10 @@ use hir_expand::{ hygiene::Hygiene, name::{name, AsName}, }; -use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner}; +use ra_syntax::{ + ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner}, + T, +}; use super::AssociatedTypeBinding; use crate::{ @@ -113,6 +116,20 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option } segments.reverse(); generic_args.reverse(); + + // handle local_inner_macros : + // Basically, even in rustc it is quite hacky: + // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 + // We follow what it did anyway :) + if segments.len() == 1 && kind == PathKind::Plain { + let next = path.syntax().last_token().and_then(|it| it.next_token()); + if next.map_or(false, |it| it.kind() == T![!]) { + if let Some(crate_id) = hygiene.local_inner_macros() { + kind = PathKind::DollarCrate(crate_id); + } + } + } + let mod_path = ModPath { kind, segments }; return Some(Path { type_anchor, mod_path, generic_args }); diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index e60f879a3..25bb5cee3 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -38,7 +38,7 @@ macro_rules! register_builtin { _ => return None, }; - Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind) }) + Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind),local_inner:false }) } }; } diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index e0fef613d..d8b3d342c 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -73,11 +73,13 @@ pub fn find_builtin_macro( krate: Some(krate), ast_id: Some(ast_id), kind: MacroDefKind::BuiltIn(kind), + local_inner: false, }), Either::Right(kind) => Some(MacroDefId { krate: Some(krate), ast_id: Some(ast_id), kind: MacroDefKind::BuiltInEager(kind), + local_inner: false, }), } } @@ -406,6 +408,7 @@ mod tests { krate: Some(CrateId(0)), ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), kind: MacroDefKind::BuiltIn(expander), + local_inner: false, }; let loc = MacroCallLoc { @@ -425,6 +428,7 @@ mod tests { krate: Some(CrateId(0)), ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), kind: MacroDefKind::BuiltInEager(expander), + local_inner: false, }; let args = macro_calls[1].token_tree().unwrap(); diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs index 0b41d0e95..3da93de21 100644 --- a/crates/ra_hir_expand/src/hygiene.rs +++ b/crates/ra_hir_expand/src/hygiene.rs @@ -16,31 +16,34 @@ use crate::{ pub struct Hygiene { // This is what `$crate` expands to def_crate: Option, + + // Indiciate this is a local inner macro + local_inner: bool, } impl Hygiene { pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene { - let def_crate = match file_id.0 { - HirFileIdRepr::FileId(_) => None, + let (def_crate, local_inner) = match file_id.0 { + HirFileIdRepr::FileId(_) => (None, false), HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { MacroCallId::LazyMacro(id) => { let loc = db.lookup_intern_macro(id); match loc.def.kind { - MacroDefKind::Declarative => loc.def.krate, - MacroDefKind::BuiltIn(_) => None, - MacroDefKind::BuiltInDerive(_) => None, - MacroDefKind::BuiltInEager(_) => None, - MacroDefKind::CustomDerive(_) => None, + MacroDefKind::Declarative => (loc.def.krate, loc.def.local_inner), + MacroDefKind::BuiltIn(_) => (None, false), + MacroDefKind::BuiltInDerive(_) => (None, false), + MacroDefKind::BuiltInEager(_) => (None, false), + MacroDefKind::CustomDerive(_) => (None, false), } } - MacroCallId::EagerMacro(_id) => None, + MacroCallId::EagerMacro(_id) => (None, false), }, }; - Hygiene { def_crate } + Hygiene { def_crate, local_inner } } pub fn new_unhygienic() -> Hygiene { - Hygiene { def_crate: None } + Hygiene { def_crate: None, local_inner: false } } // FIXME: this should just return name @@ -52,4 +55,12 @@ impl Hygiene { } Either::Left(name_ref.as_name()) } + + pub fn local_inner_macros(&self) -> Option { + if self.local_inner { + self.def_crate + } else { + None + } + } } diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 754a0f005..f440c073b 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -204,6 +204,8 @@ pub struct MacroDefId { pub krate: Option, pub ast_id: Option>, pub kind: MacroDefKind, + + pub local_inner: bool, } impl MacroDefId { diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 5ddecbdc6..70e17bc94 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -387,6 +387,32 @@ fn main() { ); } +#[test] +fn infer_local_inner_macros() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:foo +fn test() { + let x = foo::foo!(1); + x<|>; +} + +//- /lib.rs crate:foo +#[macro_export(local_inner_macros)] +macro_rules! foo { + (1) => { bar!() }; +} + +#[macro_export] +macro_rules! bar { + () => { 42 } +} + +"#, + ); + assert_eq!("i32", type_at_pos(&db, pos)); +} + #[test] fn infer_builtin_macros_line() { assert_snapshot!( -- cgit v1.2.3 From 7bbdeb43a4972300779a8d30c7323445c1105f44 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 1 May 2020 20:58:24 +0800 Subject: Make AttrQuery copyable --- crates/ra_hir_def/src/attr.rs | 1 + crates/ra_hir_def/src/nameres/raw.rs | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 5a86af8ba..576cd0c65 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -140,6 +140,7 @@ impl Attr { } } +#[derive(Debug, Clone, Copy)] pub struct AttrQuery<'a> { attrs: &'a Attrs, key: &'static str, diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index aed9dcc72..a71503c76 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -404,16 +404,20 @@ impl RawItemsCollector { let ast_id = self.source_ast_id_map.ast_id(&m); // FIXME: cfg_attr - let export = attrs.by_key("macro_export").exists(); - let local_inner = - attrs.by_key("macro_export").tt_values().map(|it| &it.token_trees).flatten().any( - |it| match it { - tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { - ident.text.contains("local_inner_macros") - } - _ => false, - }, - ); + let export_attr = attrs.by_key("macro_export"); + + let export = export_attr.exists(); + let local_inner = if export { + export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { + tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { + ident.text.contains("local_inner_macros") + } + _ => false, + }) + } else { + false + }; + let builtin = attrs.by_key("rustc_builtin_macro").exists(); let m = self.raw_items.macros.alloc(MacroData { -- cgit v1.2.3 From 19e28888aa41b2845b47adb7314aed99d3c48679 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Fri, 1 May 2020 16:26:22 +0200 Subject: wip Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/goto_definition.rs | 18 ++++++++++++++++++ crates/ra_ide_db/src/defs.rs | 8 +++++++- crates/ra_ide_db/src/marks.rs | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 1dfca819d..31f567541 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -243,6 +243,24 @@ mod tests { ); } + #[test] + fn goto_def_for_use_alias() { + covers!(ra_ide_db::goto_def_for_use_alias); + check_goto( + " + //- /lib.rs + use foo as <|>bar; + + + //- /foo/lib.rs + #[macro_export] + macro_rules! foo { () => { () } } + ", + "foo MACRO_CALL FileId(2) 0..49 29..32", + "#[macro_export]\nmacro_rules! foo { () => { () } }|foo", + ); + } + #[test] fn goto_def_for_macros_in_use_tree() { check_goto( diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 7cd2384e9..54543e6e4 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs @@ -11,7 +11,7 @@ use hir::{ }; use ra_prof::profile; use ra_syntax::{ - ast::{self, AstNode}, + ast::{self, AstNode, NameOwner}, match_ast, }; use test_utils::tested_by; @@ -115,10 +115,16 @@ pub fn classify_name(sema: &Semantics, name: &ast::Name) -> Option } fn classify_name_inner(sema: &Semantics, name: &ast::Name) -> Option { + println!("name : {} -- {:?}", name, name); let parent = name.syntax().parent()?; + println!("parent : {} -- {:?}", parent, parent); match_ast! { match parent { + ast::Alias(it) => { + let def = sema.to_def(&it)?; + Some(Definition::ModuleDef(def.into())) + }, ast::BindPat(it) => { let local = sema.to_def(&it)?; Some(Definition::Local(local)) diff --git a/crates/ra_ide_db/src/marks.rs b/crates/ra_ide_db/src/marks.rs index 03b4be21c..386fe605c 100644 --- a/crates/ra_ide_db/src/marks.rs +++ b/crates/ra_ide_db/src/marks.rs @@ -2,6 +2,7 @@ test_utils::marks![ goto_def_for_macros + goto_def_for_use_alias goto_def_for_methods goto_def_for_fields goto_def_for_record_fields -- cgit v1.2.3 From df7899e47a83fb5544d09d2db9405762d3ce29b7 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Fri, 1 May 2020 16:41:29 +0200 Subject: Add unwrap block assist #4156 Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_assists/src/handlers/unwrap_block.rs | 69 +++++++++----------------- 1 file changed, 23 insertions(+), 46 deletions(-) diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs index 35d87bc9e..71d6d462b 100644 --- a/crates/ra_assists/src/handlers/unwrap_block.rs +++ b/crates/ra_assists/src/handlers/unwrap_block.rs @@ -1,8 +1,8 @@ use crate::{Assist, AssistCtx, AssistId}; -use ast::LoopBodyOwner; +use ast::{BlockExpr, Expr, LoopBodyOwner}; use ra_fmt::unwrap_trivial_block; -use ra_syntax::{ast, AstNode}; +use ra_syntax::{ast, AstNode, TextRange}; // Assist: unwrap_block // @@ -26,24 +26,14 @@ pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option { // if expression let mut expr_to_unwrap: Option = None; for block_expr in if_expr.blocks() { - if let Some(block) = block_expr.block() { - let cursor_in_range = - block.l_curly_token()?.text_range().contains_range(ctx.frange.range); - - if cursor_in_range { - let exprto = unwrap_trivial_block(block_expr); - expr_to_unwrap = Some(exprto); - break; - } + if let Some(expr) = excract_expr(ctx.frange.range, block_expr) { + expr_to_unwrap = Some(expr); + break; } } let expr_to_unwrap = expr_to_unwrap?; // Find if we are in a else if block - let ancestor = ctx - .sema - .ancestors_with_macros(if_expr.syntax().clone()) - .skip(1) - .find_map(ast::IfExpr::cast); + let ancestor = if_expr.syntax().ancestors().skip(1).find_map(ast::IfExpr::cast); if let Some(ancestor) = ancestor { Some((ast::Expr::IfExpr(ancestor), expr_to_unwrap)) @@ -53,42 +43,18 @@ pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option { } else if let Some(for_expr) = ctx.find_node_at_offset::() { // for expression let block_expr = for_expr.loop_body()?; - let block = block_expr.block()?; - let cursor_in_range = block.l_curly_token()?.text_range().contains_range(ctx.frange.range); - - if cursor_in_range { - let expr_to_unwrap = unwrap_trivial_block(block_expr); - - Some((ast::Expr::ForExpr(for_expr), expr_to_unwrap)) - } else { - None - } + excract_expr(ctx.frange.range, block_expr) + .map(|expr_to_unwrap| (ast::Expr::ForExpr(for_expr), expr_to_unwrap)) } else if let Some(while_expr) = ctx.find_node_at_offset::() { // while expression let block_expr = while_expr.loop_body()?; - let block = block_expr.block()?; - let cursor_in_range = block.l_curly_token()?.text_range().contains_range(ctx.frange.range); - - if cursor_in_range { - let expr_to_unwrap = unwrap_trivial_block(block_expr); - - Some((ast::Expr::WhileExpr(while_expr), expr_to_unwrap)) - } else { - None - } + excract_expr(ctx.frange.range, block_expr) + .map(|expr_to_unwrap| (ast::Expr::WhileExpr(while_expr), expr_to_unwrap)) } else if let Some(loop_expr) = ctx.find_node_at_offset::() { // loop expression let block_expr = loop_expr.loop_body()?; - let block = block_expr.block()?; - let cursor_in_range = block.l_curly_token()?.text_range().contains_range(ctx.frange.range); - - if cursor_in_range { - let expr_to_unwrap = unwrap_trivial_block(block_expr); - - Some((ast::Expr::LoopExpr(loop_expr), expr_to_unwrap)) - } else { - None - } + excract_expr(ctx.frange.range, block_expr) + .map(|expr_to_unwrap| (ast::Expr::LoopExpr(loop_expr), expr_to_unwrap)) } else { None }; @@ -114,6 +80,17 @@ pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option { }) } +fn excract_expr(cursor_range: TextRange, block_expr: BlockExpr) -> Option { + let block = block_expr.block()?; + let cursor_in_range = block.l_curly_token()?.text_range().contains_range(cursor_range); + + if cursor_in_range { + Some(unwrap_trivial_block(block_expr)) + } else { + None + } +} + #[cfg(test)] mod tests { use crate::helpers::{check_assist, check_assist_not_applicable}; -- cgit v1.2.3 From 810c96196167cc44886e40d9b80a14309e3d663a Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 1 May 2020 18:26:42 -0400 Subject: Update crates --- Cargo.lock | 12 ++++++------ crates/rust-analyzer/src/caps.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 85ea4f178..5d50a766f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -655,9 +655,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.74.0" +version = "0.74.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "820f746e5716ab9a2d664794636188bd003023b72e55404ee27105dc22869922" +checksum = "57c0e6a2b8837d27b29deb3f3e6dc1c6d2f57947677f9be1024e482ec5b59525" dependencies = [ "base64", "bitflags", @@ -706,9 +706,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ "cfg-if", "fuchsia-zircon", @@ -749,9 +749,9 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" dependencies = [ "cfg-if", "libc", diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index c0d320926..44222d8bd 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs @@ -43,7 +43,7 @@ pub fn server_capabilities() -> ServerCapabilities { code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions { // Advertise support for all built-in CodeActionKinds code_action_kinds: Some(vec![ - String::new(), + lsp_types::code_action_kind::EMPTY.to_string(), lsp_types::code_action_kind::QUICKFIX.to_string(), lsp_types::code_action_kind::REFACTOR.to_string(), lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(), -- cgit v1.2.3 From fd030f9450ed6910677e30f8fa65b06e71fcffa2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 2 May 2020 01:12:37 +0200 Subject: Revert "Merge #4233" This reverts commit a5f2b16366f027ad60c58266a66eb7fbdcbda9f9, reversing changes made to c96b2180c1c4206a0a98c280b4d30897eb116336. --- crates/ra_hir_def/src/body/lower.rs | 4 +++ crates/ra_hir_def/src/expr.rs | 4 +++ crates/ra_hir_ty/src/infer/expr.rs | 5 ++++ crates/ra_parser/src/grammar/expressions/atom.rs | 6 ++-- crates/ra_parser/src/syntax_kind/generated.rs | 1 + crates/ra_syntax/src/ast.rs | 4 +-- crates/ra_syntax/src/ast/expr_extensions.rs | 27 ++++------------- crates/ra_syntax/src/ast/generated/nodes.rs | 37 ++++++++++++++++++++++-- xtask/src/ast_src.rs | 5 +++- 9 files changed, 63 insertions(+), 30 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index e9dd65b0a..f06cc115b 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -203,6 +203,10 @@ impl ExprCollector<'_> { self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) } + ast::Expr::TryBlockExpr(e) => { + let body = self.collect_block_opt(e.body()); + self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) + } ast::Expr::BlockExpr(e) => self.collect_block(e), ast::Expr::LoopExpr(e) => { let body = self.collect_block_opt(e.loop_body()); diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index aad12e123..a0cdad529 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs @@ -101,6 +101,9 @@ pub enum Expr { Try { expr: ExprId, }, + TryBlock { + body: ExprId, + }, Cast { expr: ExprId, type_ref: TypeRef, @@ -236,6 +239,7 @@ impl Expr { f(*expr); } } + Expr::TryBlock { body } => f(*body), Expr::Loop { body } => f(*body), Expr::While { condition, body } => { f(*condition); diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index efc60986b..83f946eee 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -73,6 +73,11 @@ impl<'a> InferenceContext<'a> { self.coerce_merge_branch(&then_ty, &else_ty) } Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), + Expr::TryBlock { body } => { + let _inner = self.infer_expr(*body, expected); + // FIXME should be std::result::Result<{inner}, _> + Ty::Unknown + } Expr::Loop { body } => { self.infer_expr(*body, &Expectation::has_type(Ty::unit())); // FIXME handle break with value diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 76aa601cb..166dfc472 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -84,7 +84,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar T![box] => box_expr(p, None), T![for] => for_expr(p, None), T![while] => while_expr(p, None), - T![try] => try_expr(p, None), + T![try] => try_block_expr(p, None), LIFETIME if la == T![:] => { let m = p.start(); label(p); @@ -134,7 +134,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar } }; let blocklike = match done.kind() { - IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_EXPR => { + IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_BLOCK_EXPR => { BlockLike::Block } _ => BlockLike::NotBlock, @@ -532,7 +532,7 @@ fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { // fn foo() { // let _ = try {}; // } -fn try_expr(p: &mut Parser, m: Option) -> CompletedMarker { +fn try_block_expr(p: &mut Parser, m: Option) -> CompletedMarker { assert!(p.at(T![try])); let m = m.unwrap_or_else(|| p.start()); // Special-case `try!` as macro. diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index ab727ed7e..524e7d784 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -191,6 +191,7 @@ pub enum SyntaxKind { RECORD_LIT, RECORD_FIELD_LIST, RECORD_FIELD, + TRY_BLOCK_EXPR, BOX_EXPR, CALL_EXPR, INDEX_EXPR, diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 521ca8ab8..a716e525b 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -16,9 +16,7 @@ use crate::{ }; pub use self::{ - expr_extensions::{ - ArrayExprKind, BinOp, BlockModifier, ElseBranch, LiteralKind, PrefixOp, RangeOp, - }, + expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, extensions::{ AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs index 352c0d2c5..ecf74fd36 100644 --- a/crates/ra_syntax/src/ast/expr_extensions.rs +++ b/crates/ra_syntax/src/ast/expr_extensions.rs @@ -16,7 +16,7 @@ impl ast::Expr { | ast::Expr::WhileExpr(_) | ast::Expr::BlockExpr(_) | ast::Expr::MatchExpr(_) - | ast::Expr::TryExpr(_) => true, + | ast::Expr::TryBlockExpr(_) => true, _ => false, } } @@ -359,22 +359,7 @@ impl ast::Literal { } } -pub enum BlockModifier { - Async(SyntaxToken), - Unsafe(SyntaxToken), -} - impl ast::BlockExpr { - pub fn modifier(&self) -> Option { - if let Some(token) = self.async_token() { - return Some(BlockModifier::Async(token)); - } - if let Some(token) = self.unsafe_token() { - return Some(BlockModifier::Unsafe(token)); - } - None - } - /// false if the block is an intrinsic part of the syntax and can't be /// replaced with arbitrary expression. /// @@ -383,15 +368,15 @@ impl ast::BlockExpr { /// const FOO: () = { stand_alone }; /// ``` pub fn is_standalone(&self) -> bool { - if self.modifier().is_some() { + if self.unsafe_token().is_some() || self.async_token().is_some() { return false; } - let parent = match self.syntax().parent() { - Some(it) => it, + let kind = match self.syntax().parent() { None => return true, + Some(it) => it.kind(), }; - match parent.kind() { - FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR => false, + match kind { + FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | TRY_BLOCK_EXPR => false, _ => true, } } diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 3f16592b6..2096f12f1 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs @@ -475,6 +475,16 @@ impl LoopExpr { pub fn loop_token(&self) -> Option { support::token(&self.syntax, T![loop]) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TryBlockExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::AttrsOwner for TryBlockExpr {} +impl TryBlockExpr { + pub fn try_token(&self) -> Option { support::token(&self.syntax, T![try]) } + pub fn body(&self) -> Option { support::child(&self.syntax) } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ForExpr { pub(crate) syntax: SyntaxNode, @@ -1467,6 +1477,7 @@ pub enum Expr { FieldExpr(FieldExpr), AwaitExpr(AwaitExpr), TryExpr(TryExpr), + TryBlockExpr(TryBlockExpr), CastExpr(CastExpr), RefExpr(RefExpr), PrefixExpr(PrefixExpr), @@ -1949,6 +1960,17 @@ impl AstNode for LoopExpr { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for TryBlockExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_BLOCK_EXPR } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for ForExpr { fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR } fn cast(syntax: SyntaxNode) -> Option { @@ -3290,6 +3312,9 @@ impl From for Expr { impl From for Expr { fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) } } +impl From for Expr { + fn from(node: TryBlockExpr) -> Expr { Expr::TryBlockExpr(node) } +} impl From for Expr { fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) } } @@ -3320,8 +3345,9 @@ impl AstNode for Expr { TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR - | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | CAST_EXPR | REF_EXPR - | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL | BOX_EXPR => true, + | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR + | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL + | BOX_EXPR => true, _ => false, } } @@ -3349,6 +3375,7 @@ impl AstNode for Expr { FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }), AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }), TRY_EXPR => Expr::TryExpr(TryExpr { syntax }), + TRY_BLOCK_EXPR => Expr::TryBlockExpr(TryBlockExpr { syntax }), CAST_EXPR => Expr::CastExpr(CastExpr { syntax }), REF_EXPR => Expr::RefExpr(RefExpr { syntax }), PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }), @@ -3385,6 +3412,7 @@ impl AstNode for Expr { Expr::FieldExpr(it) => &it.syntax, Expr::AwaitExpr(it) => &it.syntax, Expr::TryExpr(it) => &it.syntax, + Expr::TryBlockExpr(it) => &it.syntax, Expr::CastExpr(it) => &it.syntax, Expr::RefExpr(it) => &it.syntax, Expr::PrefixExpr(it) => &it.syntax, @@ -3865,6 +3893,11 @@ impl std::fmt::Display for LoopExpr { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for TryBlockExpr { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for ForExpr { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 703fb9be9..1abb62f6f 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -162,6 +162,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { "RECORD_LIT", "RECORD_FIELD_LIST", "RECORD_FIELD", + "TRY_BLOCK_EXPR", "BOX_EXPR", // postfix "CALL_EXPR", @@ -439,6 +440,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { } struct IfExpr: AttrsOwner { T![if], Condition } struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] } + struct TryBlockExpr: AttrsOwner { T![try], body: BlockExpr } struct ForExpr: AttrsOwner, LoopBodyOwner { T![for], Pat, @@ -449,7 +451,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] } struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr } struct Label { T![lifetime] } - struct BlockExpr: AttrsOwner { Label, T![unsafe], T![async], Block } + struct BlockExpr: AttrsOwner { Label, T![unsafe], T![async], Block } struct ReturnExpr: AttrsOwner { Expr } struct CallExpr: ArgListOwner { Expr } struct MethodCallExpr: AttrsOwner, ArgListOwner { @@ -720,6 +722,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { FieldExpr, AwaitExpr, TryExpr, + TryBlockExpr, CastExpr, RefExpr, PrefixExpr, -- cgit v1.2.3 From 76f34a15e61fc69ccafe1ec4804712dcd3069de5 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Fri, 1 May 2020 19:13:52 -0400 Subject: Improve formatting of analyzer status text --- crates/rust-analyzer/src/main_loop/handlers.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 0f623949e..574e070fc 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs @@ -46,11 +46,11 @@ use crate::{ pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result { let _p = profile("handle_analyzer_status"); let mut buf = world.status(); - format_to!(buf, "\n\nrequests:"); + format_to!(buf, "\n\nrequests:\n"); let requests = world.latest_requests.read(); for (is_last, r) in requests.iter() { let mark = if is_last { "*" } else { " " }; - format_to!(buf, "{}{:4} {:<36}{}ms", mark, r.id, r.method, r.duration.as_millis()); + format_to!(buf, "{}{:4} {:<36}{}ms\n", mark, r.id, r.method, r.duration.as_millis()); } Ok(buf) } -- cgit v1.2.3 From 65234e8828defc0a56cb1d5e20793b5163b5330d Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Fri, 1 May 2020 18:59:19 -0400 Subject: Remove `workspaceLoaded` setting The `workspaceLoaded` notification setting was originally designed to control the display of a popup message that said: "workspace loaded, {} rust packages" This popup was removed and replaced by a much sleeker message in the VSCode status bar that provides a real-time status while loading: rust-analyzer: {}/{} packages This was done as part of #3587 The new status-bar indicator is unobtrusive and shouldn't need to be disabled. So this setting is removed. --- crates/rust-analyzer/src/config.rs | 7 +------ crates/rust-analyzer/src/main_loop.rs | 3 +-- editors/code/package.json | 5 ----- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 177da94cc..15b7c6912 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -49,7 +49,6 @@ pub enum FilesWatcher { #[derive(Debug, Clone)] pub struct NotificationsConfig { - pub workspace_loaded: bool, pub cargo_toml_not_found: bool, } @@ -83,10 +82,7 @@ impl Default for Config { lru_capacity: None, proc_macro_srv: None, files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, - notifications: NotificationsConfig { - workspace_loaded: true, - cargo_toml_not_found: true, - }, + notifications: NotificationsConfig { cargo_toml_not_found: true }, cargo: CargoConfig::default(), rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() }, @@ -129,7 +125,6 @@ impl Config { Some("client") => FilesWatcher::Client, Some("notify") | _ => FilesWatcher::Notify }; - set(value, "/notifications/workspaceLoaded", &mut self.notifications.workspace_loaded); set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found); set(value, "/cargo/noDefaultFeatures", &mut self.cargo.no_default_features); diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 0a0e616c9..3bc2e0a46 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -415,8 +415,7 @@ fn loop_turn( }); } - let show_progress = - !loop_state.workspace_loaded && world_state.config.notifications.workspace_loaded; + let show_progress = !loop_state.workspace_loaded; if !loop_state.workspace_loaded && loop_state.roots_scanned == loop_state.roots_total diff --git a/editors/code/package.json b/editors/code/package.json index d30673791..7ef727b9d 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -205,11 +205,6 @@ "default": [], "description": "Paths to exclude from analysis." }, - "rust-analyzer.notifications.workspaceLoaded": { - "type": "boolean", - "default": true, - "markdownDescription": "Whether to show `workspace loaded` message." - }, "rust-analyzer.notifications.cargoTomlNotFound": { "type": "boolean", "default": true, -- cgit v1.2.3 From 443762cda914e56487e51ed0e104b3aac7285b1a Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 2 May 2020 09:56:38 +0800 Subject: Update crates/ra_hir_expand/src/builtin_derive.rs Fix spacing Co-authored-by: Jonas Schievink --- crates/ra_hir_expand/src/builtin_derive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index 25bb5cee3..1dc9cac66 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -38,7 +38,7 @@ macro_rules! register_builtin { _ => return None, }; - Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind),local_inner:false }) + Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind), local_inner: false }) } }; } -- cgit v1.2.3 From 291d03949bbd1e8f96dcf348e184d91d57204419 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 2 May 2020 10:06:17 +0800 Subject: Add test in name resolutions --- crates/ra_hir_def/src/nameres/tests/macros.rs | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs index b0befdfbd..9bc0e6287 100644 --- a/crates/ra_hir_def/src/nameres/tests/macros.rs +++ b/crates/ra_hir_def/src/nameres/tests/macros.rs @@ -135,6 +135,43 @@ fn macro_rules_export_with_local_inner_macros_are_visible() { "###); } +#[test] +fn local_inner_macros_makes_local_macros_usable() { + let map = def_map( + " + //- /main.rs crate:main deps:foo + foo::structs!(Foo, Bar); + mod bar; + //- /bar.rs + use crate::*; + //- /lib.rs crate:foo + #[macro_export(local_inner_macros)] + macro_rules! structs { + ($($i:ident),*) => { + inner!($($i),*); + } + } + #[macro_export] + macro_rules! inner { + ($($i:ident),*) => { + $(struct $i { field: u32 } )* + } + } + ", + ); + assert_snapshot!(map, @r###" + ⋮crate + ⋮Bar: t v + ⋮Foo: t v + ⋮bar: t + ⋮ + ⋮crate::bar + ⋮Bar: t v + ⋮Foo: t v + ⋮bar: t + "###); +} + #[test] fn unexpanded_macro_should_expand_by_fixedpoint_loop() { let map = def_map( -- cgit v1.2.3 From edf0b4c1528407d5077220191e601ac41f790b99 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 2 May 2020 10:16:26 +0800 Subject: Test whether it is bang macro properly --- crates/ra_hir_def/src/path/lower.rs | 14 ++++++-------- crates/ra_syntax/src/ast/extensions.rs | 4 ++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index e632f1afb..b902cacd1 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs @@ -9,10 +9,7 @@ use hir_expand::{ hygiene::Hygiene, name::{name, AsName}, }; -use ra_syntax::{ - ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner}, - T, -}; +use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner}; use super::AssociatedTypeBinding; use crate::{ @@ -122,10 +119,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 // We follow what it did anyway :) if segments.len() == 1 && kind == PathKind::Plain { - let next = path.syntax().last_token().and_then(|it| it.next_token()); - if next.map_or(false, |it| it.kind() == T![!]) { - if let Some(crate_id) = hygiene.local_inner_macros() { - kind = PathKind::DollarCrate(crate_id); + if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { + if macro_call.is_bang() { + if let Some(crate_id) = hygiene.local_inner_macros() { + kind = PathKind::DollarCrate(crate_id); + } } } } diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index f2ea5088e..d68f1029f 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -423,6 +423,10 @@ impl ast::MacroCall { None } } + + pub fn is_bang(&self) -> bool { + self.is_macro_rules().is_none() + } } impl ast::LifetimeParam { -- cgit v1.2.3 From 247d32cbfdc2683ee4f6fd1474b65840131551dc Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 2 May 2020 10:57:37 +0200 Subject: Test/check the whole package Closes #4255 --- crates/rust-analyzer/src/main_loop/handlers.rs | 6 +----- crates/rust-analyzer/tests/heavy_tests/main.rs | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 0f623949e..914062902 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs @@ -400,11 +400,7 @@ pub fn handle_runnables( range: Default::default(), label: format!("cargo {} -p {}", cmd, spec.package), bin: "cargo".to_string(), - args: { - let mut args = vec![cmd.to_string()]; - spec.clone().push_to(&mut args); - args - }, + args: vec![cmd.to_string(), "--package".to_string(), spec.package.clone()], extra_args: Vec::new(), env: FxHashMap::default(), cwd: workspace_root.map(|root| root.to_owned()), diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index 07b8114c6..a218da76d 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs @@ -149,7 +149,7 @@ fn main() {} "cwd": server.path().join("foo") }, { - "args": [ "check", "--package", "foo", "--test", "spam" ], + "args": [ "check", "--package", "foo" ], "extraArgs": [], "bin": "cargo", "env": {}, @@ -161,7 +161,7 @@ fn main() {} "cwd": server.path().join("foo") }, { - "args": [ "test", "--package", "foo", "--test", "spam" ], + "args": [ "test", "--package", "foo" ], "extraArgs": [], "bin": "cargo", "env": {}, -- cgit v1.2.3 From 4f2134cc33f07c09fe166cec42971828843bc0ef Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 2 May 2020 01:18:19 +0200 Subject: Introduce EffectExpr --- crates/ra_assists/src/handlers/early_return.rs | 16 +-- .../src/handlers/inline_local_variable.rs | 1 + .../ra_assists/src/handlers/introduce_variable.rs | 2 +- crates/ra_assists/src/handlers/move_guard.rs | 4 +- crates/ra_fmt/src/lib.rs | 1 - crates/ra_hir_def/src/body/lower.rs | 24 ++-- crates/ra_hir_expand/src/db.rs | 3 +- crates/ra_ide/src/completion/completion_context.rs | 2 +- crates/ra_ide/src/folding_ranges.rs | 2 +- crates/ra_ide/src/join_lines.rs | 3 +- crates/ra_ide/src/syntax_tree.rs | 77 +++++------ crates/ra_mbe/src/tests.rs | 152 ++++++++++----------- crates/ra_parser/src/grammar.rs | 2 +- crates/ra_parser/src/grammar/expressions.rs | 13 +- crates/ra_parser/src/grammar/expressions/atom.rs | 29 ++-- crates/ra_parser/src/syntax_kind/generated.rs | 3 +- crates/ra_syntax/src/ast.rs | 2 +- crates/ra_syntax/src/ast/edit.rs | 2 +- crates/ra_syntax/src/ast/expr_extensions.rs | 40 ++++-- crates/ra_syntax/src/ast/generated/nodes.rs | 74 ++++------ crates/ra_syntax/src/ast/make.rs | 4 +- crates/ra_syntax/src/lib.rs | 7 +- crates/ra_syntax/src/validation/block.rs | 20 ++- xtask/src/ast_src.rs | 19 +-- xtask/src/codegen/gen_syntax.rs | 1 + 25 files changed, 242 insertions(+), 261 deletions(-) diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs index ea6c56f8c..eede2fe91 100644 --- a/crates/ra_assists/src/handlers/early_return.rs +++ b/crates/ra_assists/src/handlers/early_return.rs @@ -2,7 +2,7 @@ use std::{iter::once, ops::RangeInclusive}; use ra_syntax::{ algo::replace_children, - ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat}, + ast::{self, edit::IndentLevel, make}, AstNode, SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE}, SyntaxNode, @@ -47,7 +47,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option { // Check if there is an IfLet that we can handle. let if_let_pat = match cond.pat() { None => None, // No IfLet, supported. - Some(TupleStructPat(pat)) if pat.args().count() == 1 => { + Some(ast::Pat::TupleStructPat(pat)) if pat.args().count() == 1 => { let path = pat.path()?; match path.qualifier() { None => { @@ -61,9 +61,9 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option { }; let cond_expr = cond.expr()?; - let then_block = if_expr.then_branch()?.block()?; + let then_block = if_expr.then_branch()?; - let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::Block::cast)?; + let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::BlockExpr::cast)?; if parent_block.expr()? != if_expr.clone().into() { return None; @@ -80,7 +80,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option { return None; } - let parent_container = parent_block.syntax().parent()?.parent()?; + let parent_container = parent_block.syntax().parent()?; let early_expression: ast::Expr = match parent_container.kind() { WHILE_EXPR | LOOP_EXPR => make::expr_continue(), @@ -144,13 +144,13 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option { } }; edit.target(if_expr.syntax().text_range()); - edit.replace_ast(parent_block, ast::Block::cast(new_block).unwrap()); + edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap()); edit.set_cursor(cursor_position); fn replace( new_expr: &SyntaxNode, - then_block: &Block, - parent_block: &Block, + then_block: &ast::BlockExpr, + parent_block: &ast::BlockExpr, if_expr: &ast::IfExpr, ) -> SyntaxNode { let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone()); diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index f5702f6e0..60ec536a7 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs @@ -89,6 +89,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option { | (ast::Expr::ParenExpr(_), _) | (ast::Expr::PathExpr(_), _) | (ast::Expr::BlockExpr(_), _) + | (ast::Expr::EffectExpr(_), _) | (_, ast::Expr::CallExpr(_)) | (_, ast::Expr::TupleExpr(_)) | (_, ast::Expr::ArrayExpr(_)) diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index eda9ac296..39c656305 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs @@ -111,7 +111,7 @@ fn valid_target_expr(node: SyntaxNode) -> Option { /// expression like a lambda or match arm. fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> { expr.syntax().ancestors().find_map(|node| { - if let Some(expr) = node.parent().and_then(ast::Block::cast).and_then(|it| it.expr()) { + if let Some(expr) = node.parent().and_then(ast::BlockExpr::cast).and_then(|it| it.expr()) { if expr.syntax() == &node { tested_by!(test_introduce_var_last_expr); return Some((node, false)); diff --git a/crates/ra_assists/src/handlers/move_guard.rs b/crates/ra_assists/src/handlers/move_guard.rs index d5ccdd91c..b084dd9ee 100644 --- a/crates/ra_assists/src/handlers/move_guard.rs +++ b/crates/ra_assists/src/handlers/move_guard.rs @@ -113,9 +113,9 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option { "Move condition to match guard", |edit| { edit.target(if_expr.syntax().text_range()); - let then_only_expr = then_block.block().and_then(|it| it.statements().next()).is_none(); + let then_only_expr = then_block.statements().next().is_none(); - match &then_block.block().and_then(|it| it.expr()) { + match &then_block.expr() { Some(then_expr) if then_only_expr => { edit.replace(if_expr.syntax().text_range(), then_expr.syntax().text()) } diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs index 1a30b2b3a..f910ded9d 100644 --- a/crates/ra_fmt/src/lib.rs +++ b/crates/ra_fmt/src/lib.rs @@ -42,7 +42,6 @@ pub fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { } pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option { - let block = block.block()?; let has_anything_else = |thing: &SyntaxNode| -> bool { let mut non_trivial_children = block.syntax().children_with_tokens().filter(|it| match it.kind() { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index f06cc115b..58b3d10d8 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -203,10 +203,16 @@ impl ExprCollector<'_> { self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) } - ast::Expr::TryBlockExpr(e) => { - let body = self.collect_block_opt(e.body()); - self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) - } + ast::Expr::EffectExpr(e) => match e.effect() { + ast::Effect::Try(_) => { + let body = self.collect_block_opt(e.block_expr()); + self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) + } + // FIXME: we need to record these effects somewhere... + ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => { + self.collect_block_opt(e.block_expr()) + } + }, ast::Expr::BlockExpr(e) => self.collect_block(e), ast::Expr::LoopExpr(e) => { let body = self.collect_block_opt(e.loop_body()); @@ -494,12 +500,8 @@ impl ExprCollector<'_> { } } - fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { - let syntax_node_ptr = AstPtr::new(&expr.clone().into()); - let block = match expr.block() { - Some(block) => block, - None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), - }; + fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { + let syntax_node_ptr = AstPtr::new(&block.clone().into()); self.collect_block_items(&block); let statements = block .statements() @@ -517,7 +519,7 @@ impl ExprCollector<'_> { self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) } - fn collect_block_items(&mut self, block: &ast::Block) { + fn collect_block_items(&mut self, block: &ast::BlockExpr) { let container = ContainerId::DefWithBodyId(self.def); for item in block.items() { let (def, name): (ModuleDefId, Option) = match item { diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 047452306..4c12d0a15 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -330,7 +330,7 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { FragmentKind::Expr } // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that - EXPR_STMT | BLOCK => FragmentKind::Expr, + EXPR_STMT | BLOCK_EXPR => FragmentKind::Expr, ARG_LIST => FragmentKind::Expr, TRY_EXPR => FragmentKind::Expr, TUPLE_EXPR => FragmentKind::Expr, @@ -342,7 +342,6 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { CONDITION => FragmentKind::Expr, BREAK_EXPR => FragmentKind::Expr, RETURN_EXPR => FragmentKind::Expr, - BLOCK_EXPR => FragmentKind::Expr, MATCH_EXPR => FragmentKind::Expr, MATCH_ARM => FragmentKind::Expr, MATCH_GUARD => FragmentKind::Expr, diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 118fceb2e..c529752d4 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -344,7 +344,7 @@ impl<'a> CompletionContext<'a> { stmt.syntax().text_range() == name_ref.syntax().text_range(), ); } - if let Some(block) = ast::Block::cast(node) { + if let Some(block) = ast::BlockExpr::cast(node) { return Some( block.expr().map(|e| e.syntax().text_range()) == Some(name_ref.syntax().text_range()), diff --git a/crates/ra_ide/src/folding_ranges.rs b/crates/ra_ide/src/folding_ranges.rs index 4379005aa..8657377de 100644 --- a/crates/ra_ide/src/folding_ranges.rs +++ b/crates/ra_ide/src/folding_ranges.rs @@ -88,7 +88,7 @@ fn fold_kind(kind: SyntaxKind) -> Option { | ITEM_LIST | EXTERN_ITEM_LIST | USE_TREE_LIST - | BLOCK + | BLOCK_EXPR | MATCH_ARM_LIST | ENUM_VARIANT_LIST | TOKEN_TREE => Some(FoldKind::Block), diff --git a/crates/ra_ide/src/join_lines.rs b/crates/ra_ide/src/join_lines.rs index d0def7eaa..63fd6b3e4 100644 --- a/crates/ra_ide/src/join_lines.rs +++ b/crates/ra_ide/src/join_lines.rs @@ -129,8 +129,7 @@ fn has_comma_after(node: &SyntaxNode) -> bool { } fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> { - let block = ast::Block::cast(token.parent())?; - let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; + let block_expr = ast::BlockExpr::cast(token.parent())?; if !block_expr.is_standalone() { return None; } diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs index bf97f8c56..86c70ff83 100644 --- a/crates/ra_ide/src/syntax_tree.rs +++ b/crates/ra_ide/src/syntax_tree.rs @@ -120,9 +120,8 @@ SOURCE_FILE@0..11 R_PAREN@7..8 ")" WHITESPACE@8..9 " " BLOCK_EXPR@9..11 - BLOCK@9..11 - L_CURLY@9..10 "{" - R_CURLY@10..11 "}" + L_CURLY@9..10 "{" + R_CURLY@10..11 "}" "# .trim() ); @@ -153,26 +152,25 @@ SOURCE_FILE@0..60 R_PAREN@8..9 ")" WHITESPACE@9..10 " " BLOCK_EXPR@10..60 - BLOCK@10..60 - L_CURLY@10..11 "{" - WHITESPACE@11..16 "\n " - EXPR_STMT@16..58 - MACRO_CALL@16..57 - PATH@16..22 - PATH_SEGMENT@16..22 - NAME_REF@16..22 - IDENT@16..22 "assert" - BANG@22..23 "!" - TOKEN_TREE@23..57 - L_PAREN@23..24 "(" - STRING@24..52 "\"\n fn foo() {\n ..." - COMMA@52..53 "," - WHITESPACE@53..54 " " - STRING@54..56 "\"\"" - R_PAREN@56..57 ")" - SEMICOLON@57..58 ";" - WHITESPACE@58..59 "\n" - R_CURLY@59..60 "}" + L_CURLY@10..11 "{" + WHITESPACE@11..16 "\n " + EXPR_STMT@16..58 + MACRO_CALL@16..57 + PATH@16..22 + PATH_SEGMENT@16..22 + NAME_REF@16..22 + IDENT@16..22 "assert" + BANG@22..23 "!" + TOKEN_TREE@23..57 + L_PAREN@23..24 "(" + STRING@24..52 "\"\n fn foo() {\n ..." + COMMA@52..53 "," + WHITESPACE@53..54 " " + STRING@54..56 "\"\"" + R_PAREN@56..57 ")" + SEMICOLON@57..58 ";" + WHITESPACE@58..59 "\n" + R_CURLY@59..60 "}" "# .trim() ); @@ -196,9 +194,8 @@ FN_DEF@0..11 R_PAREN@7..8 ")" WHITESPACE@8..9 " " BLOCK_EXPR@9..11 - BLOCK@9..11 - L_CURLY@9..10 "{" - R_CURLY@10..11 "}" + L_CURLY@9..10 "{" + R_CURLY@10..11 "}" "# .trim() ); @@ -265,10 +262,9 @@ SOURCE_FILE@0..12 R_PAREN@7..8 ")" WHITESPACE@8..9 " " BLOCK_EXPR@9..12 - BLOCK@9..12 - L_CURLY@9..10 "{" - WHITESPACE@10..11 "\n" - R_CURLY@11..12 "}" + L_CURLY@9..10 "{" + WHITESPACE@10..11 "\n" + R_CURLY@11..12 "}" "# .trim() ); @@ -300,10 +296,9 @@ SOURCE_FILE@0..12 R_PAREN@7..8 ")" WHITESPACE@8..9 " " BLOCK_EXPR@9..12 - BLOCK@9..12 - L_CURLY@9..10 "{" - WHITESPACE@10..11 "\n" - R_CURLY@11..12 "}" + L_CURLY@9..10 "{" + WHITESPACE@10..11 "\n" + R_CURLY@11..12 "}" "# .trim() ); @@ -334,10 +329,9 @@ SOURCE_FILE@0..25 R_PAREN@7..8 ")" WHITESPACE@8..9 " " BLOCK_EXPR@9..12 - BLOCK@9..12 - L_CURLY@9..10 "{" - WHITESPACE@10..11 "\n" - R_CURLY@11..12 "}" + L_CURLY@9..10 "{" + WHITESPACE@10..11 "\n" + R_CURLY@11..12 "}" WHITESPACE@12..13 "\n" FN_DEF@13..25 FN_KW@13..15 "fn" @@ -349,10 +343,9 @@ SOURCE_FILE@0..25 R_PAREN@20..21 ")" WHITESPACE@21..22 " " BLOCK_EXPR@22..25 - BLOCK@22..25 - L_CURLY@22..23 "{" - WHITESPACE@23..24 "\n" - R_CURLY@24..25 "}" + L_CURLY@22..23 "{" + WHITESPACE@23..24 "\n" + R_CURLY@24..25 "}" "# .trim() ); diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 0d924ce58..c43003fd6 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs @@ -266,21 +266,20 @@ fn test_expr_order() { L_PAREN@5..6 "(" R_PAREN@6..7 ")" BLOCK_EXPR@7..15 - BLOCK@7..15 - L_CURLY@7..8 "{" - EXPR_STMT@8..14 - BIN_EXPR@8..13 - BIN_EXPR@8..11 - LITERAL@8..9 - INT_NUMBER@8..9 "1" - PLUS@9..10 "+" - LITERAL@10..11 - INT_NUMBER@10..11 "1" - STAR@11..12 "*" - LITERAL@12..13 - INT_NUMBER@12..13 "2" - SEMICOLON@13..14 ";" - R_CURLY@14..15 "}""#, + L_CURLY@7..8 "{" + EXPR_STMT@8..14 + BIN_EXPR@8..13 + BIN_EXPR@8..11 + LITERAL@8..9 + INT_NUMBER@8..9 "1" + PLUS@9..10 "+" + LITERAL@10..11 + INT_NUMBER@10..11 "1" + STAR@11..12 "*" + LITERAL@12..13 + INT_NUMBER@12..13 "2" + SEMICOLON@13..14 ";" + R_CURLY@14..15 "}""#, ); } @@ -1114,68 +1113,67 @@ fn test_vec() { assert_eq!( format!("{:#?}", tree).trim(), r#"BLOCK_EXPR@0..45 - BLOCK@0..45 - L_CURLY@0..1 "{" - LET_STMT@1..20 - LET_KW@1..4 "let" - BIND_PAT@4..8 - MUT_KW@4..7 "mut" - NAME@7..8 - IDENT@7..8 "v" - EQ@8..9 "=" - CALL_EXPR@9..19 - PATH_EXPR@9..17 - PATH@9..17 - PATH@9..12 - PATH_SEGMENT@9..12 - NAME_REF@9..12 - IDENT@9..12 "Vec" - COLON2@12..14 "::" - PATH_SEGMENT@14..17 - NAME_REF@14..17 - IDENT@14..17 "new" - ARG_LIST@17..19 - L_PAREN@17..18 "(" - R_PAREN@18..19 ")" - SEMICOLON@19..20 ";" - EXPR_STMT@20..33 - METHOD_CALL_EXPR@20..32 - PATH_EXPR@20..21 - PATH@20..21 - PATH_SEGMENT@20..21 - NAME_REF@20..21 - IDENT@20..21 "v" - DOT@21..22 "." - NAME_REF@22..26 - IDENT@22..26 "push" - ARG_LIST@26..32 - L_PAREN@26..27 "(" - LITERAL@27..31 - INT_NUMBER@27..31 "1u32" - R_PAREN@31..32 ")" - SEMICOLON@32..33 ";" - EXPR_STMT@33..43 - METHOD_CALL_EXPR@33..42 - PATH_EXPR@33..34 - PATH@33..34 - PATH_SEGMENT@33..34 - NAME_REF@33..34 - IDENT@33..34 "v" - DOT@34..35 "." - NAME_REF@35..39 - IDENT@35..39 "push" - ARG_LIST@39..42 - L_PAREN@39..40 "(" - LITERAL@40..41 - INT_NUMBER@40..41 "2" - R_PAREN@41..42 ")" - SEMICOLON@42..43 ";" - PATH_EXPR@43..44 - PATH@43..44 - PATH_SEGMENT@43..44 - NAME_REF@43..44 - IDENT@43..44 "v" - R_CURLY@44..45 "}""# + L_CURLY@0..1 "{" + LET_STMT@1..20 + LET_KW@1..4 "let" + BIND_PAT@4..8 + MUT_KW@4..7 "mut" + NAME@7..8 + IDENT@7..8 "v" + EQ@8..9 "=" + CALL_EXPR@9..19 + PATH_EXPR@9..17 + PATH@9..17 + PATH@9..12 + PATH_SEGMENT@9..12 + NAME_REF@9..12 + IDENT@9..12 "Vec" + COLON2@12..14 "::" + PATH_SEGMENT@14..17 + NAME_REF@14..17 + IDENT@14..17 "new" + ARG_LIST@17..19 + L_PAREN@17..18 "(" + R_PAREN@18..19 ")" + SEMICOLON@19..20 ";" + EXPR_STMT@20..33 + METHOD_CALL_EXPR@20..32 + PATH_EXPR@20..21 + PATH@20..21 + PATH_SEGMENT@20..21 + NAME_REF@20..21 + IDENT@20..21 "v" + DOT@21..22 "." + NAME_REF@22..26 + IDENT@22..26 "push" + ARG_LIST@26..32 + L_PAREN@26..27 "(" + LITERAL@27..31 + INT_NUMBER@27..31 "1u32" + R_PAREN@31..32 ")" + SEMICOLON@32..33 ";" + EXPR_STMT@33..43 + METHOD_CALL_EXPR@33..42 + PATH_EXPR@33..34 + PATH@33..34 + PATH_SEGMENT@33..34 + NAME_REF@33..34 + IDENT@33..34 "v" + DOT@34..35 "." + NAME_REF@35..39 + IDENT@35..39 "push" + ARG_LIST@39..42 + L_PAREN@39..40 "(" + LITERAL@40..41 + INT_NUMBER@40..41 "2" + R_PAREN@41..42 ")" + SEMICOLON@42..43 ";" + PATH_EXPR@43..44 + PATH@43..44 + PATH_SEGMENT@43..44 + NAME_REF@43..44 + IDENT@43..44 "v" + R_CURLY@44..45 "}""# ); } diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index c2a6e82e9..d9824ff9b 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs @@ -143,7 +143,7 @@ pub(crate) fn reparser( parent: Option, ) -> Option { let res = match node { - BLOCK => expressions::naked_block, + BLOCK_EXPR => expressions::block, RECORD_FIELD_DEF_LIST => items::record_field_def_list, RECORD_FIELD_LIST => items::record_field_list, ENUM_VARIANT_LIST => items::enum_variant_list, diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index cb30b25a8..a23dbcacf 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs @@ -59,16 +59,7 @@ pub(crate) fn block(p: &mut Parser) { p.error("expected a block"); return; } - atom::block_expr(p, None); -} - -pub(crate) fn naked_block(p: &mut Parser) { - assert!(p.at(T!['{'])); - let m = p.start(); - p.bump(T!['{']); - expr_block_contents(p); - p.expect(T!['}']); - m.complete(p, BLOCK); + atom::block_expr(p); } fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool { @@ -197,7 +188,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { } } -pub(crate) fn expr_block_contents(p: &mut Parser) { +pub(super) fn expr_block_contents(p: &mut Parser) { // This is checked by a validator attributes::inner_attributes(p); diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 166dfc472..c76b7330c 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -92,7 +92,10 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar T![loop] => loop_expr(p, Some(m)), T![for] => for_expr(p, Some(m)), T![while] => while_expr(p, Some(m)), - T!['{'] => block_expr(p, Some(m)), + T!['{'] => { + block_expr(p); + m.complete(p, EFFECT_EXPR) + } _ => { // test_err misplaced_label_err // fn main() { @@ -108,13 +111,15 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar let m = p.start(); p.bump(T![async]); p.eat(T![move]); - block_expr(p, Some(m)) + block_expr(p); + m.complete(p, EFFECT_EXPR) } T![match] => match_expr(p), T![unsafe] if la == T!['{'] => { let m = p.start(); p.bump(T![unsafe]); - block_expr(p, Some(m)) + block_expr(p); + m.complete(p, EFFECT_EXPR) } T!['{'] => { // test for_range_from @@ -123,7 +128,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar // break; // } // } - block_expr(p, None) + block_expr(p) } T![return] => return_expr(p), T![continue] => continue_expr(p), @@ -134,7 +139,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar } }; let blocklike = match done.kind() { - IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_BLOCK_EXPR => { + IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | EFFECT_EXPR => { BlockLike::Block } _ => BlockLike::NotBlock, @@ -234,7 +239,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { if p.at(T!['{']) { // test lambda_ret_block // fn main() { || -> i32 { 92 }(); } - block_expr(p, None); + block_expr(p); } else { p.error("expected `{`"); } @@ -464,10 +469,12 @@ fn match_guard(p: &mut Parser) -> CompletedMarker { // unsafe {}; // 'label: {}; // } -pub(super) fn block_expr(p: &mut Parser, m: Option) -> CompletedMarker { +pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker { assert!(p.at(T!['{'])); - let m = m.unwrap_or_else(|| p.start()); - naked_block(p); + let m = p.start(); + p.bump(T!['{']); + expr_block_contents(p); + p.expect(T!['}']); m.complete(p, BLOCK_EXPR) } @@ -552,8 +559,8 @@ fn try_block_expr(p: &mut Parser, m: Option) -> CompletedMarker { } p.bump(T![try]); - block(p); - m.complete(p, TRY_EXPR) + block_expr(p); + m.complete(p, EFFECT_EXPR) } // test box_expr diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index 524e7d784..e7404492a 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -191,7 +191,7 @@ pub enum SyntaxKind { RECORD_LIT, RECORD_FIELD_LIST, RECORD_FIELD, - TRY_BLOCK_EXPR, + EFFECT_EXPR, BOX_EXPR, CALL_EXPR, INDEX_EXPR, @@ -204,7 +204,6 @@ pub enum SyntaxKind { PREFIX_EXPR, RANGE_EXPR, BIN_EXPR, - BLOCK, EXTERN_BLOCK, EXTERN_ITEM_LIST, ENUM_VARIANT, diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index a716e525b..1876afe95 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -16,7 +16,7 @@ use crate::{ }; pub use self::{ - expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, + expr_extensions::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, extensions::{ AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 26e4576ff..c507dc683 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs @@ -28,7 +28,7 @@ impl ast::BinExpr { impl ast::FnDef { #[must_use] - pub fn with_body(&self, body: ast::Block) -> ast::FnDef { + pub fn with_body(&self, body: ast::BlockExpr) -> ast::FnDef { let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { old_body.syntax().clone().into() diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs index ecf74fd36..7ee36e60c 100644 --- a/crates/ra_syntax/src/ast/expr_extensions.rs +++ b/crates/ra_syntax/src/ast/expr_extensions.rs @@ -16,7 +16,7 @@ impl ast::Expr { | ast::Expr::WhileExpr(_) | ast::Expr::BlockExpr(_) | ast::Expr::MatchExpr(_) - | ast::Expr::TryBlockExpr(_) => true, + | ast::Expr::EffectExpr(_) => true, _ => false, } } @@ -359,6 +359,33 @@ impl ast::Literal { } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Effect { + Async(SyntaxToken), + Unsafe(SyntaxToken), + Try(SyntaxToken), + // Very much not an effect, but we stuff it into this node anyway + Label(ast::Label), +} + +impl ast::EffectExpr { + pub fn effect(&self) -> Effect { + if let Some(token) = self.async_token() { + return Effect::Async(token); + } + if let Some(token) = self.unsafe_token() { + return Effect::Unsafe(token); + } + if let Some(token) = self.try_token() { + return Effect::Try(token); + } + if let Some(label) = self.label() { + return Effect::Label(label); + } + unreachable!("ast::EffectExpr without Effect") + } +} + impl ast::BlockExpr { /// false if the block is an intrinsic part of the syntax and can't be /// replaced with arbitrary expression. @@ -368,15 +395,12 @@ impl ast::BlockExpr { /// const FOO: () = { stand_alone }; /// ``` pub fn is_standalone(&self) -> bool { - if self.unsafe_token().is_some() || self.async_token().is_some() { - return false; - } - let kind = match self.syntax().parent() { + let parent = match self.syntax().parent() { + Some(it) => it, None => return true, - Some(it) => it.kind(), }; - match kind { - FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | TRY_BLOCK_EXPR => false, + match parent.kind() { + FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR => false, _ => true, } } diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 2096f12f1..5e844d5ae 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs @@ -476,13 +476,16 @@ impl LoopExpr { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TryBlockExpr { +pub struct EffectExpr { pub(crate) syntax: SyntaxNode, } -impl ast::AttrsOwner for TryBlockExpr {} -impl TryBlockExpr { +impl ast::AttrsOwner for EffectExpr {} +impl EffectExpr { + pub fn label(&self) -> Option