aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock48
-rw-r--r--crates/assists/src/assist_context.rs5
-rw-r--r--crates/assists/src/handlers/inline_local_variable.rs45
-rw-r--r--crates/completion/src/context.rs8
-rw-r--r--crates/hir_def/src/body/lower.rs4
-rw-r--r--crates/hir_def/src/expr.rs5
-rw-r--r--crates/hir_expand/src/db.rs2
-rw-r--r--crates/hir_expand/src/lib.rs8
-rw-r--r--crates/hir_ty/src/infer/expr.rs7
-rw-r--r--crates/ide/src/extend_selection.rs6
-rw-r--r--crates/ide/src/join_lines.rs4
-rw-r--r--crates/ide/src/syntax_tree.rs4
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs16
-rw-r--r--crates/parser/src/syntax_kind/generated.rs8
-rw-r--r--crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt47
-rw-r--r--crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt47
-rw-r--r--crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt47
-rw-r--r--crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt120
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs53
-rw-r--r--crates/syntax/src/algo.rs6
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs34
-rw-r--r--crates/syntax/src/parsing/reparsing.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0159_yield_expr.rast28
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0159_yield_expr.rs4
-rw-r--r--xtask/Cargo.toml2
-rw-r--r--xtask/src/ast_src.rs3
26 files changed, 204 insertions, 362 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f9f1c041e..dcf939d60 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -26,9 +26,9 @@ dependencies = [
26 26
27[[package]] 27[[package]]
28name = "anyhow" 28name = "anyhow"
29version = "1.0.38" 29version = "1.0.37"
30source = "registry+https://github.com/rust-lang/crates.io-index" 30source = "registry+https://github.com/rust-lang/crates.io-index"
31checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" 31checksum = "ee67c11feeac938fae061b232e38e0b6d94f97a9df10e6271319325ac4c56a86"
32 32
33[[package]] 33[[package]]
34name = "anymap" 34name = "anymap"
@@ -118,9 +118,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
118 118
119[[package]] 119[[package]]
120name = "byteorder" 120name = "byteorder"
121version = "1.4.2" 121version = "1.3.4"
122source = "registry+https://github.com/rust-lang/crates.io-index" 122source = "registry+https://github.com/rust-lang/crates.io-index"
123checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" 123checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
124 124
125[[package]] 125[[package]]
126name = "cargo-platform" 126name = "cargo-platform"
@@ -269,9 +269,9 @@ dependencies = [
269 269
270[[package]] 270[[package]]
271name = "const_fn" 271name = "const_fn"
272version = "0.4.5" 272version = "0.4.4"
273source = "registry+https://github.com/rust-lang/crates.io-index" 273source = "registry+https://github.com/rust-lang/crates.io-index"
274checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" 274checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
275 275
276[[package]] 276[[package]]
277name = "crc32fast" 277name = "crc32fast"
@@ -791,9 +791,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
791 791
792[[package]] 792[[package]]
793name = "libc" 793name = "libc"
794version = "0.2.82" 794version = "0.2.81"
795source = "registry+https://github.com/rust-lang/crates.io-index" 795source = "registry+https://github.com/rust-lang/crates.io-index"
796checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" 796checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
797 797
798[[package]] 798[[package]]
799name = "libloading" 799name = "libloading"
@@ -825,9 +825,9 @@ dependencies = [
825 825
826[[package]] 826[[package]]
827name = "log" 827name = "log"
828version = "0.4.13" 828version = "0.4.11"
829source = "registry+https://github.com/rust-lang/crates.io-index" 829source = "registry+https://github.com/rust-lang/crates.io-index"
830checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" 830checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
831dependencies = [ 831dependencies = [
832 "cfg-if 0.1.10", 832 "cfg-if 0.1.10",
833] 833]
@@ -1160,9 +1160,9 @@ checksum = "28b9b4df73455c861d7cbf8be42f01d3b373ed7f02e378d55fa84eafc6f638b1"
1160 1160
1161[[package]] 1161[[package]]
1162name = "pin-project-lite" 1162name = "pin-project-lite"
1163version = "0.2.4" 1163version = "0.2.0"
1164source = "registry+https://github.com/rust-lang/crates.io-index" 1164source = "registry+https://github.com/rust-lang/crates.io-index"
1165checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" 1165checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
1166 1166
1167[[package]] 1167[[package]]
1168name = "proc-macro2" 1168name = "proc-macro2"
@@ -1300,9 +1300,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
1300 1300
1301[[package]] 1301[[package]]
1302name = "regex" 1302name = "regex"
1303version = "1.4.3" 1303version = "1.4.2"
1304source = "registry+https://github.com/rust-lang/crates.io-index" 1304source = "registry+https://github.com/rust-lang/crates.io-index"
1305checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" 1305checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
1306dependencies = [ 1306dependencies = [
1307 "regex-syntax", 1307 "regex-syntax",
1308] 1308]
@@ -1319,9 +1319,9 @@ dependencies = [
1319 1319
1320[[package]] 1320[[package]]
1321name = "regex-syntax" 1321name = "regex-syntax"
1322version = "0.6.22" 1322version = "0.6.21"
1323source = "registry+https://github.com/rust-lang/crates.io-index" 1323source = "registry+https://github.com/rust-lang/crates.io-index"
1324checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" 1324checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
1325 1325
1326[[package]] 1326[[package]]
1327name = "rowan" 1327name = "rowan"
@@ -1550,9 +1550,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1550 1550
1551[[package]] 1551[[package]]
1552name = "smallvec" 1552name = "smallvec"
1553version = "1.6.1" 1553version = "1.6.0"
1554source = "registry+https://github.com/rust-lang/crates.io-index" 1554source = "registry+https://github.com/rust-lang/crates.io-index"
1555checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 1555checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0"
1556 1556
1557[[package]] 1557[[package]]
1558name = "smol_str" 1558name = "smol_str"
@@ -1592,9 +1592,9 @@ dependencies = [
1592 1592
1593[[package]] 1593[[package]]
1594name = "syn" 1594name = "syn"
1595version = "1.0.58" 1595version = "1.0.57"
1596source = "registry+https://github.com/rust-lang/crates.io-index" 1596source = "registry+https://github.com/rust-lang/crates.io-index"
1597checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" 1597checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6"
1598dependencies = [ 1598dependencies = [
1599 "proc-macro2", 1599 "proc-macro2",
1600 "quote", 1600 "quote",
@@ -1671,9 +1671,9 @@ dependencies = [
1671 1671
1672[[package]] 1672[[package]]
1673name = "thread_local" 1673name = "thread_local"
1674version = "1.1.0" 1674version = "1.0.1"
1675source = "registry+https://github.com/rust-lang/crates.io-index" 1675source = "registry+https://github.com/rust-lang/crates.io-index"
1676checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447" 1676checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
1677dependencies = [ 1677dependencies = [
1678 "lazy_static", 1678 "lazy_static",
1679] 1679]
@@ -1837,9 +1837,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
1837 1837
1838[[package]] 1838[[package]]
1839name = "ungrammar" 1839name = "ungrammar"
1840version = "1.6.0" 1840version = "1.7.0"
1841source = "registry+https://github.com/rust-lang/crates.io-index" 1841source = "registry+https://github.com/rust-lang/crates.io-index"
1842checksum = "f96cc1b6938f7c548fbcc630bac5c896ae77a130909829ab18b8eab78c51b7ee" 1842checksum = "7758fccf6038d5c368a17c7224abc85d6508d5ae266d5a3de25faac3cc168509"
1843 1843
1844[[package]] 1844[[package]]
1845name = "unicase" 1845name = "unicase"
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs
index 321fe77f3..8d93edba2 100644
--- a/crates/assists/src/assist_context.rs
+++ b/crates/assists/src/assist_context.rs
@@ -2,7 +2,6 @@
2 2
3use std::mem; 3use std::mem;
4 4
5use algo::find_covering_element;
6use hir::Semantics; 5use hir::Semantics;
7use ide_db::{ 6use ide_db::{
8 base_db::{AnchoredPathBuf, FileId, FileRange}, 7 base_db::{AnchoredPathBuf, FileId, FileRange},
@@ -94,11 +93,11 @@ impl<'a> AssistContext<'a> {
94 self.sema.find_node_at_offset_with_descend(self.source_file.syntax(), self.offset()) 93 self.sema.find_node_at_offset_with_descend(self.source_file.syntax(), self.offset())
95 } 94 }
96 pub(crate) fn covering_element(&self) -> SyntaxElement { 95 pub(crate) fn covering_element(&self) -> SyntaxElement {
97 find_covering_element(self.source_file.syntax(), self.frange.range) 96 self.source_file.syntax().covering_element(self.frange.range)
98 } 97 }
99 // FIXME: remove 98 // FIXME: remove
100 pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { 99 pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {
101 find_covering_element(self.source_file.syntax(), range) 100 self.source_file.syntax().covering_element(range)
102 } 101 }
103} 102}
104 103
diff --git a/crates/assists/src/handlers/inline_local_variable.rs b/crates/assists/src/handlers/inline_local_variable.rs
index dc798daaa..0e63a60e8 100644
--- a/crates/assists/src/handlers/inline_local_variable.rs
+++ b/crates/assists/src/handlers/inline_local_variable.rs
@@ -79,29 +79,30 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> O
79 None => return Ok(false), 79 None => return Ok(false),
80 }; 80 };
81 81
82 Ok(!matches!((&initializer_expr, usage_parent), 82 Ok(!matches!(
83 (&initializer_expr, usage_parent),
83 (ast::Expr::CallExpr(_), _) 84 (ast::Expr::CallExpr(_), _)
84 | (ast::Expr::IndexExpr(_), _) 85 | (ast::Expr::IndexExpr(_), _)
85 | (ast::Expr::MethodCallExpr(_), _) 86 | (ast::Expr::MethodCallExpr(_), _)
86 | (ast::Expr::FieldExpr(_), _) 87 | (ast::Expr::FieldExpr(_), _)
87 | (ast::Expr::TryExpr(_), _) 88 | (ast::Expr::TryExpr(_), _)
88 | (ast::Expr::RefExpr(_), _) 89 | (ast::Expr::RefExpr(_), _)
89 | (ast::Expr::Literal(_), _) 90 | (ast::Expr::Literal(_), _)
90 | (ast::Expr::TupleExpr(_), _) 91 | (ast::Expr::TupleExpr(_), _)
91 | (ast::Expr::ArrayExpr(_), _) 92 | (ast::Expr::ArrayExpr(_), _)
92 | (ast::Expr::ParenExpr(_), _) 93 | (ast::Expr::ParenExpr(_), _)
93 | (ast::Expr::PathExpr(_), _) 94 | (ast::Expr::PathExpr(_), _)
94 | (ast::Expr::BlockExpr(_), _) 95 | (ast::Expr::BlockExpr(_), _)
95 | (ast::Expr::EffectExpr(_), _) 96 | (ast::Expr::EffectExpr(_), _)
96 | (_, ast::Expr::CallExpr(_)) 97 | (_, ast::Expr::CallExpr(_))
97 | (_, ast::Expr::TupleExpr(_)) 98 | (_, ast::Expr::TupleExpr(_))
98 | (_, ast::Expr::ArrayExpr(_)) 99 | (_, ast::Expr::ArrayExpr(_))
99 | (_, ast::Expr::ParenExpr(_)) 100 | (_, ast::Expr::ParenExpr(_))
100 | (_, ast::Expr::ForExpr(_)) 101 | (_, ast::Expr::ForExpr(_))
101 | (_, ast::Expr::WhileExpr(_)) 102 | (_, ast::Expr::WhileExpr(_))
102 | (_, ast::Expr::BreakExpr(_)) 103 | (_, ast::Expr::BreakExpr(_))
103 | (_, ast::Expr::ReturnExpr(_)) 104 | (_, ast::Expr::ReturnExpr(_))
104 | (_, ast::Expr::MatchExpr(_)) 105 | (_, ast::Expr::MatchExpr(_))
105 )) 106 ))
106 }) 107 })
107 .collect::<Result<Vec<_>, _>>()?; 108 .collect::<Result<Vec<_>, _>>()?;
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs
index d809460e2..b1e8eba85 100644
--- a/crates/completion/src/context.rs
+++ b/crates/completion/src/context.rs
@@ -4,10 +4,8 @@ use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type};
4use ide_db::base_db::{FilePosition, SourceDatabase}; 4use ide_db::base_db::{FilePosition, SourceDatabase};
5use ide_db::{call_info::ActiveParameter, RootDatabase}; 5use ide_db::{call_info::ActiveParameter, RootDatabase};
6use syntax::{ 6use syntax::{
7 algo::{find_covering_element, find_node_at_offset}, 7 algo::find_node_at_offset, ast, match_ast, AstNode, NodeOrToken, SyntaxKind::*, SyntaxNode,
8 ast, match_ast, AstNode, NodeOrToken, 8 SyntaxToken, TextRange, TextSize,
9 SyntaxKind::*,
10 SyntaxNode, SyntaxToken, TextRange, TextSize,
11}; 9};
12use test_utils::mark; 10use test_utils::mark;
13use text_edit::Indel; 11use text_edit::Indel;
@@ -513,7 +511,7 @@ impl<'a> CompletionContext<'a> {
513} 511}
514 512
515fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> { 513fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
516 find_covering_element(syntax, range).ancestors().find_map(N::cast) 514 syntax.covering_element(range).ancestors().find_map(N::cast)
517} 515}
518 516
519fn is_node<N: AstNode>(node: &SyntaxNode) -> bool { 517fn is_node<N: AstNode>(node: &SyntaxNode) -> bool {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 27575c537..4ce5e5b72 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -386,6 +386,10 @@ impl ExprCollector<'_> {
386 let expr = e.expr().map(|e| self.collect_expr(e)); 386 let expr = e.expr().map(|e| self.collect_expr(e));
387 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 387 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
388 } 388 }
389 ast::Expr::YieldExpr(e) => {
390 let expr = e.expr().map(|e| self.collect_expr(e));
391 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
392 }
389 ast::Expr::RecordExpr(e) => { 393 ast::Expr::RecordExpr(e) => {
390 let path = e.path().and_then(|path| self.expander.parse_path(path)); 394 let path = e.path().and_then(|path| self.expander.parse_path(path));
391 let mut field_ptrs = Vec::new(); 395 let mut field_ptrs = Vec::new();
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index af01d32dc..a293df9f1 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -99,6 +99,9 @@ pub enum Expr {
99 Return { 99 Return {
100 expr: Option<ExprId>, 100 expr: Option<ExprId>,
101 }, 101 },
102 Yield {
103 expr: Option<ExprId>,
104 },
102 RecordLit { 105 RecordLit {
103 path: Option<Path>, 106 path: Option<Path>,
104 fields: Vec<RecordLitField>, 107 fields: Vec<RecordLitField>,
@@ -294,7 +297,7 @@ impl Expr {
294 } 297 }
295 } 298 }
296 Expr::Continue { .. } => {} 299 Expr::Continue { .. } => {}
297 Expr::Break { expr, .. } | Expr::Return { expr } => { 300 Expr::Break { expr, .. } | Expr::Return { expr } | Expr::Yield { expr } => {
298 if let Some(expr) = expr { 301 if let Some(expr) = expr {
299 f(*expr); 302 f(*expr);
300 } 303 }
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index c62086390..467516eb7 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -118,7 +118,7 @@ pub fn expand_hypothetical(
118 parse_macro_with_arg(db, macro_file, Some(std::sync::Arc::new((tt, tmap_1)))).value?; 118 parse_macro_with_arg(db, macro_file, Some(std::sync::Arc::new((tt, tmap_1)))).value?;
119 let token_id = macro_def.0.map_id_down(token_id); 119 let token_id = macro_def.0.map_id_down(token_id);
120 let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?; 120 let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?;
121 let token = syntax::algo::find_covering_element(&node.syntax_node(), range).into_token()?; 121 let token = node.syntax_node().covering_element(range).into_token()?;
122 Some((node.syntax_node(), token)) 122 Some((node.syntax_node(), token))
123} 123}
124 124
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 3fa1b1d77..e388ddacc 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -22,7 +22,7 @@ use std::sync::Arc;
22 22
23use base_db::{impl_intern_key, salsa, CrateId, FileId, FileRange}; 23use base_db::{impl_intern_key, salsa, CrateId, FileId, FileRange};
24use syntax::{ 24use syntax::{
25 algo::{self, skip_trivia_token}, 25 algo::skip_trivia_token,
26 ast::{self, AstNode}, 26 ast::{self, AstNode},
27 Direction, SyntaxNode, SyntaxToken, TextRange, TextSize, 27 Direction, SyntaxNode, SyntaxToken, TextRange, TextSize,
28}; 28};
@@ -335,7 +335,7 @@ impl ExpansionInfo {
335 335
336 let range = self.exp_map.range_by_token(token_id)?.by_kind(token.value.kind())?; 336 let range = self.exp_map.range_by_token(token_id)?.by_kind(token.value.kind())?;
337 337
338 let token = algo::find_covering_element(&self.expanded.value, range).into_token()?; 338 let token = self.expanded.value.covering_element(range).into_token()?;
339 339
340 Some(self.expanded.with_value(token)) 340 Some(self.expanded.with_value(token))
341 } 341 }
@@ -360,8 +360,8 @@ impl ExpansionInfo {
360 }; 360 };
361 361
362 let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?; 362 let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?;
363 let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) 363 let token =
364 .into_token()?; 364 tt.value.covering_element(range + tt.value.text_range().start()).into_token()?;
365 Some((tt.with_value(token), origin)) 365 Some((tt.with_value(token), origin))
366 } 366 }
367} 367}
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index f2fc69b2f..9bf3b51b0 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -367,6 +367,13 @@ impl<'a> InferenceContext<'a> {
367 } 367 }
368 Ty::simple(TypeCtor::Never) 368 Ty::simple(TypeCtor::Never)
369 } 369 }
370 Expr::Yield { expr } => {
371 // FIXME: track yield type for coercion
372 if let Some(expr) = expr {
373 self.infer_expr(*expr, &Expectation::none());
374 }
375 Ty::simple(TypeCtor::Never)
376 }
370 Expr::RecordLit { path, fields, spread } => { 377 Expr::RecordLit { path, fields, spread } => {
371 let (ty, def_id) = self.resolve_variant(path.as_ref()); 378 let (ty, def_id) = self.resolve_variant(path.as_ref());
372 if let Some(variant) = def_id { 379 if let Some(variant) = def_id {
diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs
index 56418c960..17a540972 100644
--- a/crates/ide/src/extend_selection.rs
+++ b/crates/ide/src/extend_selection.rs
@@ -3,7 +3,7 @@ use std::iter::successors;
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::RootDatabase; 4use ide_db::RootDatabase;
5use syntax::{ 5use syntax::{
6 algo::{self, find_covering_element, skip_trivia_token}, 6 algo::{self, skip_trivia_token},
7 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
8 Direction, NodeOrToken, 8 Direction, NodeOrToken,
9 SyntaxKind::{self, *}, 9 SyntaxKind::{self, *},
@@ -76,7 +76,7 @@ fn try_extend_selection(
76 }; 76 };
77 return Some(leaf_range); 77 return Some(leaf_range);
78 }; 78 };
79 let node = match find_covering_element(root, range) { 79 let node = match root.covering_element(range) {
80 NodeOrToken::Token(token) => { 80 NodeOrToken::Token(token) => {
81 if token.text_range() != range { 81 if token.text_range() != range {
82 return Some(token.text_range()); 82 return Some(token.text_range());
@@ -120,7 +120,7 @@ fn extend_tokens_from_range(
120 macro_call: ast::MacroCall, 120 macro_call: ast::MacroCall,
121 original_range: TextRange, 121 original_range: TextRange,
122) -> Option<TextRange> { 122) -> Option<TextRange> {
123 let src = find_covering_element(&macro_call.syntax(), original_range); 123 let src = macro_call.syntax().covering_element(original_range);
124 let (first_token, last_token) = match src { 124 let (first_token, last_token) = match src {
125 NodeOrToken::Node(it) => (it.first_token()?, it.last_token()?), 125 NodeOrToken::Node(it) => (it.first_token()?, it.last_token()?),
126 NodeOrToken::Token(it) => (it.clone(), it), 126 NodeOrToken::Token(it) => (it.clone(), it),
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs
index 05380f2a1..981467c8d 100644
--- a/crates/ide/src/join_lines.rs
+++ b/crates/ide/src/join_lines.rs
@@ -1,7 +1,7 @@
1use assists::utils::extract_trivial_expression; 1use assists::utils::extract_trivial_expression;
2use itertools::Itertools; 2use itertools::Itertools;
3use syntax::{ 3use syntax::{
4 algo::{find_covering_element, non_trivia_sibling}, 4 algo::non_trivia_sibling,
5 ast::{self, AstNode, AstToken}, 5 ast::{self, AstNode, AstToken},
6 Direction, NodeOrToken, SourceFile, 6 Direction, NodeOrToken, SourceFile,
7 SyntaxKind::{self, USE_TREE, WHITESPACE}, 7 SyntaxKind::{self, USE_TREE, WHITESPACE},
@@ -31,7 +31,7 @@ pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit {
31 range 31 range
32 }; 32 };
33 33
34 let node = match find_covering_element(file.syntax(), range) { 34 let node = match file.syntax().covering_element(range) {
35 NodeOrToken::Node(node) => node, 35 NodeOrToken::Node(node) => node,
36 NodeOrToken::Token(token) => token.parent(), 36 NodeOrToken::Token(token) => token.parent(),
37 }; 37 };
diff --git a/crates/ide/src/syntax_tree.rs b/crates/ide/src/syntax_tree.rs
index 1f26f8043..1d4bac7ad 100644
--- a/crates/ide/src/syntax_tree.rs
+++ b/crates/ide/src/syntax_tree.rs
@@ -1,7 +1,7 @@
1use ide_db::base_db::{FileId, SourceDatabase}; 1use ide_db::base_db::{FileId, SourceDatabase};
2use ide_db::RootDatabase; 2use ide_db::RootDatabase;
3use syntax::{ 3use syntax::{
4 algo, AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize, 4 AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize,
5}; 5};
6 6
7// Feature: Show Syntax Tree 7// Feature: Show Syntax Tree
@@ -21,7 +21,7 @@ pub(crate) fn syntax_tree(
21) -> String { 21) -> String {
22 let parse = db.parse(file_id); 22 let parse = db.parse(file_id);
23 if let Some(text_range) = text_range { 23 if let Some(text_range) = text_range {
24 let node = match algo::find_covering_element(parse.tree().syntax(), text_range) { 24 let node = match parse.tree().syntax().covering_element(text_range) {
25 NodeOrToken::Node(node) => node, 25 NodeOrToken::Node(node) => node,
26 NodeOrToken::Token(token) => { 26 NodeOrToken::Token(token) => {
27 if let Some(tree) = syntax_tree_for_string(&token, text_range) { 27 if let Some(tree) = syntax_tree_for_string(&token, text_range) {
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index d61950b96..093a9890d 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -50,6 +50,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
50 T![match], 50 T![match],
51 T![unsafe], 51 T![unsafe],
52 T![return], 52 T![return],
53 T![yield],
53 T![break], 54 T![break],
54 T![continue], 55 T![continue],
55 T![async], 56 T![async],
@@ -142,6 +143,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
142 block_expr_unchecked(p) 143 block_expr_unchecked(p)
143 } 144 }
144 T![return] => return_expr(p), 145 T![return] => return_expr(p),
146 T![yield] => yield_expr(p),
145 T![continue] => continue_expr(p), 147 T![continue] => continue_expr(p),
146 T![break] => break_expr(p, r), 148 T![break] => break_expr(p, r),
147 _ => { 149 _ => {
@@ -508,6 +510,20 @@ fn return_expr(p: &mut Parser) -> CompletedMarker {
508 } 510 }
509 m.complete(p, RETURN_EXPR) 511 m.complete(p, RETURN_EXPR)
510} 512}
513// test yield_expr
514// fn foo() {
515// yield;
516// yield 1;
517// }
518fn yield_expr(p: &mut Parser) -> CompletedMarker {
519 assert!(p.at(T![yield]));
520 let m = p.start();
521 p.bump(T![yield]);
522 if p.at_ts(EXPR_FIRST) {
523 expr(p);
524 }
525 m.complete(p, YIELD_EXPR)
526}
511 527
512// test continue_expr 528// test continue_expr
513// fn foo() { 529// fn foo() {
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index f69e71bdb..7d53cc4cd 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -101,6 +101,7 @@ pub enum SyntaxKind {
101 USE_KW, 101 USE_KW,
102 WHERE_KW, 102 WHERE_KW,
103 WHILE_KW, 103 WHILE_KW,
104 YIELD_KW,
104 AUTO_KW, 105 AUTO_KW,
105 DEFAULT_KW, 106 DEFAULT_KW,
106 EXISTENTIAL_KW, 107 EXISTENTIAL_KW,
@@ -186,6 +187,7 @@ pub enum SyntaxKind {
186 LABEL, 187 LABEL,
187 BLOCK_EXPR, 188 BLOCK_EXPR,
188 RETURN_EXPR, 189 RETURN_EXPR,
190 YIELD_EXPR,
189 MATCH_EXPR, 191 MATCH_EXPR,
190 MATCH_ARM_LIST, 192 MATCH_ARM_LIST,
191 MATCH_ARM, 193 MATCH_ARM,
@@ -263,7 +265,8 @@ impl SyntaxKind {
263 | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW 265 | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
264 | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW 266 | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW
265 | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW 267 | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW
266 | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW | MACRO_RULES_KW => true, 268 | YIELD_KW | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW
269 | MACRO_RULES_KW => true,
267 _ => false, 270 _ => false,
268 } 271 }
269 } 272 }
@@ -326,6 +329,7 @@ impl SyntaxKind {
326 "use" => USE_KW, 329 "use" => USE_KW,
327 "where" => WHERE_KW, 330 "where" => WHERE_KW,
328 "while" => WHILE_KW, 331 "while" => WHILE_KW,
332 "yield" => YIELD_KW,
329 _ => return None, 333 _ => return None,
330 }; 334 };
331 Some(kw) 335 Some(kw)
@@ -366,4 +370,4 @@ impl SyntaxKind {
366 } 370 }
367} 371}
368#[macro_export] 372#[macro_export]
369macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } 373macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt
index 23d42b4d0..5c282fe67 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt
@@ -66,52 +66,7 @@
66 ), 66 ),
67 data: None, 67 data: None,
68 }, 68 },
69 fixes: [ 69 fixes: [],
70 CodeAction {
71 title: "consider prefixing with an underscore",
72 group: None,
73 kind: Some(
74 CodeActionKind(
75 "quickfix",
76 ),
77 ),
78 edit: Some(
79 SnippetWorkspaceEdit {
80 changes: Some(
81 {
82 Url {
83 scheme: "file",
84 host: None,
85 port: None,
86 path: "/test/driver/subcommand/repl.rs",
87 query: None,
88 fragment: None,
89 }: [
90 TextEdit {
91 range: Range {
92 start: Position {
93 line: 290,
94 character: 8,
95 },
96 end: Position {
97 line: 290,
98 character: 11,
99 },
100 },
101 new_text: "_foo",
102 },
103 ],
104 },
105 ),
106 document_changes: None,
107 },
108 ),
109 is_preferred: Some(
110 true,
111 ),
112 data: None,
113 },
114 ],
115 }, 70 },
116 MappedRustDiagnostic { 71 MappedRustDiagnostic {
117 url: Url { 72 url: Url {
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt
index 4e428bedc..d36d7693d 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt
@@ -66,52 +66,7 @@
66 ), 66 ),
67 data: None, 67 data: None,
68 }, 68 },
69 fixes: [ 69 fixes: [],
70 CodeAction {
71 title: "consider prefixing with an underscore",
72 group: None,
73 kind: Some(
74 CodeActionKind(
75 "quickfix",
76 ),
77 ),
78 edit: Some(
79 SnippetWorkspaceEdit {
80 changes: Some(
81 {
82 Url {
83 scheme: "file",
84 host: None,
85 port: None,
86 path: "/test/driver/subcommand/repl.rs",
87 query: None,
88 fragment: None,
89 }: [
90 TextEdit {
91 range: Range {
92 start: Position {
93 line: 290,
94 character: 8,
95 },
96 end: Position {
97 line: 290,
98 character: 11,
99 },
100 },
101 new_text: "_foo",
102 },
103 ],
104 },
105 ),
106 document_changes: None,
107 },
108 ),
109 is_preferred: Some(
110 true,
111 ),
112 data: None,
113 },
114 ],
115 }, 70 },
116 MappedRustDiagnostic { 71 MappedRustDiagnostic {
117 url: Url { 72 url: Url {
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt
index 4ddd7efae..17845b711 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt
@@ -66,52 +66,7 @@
66 ), 66 ),
67 data: None, 67 data: None,
68 }, 68 },
69 fixes: [ 69 fixes: [],
70 CodeAction {
71 title: "consider prefixing with an underscore",
72 group: None,
73 kind: Some(
74 CodeActionKind(
75 "quickfix",
76 ),
77 ),
78 edit: Some(
79 SnippetWorkspaceEdit {
80 changes: Some(
81 {
82 Url {
83 scheme: "file",
84 host: None,
85 port: None,
86 path: "/test/driver/subcommand/repl.rs",
87 query: None,
88 fragment: None,
89 }: [
90 TextEdit {
91 range: Range {
92 start: Position {
93 line: 290,
94 character: 8,
95 },
96 end: Position {
97 line: 290,
98 character: 11,
99 },
100 },
101 new_text: "_foo",
102 },
103 ],
104 },
105 ),
106 document_changes: None,
107 },
108 ),
109 is_preferred: Some(
110 true,
111 ),
112 data: None,
113 },
114 ],
115 }, 70 },
116 MappedRustDiagnostic { 71 MappedRustDiagnostic {
117 url: Url { 72 url: Url {
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt
index 4cbdb3b92..a19962167 100644
--- a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt
+++ b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt
@@ -102,65 +102,7 @@
102 tags: None, 102 tags: None,
103 data: None, 103 data: None,
104 }, 104 },
105 fixes: [ 105 fixes: [],
106 CodeAction {
107 title: "return the expression directly",
108 group: None,
109 kind: Some(
110 CodeActionKind(
111 "quickfix",
112 ),
113 ),
114 edit: Some(
115 SnippetWorkspaceEdit {
116 changes: Some(
117 {
118 Url {
119 scheme: "file",
120 host: None,
121 port: None,
122 path: "/test/src/main.rs",
123 query: None,
124 fragment: None,
125 }: [
126 TextEdit {
127 range: Range {
128 start: Position {
129 line: 2,
130 character: 4,
131 },
132 end: Position {
133 line: 2,
134 character: 30,
135 },
136 },
137 new_text: "",
138 },
139 TextEdit {
140 range: Range {
141 start: Position {
142 line: 3,
143 character: 4,
144 },
145 end: Position {
146 line: 3,
147 character: 5,
148 },
149 },
150 new_text: "(0..10).collect()",
151 },
152 ],
153 },
154 ),
155 document_changes: None,
156 },
157 ),
158 is_preferred: Some(
159 true,
160 ),
161 data: None,
162 },
163 ],
164 }, 106 },
165 MappedRustDiagnostic { 107 MappedRustDiagnostic {
166 url: Url { 108 url: Url {
@@ -242,65 +184,7 @@
242 tags: None, 184 tags: None,
243 data: None, 185 data: None,
244 }, 186 },
245 fixes: [ 187 fixes: [],
246 CodeAction {
247 title: "return the expression directly",
248 group: None,
249 kind: Some(
250 CodeActionKind(
251 "quickfix",
252 ),
253 ),
254 edit: Some(
255 SnippetWorkspaceEdit {
256 changes: Some(
257 {
258 Url {
259 scheme: "file",
260 host: None,
261 port: None,
262 path: "/test/src/main.rs",
263 query: None,
264 fragment: None,
265 }: [
266 TextEdit {
267 range: Range {
268 start: Position {
269 line: 2,
270 character: 4,
271 },
272 end: Position {
273 line: 2,
274 character: 30,
275 },
276 },
277 new_text: "",
278 },
279 TextEdit {
280 range: Range {
281 start: Position {
282 line: 3,
283 character: 4,
284 },
285 end: Position {
286 line: 3,
287 character: 5,
288 },
289 },
290 new_text: "(0..10).collect()",
291 },
292 ],
293 },
294 ),
295 document_changes: None,
296 },
297 ),
298 is_preferred: Some(
299 true,
300 ),
301 data: None,
302 },
303 ],
304 }, 188 },
305 MappedRustDiagnostic { 189 MappedRustDiagnostic {
306 url: Url { 190 url: Url {
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index 540759198..757899484 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -74,11 +74,13 @@ fn diagnostic_related_information(
74 Some(lsp_types::DiagnosticRelatedInformation { location, message }) 74 Some(lsp_types::DiagnosticRelatedInformation { location, message })
75} 75}
76 76
77struct SubDiagnostic {
78 related: lsp_types::DiagnosticRelatedInformation,
79 suggested_fix: Option<lsp_ext::CodeAction>,
80}
81
77enum MappedRustChildDiagnostic { 82enum MappedRustChildDiagnostic {
78 Related { 83 SubDiagnostic(SubDiagnostic),
79 related: lsp_types::DiagnosticRelatedInformation,
80 suggested_fix: Option<lsp_ext::CodeAction>,
81 },
82 MessageLine(String), 84 MessageLine(String),
83} 85}
84 86
@@ -105,15 +107,15 @@ fn map_rust_child_diagnostic(
105 } 107 }
106 108
107 if edit_map.is_empty() { 109 if edit_map.is_empty() {
108 MappedRustChildDiagnostic::Related { 110 MappedRustChildDiagnostic::SubDiagnostic(SubDiagnostic {
109 related: lsp_types::DiagnosticRelatedInformation { 111 related: lsp_types::DiagnosticRelatedInformation {
110 location: location(workspace_root, spans[0]), 112 location: location(workspace_root, spans[0]),
111 message: rd.message.clone(), 113 message: rd.message.clone(),
112 }, 114 },
113 suggested_fix: None, 115 suggested_fix: None,
114 } 116 })
115 } else { 117 } else {
116 MappedRustChildDiagnostic::Related { 118 MappedRustChildDiagnostic::SubDiagnostic(SubDiagnostic {
117 related: lsp_types::DiagnosticRelatedInformation { 119 related: lsp_types::DiagnosticRelatedInformation {
118 location: location(workspace_root, spans[0]), 120 location: location(workspace_root, spans[0]),
119 message: rd.message.clone(), 121 message: rd.message.clone(),
@@ -130,7 +132,7 @@ fn map_rust_child_diagnostic(
130 is_preferred: Some(true), 132 is_preferred: Some(true),
131 data: None, 133 data: None,
132 }), 134 }),
133 } 135 })
134 } 136 }
135} 137}
136 138
@@ -175,26 +177,22 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
175 } 177 }
176 178
177 let mut needs_primary_span_label = true; 179 let mut needs_primary_span_label = true;
178 let mut related_information = Vec::new(); 180 let mut subdiagnostics = Vec::new();
179 let mut tags = Vec::new(); 181 let mut tags = Vec::new();
180 182
181 for secondary_span in rd.spans.iter().filter(|s| !s.is_primary) { 183 for secondary_span in rd.spans.iter().filter(|s| !s.is_primary) {
182 let related = diagnostic_related_information(workspace_root, secondary_span); 184 let related = diagnostic_related_information(workspace_root, secondary_span);
183 if let Some(related) = related { 185 if let Some(related) = related {
184 related_information.push(related); 186 subdiagnostics.push(SubDiagnostic { related, suggested_fix: None });
185 } 187 }
186 } 188 }
187 189
188 let mut fixes = Vec::new();
189 let mut message = rd.message.clone(); 190 let mut message = rd.message.clone();
190 for child in &rd.children { 191 for child in &rd.children {
191 let child = map_rust_child_diagnostic(workspace_root, &child); 192 let child = map_rust_child_diagnostic(workspace_root, &child);
192 match child { 193 match child {
193 MappedRustChildDiagnostic::Related { related, suggested_fix } => { 194 MappedRustChildDiagnostic::SubDiagnostic(sub) => {
194 related_information.push(related); 195 subdiagnostics.push(sub);
195 if let Some(code_action) = suggested_fix {
196 fixes.push(code_action);
197 }
198 } 196 }
199 MappedRustChildDiagnostic::MessageLine(message_line) => { 197 MappedRustChildDiagnostic::MessageLine(message_line) => {
200 format_to!(message, "\n{}", message_line); 198 format_to!(message, "\n{}", message_line);
@@ -284,7 +282,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
284 diagnostics.push(MappedRustDiagnostic { 282 diagnostics.push(MappedRustDiagnostic {
285 url: in_macro_location.uri, 283 url: in_macro_location.uri,
286 diagnostic, 284 diagnostic,
287 fixes: fixes.clone(), 285 fixes: Vec::new(),
288 }); 286 });
289 } 287 }
290 288
@@ -298,17 +296,20 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
298 code_description: code_description.clone(), 296 code_description: code_description.clone(),
299 source: Some(source.clone()), 297 source: Some(source.clone()),
300 message, 298 message,
301 related_information: if related_information.is_empty() { 299 related_information: if subdiagnostics.is_empty() {
302 None 300 None
303 } else { 301 } else {
304 let mut related = related_information.clone(); 302 let mut related = subdiagnostics
303 .iter()
304 .map(|sub| sub.related.clone())
305 .collect::<Vec<_>>();
305 related.extend(related_macro_info); 306 related.extend(related_macro_info);
306 Some(related) 307 Some(related)
307 }, 308 },
308 tags: if tags.is_empty() { None } else { Some(tags.clone()) }, 309 tags: if tags.is_empty() { None } else { Some(tags.clone()) },
309 data: None, 310 data: None,
310 }, 311 },
311 fixes: fixes.clone(), 312 fixes: Vec::new(),
312 }); 313 });
313 314
314 // Emit hint-level diagnostics for all `related_information` entries such as "help"s. 315 // Emit hint-level diagnostics for all `related_information` entries such as "help"s.
@@ -318,21 +319,21 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
318 location, 319 location,
319 message: "original diagnostic".to_string(), 320 message: "original diagnostic".to_string(),
320 }; 321 };
321 for info in &related_information { 322 for sub in &subdiagnostics {
322 // Filter out empty/non-existent messages, as they greatly confuse VS Code. 323 // Filter out empty/non-existent messages, as they greatly confuse VS Code.
323 if info.message.is_empty() { 324 if sub.related.message.is_empty() {
324 continue; 325 continue;
325 } 326 }
326 diagnostics.push(MappedRustDiagnostic { 327 diagnostics.push(MappedRustDiagnostic {
327 url: info.location.uri.clone(), 328 url: sub.related.location.uri.clone(),
328 fixes: fixes.clone(), // share fixes to make them easier to apply 329 fixes: sub.suggested_fix.iter().cloned().collect(),
329 diagnostic: lsp_types::Diagnostic { 330 diagnostic: lsp_types::Diagnostic {
330 range: info.location.range, 331 range: sub.related.location.range,
331 severity: Some(lsp_types::DiagnosticSeverity::Hint), 332 severity: Some(lsp_types::DiagnosticSeverity::Hint),
332 code: code.clone().map(lsp_types::NumberOrString::String), 333 code: code.clone().map(lsp_types::NumberOrString::String),
333 code_description: code_description.clone(), 334 code_description: code_description.clone(),
334 source: Some(source.clone()), 335 source: Some(source.clone()),
335 message: info.message.clone(), 336 message: sub.related.message.clone(),
336 related_information: Some(vec![back_ref.clone()]), 337 related_information: Some(vec![back_ref.clone()]),
337 tags: None, // don't apply modifiers again 338 tags: None, // don't apply modifiers again
338 data: None, 339 data: None,
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
index 384d031e7..1456270d0 100644
--- a/crates/syntax/src/algo.rs
+++ b/crates/syntax/src/algo.rs
@@ -45,7 +45,7 @@ pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextSize) ->
45} 45}
46 46
47pub fn find_node_at_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> { 47pub fn find_node_at_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
48 find_covering_element(syntax, range).ancestors().find_map(N::cast) 48 syntax.covering_element(range).ancestors().find_map(N::cast)
49} 49}
50 50
51/// Skip to next non `trivia` token 51/// Skip to next non `trivia` token
@@ -74,10 +74,6 @@ pub fn non_trivia_sibling(element: SyntaxElement, direction: Direction) -> Optio
74 } 74 }
75} 75}
76 76
77pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxElement {
78 root.covering_element(range)
79}
80
81pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> { 77pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> {
82 if u == v { 78 if u == v {
83 return Some(u.clone()); 79 return Some(u.clone());
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 92ed2ee9d..9c96d3d07 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -931,6 +931,15 @@ impl WhileExpr {
931 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } 931 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
932} 932}
933#[derive(Debug, Clone, PartialEq, Eq, Hash)] 933#[derive(Debug, Clone, PartialEq, Eq, Hash)]
934pub struct YieldExpr {
935 pub(crate) syntax: SyntaxNode,
936}
937impl ast::AttrsOwner for YieldExpr {}
938impl YieldExpr {
939 pub fn yield_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yield]) }
940 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
941}
942#[derive(Debug, Clone, PartialEq, Eq, Hash)]
934pub struct Label { 943pub struct Label {
935 pub(crate) syntax: SyntaxNode, 944 pub(crate) syntax: SyntaxNode,
936} 945}
@@ -1334,6 +1343,7 @@ pub enum Expr {
1334 TryExpr(TryExpr), 1343 TryExpr(TryExpr),
1335 TupleExpr(TupleExpr), 1344 TupleExpr(TupleExpr),
1336 WhileExpr(WhileExpr), 1345 WhileExpr(WhileExpr),
1346 YieldExpr(YieldExpr),
1337} 1347}
1338#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1348#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1339pub enum Item { 1349pub enum Item {
@@ -2386,6 +2396,17 @@ impl AstNode for WhileExpr {
2386 } 2396 }
2387 fn syntax(&self) -> &SyntaxNode { &self.syntax } 2397 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2388} 2398}
2399impl AstNode for YieldExpr {
2400 fn can_cast(kind: SyntaxKind) -> bool { kind == YIELD_EXPR }
2401 fn cast(syntax: SyntaxNode) -> Option<Self> {
2402 if Self::can_cast(syntax.kind()) {
2403 Some(Self { syntax })
2404 } else {
2405 None
2406 }
2407 }
2408 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2409}
2389impl AstNode for Label { 2410impl AstNode for Label {
2390 fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL } 2411 fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL }
2391 fn cast(syntax: SyntaxNode) -> Option<Self> { 2412 fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3028,6 +3049,9 @@ impl From<TupleExpr> for Expr {
3028impl From<WhileExpr> for Expr { 3049impl From<WhileExpr> for Expr {
3029 fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) } 3050 fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) }
3030} 3051}
3052impl From<YieldExpr> for Expr {
3053 fn from(node: YieldExpr) -> Expr { Expr::YieldExpr(node) }
3054}
3031impl AstNode for Expr { 3055impl AstNode for Expr {
3032 fn can_cast(kind: SyntaxKind) -> bool { 3056 fn can_cast(kind: SyntaxKind) -> bool {
3033 match kind { 3057 match kind {
@@ -3035,7 +3059,8 @@ impl AstNode for Expr {
3035 | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR 3059 | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR
3036 | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MATCH_EXPR 3060 | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MATCH_EXPR
3037 | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR 3061 | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR
3038 | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR => true, 3062 | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR
3063 | YIELD_EXPR => true,
3039 _ => false, 3064 _ => false,
3040 } 3065 }
3041 } 3066 }
@@ -3071,6 +3096,7 @@ impl AstNode for Expr {
3071 TRY_EXPR => Expr::TryExpr(TryExpr { syntax }), 3096 TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
3072 TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }), 3097 TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }),
3073 WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }), 3098 WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
3099 YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }),
3074 _ => return None, 3100 _ => return None,
3075 }; 3101 };
3076 Some(res) 3102 Some(res)
@@ -3107,6 +3133,7 @@ impl AstNode for Expr {
3107 Expr::TryExpr(it) => &it.syntax, 3133 Expr::TryExpr(it) => &it.syntax,
3108 Expr::TupleExpr(it) => &it.syntax, 3134 Expr::TupleExpr(it) => &it.syntax,
3109 Expr::WhileExpr(it) => &it.syntax, 3135 Expr::WhileExpr(it) => &it.syntax,
3136 Expr::YieldExpr(it) => &it.syntax,
3110 } 3137 }
3111 } 3138 }
3112} 3139}
@@ -3983,6 +4010,11 @@ impl std::fmt::Display for WhileExpr {
3983 std::fmt::Display::fmt(self.syntax(), f) 4010 std::fmt::Display::fmt(self.syntax(), f)
3984 } 4011 }
3985} 4012}
4013impl std::fmt::Display for YieldExpr {
4014 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4015 std::fmt::Display::fmt(self.syntax(), f)
4016 }
4017}
3986impl std::fmt::Display for Label { 4018impl std::fmt::Display for Label {
3987 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 4019 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3988 std::fmt::Display::fmt(self.syntax(), f) 4020 std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/parsing/reparsing.rs b/crates/syntax/src/parsing/reparsing.rs
index 78eaf3410..76f01084c 100644
--- a/crates/syntax/src/parsing/reparsing.rs
+++ b/crates/syntax/src/parsing/reparsing.rs
@@ -10,7 +10,6 @@ use parser::Reparser;
10use text_edit::Indel; 10use text_edit::Indel;
11 11
12use crate::{ 12use crate::{
13 algo,
14 parsing::{ 13 parsing::{
15 lexer::{lex_single_syntax_kind, tokenize, Token}, 14 lexer::{lex_single_syntax_kind, tokenize, Token},
16 text_token_source::TextTokenSource, 15 text_token_source::TextTokenSource,
@@ -41,7 +40,7 @@ fn reparse_token<'node>(
41 root: &'node SyntaxNode, 40 root: &'node SyntaxNode,
42 edit: &Indel, 41 edit: &Indel,
43) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> { 42) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
44 let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone(); 43 let prev_token = root.covering_element(edit.delete).as_token()?.clone();
45 let prev_token_kind = prev_token.kind(); 44 let prev_token_kind = prev_token.kind();
46 match prev_token_kind { 45 match prev_token_kind {
47 WHITESPACE | COMMENT | IDENT | STRING => { 46 WHITESPACE | COMMENT | IDENT | STRING => {
@@ -124,7 +123,7 @@ fn is_contextual_kw(text: &str) -> bool {
124} 123}
125 124
126fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(SyntaxNode, Reparser)> { 125fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(SyntaxNode, Reparser)> {
127 let node = algo::find_covering_element(node, range); 126 let node = node.covering_element(range);
128 127
129 let mut ancestors = match node { 128 let mut ancestors = match node {
130 NodeOrToken::Token(it) => it.parent().ancestors(), 129 NodeOrToken::Token(it) => it.parent().ancestors(),
diff --git a/crates/syntax/test_data/parser/inline/ok/0159_yield_expr.rast b/crates/syntax/test_data/parser/inline/ok/0159_yield_expr.rast
new file mode 100644
index 000000000..05fc90743
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0159_yield_expr.rast
@@ -0,0 +1,28 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "foo"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] "\n "
14 [email protected]
15 [email protected]
16 [email protected] "yield"
17 [email protected] ";"
18 [email protected] "\n "
19 [email protected]
20 [email protected]
21 [email protected] "yield"
22 [email protected] " "
23 [email protected]
24 [email protected] "1"
25 [email protected] ";"
26 [email protected] "\n"
27 [email protected] "}"
28 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0159_yield_expr.rs b/crates/syntax/test_data/parser/inline/ok/0159_yield_expr.rs
new file mode 100644
index 000000000..596e221f7
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0159_yield_expr.rs
@@ -0,0 +1,4 @@
1fn foo() {
2 yield;
3 yield 1;
4}
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index 7a2937f0e..61a944c13 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -15,7 +15,7 @@ flate2 = "1.0"
15pico-args = "0.3.1" 15pico-args = "0.3.1"
16proc-macro2 = "1.0.8" 16proc-macro2 = "1.0.8"
17quote = "1.0.2" 17quote = "1.0.2"
18ungrammar = "1.6" 18ungrammar = "1.7"
19walkdir = "2.3.1" 19walkdir = "2.3.1"
20write-json = "0.1.0" 20write-json = "0.1.0"
21xshell = "0.1" 21xshell = "0.1"
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 2b8012bdd..046d68f52 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -68,7 +68,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
68 "as", "async", "await", "box", "break", "const", "continue", "crate", "dyn", "else", 68 "as", "async", "await", "box", "break", "const", "continue", "crate", "dyn", "else",
69 "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "macro", 69 "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "macro",
70 "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super", 70 "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super",
71 "trait", "true", "try", "type", "unsafe", "use", "where", "while", 71 "trait", "true", "try", "type", "unsafe", "use", "where", "while", "yield",
72 ], 72 ],
73 contextual_keywords: &["auto", "default", "existential", "union", "raw", "macro_rules"], 73 contextual_keywords: &["auto", "default", "existential", "union", "raw", "macro_rules"],
74 literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING"], 74 literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING"],
@@ -149,6 +149,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
149 "LABEL", 149 "LABEL",
150 "BLOCK_EXPR", 150 "BLOCK_EXPR",
151 "RETURN_EXPR", 151 "RETURN_EXPR",
152 "YIELD_EXPR",
152 "MATCH_EXPR", 153 "MATCH_EXPR",
153 "MATCH_ARM_LIST", 154 "MATCH_ARM_LIST",
154 "MATCH_ARM", 155 "MATCH_ARM",