diff options
255 files changed, 2629 insertions, 5124 deletions
diff --git a/Cargo.lock b/Cargo.lock index f695a7f2c..975c1aef8 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -614,9 +614,9 @@ checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" | |||
614 | 614 | ||
615 | [[package]] | 615 | [[package]] |
616 | name = "lock_api" | 616 | name = "lock_api" |
617 | version = "0.3.3" | 617 | version = "0.3.4" |
618 | source = "registry+https://github.com/rust-lang/crates.io-index" | 618 | source = "registry+https://github.com/rust-lang/crates.io-index" |
619 | checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" | 619 | checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" |
620 | dependencies = [ | 620 | dependencies = [ |
621 | "scopeguard", | 621 | "scopeguard", |
622 | ] | 622 | ] |
@@ -779,9 +779,9 @@ checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" | |||
779 | 779 | ||
780 | [[package]] | 780 | [[package]] |
781 | name = "parking_lot" | 781 | name = "parking_lot" |
782 | version = "0.10.0" | 782 | version = "0.10.1" |
783 | source = "registry+https://github.com/rust-lang/crates.io-index" | 783 | source = "registry+https://github.com/rust-lang/crates.io-index" |
784 | checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" | 784 | checksum = "6fdfcb5f20930a79e326f7ec992a9fdb5b7bd809254b1e735bdd5a99f78bee0d" |
785 | dependencies = [ | 785 | dependencies = [ |
786 | "lock_api", | 786 | "lock_api", |
787 | "parking_lot_core", | 787 | "parking_lot_core", |
@@ -789,9 +789,9 @@ dependencies = [ | |||
789 | 789 | ||
790 | [[package]] | 790 | [[package]] |
791 | name = "parking_lot_core" | 791 | name = "parking_lot_core" |
792 | version = "0.7.0" | 792 | version = "0.7.1" |
793 | source = "registry+https://github.com/rust-lang/crates.io-index" | 793 | source = "registry+https://github.com/rust-lang/crates.io-index" |
794 | checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" | 794 | checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb" |
795 | dependencies = [ | 795 | dependencies = [ |
796 | "cfg-if", | 796 | "cfg-if", |
797 | "cloudabi", | 797 | "cloudabi", |
@@ -1021,6 +1021,7 @@ dependencies = [ | |||
1021 | "ra_prof", | 1021 | "ra_prof", |
1022 | "ra_syntax", | 1022 | "ra_syntax", |
1023 | "rustc-hash", | 1023 | "rustc-hash", |
1024 | "scoped-tls", | ||
1024 | "smallvec", | 1025 | "smallvec", |
1025 | "stdx", | 1026 | "stdx", |
1026 | "test_utils", | 1027 | "test_utils", |
@@ -1420,6 +1421,12 @@ dependencies = [ | |||
1420 | ] | 1421 | ] |
1421 | 1422 | ||
1422 | [[package]] | 1423 | [[package]] |
1424 | name = "scoped-tls" | ||
1425 | version = "1.0.0" | ||
1426 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1427 | checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" | ||
1428 | |||
1429 | [[package]] | ||
1423 | name = "scopeguard" | 1430 | name = "scopeguard" |
1424 | version = "1.1.0" | 1431 | version = "1.1.0" |
1425 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1432 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1523,9 +1530,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" | |||
1523 | 1530 | ||
1524 | [[package]] | 1531 | [[package]] |
1525 | name = "smallvec" | 1532 | name = "smallvec" |
1526 | version = "1.2.0" | 1533 | version = "1.3.0" |
1527 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1534 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1528 | checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" | 1535 | checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a" |
1529 | 1536 | ||
1530 | [[package]] | 1537 | [[package]] |
1531 | name = "smol_str" | 1538 | name = "smol_str" |
@@ -1573,9 +1580,9 @@ dependencies = [ | |||
1573 | 1580 | ||
1574 | [[package]] | 1581 | [[package]] |
1575 | name = "termios" | 1582 | name = "termios" |
1576 | version = "0.3.1" | 1583 | version = "0.3.2" |
1577 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1584 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1578 | checksum = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" | 1585 | checksum = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2" |
1579 | dependencies = [ | 1586 | dependencies = [ |
1580 | "libc", | 1587 | "libc", |
1581 | ] | 1588 | ] |
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index e7dcfb44e..d86d804b2 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use hir::HirDisplay; | 1 | use hir::HirDisplay; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | ast::{self, AstNode, AstToken, LetStmt, NameOwner, TypeAscriptionOwner}, | 3 | ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner}, |
4 | TextRange, | 4 | TextRange, |
5 | }; | 5 | }; |
6 | 6 | ||
@@ -35,7 +35,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> { | |||
35 | let name = pat.name()?; | 35 | let name = pat.name()?; |
36 | let name_range = name.syntax().text_range(); | 36 | let name_range = name.syntax().text_range(); |
37 | let stmt_range = stmt.syntax().text_range(); | 37 | let stmt_range = stmt.syntax().text_range(); |
38 | let eq_range = stmt.eq_token()?.syntax().text_range(); | 38 | let eq_range = stmt.eq_token()?.text_range(); |
39 | // Assist should only be applicable if cursor is between 'let' and '=' | 39 | // Assist should only be applicable if cursor is between 'let' and '=' |
40 | let let_range = TextRange::from_to(stmt_range.start(), eq_range.start()); | 40 | let let_range = TextRange::from_to(stmt_range.start(), eq_range.start()); |
41 | let cursor_in_range = ctx.frange.range.is_subrange(&let_range); | 41 | let cursor_in_range = ctx.frange.range.is_subrange(&let_range); |
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index 26dfed237..6622eadb2 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ra_syntax::{ | 1 | use ra_syntax::{ |
2 | ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner}, | 2 | ast::{self, AstNode, NameOwner, TypeParamsOwner}, |
3 | TextUnit, | 3 | TextUnit, |
4 | }; | 4 | }; |
5 | use stdx::{format_to, SepBy}; | 5 | use stdx::{format_to, SepBy}; |
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index 30360af94..240b19fa3 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs | |||
@@ -1,8 +1,7 @@ | |||
1 | use hir::Adt; | 1 | use hir::Adt; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | ast::{ | 3 | ast::{ |
4 | self, AstNode, AstToken, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, | 4 | self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, |
5 | VisibilityOwner, | ||
6 | }, | 5 | }, |
7 | TextUnit, T, | 6 | TextUnit, T, |
8 | }; | 7 | }; |
diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index b9eb09676..c4fb425b0 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs | |||
@@ -29,7 +29,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> { | |||
29 | ast::Pat::BindPat(pat) => pat, | 29 | ast::Pat::BindPat(pat) => pat, |
30 | _ => return None, | 30 | _ => return None, |
31 | }; | 31 | }; |
32 | if bind_pat.mut_kw_token().is_some() { | 32 | if bind_pat.mut_token().is_some() { |
33 | tested_by!(test_not_inline_mut_variable); | 33 | tested_by!(test_not_inline_mut_variable); |
34 | return None; | 34 | return None; |
35 | } | 35 | } |
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index ab6bdf6bb..8d0f7e922 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs | |||
@@ -61,7 +61,7 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> { | |||
61 | }; | 61 | }; |
62 | if is_full_stmt { | 62 | if is_full_stmt { |
63 | tested_by!(test_introduce_var_expr_stmt); | 63 | tested_by!(test_introduce_var_expr_stmt); |
64 | if full_stmt.unwrap().semi_token().is_none() { | 64 | if full_stmt.unwrap().semicolon_token().is_none() { |
65 | buf.push_str(";"); | 65 | buf.push_str(";"); |
66 | } | 66 | } |
67 | edit.replace(expr.syntax().text_range(), buf); | 67 | edit.replace(expr.syntax().text_range(), buf); |
diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs index 936d50ab4..0958f52f1 100644 --- a/crates/ra_assists/src/handlers/merge_imports.rs +++ b/crates/ra_assists/src/handlers/merge_imports.rs | |||
@@ -3,7 +3,7 @@ use std::iter::successors; | |||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | algo::{neighbor, SyntaxRewriter}, | 4 | algo::{neighbor, SyntaxRewriter}, |
5 | ast::{self, edit::AstNodeEdit, make}, | 5 | ast::{self, edit::AstNodeEdit, make}, |
6 | AstNode, AstToken, Direction, InsertPosition, SyntaxElement, T, | 6 | AstNode, Direction, InsertPosition, SyntaxElement, T, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | use crate::{Assist, AssistCtx, AssistId}; | 9 | use crate::{Assist, AssistCtx, AssistId}; |
@@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTre | |||
82 | .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']), | 82 | .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']), |
83 | ); | 83 | ); |
84 | let use_tree_list = lhs.use_tree_list()?; | 84 | let use_tree_list = lhs.use_tree_list()?; |
85 | let pos = InsertPosition::Before(use_tree_list.r_curly_token()?.syntax().clone().into()); | 85 | let pos = InsertPosition::Before(use_tree_list.r_curly_token()?.into()); |
86 | let use_tree_list = use_tree_list.insert_children(pos, to_insert); | 86 | let use_tree_list = use_tree_list.insert_children(pos, to_insert); |
87 | Some(lhs.with_use_tree_list(use_tree_list)) | 87 | Some(lhs.with_use_tree_list(use_tree_list)) |
88 | } | 88 | } |
diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs index 93f26f51a..0f26884dc 100644 --- a/crates/ra_assists/src/handlers/move_bounds.rs +++ b/crates/ra_assists/src/handlers/move_bounds.rs | |||
@@ -2,6 +2,7 @@ use ra_syntax::{ | |||
2 | ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner, TypeBoundsOwner}, | 2 | ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner, TypeBoundsOwner}, |
3 | match_ast, | 3 | match_ast, |
4 | SyntaxKind::*, | 4 | SyntaxKind::*, |
5 | T, | ||
5 | }; | 6 | }; |
6 | 7 | ||
7 | use crate::{Assist, AssistCtx, AssistId}; | 8 | use crate::{Assist, AssistCtx, AssistId}; |
@@ -42,7 +43,7 @@ pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> { | |||
42 | ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(), | 43 | ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(), |
43 | ast::StructDef(it) => { | 44 | ast::StructDef(it) => { |
44 | it.syntax().children_with_tokens() | 45 | it.syntax().children_with_tokens() |
45 | .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == SEMI)? | 46 | .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == T![;])? |
46 | }, | 47 | }, |
47 | _ => return None | 48 | _ => return None |
48 | } | 49 | } |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 45631f8fd..226fb4534 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -255,7 +255,7 @@ impl SourceAnalyzer { | |||
255 | _ => return None, | 255 | _ => return None, |
256 | }; | 256 | }; |
257 | 257 | ||
258 | let (variant, missing_fields) = | 258 | let (variant, missing_fields, _exhaustive) = |
259 | record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; | 259 | record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; |
260 | let res = self.missing_fields(db, krate, substs, variant, missing_fields); | 260 | let res = self.missing_fields(db, krate, substs, variant, missing_fields); |
261 | Some(res) | 261 | Some(res) |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 7fc4cd76e..be4b0accb 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -4,6 +4,7 @@ use std::sync::Arc; | |||
4 | 4 | ||
5 | use either::Either; | 5 | use either::Either; |
6 | use hir_expand::{ | 6 | use hir_expand::{ |
7 | hygiene::Hygiene, | ||
7 | name::{AsName, Name}, | 8 | name::{AsName, Name}, |
8 | InFile, | 9 | InFile, |
9 | }; | 10 | }; |
@@ -12,9 +13,9 @@ use ra_prof::profile; | |||
12 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; | 13 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; |
13 | 14 | ||
14 | use crate::{ | 15 | use crate::{ |
15 | db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, | 16 | attr::Attrs, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, |
16 | visibility::RawVisibility, EnumId, LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, | 17 | type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, |
17 | UnionId, VariantId, | 18 | LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, |
18 | }; | 19 | }; |
19 | 20 | ||
20 | /// Note that we use `StructData` for unions as well! | 21 | /// Note that we use `StructData` for unions as well! |
@@ -56,7 +57,8 @@ impl StructData { | |||
56 | let src = id.lookup(db).source(db); | 57 | let src = id.lookup(db).source(db); |
57 | 58 | ||
58 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 59 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
59 | let variant_data = VariantData::new(db, src.map(|s| s.kind())); | 60 | let variant_data = |
61 | VariantData::new(db, src.map(|s| s.kind()), id.lookup(db).container.module(db)); | ||
60 | let variant_data = Arc::new(variant_data); | 62 | let variant_data = Arc::new(variant_data); |
61 | Arc::new(StructData { name, variant_data }) | 63 | Arc::new(StructData { name, variant_data }) |
62 | } | 64 | } |
@@ -70,6 +72,7 @@ impl StructData { | |||
70 | .map(ast::StructKind::Record) | 72 | .map(ast::StructKind::Record) |
71 | .unwrap_or(ast::StructKind::Unit) | 73 | .unwrap_or(ast::StructKind::Unit) |
72 | }), | 74 | }), |
75 | id.lookup(db).container.module(db), | ||
73 | ); | 76 | ); |
74 | let variant_data = Arc::new(variant_data); | 77 | let variant_data = Arc::new(variant_data); |
75 | Arc::new(StructData { name, variant_data }) | 78 | Arc::new(StructData { name, variant_data }) |
@@ -82,7 +85,7 @@ impl EnumData { | |||
82 | let src = e.lookup(db).source(db); | 85 | let src = e.lookup(db).source(db); |
83 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 86 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
84 | let mut trace = Trace::new_for_arena(); | 87 | let mut trace = Trace::new_for_arena(); |
85 | lower_enum(db, &mut trace, &src); | 88 | lower_enum(db, &mut trace, &src, e.lookup(db).container.module(db)); |
86 | Arc::new(EnumData { name, variants: trace.into_arena() }) | 89 | Arc::new(EnumData { name, variants: trace.into_arena() }) |
87 | } | 90 | } |
88 | 91 | ||
@@ -98,7 +101,7 @@ impl HasChildSource for EnumId { | |||
98 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { | 101 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { |
99 | let src = self.lookup(db).source(db); | 102 | let src = self.lookup(db).source(db); |
100 | let mut trace = Trace::new_for_map(); | 103 | let mut trace = Trace::new_for_map(); |
101 | lower_enum(db, &mut trace, &src); | 104 | lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db)); |
102 | src.with_value(trace.into_map()) | 105 | src.with_value(trace.into_map()) |
103 | } | 106 | } |
104 | } | 107 | } |
@@ -107,22 +110,23 @@ fn lower_enum( | |||
107 | db: &dyn DefDatabase, | 110 | db: &dyn DefDatabase, |
108 | trace: &mut Trace<EnumVariantData, ast::EnumVariant>, | 111 | trace: &mut Trace<EnumVariantData, ast::EnumVariant>, |
109 | ast: &InFile<ast::EnumDef>, | 112 | ast: &InFile<ast::EnumDef>, |
113 | module_id: ModuleId, | ||
110 | ) { | 114 | ) { |
111 | for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { | 115 | for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { |
112 | trace.alloc( | 116 | trace.alloc( |
113 | || var.clone(), | 117 | || var.clone(), |
114 | || EnumVariantData { | 118 | || EnumVariantData { |
115 | name: var.name().map_or_else(Name::missing, |it| it.as_name()), | 119 | name: var.name().map_or_else(Name::missing, |it| it.as_name()), |
116 | variant_data: Arc::new(VariantData::new(db, ast.with_value(var.kind()))), | 120 | variant_data: Arc::new(VariantData::new(db, ast.with_value(var.kind()), module_id)), |
117 | }, | 121 | }, |
118 | ); | 122 | ); |
119 | } | 123 | } |
120 | } | 124 | } |
121 | 125 | ||
122 | impl VariantData { | 126 | impl VariantData { |
123 | fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>) -> Self { | 127 | fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self { |
124 | let mut trace = Trace::new_for_arena(); | 128 | let mut trace = Trace::new_for_arena(); |
125 | match lower_struct(db, &mut trace, &flavor) { | 129 | match lower_struct(db, &mut trace, &flavor, module_id) { |
126 | StructKind::Tuple => VariantData::Tuple(trace.into_arena()), | 130 | StructKind::Tuple => VariantData::Tuple(trace.into_arena()), |
127 | StructKind::Record => VariantData::Record(trace.into_arena()), | 131 | StructKind::Record => VariantData::Record(trace.into_arena()), |
128 | StructKind::Unit => VariantData::Unit, | 132 | StructKind::Unit => VariantData::Unit, |
@@ -155,22 +159,27 @@ impl HasChildSource for VariantId { | |||
155 | type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>; | 159 | type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>; |
156 | 160 | ||
157 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { | 161 | fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { |
158 | let src = match self { | 162 | let (src, module_id) = match self { |
159 | VariantId::EnumVariantId(it) => { | 163 | VariantId::EnumVariantId(it) => { |
160 | // I don't really like the fact that we call into parent source | 164 | // I don't really like the fact that we call into parent source |
161 | // here, this might add to more queries then necessary. | 165 | // here, this might add to more queries then necessary. |
162 | let src = it.parent.child_source(db); | 166 | let src = it.parent.child_source(db); |
163 | src.map(|map| map[it.local_id].kind()) | 167 | (src.map(|map| map[it.local_id].kind()), it.parent.lookup(db).container.module(db)) |
164 | } | 168 | } |
165 | VariantId::StructId(it) => it.lookup(db).source(db).map(|it| it.kind()), | 169 | VariantId::StructId(it) => { |
166 | VariantId::UnionId(it) => it.lookup(db).source(db).map(|it| { | 170 | (it.lookup(db).source(db).map(|it| it.kind()), it.lookup(db).container.module(db)) |
167 | it.record_field_def_list() | 171 | } |
168 | .map(ast::StructKind::Record) | 172 | VariantId::UnionId(it) => ( |
169 | .unwrap_or(ast::StructKind::Unit) | 173 | it.lookup(db).source(db).map(|it| { |
170 | }), | 174 | it.record_field_def_list() |
175 | .map(ast::StructKind::Record) | ||
176 | .unwrap_or(ast::StructKind::Unit) | ||
177 | }), | ||
178 | it.lookup(db).container.module(db), | ||
179 | ), | ||
171 | }; | 180 | }; |
172 | let mut trace = Trace::new_for_map(); | 181 | let mut trace = Trace::new_for_map(); |
173 | lower_struct(db, &mut trace, &src); | 182 | lower_struct(db, &mut trace, &src, module_id); |
174 | src.with_value(trace.into_map()) | 183 | src.with_value(trace.into_map()) |
175 | } | 184 | } |
176 | } | 185 | } |
@@ -186,10 +195,17 @@ fn lower_struct( | |||
186 | db: &dyn DefDatabase, | 195 | db: &dyn DefDatabase, |
187 | trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, | 196 | trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, |
188 | ast: &InFile<ast::StructKind>, | 197 | ast: &InFile<ast::StructKind>, |
198 | module_id: ModuleId, | ||
189 | ) -> StructKind { | 199 | ) -> StructKind { |
200 | let crate_graph = db.crate_graph(); | ||
190 | match &ast.value { | 201 | match &ast.value { |
191 | ast::StructKind::Tuple(fl) => { | 202 | ast::StructKind::Tuple(fl) => { |
192 | for (i, fd) in fl.fields().enumerate() { | 203 | for (i, fd) in fl.fields().enumerate() { |
204 | let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id)); | ||
205 | if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { | ||
206 | continue; | ||
207 | } | ||
208 | |||
193 | trace.alloc( | 209 | trace.alloc( |
194 | || Either::Left(fd.clone()), | 210 | || Either::Left(fd.clone()), |
195 | || StructFieldData { | 211 | || StructFieldData { |
@@ -203,6 +219,11 @@ fn lower_struct( | |||
203 | } | 219 | } |
204 | ast::StructKind::Record(fl) => { | 220 | ast::StructKind::Record(fl) => { |
205 | for fd in fl.fields() { | 221 | for fd in fl.fields() { |
222 | let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id)); | ||
223 | if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { | ||
224 | continue; | ||
225 | } | ||
226 | |||
206 | trace.alloc( | 227 | trace.alloc( |
207 | || Either::Right(fd.clone()), | 228 | || Either::Right(fd.clone()), |
208 | || StructFieldData { | 229 | || StructFieldData { |
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 71a18f5e1..7b0c506b1 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs | |||
@@ -5,6 +5,7 @@ use std::{ops, sync::Arc}; | |||
5 | use either::Either; | 5 | use either::Either; |
6 | use hir_expand::{hygiene::Hygiene, AstId, InFile}; | 6 | use hir_expand::{hygiene::Hygiene, AstId, InFile}; |
7 | use mbe::ast_to_token_tree; | 7 | use mbe::ast_to_token_tree; |
8 | use ra_cfg::CfgOptions; | ||
8 | use ra_syntax::{ | 9 | use ra_syntax::{ |
9 | ast::{self, AstNode, AttrsOwner}, | 10 | ast::{self, AstNode, AttrsOwner}, |
10 | SmolStr, | 11 | SmolStr, |
@@ -90,6 +91,10 @@ impl Attrs { | |||
90 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { | 91 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { |
91 | AttrQuery { attrs: self, key } | 92 | AttrQuery { attrs: self, key } |
92 | } | 93 | } |
94 | |||
95 | pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { | ||
96 | self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) | ||
97 | } | ||
93 | } | 98 | } |
94 | 99 | ||
95 | #[derive(Debug, Clone, PartialEq, Eq)] | 100 | #[derive(Debug, Clone, PartialEq, Eq)] |
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 5f9d53ecb..e09996c6f 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -236,7 +236,7 @@ impl Index<PatId> for Body { | |||
236 | 236 | ||
237 | impl BodySourceMap { | 237 | impl BodySourceMap { |
238 | pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { | 238 | pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { |
239 | self.expr_map_back[expr] | 239 | self.expr_map_back[expr].clone() |
240 | } | 240 | } |
241 | 241 | ||
242 | pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> { | 242 | pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> { |
@@ -255,7 +255,7 @@ impl BodySourceMap { | |||
255 | } | 255 | } |
256 | 256 | ||
257 | pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> { | 257 | pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> { |
258 | self.pat_map_back[pat] | 258 | self.pat_map_back[pat].clone() |
259 | } | 259 | } |
260 | 260 | ||
261 | pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> { | 261 | pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> { |
@@ -264,6 +264,6 @@ impl BodySourceMap { | |||
264 | } | 264 | } |
265 | 265 | ||
266 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> { | 266 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> { |
267 | self.field_map[&(expr, field)] | 267 | self.field_map[&(expr, field)].clone() |
268 | } | 268 | } |
269 | } | 269 | } |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index c4a5ec59c..9d6ee095e 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -4,6 +4,7 @@ | |||
4 | use either::Either; | 4 | use either::Either; |
5 | 5 | ||
6 | use hir_expand::{ | 6 | use hir_expand::{ |
7 | hygiene::Hygiene, | ||
7 | name::{name, AsName, Name}, | 8 | name::{name, AsName, Name}, |
8 | MacroDefId, MacroDefKind, | 9 | MacroDefId, MacroDefKind, |
9 | }; | 10 | }; |
@@ -20,6 +21,7 @@ use test_utils::tested_by; | |||
20 | use super::{ExprSource, PatSource}; | 21 | use super::{ExprSource, PatSource}; |
21 | use crate::{ | 22 | use crate::{ |
22 | adt::StructKind, | 23 | adt::StructKind, |
24 | attr::Attrs, | ||
23 | body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, | 25 | body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, |
24 | builtin_type::{BuiltinFloat, BuiltinInt}, | 26 | builtin_type::{BuiltinFloat, BuiltinInt}, |
25 | db::DefDatabase, | 27 | db::DefDatabase, |
@@ -31,8 +33,8 @@ use crate::{ | |||
31 | path::GenericArgs, | 33 | path::GenericArgs, |
32 | path::Path, | 34 | path::Path, |
33 | type_ref::{Mutability, TypeRef}, | 35 | type_ref::{Mutability, TypeRef}, |
34 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, | 36 | AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, HasModule, Intern, |
35 | StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, | 37 | ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, |
36 | }; | 38 | }; |
37 | 39 | ||
38 | pub(super) fn lower( | 40 | pub(super) fn lower( |
@@ -104,7 +106,7 @@ impl ExprCollector<'_> { | |||
104 | fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { | 106 | fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { |
105 | let ptr = Either::Left(ptr); | 107 | let ptr = Either::Left(ptr); |
106 | let src = self.expander.to_source(ptr); | 108 | let src = self.expander.to_source(ptr); |
107 | let id = self.make_expr(expr, Ok(src)); | 109 | let id = self.make_expr(expr, Ok(src.clone())); |
108 | self.source_map.expr_map.insert(src, id); | 110 | self.source_map.expr_map.insert(src, id); |
109 | id | 111 | id |
110 | } | 112 | } |
@@ -116,7 +118,7 @@ impl ExprCollector<'_> { | |||
116 | fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId { | 118 | fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId { |
117 | let ptr = Either::Right(ptr); | 119 | let ptr = Either::Right(ptr); |
118 | let src = self.expander.to_source(ptr); | 120 | let src = self.expander.to_source(ptr); |
119 | let id = self.make_expr(expr, Ok(src)); | 121 | let id = self.make_expr(expr, Ok(src.clone())); |
120 | self.source_map.expr_map.insert(src, id); | 122 | self.source_map.expr_map.insert(src, id); |
121 | id | 123 | id |
122 | } | 124 | } |
@@ -134,7 +136,7 @@ impl ExprCollector<'_> { | |||
134 | 136 | ||
135 | fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { | 137 | fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { |
136 | let src = self.expander.to_source(ptr); | 138 | let src = self.expander.to_source(ptr); |
137 | let id = self.make_pat(pat, Ok(src)); | 139 | let id = self.make_pat(pat, Ok(src.clone())); |
138 | self.source_map.pat_map.insert(src, id); | 140 | self.source_map.pat_map.insert(src, id); |
139 | id | 141 | id |
140 | } | 142 | } |
@@ -298,28 +300,41 @@ impl ExprCollector<'_> { | |||
298 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) | 300 | self.alloc_expr(Expr::Return { expr }, syntax_ptr) |
299 | } | 301 | } |
300 | ast::Expr::RecordLit(e) => { | 302 | ast::Expr::RecordLit(e) => { |
303 | let crate_graph = self.db.crate_graph(); | ||
301 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 304 | let path = e.path().and_then(|path| self.expander.parse_path(path)); |
302 | let mut field_ptrs = Vec::new(); | 305 | let mut field_ptrs = Vec::new(); |
303 | let record_lit = if let Some(nfl) = e.record_field_list() { | 306 | let record_lit = if let Some(nfl) = e.record_field_list() { |
304 | let fields = nfl | 307 | let fields = nfl |
305 | .fields() | 308 | .fields() |
306 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | 309 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) |
307 | .map(|field| RecordLitField { | 310 | .filter_map(|field| { |
308 | name: field | 311 | let module_id = ContainerId::DefWithBodyId(self.def).module(self.db); |
309 | .name_ref() | 312 | let attrs = Attrs::new( |
310 | .map(|nr| nr.as_name()) | 313 | &field, |
311 | .unwrap_or_else(Name::missing), | 314 | &Hygiene::new(self.db.upcast(), self.expander.current_file_id), |
312 | expr: if let Some(e) = field.expr() { | 315 | ); |
313 | self.collect_expr(e) | 316 | |
314 | } else if let Some(nr) = field.name_ref() { | 317 | if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) { |
315 | // field shorthand | 318 | return None; |
316 | self.alloc_expr_field_shorthand( | 319 | } |
317 | Expr::Path(Path::from_name_ref(&nr)), | 320 | |
318 | AstPtr::new(&field), | 321 | Some(RecordLitField { |
319 | ) | 322 | name: field |
320 | } else { | 323 | .name_ref() |
321 | self.missing_expr() | 324 | .map(|nr| nr.as_name()) |
322 | }, | 325 | .unwrap_or_else(Name::missing), |
326 | expr: if let Some(e) = field.expr() { | ||
327 | self.collect_expr(e) | ||
328 | } else if let Some(nr) = field.name_ref() { | ||
329 | // field shorthand | ||
330 | self.alloc_expr_field_shorthand( | ||
331 | Expr::Path(Path::from_name_ref(&nr)), | ||
332 | AstPtr::new(&field), | ||
333 | ) | ||
334 | } else { | ||
335 | self.missing_expr() | ||
336 | }, | ||
337 | }) | ||
323 | }) | 338 | }) |
324 | .collect(); | 339 | .collect(); |
325 | let spread = nfl.spread().map(|s| self.collect_expr(s)); | 340 | let spread = nfl.spread().map(|s| self.collect_expr(s)); |
@@ -357,7 +372,7 @@ impl ExprCollector<'_> { | |||
357 | } | 372 | } |
358 | ast::Expr::RefExpr(e) => { | 373 | ast::Expr::RefExpr(e) => { |
359 | let expr = self.collect_expr_opt(e.expr()); | 374 | let expr = self.collect_expr_opt(e.expr()); |
360 | let mutability = Mutability::from_mutable(e.is_mut()); | 375 | let mutability = Mutability::from_mutable(e.mut_token().is_some()); |
361 | self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr) | 376 | self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr) |
362 | } | 377 | } |
363 | ast::Expr::PrefixExpr(e) => { | 378 | ast::Expr::PrefixExpr(e) => { |
@@ -572,10 +587,8 @@ impl ExprCollector<'_> { | |||
572 | let pattern = match &pat { | 587 | let pattern = match &pat { |
573 | ast::Pat::BindPat(bp) => { | 588 | ast::Pat::BindPat(bp) => { |
574 | let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); | 589 | let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); |
575 | let annotation = BindingAnnotation::new( | 590 | let annotation = |
576 | bp.mut_kw_token().is_some(), | 591 | BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some()); |
577 | bp.ref_kw_token().is_some(), | ||
578 | ); | ||
579 | let subpat = bp.pat().map(|subpat| self.collect_pat(subpat)); | 592 | let subpat = bp.pat().map(|subpat| self.collect_pat(subpat)); |
580 | if annotation == BindingAnnotation::Unannotated && subpat.is_none() { | 593 | if annotation == BindingAnnotation::Unannotated && subpat.is_none() { |
581 | // This could also be a single-segment path pattern. To | 594 | // This could also be a single-segment path pattern. To |
@@ -616,7 +629,7 @@ impl ExprCollector<'_> { | |||
616 | } | 629 | } |
617 | ast::Pat::RefPat(p) => { | 630 | ast::Pat::RefPat(p) => { |
618 | let pat = self.collect_pat_opt(p.pat()); | 631 | let pat = self.collect_pat_opt(p.pat()); |
619 | let mutability = Mutability::from_mutable(p.mut_kw_token().is_some()); | 632 | let mutability = Mutability::from_mutable(p.mut_token().is_some()); |
620 | Pat::Ref { pat, mutability } | 633 | Pat::Ref { pat, mutability } |
621 | } | 634 | } |
622 | ast::Pat::PathPat(p) => { | 635 | ast::Pat::PathPat(p) => { |
@@ -655,7 +668,9 @@ impl ExprCollector<'_> { | |||
655 | }); | 668 | }); |
656 | fields.extend(iter); | 669 | fields.extend(iter); |
657 | 670 | ||
658 | Pat::Record { path, args: fields } | 671 | let ellipsis = record_field_pat_list.dotdot_token().is_some(); |
672 | |||
673 | Pat::Record { path, args: fields, ellipsis } | ||
659 | } | 674 | } |
660 | ast::Pat::SlicePat(p) => { | 675 | ast::Pat::SlicePat(p) => { |
661 | let SlicePatComponents { prefix, slice, suffix } = p.components(); | 676 | let SlicePatComponents { prefix, slice, suffix } = p.components(); |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 689bb6c5c..b8fbf0ed4 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -7,7 +7,6 @@ use hir_expand::{ | |||
7 | name::{name, AsName, Name}, | 7 | name::{name, AsName, Name}, |
8 | AstId, InFile, | 8 | AstId, InFile, |
9 | }; | 9 | }; |
10 | use ra_cfg::CfgOptions; | ||
11 | use ra_prof::profile; | 10 | use ra_prof::profile; |
12 | use ra_syntax::ast::{ | 11 | use ra_syntax::ast::{ |
13 | self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, | 12 | self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, |
@@ -75,7 +74,7 @@ impl FunctionData { | |||
75 | TypeRef::unit() | 74 | TypeRef::unit() |
76 | }; | 75 | }; |
77 | 76 | ||
78 | let ret_type = if src.value.async_kw_token().is_some() { | 77 | let ret_type = if src.value.async_token().is_some() { |
79 | let future_impl = desugar_future_path(ret_type); | 78 | let future_impl = desugar_future_path(ret_type); |
80 | let ty_bound = TypeBound::Path(future_impl); | 79 | let ty_bound = TypeBound::Path(future_impl); |
81 | TypeRef::ImplTrait(vec![ty_bound]) | 80 | TypeRef::ImplTrait(vec![ty_bound]) |
@@ -136,7 +135,7 @@ impl TraitData { | |||
136 | pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { | 135 | pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { |
137 | let src = tr.lookup(db).source(db); | 136 | let src = tr.lookup(db).source(db); |
138 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 137 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
139 | let auto = src.value.auto_kw_token().is_some(); | 138 | let auto = src.value.auto_token().is_some(); |
140 | let ast_id_map = db.ast_id_map(src.file_id); | 139 | let ast_id_map = db.ast_id_map(src.file_id); |
141 | 140 | ||
142 | let container = AssocContainerId::TraitId(tr); | 141 | let container = AssocContainerId::TraitId(tr); |
@@ -318,10 +317,6 @@ fn collect_impl_items_in_macro( | |||
318 | } | 317 | } |
319 | } | 318 | } |
320 | 319 | ||
321 | fn is_cfg_enabled(cfg_options: &CfgOptions, attrs: &Attrs) -> bool { | ||
322 | attrs.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) | ||
323 | } | ||
324 | |||
325 | fn collect_impl_items( | 320 | fn collect_impl_items( |
326 | db: &dyn DefDatabase, | 321 | db: &dyn DefDatabase, |
327 | impl_items: impl Iterator<Item = ImplItem>, | 322 | impl_items: impl Iterator<Item = ImplItem>, |
@@ -341,10 +336,11 @@ fn collect_impl_items( | |||
341 | } | 336 | } |
342 | .intern(db); | 337 | .intern(db); |
343 | 338 | ||
344 | if !is_cfg_enabled( | 339 | if !db |
345 | &crate_graph[module_id.krate].cfg_options, | 340 | .function_data(def) |
346 | &db.function_data(def).attrs, | 341 | .attrs |
347 | ) { | 342 | .is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) |
343 | { | ||
348 | None | 344 | None |
349 | } else { | 345 | } else { |
350 | Some(def.into()) | 346 | Some(def.into()) |
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs index 095498429..cfa0f2f76 100644 --- a/crates/ra_hir_def/src/diagnostics.rs +++ b/crates/ra_hir_def/src/diagnostics.rs | |||
@@ -20,7 +20,7 @@ impl Diagnostic for UnresolvedModule { | |||
20 | "unresolved module".to_string() | 20 | "unresolved module".to_string() |
21 | } | 21 | } |
22 | fn source(&self) -> InFile<SyntaxNodePtr> { | 22 | fn source(&self) -> InFile<SyntaxNodePtr> { |
23 | InFile { file_id: self.file, value: self.decl.into() } | 23 | InFile { file_id: self.file, value: self.decl.clone().into() } |
24 | } | 24 | } |
25 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 25 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
26 | self | 26 | self |
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index 197bbe9bd..e11bdf3ec 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs | |||
@@ -376,35 +376,14 @@ pub enum Pat { | |||
376 | Wild, | 376 | Wild, |
377 | Tuple(Vec<PatId>), | 377 | Tuple(Vec<PatId>), |
378 | Or(Vec<PatId>), | 378 | Or(Vec<PatId>), |
379 | Record { | 379 | Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, |
380 | path: Option<Path>, | 380 | Range { start: ExprId, end: ExprId }, |
381 | args: Vec<RecordFieldPat>, | 381 | Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, |
382 | // FIXME: 'ellipsis' option | ||
383 | }, | ||
384 | Range { | ||
385 | start: ExprId, | ||
386 | end: ExprId, | ||
387 | }, | ||
388 | Slice { | ||
389 | prefix: Vec<PatId>, | ||
390 | slice: Option<PatId>, | ||
391 | suffix: Vec<PatId>, | ||
392 | }, | ||
393 | Path(Path), | 382 | Path(Path), |
394 | Lit(ExprId), | 383 | Lit(ExprId), |
395 | Bind { | 384 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, |
396 | mode: BindingAnnotation, | 385 | TupleStruct { path: Option<Path>, args: Vec<PatId> }, |
397 | name: Name, | 386 | Ref { pat: PatId, mutability: Mutability }, |
398 | subpat: Option<PatId>, | ||
399 | }, | ||
400 | TupleStruct { | ||
401 | path: Option<Path>, | ||
402 | args: Vec<PatId>, | ||
403 | }, | ||
404 | Ref { | ||
405 | pat: PatId, | ||
406 | mutability: Mutability, | ||
407 | }, | ||
408 | } | 387 | } |
409 | 388 | ||
410 | impl Pat { | 389 | impl Pat { |
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index 01b367278..d96ac8c0a 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs | |||
@@ -4,6 +4,7 @@ | |||
4 | //! features, such as Fn family of traits. | 4 | //! features, such as Fn family of traits. |
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use ra_prof::profile; | ||
7 | use ra_syntax::SmolStr; | 8 | use ra_syntax::SmolStr; |
8 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
9 | 10 | ||
@@ -78,6 +79,8 @@ impl LangItems { | |||
78 | 79 | ||
79 | /// Salsa query. This will look for lang items in a specific crate. | 80 | /// Salsa query. This will look for lang items in a specific crate. |
80 | pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> { | 81 | pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> { |
82 | let _p = profile("crate_lang_items_query"); | ||
83 | |||
81 | let mut lang_items = LangItems::default(); | 84 | let mut lang_items = LangItems::default(); |
82 | 85 | ||
83 | let crate_def_map = db.crate_def_map(krate); | 86 | let crate_def_map = db.crate_def_map(krate); |
@@ -95,6 +98,7 @@ impl LangItems { | |||
95 | db: &dyn DefDatabase, | 98 | db: &dyn DefDatabase, |
96 | module: ModuleId, | 99 | module: ModuleId, |
97 | ) -> Option<Arc<LangItems>> { | 100 | ) -> Option<Arc<LangItems>> { |
101 | let _p = profile("module_lang_items_query"); | ||
98 | let mut lang_items = LangItems::default(); | 102 | let mut lang_items = LangItems::default(); |
99 | lang_items.collect_lang_items(db, module); | 103 | lang_items.collect_lang_items(db, module); |
100 | if lang_items.items.is_empty() { | 104 | if lang_items.items.is_empty() { |
@@ -111,6 +115,7 @@ impl LangItems { | |||
111 | start_crate: CrateId, | 115 | start_crate: CrateId, |
112 | item: SmolStr, | 116 | item: SmolStr, |
113 | ) -> Option<LangItemTarget> { | 117 | ) -> Option<LangItemTarget> { |
118 | let _p = profile("lang_item_query"); | ||
114 | let lang_items = db.crate_lang_items(start_crate); | 119 | let lang_items = db.crate_lang_items(start_crate); |
115 | let start_crate_target = lang_items.items.get(&item); | 120 | let start_crate_target = lang_items.items.get(&item); |
116 | if let Some(target) = start_crate_target { | 121 | if let Some(target) = start_crate_target { |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index e72ba52cf..afd538e4a 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -287,7 +287,7 @@ impl RawItemsCollector { | |||
287 | let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene); | 287 | let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene); |
288 | 288 | ||
289 | let ast_id = self.source_ast_id_map.ast_id(&module); | 289 | let ast_id = self.source_ast_id_map.ast_id(&module); |
290 | if module.semi_token().is_some() { | 290 | if module.semicolon_token().is_some() { |
291 | let item = | 291 | let item = |
292 | self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id }); | 292 | self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id }); |
293 | self.push_item(current_module, attrs, RawItemKind::Module(item)); | 293 | self.push_item(current_module, attrs, RawItemKind::Module(item)); |
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs index 7a8338937..ea29c4176 100644 --- a/crates/ra_hir_def/src/type_ref.rs +++ b/crates/ra_hir_def/src/type_ref.rs | |||
@@ -77,7 +77,7 @@ impl TypeRef { | |||
77 | } | 77 | } |
78 | ast::TypeRef::PointerType(inner) => { | 78 | ast::TypeRef::PointerType(inner) => { |
79 | let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); | 79 | let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); |
80 | let mutability = Mutability::from_mutable(inner.mut_kw_token().is_some()); | 80 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
81 | TypeRef::RawPtr(Box::new(inner_ty), mutability) | 81 | TypeRef::RawPtr(Box::new(inner_ty), mutability) |
82 | } | 82 | } |
83 | ast::TypeRef::ArrayType(inner) => { | 83 | ast::TypeRef::ArrayType(inner) => { |
@@ -88,7 +88,7 @@ impl TypeRef { | |||
88 | } | 88 | } |
89 | ast::TypeRef::ReferenceType(inner) => { | 89 | ast::TypeRef::ReferenceType(inner) => { |
90 | let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); | 90 | let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); |
91 | let mutability = Mutability::from_mutable(inner.mut_kw_token().is_some()); | 91 | let mutability = Mutability::from_mutable(inner.mut_token().is_some()); |
92 | TypeRef::Reference(Box::new(inner_ty), mutability) | 92 | TypeRef::Reference(Box::new(inner_ty), mutability) |
93 | } | 93 | } |
94 | ast::TypeRef::PlaceholderType(_inner) => TypeRef::Placeholder, | 94 | ast::TypeRef::PlaceholderType(_inner) => TypeRef::Placeholder, |
diff --git a/crates/ra_hir_expand/src/ast_id_map.rs b/crates/ra_hir_expand/src/ast_id_map.rs index 5643ecdce..a3ca302c2 100644 --- a/crates/ra_hir_expand/src/ast_id_map.rs +++ b/crates/ra_hir_expand/src/ast_id_map.rs | |||
@@ -90,7 +90,7 @@ impl AstIdMap { | |||
90 | } | 90 | } |
91 | 91 | ||
92 | pub(crate) fn get<N: AstNode>(&self, id: FileAstId<N>) -> AstPtr<N> { | 92 | pub(crate) fn get<N: AstNode>(&self, id: FileAstId<N>) -> AstPtr<N> { |
93 | self.arena[id.raw].cast::<N>().unwrap() | 93 | self.arena[id.raw].clone().cast::<N>().unwrap() |
94 | } | 94 | } |
95 | 95 | ||
96 | fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId { | 96 | fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId { |
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index 9a4a7aa6f..59efc1c31 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -24,6 +24,8 @@ ra_prof = { path = "../ra_prof" } | |||
24 | ra_syntax = { path = "../ra_syntax" } | 24 | ra_syntax = { path = "../ra_syntax" } |
25 | test_utils = { path = "../test_utils" } | 25 | test_utils = { path = "../test_utils" } |
26 | 26 | ||
27 | scoped-tls = "1" | ||
28 | |||
27 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } | 29 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } |
28 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } | 30 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } |
29 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } | 31 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" } |
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 8cbce1168..927896d6f 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs | |||
@@ -21,7 +21,7 @@ impl Diagnostic for NoSuchField { | |||
21 | } | 21 | } |
22 | 22 | ||
23 | fn source(&self) -> InFile<SyntaxNodePtr> { | 23 | fn source(&self) -> InFile<SyntaxNodePtr> { |
24 | InFile { file_id: self.file, value: self.field.into() } | 24 | InFile { file_id: self.file, value: self.field.clone().into() } |
25 | } | 25 | } |
26 | 26 | ||
27 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 27 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
@@ -45,7 +45,7 @@ impl Diagnostic for MissingFields { | |||
45 | buf | 45 | buf |
46 | } | 46 | } |
47 | fn source(&self) -> InFile<SyntaxNodePtr> { | 47 | fn source(&self) -> InFile<SyntaxNodePtr> { |
48 | InFile { file_id: self.file, value: self.field_list.into() } | 48 | InFile { file_id: self.file, value: self.field_list.clone().into() } |
49 | } | 49 | } |
50 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 50 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
51 | self | 51 | self |
@@ -63,6 +63,29 @@ impl AstDiagnostic for MissingFields { | |||
63 | } | 63 | } |
64 | 64 | ||
65 | #[derive(Debug)] | 65 | #[derive(Debug)] |
66 | pub struct MissingPatFields { | ||
67 | pub file: HirFileId, | ||
68 | pub field_list: AstPtr<ast::RecordFieldPatList>, | ||
69 | pub missed_fields: Vec<Name>, | ||
70 | } | ||
71 | |||
72 | impl Diagnostic for MissingPatFields { | ||
73 | fn message(&self) -> String { | ||
74 | let mut buf = String::from("Missing structure fields:\n"); | ||
75 | for field in &self.missed_fields { | ||
76 | format_to!(buf, "- {}", field); | ||
77 | } | ||
78 | buf | ||
79 | } | ||
80 | fn source(&self) -> InFile<SyntaxNodePtr> { | ||
81 | InFile { file_id: self.file, value: self.field_list.clone().into() } | ||
82 | } | ||
83 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
84 | self | ||
85 | } | ||
86 | } | ||
87 | |||
88 | #[derive(Debug)] | ||
66 | pub struct MissingMatchArms { | 89 | pub struct MissingMatchArms { |
67 | pub file: HirFileId, | 90 | pub file: HirFileId, |
68 | pub match_expr: AstPtr<ast::Expr>, | 91 | pub match_expr: AstPtr<ast::Expr>, |
@@ -74,7 +97,7 @@ impl Diagnostic for MissingMatchArms { | |||
74 | String::from("Missing match arm") | 97 | String::from("Missing match arm") |
75 | } | 98 | } |
76 | fn source(&self) -> InFile<SyntaxNodePtr> { | 99 | fn source(&self) -> InFile<SyntaxNodePtr> { |
77 | InFile { file_id: self.file, value: self.match_expr.into() } | 100 | InFile { file_id: self.file, value: self.match_expr.clone().into() } |
78 | } | 101 | } |
79 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 102 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
80 | self | 103 | self |
@@ -92,7 +115,7 @@ impl Diagnostic for MissingOkInTailExpr { | |||
92 | "wrap return expression in Ok".to_string() | 115 | "wrap return expression in Ok".to_string() |
93 | } | 116 | } |
94 | fn source(&self) -> InFile<SyntaxNodePtr> { | 117 | fn source(&self) -> InFile<SyntaxNodePtr> { |
95 | InFile { file_id: self.file, value: self.expr.into() } | 118 | InFile { file_id: self.file, value: self.expr.clone().into() } |
96 | } | 119 | } |
97 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 120 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
98 | self | 121 | self |
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs index 0e9313aa1..d03bbd5a7 100644 --- a/crates/ra_hir_ty/src/display.rs +++ b/crates/ra_hir_ty/src/display.rs | |||
@@ -247,19 +247,21 @@ impl HirDisplay for ApplicationTy { | |||
247 | } | 247 | } |
248 | } | 248 | } |
249 | TypeCtor::Closure { .. } => { | 249 | TypeCtor::Closure { .. } => { |
250 | let sig = self.parameters[0] | 250 | let sig = self.parameters[0].callable_sig(f.db); |
251 | .callable_sig(f.db) | 251 | if let Some(sig) = sig { |
252 | .expect("first closure parameter should contain signature"); | 252 | if sig.params().is_empty() { |
253 | if sig.params().is_empty() { | 253 | write!(f, "||")?; |
254 | write!(f, "||")?; | 254 | } else if f.omit_verbose_types() { |
255 | } else if f.omit_verbose_types() { | 255 | write!(f, "|{}|", TYPE_HINT_TRUNCATION)?; |
256 | write!(f, "|{}|", TYPE_HINT_TRUNCATION)?; | 256 | } else { |
257 | write!(f, "|")?; | ||
258 | f.write_joined(sig.params(), ", ")?; | ||
259 | write!(f, "|")?; | ||
260 | }; | ||
261 | write!(f, " -> {}", sig.ret().display(f.db))?; | ||
257 | } else { | 262 | } else { |
258 | write!(f, "|")?; | 263 | write!(f, "{{closure}}")?; |
259 | f.write_joined(sig.params(), ", ")?; | 264 | } |
260 | write!(f, "|")?; | ||
261 | }; | ||
262 | write!(f, " -> {}", sig.ret().display(f.db))?; | ||
263 | } | 265 | } |
264 | } | 266 | } |
265 | Ok(()) | 267 | Ok(()) |
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index e45e9ea14..827b687de 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs | |||
@@ -9,7 +9,7 @@ use rustc_hash::FxHashSet; | |||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr}, | 12 | diagnostics::{MissingFields, MissingMatchArms, MissingOkInTailExpr, MissingPatFields}, |
13 | utils::variant_data, | 13 | utils::variant_data, |
14 | ApplicationTy, InferenceResult, Ty, TypeCtor, | 14 | ApplicationTy, InferenceResult, Ty, TypeCtor, |
15 | _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, | 15 | _match::{is_useful, MatchCheckCtx, Matrix, PatStack, Usefulness}, |
@@ -49,39 +49,97 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
49 | if let Some((variant_def, missed_fields, true)) = | 49 | if let Some((variant_def, missed_fields, true)) = |
50 | record_literal_missing_fields(db, &self.infer, id, expr) | 50 | record_literal_missing_fields(db, &self.infer, id, expr) |
51 | { | 51 | { |
52 | // XXX: only look at source_map if we do have missing fields | 52 | self.create_record_literal_missing_fields_diagnostic( |
53 | let (_, source_map) = db.body_with_source_map(self.func.into()); | 53 | id, |
54 | 54 | db, | |
55 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 55 | variant_def, |
56 | if let Some(expr) = source_ptr.value.left() { | 56 | missed_fields, |
57 | let root = source_ptr.file_syntax(db.upcast()); | 57 | ); |
58 | if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { | ||
59 | if let Some(field_list) = record_lit.record_field_list() { | ||
60 | let variant_data = variant_data(db.upcast(), variant_def); | ||
61 | let missed_fields = missed_fields | ||
62 | .into_iter() | ||
63 | .map(|idx| variant_data.fields()[idx].name.clone()) | ||
64 | .collect(); | ||
65 | self.sink.push(MissingFields { | ||
66 | file: source_ptr.file_id, | ||
67 | field_list: AstPtr::new(&field_list), | ||
68 | missed_fields, | ||
69 | }) | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | } | 58 | } |
75 | if let Expr::Match { expr, arms } = expr { | 59 | if let Expr::Match { expr, arms } = expr { |
76 | self.validate_match(id, *expr, arms, db, self.infer.clone()); | 60 | self.validate_match(id, *expr, arms, db, self.infer.clone()); |
77 | } | 61 | } |
78 | } | 62 | } |
63 | for (id, pat) in body.pats.iter() { | ||
64 | if let Some((variant_def, missed_fields, true)) = | ||
65 | record_pattern_missing_fields(db, &self.infer, id, pat) | ||
66 | { | ||
67 | self.create_record_pattern_missing_fields_diagnostic( | ||
68 | id, | ||
69 | db, | ||
70 | variant_def, | ||
71 | missed_fields, | ||
72 | ); | ||
73 | } | ||
74 | } | ||
79 | let body_expr = &body[body.body_expr]; | 75 | let body_expr = &body[body.body_expr]; |
80 | if let Expr::Block { tail: Some(t), .. } = body_expr { | 76 | if let Expr::Block { tail: Some(t), .. } = body_expr { |
81 | self.validate_results_in_tail_expr(body.body_expr, *t, db); | 77 | self.validate_results_in_tail_expr(body.body_expr, *t, db); |
82 | } | 78 | } |
83 | } | 79 | } |
84 | 80 | ||
81 | fn create_record_literal_missing_fields_diagnostic( | ||
82 | &mut self, | ||
83 | id: ExprId, | ||
84 | db: &dyn HirDatabase, | ||
85 | variant_def: VariantId, | ||
86 | missed_fields: Vec<LocalStructFieldId>, | ||
87 | ) { | ||
88 | // XXX: only look at source_map if we do have missing fields | ||
89 | let (_, source_map) = db.body_with_source_map(self.func.into()); | ||
90 | |||
91 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | ||
92 | if let Some(expr) = source_ptr.value.as_ref().left() { | ||
93 | let root = source_ptr.file_syntax(db.upcast()); | ||
94 | if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { | ||
95 | if let Some(field_list) = record_lit.record_field_list() { | ||
96 | let variant_data = variant_data(db.upcast(), variant_def); | ||
97 | let missed_fields = missed_fields | ||
98 | .into_iter() | ||
99 | .map(|idx| variant_data.fields()[idx].name.clone()) | ||
100 | .collect(); | ||
101 | self.sink.push(MissingFields { | ||
102 | file: source_ptr.file_id, | ||
103 | field_list: AstPtr::new(&field_list), | ||
104 | missed_fields, | ||
105 | }) | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | fn create_record_pattern_missing_fields_diagnostic( | ||
113 | &mut self, | ||
114 | id: PatId, | ||
115 | db: &dyn HirDatabase, | ||
116 | variant_def: VariantId, | ||
117 | missed_fields: Vec<LocalStructFieldId>, | ||
118 | ) { | ||
119 | // XXX: only look at source_map if we do have missing fields | ||
120 | let (_, source_map) = db.body_with_source_map(self.func.into()); | ||
121 | |||
122 | if let Ok(source_ptr) = source_map.pat_syntax(id) { | ||
123 | if let Some(expr) = source_ptr.value.as_ref().left() { | ||
124 | let root = source_ptr.file_syntax(db.upcast()); | ||
125 | if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { | ||
126 | if let Some(field_list) = record_pat.record_field_pat_list() { | ||
127 | let variant_data = variant_data(db.upcast(), variant_def); | ||
128 | let missed_fields = missed_fields | ||
129 | .into_iter() | ||
130 | .map(|idx| variant_data.fields()[idx].name.clone()) | ||
131 | .collect(); | ||
132 | self.sink.push(MissingPatFields { | ||
133 | file: source_ptr.file_id, | ||
134 | field_list: AstPtr::new(&field_list), | ||
135 | missed_fields, | ||
136 | }) | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | |||
85 | fn validate_match( | 143 | fn validate_match( |
86 | &mut self, | 144 | &mut self, |
87 | id: ExprId, | 145 | id: ExprId, |
@@ -147,7 +205,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
147 | } | 205 | } |
148 | 206 | ||
149 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 207 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
150 | if let Some(expr) = source_ptr.value.left() { | 208 | if let Some(expr) = source_ptr.value.as_ref().left() { |
151 | let root = source_ptr.file_syntax(db.upcast()); | 209 | let root = source_ptr.file_syntax(db.upcast()); |
152 | if let ast::Expr::MatchExpr(match_expr) = expr.to_node(&root) { | 210 | if let ast::Expr::MatchExpr(match_expr) = expr.to_node(&root) { |
153 | if let (Some(match_expr), Some(arms)) = | 211 | if let (Some(match_expr), Some(arms)) = |
@@ -232,9 +290,9 @@ pub fn record_pattern_missing_fields( | |||
232 | infer: &InferenceResult, | 290 | infer: &InferenceResult, |
233 | id: PatId, | 291 | id: PatId, |
234 | pat: &Pat, | 292 | pat: &Pat, |
235 | ) -> Option<(VariantId, Vec<LocalStructFieldId>)> { | 293 | ) -> Option<(VariantId, Vec<LocalStructFieldId>, /*exhaustive*/ bool)> { |
236 | let fields = match pat { | 294 | let (fields, exhaustive) = match pat { |
237 | Pat::Record { path: _, args } => args, | 295 | Pat::Record { path: _, args, ellipsis } => (args, !ellipsis), |
238 | _ => return None, | 296 | _ => return None, |
239 | }; | 297 | }; |
240 | 298 | ||
@@ -254,5 +312,5 @@ pub fn record_pattern_missing_fields( | |||
254 | if missed_fields.is_empty() { | 312 | if missed_fields.is_empty() { |
255 | return None; | 313 | return None; |
256 | } | 314 | } |
257 | Some((variant_def, missed_fields)) | 315 | Some((variant_def, missed_fields, exhaustive)) |
258 | } | 316 | } |
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index 69bbb4307..078476f76 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -158,7 +158,7 @@ impl<'a> InferenceContext<'a> { | |||
158 | Pat::TupleStruct { path: p, args: subpats } => { | 158 | Pat::TupleStruct { path: p, args: subpats } => { |
159 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm, pat) | 159 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm, pat) |
160 | } | 160 | } |
161 | Pat::Record { path: p, args: fields } => { | 161 | Pat::Record { path: p, args: fields, ellipsis: _ } => { |
162 | self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) | 162 | self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) |
163 | } | 163 | } |
164 | Pat::Path(path) => { | 164 | Pat::Path(path) => { |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index f97e0bfeb..54e31602f 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -23,7 +23,7 @@ use insta::assert_snapshot; | |||
23 | use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; | 23 | use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; |
24 | use ra_syntax::{ | 24 | use ra_syntax::{ |
25 | algo, | 25 | algo, |
26 | ast::{self, AstNode, AstToken}, | 26 | ast::{self, AstNode}, |
27 | }; | 27 | }; |
28 | use stdx::format_to; | 28 | use stdx::format_to; |
29 | 29 | ||
@@ -87,7 +87,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
87 | } | 87 | } |
88 | Err(SyntheticSyntax) => continue, | 88 | Err(SyntheticSyntax) => continue, |
89 | }; | 89 | }; |
90 | types.push((syntax_ptr, ty)); | 90 | types.push((syntax_ptr.clone(), ty)); |
91 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { | 91 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { |
92 | mismatches.push((syntax_ptr, mismatch)); | 92 | mismatches.push((syntax_ptr, mismatch)); |
93 | } | 93 | } |
@@ -101,7 +101,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
101 | let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db)); | 101 | let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db)); |
102 | 102 | ||
103 | let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { | 103 | let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { |
104 | (self_param.self_kw_token().unwrap().syntax().text_range(), "self".to_string()) | 104 | (self_param.self_token().unwrap().text_range(), "self".to_string()) |
105 | } else { | 105 | } else { |
106 | (src_ptr.value.range(), node.text().to_string().replace("\n", " ")) | 106 | (src_ptr.value.range(), node.text().to_string().replace("\n", " ")) |
107 | }; | 107 | }; |
@@ -349,3 +349,103 @@ fn no_such_field_with_feature_flag_diagnostics() { | |||
349 | 349 | ||
350 | assert_snapshot!(diagnostics, @r###""###); | 350 | assert_snapshot!(diagnostics, @r###""###); |
351 | } | 351 | } |
352 | |||
353 | #[test] | ||
354 | fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() { | ||
355 | let diagnostics = TestDB::with_files( | ||
356 | r#" | ||
357 | //- /lib.rs crate:foo cfg:feature=foo | ||
358 | struct S { | ||
359 | #[cfg(feature = "foo")] | ||
360 | foo: u32, | ||
361 | #[cfg(not(feature = "foo"))] | ||
362 | bar: u32, | ||
363 | } | ||
364 | |||
365 | impl S { | ||
366 | #[cfg(feature = "foo")] | ||
367 | fn new(foo: u32) -> Self { | ||
368 | Self { foo } | ||
369 | } | ||
370 | #[cfg(not(feature = "foo"))] | ||
371 | fn new(bar: u32) -> Self { | ||
372 | Self { bar } | ||
373 | } | ||
374 | } | ||
375 | "#, | ||
376 | ) | ||
377 | .diagnostics() | ||
378 | .0; | ||
379 | |||
380 | assert_snapshot!(diagnostics, @r###""###); | ||
381 | } | ||
382 | |||
383 | #[test] | ||
384 | fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() { | ||
385 | let diagnostics = TestDB::with_files( | ||
386 | r#" | ||
387 | //- /lib.rs crate:foo cfg:feature=foo | ||
388 | struct S { | ||
389 | #[cfg(feature = "foo")] | ||
390 | foo: u32, | ||
391 | #[cfg(not(feature = "foo"))] | ||
392 | bar: u32, | ||
393 | } | ||
394 | |||
395 | impl S { | ||
396 | fn new(val: u32) -> Self { | ||
397 | Self { | ||
398 | #[cfg(feature = "foo")] | ||
399 | foo: val, | ||
400 | #[cfg(not(feature = "foo"))] | ||
401 | bar: val, | ||
402 | } | ||
403 | } | ||
404 | } | ||
405 | "#, | ||
406 | ) | ||
407 | .diagnostics() | ||
408 | .0; | ||
409 | |||
410 | assert_snapshot!(diagnostics, @r###""###); | ||
411 | } | ||
412 | |||
413 | #[test] | ||
414 | fn missing_record_pat_field_diagnostic() { | ||
415 | let diagnostics = TestDB::with_files( | ||
416 | r" | ||
417 | //- /lib.rs | ||
418 | struct S { foo: i32, bar: () } | ||
419 | fn baz(s: S) { | ||
420 | let S { foo: _ } = s; | ||
421 | } | ||
422 | ", | ||
423 | ) | ||
424 | .diagnostics() | ||
425 | .0; | ||
426 | |||
427 | assert_snapshot!(diagnostics, @r###" | ||
428 | "{ foo: _ }": Missing structure fields: | ||
429 | - bar | ||
430 | "### | ||
431 | ); | ||
432 | } | ||
433 | |||
434 | #[test] | ||
435 | fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() { | ||
436 | let diagnostics = TestDB::with_files( | ||
437 | r" | ||
438 | //- /lib.rs | ||
439 | struct S { foo: i32, bar: () } | ||
440 | fn baz(s: S) -> i32 { | ||
441 | match s { | ||
442 | S { foo, .. } => foo, | ||
443 | } | ||
444 | } | ||
445 | ", | ||
446 | ) | ||
447 | .diagnostics() | ||
448 | .0; | ||
449 | |||
450 | assert_snapshot!(diagnostics, @""); | ||
451 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index ff4599b71..f2a9b1c40 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -1,10 +1,13 @@ | |||
1 | use std::fs; | ||
2 | |||
1 | use insta::assert_snapshot; | 3 | use insta::assert_snapshot; |
2 | use ra_db::fixture::WithFixture; | 4 | use ra_db::fixture::WithFixture; |
3 | 5 | use test_utils::project_dir; | |
4 | use super::{infer, type_at, type_at_pos}; | ||
5 | 6 | ||
6 | use crate::test_db::TestDB; | 7 | use crate::test_db::TestDB; |
7 | 8 | ||
9 | use super::{infer, type_at, type_at_pos}; | ||
10 | |||
8 | #[test] | 11 | #[test] |
9 | fn cfg_impl_def() { | 12 | fn cfg_impl_def() { |
10 | let (db, pos) = TestDB::with_position( | 13 | let (db, pos) = TestDB::with_position( |
@@ -482,6 +485,30 @@ fn bar() -> u32 {0} | |||
482 | } | 485 | } |
483 | 486 | ||
484 | #[test] | 487 | #[test] |
488 | #[ignore] | ||
489 | fn include_accidentally_quadratic() { | ||
490 | let file = project_dir().join("crates/ra_syntax/test_data/accidentally_quadratic"); | ||
491 | let big_file = fs::read_to_string(file).unwrap(); | ||
492 | let big_file = vec![big_file; 10].join("\n"); | ||
493 | |||
494 | let fixture = r#" | ||
495 | //- /main.rs | ||
496 | #[rustc_builtin_macro] | ||
497 | macro_rules! include {() => {}} | ||
498 | |||
499 | include!("foo.rs"); | ||
500 | |||
501 | fn main() { | ||
502 | RegisterBlock { }<|>; | ||
503 | } | ||
504 | "#; | ||
505 | let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file); | ||
506 | |||
507 | let (db, pos) = TestDB::with_position(&fixture); | ||
508 | assert_eq!("RegisterBlock", type_at_pos(&db, pos)); | ||
509 | } | ||
510 | |||
511 | #[test] | ||
485 | fn infer_builtin_macros_include_concat() { | 512 | fn infer_builtin_macros_include_concat() { |
486 | let (db, pos) = TestDB::with_position( | 513 | let (db, pos) = TestDB::with_position( |
487 | r#" | 514 | r#" |
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 5a1e12ce9..21e233379 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs | |||
@@ -177,7 +177,7 @@ fn solve( | |||
177 | 177 | ||
178 | let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL); | 178 | let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL); |
179 | 179 | ||
180 | let solution = solver.solve_limited(&context, goal, || { | 180 | let should_continue = || { |
181 | context.db.check_canceled(); | 181 | context.db.check_canceled(); |
182 | let remaining = fuel.get(); | 182 | let remaining = fuel.get(); |
183 | fuel.set(remaining - 1); | 183 | fuel.set(remaining - 1); |
@@ -185,12 +185,21 @@ fn solve( | |||
185 | log::debug!("fuel exhausted"); | 185 | log::debug!("fuel exhausted"); |
186 | } | 186 | } |
187 | remaining > 0 | 187 | remaining > 0 |
188 | }); | 188 | }; |
189 | let mut solve = || solver.solve_limited(&context, goal, should_continue); | ||
190 | // don't set the TLS for Chalk unless Chalk debugging is active, to make | ||
191 | // extra sure we only use it for debugging | ||
192 | let solution = | ||
193 | if is_chalk_debug() { chalk::tls::set_current_program(db, solve) } else { solve() }; | ||
189 | 194 | ||
190 | log::debug!("solve({:?}) => {:?}", goal, solution); | 195 | log::debug!("solve({:?}) => {:?}", goal, solution); |
191 | solution | 196 | solution |
192 | } | 197 | } |
193 | 198 | ||
199 | fn is_chalk_debug() -> bool { | ||
200 | std::env::var("CHALK_DEBUG").is_ok() | ||
201 | } | ||
202 | |||
194 | fn solution_from_chalk( | 203 | fn solution_from_chalk( |
195 | db: &dyn HirDatabase, | 204 | db: &dyn HirDatabase, |
196 | solution: chalk_solve::Solution<Interner>, | 205 | solution: chalk_solve::Solution<Interner>, |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 1bc0f0713..c5f1b5232 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -20,6 +20,8 @@ use crate::{ | |||
20 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 20 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | pub(super) mod tls; | ||
24 | |||
23 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] | 25 | #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] |
24 | pub struct Interner; | 26 | pub struct Interner; |
25 | 27 | ||
@@ -33,90 +35,85 @@ impl chalk_ir::interner::Interner for Interner { | |||
33 | type Identifier = TypeAliasId; | 35 | type Identifier = TypeAliasId; |
34 | type DefId = InternId; | 36 | type DefId = InternId; |
35 | 37 | ||
36 | // FIXME: implement these | ||
37 | fn debug_struct_id( | 38 | fn debug_struct_id( |
38 | _type_kind_id: chalk_ir::StructId<Self>, | 39 | type_kind_id: StructId, |
39 | _fmt: &mut fmt::Formatter<'_>, | 40 | fmt: &mut fmt::Formatter<'_>, |
40 | ) -> Option<fmt::Result> { | 41 | ) -> Option<fmt::Result> { |
41 | None | 42 | tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) |
42 | } | 43 | } |
43 | 44 | ||
44 | fn debug_trait_id( | 45 | fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { |
45 | _type_kind_id: chalk_ir::TraitId<Self>, | 46 | tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) |
46 | _fmt: &mut fmt::Formatter<'_>, | ||
47 | ) -> Option<fmt::Result> { | ||
48 | None | ||
49 | } | 47 | } |
50 | 48 | ||
51 | fn debug_assoc_type_id( | 49 | fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { |
52 | _id: chalk_ir::AssocTypeId<Self>, | 50 | tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) |
53 | _fmt: &mut fmt::Formatter<'_>, | ||
54 | ) -> Option<fmt::Result> { | ||
55 | None | ||
56 | } | 51 | } |
57 | 52 | ||
58 | fn debug_alias( | 53 | fn debug_alias( |
59 | _projection: &chalk_ir::AliasTy<Self>, | 54 | alias: &chalk_ir::AliasTy<Interner>, |
60 | _fmt: &mut fmt::Formatter<'_>, | 55 | fmt: &mut fmt::Formatter<'_>, |
61 | ) -> Option<fmt::Result> { | 56 | ) -> Option<fmt::Result> { |
62 | None | 57 | tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) |
63 | } | 58 | } |
64 | 59 | ||
65 | fn debug_ty(_ty: &chalk_ir::Ty<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | 60 | fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { |
66 | None | 61 | tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) |
67 | } | 62 | } |
68 | 63 | ||
69 | fn debug_lifetime( | 64 | fn debug_lifetime( |
70 | _lifetime: &chalk_ir::Lifetime<Self>, | 65 | lifetime: &chalk_ir::Lifetime<Interner>, |
71 | _fmt: &mut fmt::Formatter<'_>, | 66 | fmt: &mut fmt::Formatter<'_>, |
72 | ) -> Option<fmt::Result> { | 67 | ) -> Option<fmt::Result> { |
73 | None | 68 | tls::with_current_program(|prog| Some(prog?.debug_lifetime(lifetime, fmt))) |
74 | } | 69 | } |
75 | 70 | ||
76 | fn debug_parameter( | 71 | fn debug_parameter( |
77 | _parameter: &Parameter<Self>, | 72 | parameter: &Parameter<Interner>, |
78 | _fmt: &mut fmt::Formatter<'_>, | 73 | fmt: &mut fmt::Formatter<'_>, |
79 | ) -> Option<fmt::Result> { | 74 | ) -> Option<fmt::Result> { |
80 | None | 75 | tls::with_current_program(|prog| Some(prog?.debug_parameter(parameter, fmt))) |
81 | } | 76 | } |
82 | 77 | ||
83 | fn debug_goal(_goal: &Goal<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | 78 | fn debug_goal(goal: &Goal<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { |
84 | None | 79 | tls::with_current_program(|prog| Some(prog?.debug_goal(goal, fmt))) |
85 | } | 80 | } |
86 | 81 | ||
87 | fn debug_goals( | 82 | fn debug_goals( |
88 | _goals: &chalk_ir::Goals<Self>, | 83 | goals: &chalk_ir::Goals<Interner>, |
89 | _fmt: &mut fmt::Formatter<'_>, | 84 | fmt: &mut fmt::Formatter<'_>, |
90 | ) -> Option<fmt::Result> { | 85 | ) -> Option<fmt::Result> { |
91 | None | 86 | tls::with_current_program(|prog| Some(prog?.debug_goals(goals, fmt))) |
92 | } | 87 | } |
93 | 88 | ||
94 | fn debug_program_clause_implication( | 89 | fn debug_program_clause_implication( |
95 | _pci: &chalk_ir::ProgramClauseImplication<Self>, | 90 | pci: &chalk_ir::ProgramClauseImplication<Interner>, |
96 | _fmt: &mut fmt::Formatter<'_>, | 91 | fmt: &mut fmt::Formatter<'_>, |
97 | ) -> Option<fmt::Result> { | 92 | ) -> Option<fmt::Result> { |
98 | None | 93 | tls::with_current_program(|prog| Some(prog?.debug_program_clause_implication(pci, fmt))) |
99 | } | 94 | } |
100 | 95 | ||
101 | fn debug_application_ty( | 96 | fn debug_application_ty( |
102 | _application_ty: &chalk_ir::ApplicationTy<Self>, | 97 | application_ty: &chalk_ir::ApplicationTy<Interner>, |
103 | _fmt: &mut fmt::Formatter<'_>, | 98 | fmt: &mut fmt::Formatter<'_>, |
104 | ) -> Option<fmt::Result> { | 99 | ) -> Option<fmt::Result> { |
105 | None | 100 | tls::with_current_program(|prog| Some(prog?.debug_application_ty(application_ty, fmt))) |
106 | } | 101 | } |
107 | 102 | ||
108 | fn debug_substitution( | 103 | fn debug_substitution( |
109 | _substitution: &chalk_ir::Substitution<Self>, | 104 | substitution: &chalk_ir::Substitution<Interner>, |
110 | _fmt: &mut fmt::Formatter<'_>, | 105 | fmt: &mut fmt::Formatter<'_>, |
111 | ) -> Option<fmt::Result> { | 106 | ) -> Option<fmt::Result> { |
112 | None | 107 | tls::with_current_program(|prog| Some(prog?.debug_substitution(substitution, fmt))) |
113 | } | 108 | } |
114 | 109 | ||
115 | fn debug_separator_trait_ref( | 110 | fn debug_separator_trait_ref( |
116 | _separator_trait_ref: &chalk_ir::SeparatorTraitRef<Self>, | 111 | separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>, |
117 | _fmt: &mut fmt::Formatter<'_>, | 112 | fmt: &mut fmt::Formatter<'_>, |
118 | ) -> Option<fmt::Result> { | 113 | ) -> Option<fmt::Result> { |
119 | None | 114 | tls::with_current_program(|prog| { |
115 | Some(prog?.debug_separator_trait_ref(separator_trait_ref, fmt)) | ||
116 | }) | ||
120 | } | 117 | } |
121 | 118 | ||
122 | fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { | 119 | fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { |
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs new file mode 100644 index 000000000..d9bbb54a5 --- /dev/null +++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs | |||
@@ -0,0 +1,231 @@ | |||
1 | //! Implementation of Chalk debug helper functions using TLS. | ||
2 | use std::fmt; | ||
3 | |||
4 | use chalk_ir::{AliasTy, Goal, Goals, Lifetime, Parameter, ProgramClauseImplication, TypeName}; | ||
5 | |||
6 | use super::{from_chalk, Interner}; | ||
7 | use crate::{db::HirDatabase, CallableDef, TypeCtor}; | ||
8 | use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId}; | ||
9 | |||
10 | pub use unsafe_tls::{set_current_program, with_current_program}; | ||
11 | |||
12 | pub struct DebugContext<'a>(&'a (dyn HirDatabase + 'a)); | ||
13 | |||
14 | impl DebugContext<'_> { | ||
15 | pub fn debug_struct_id( | ||
16 | &self, | ||
17 | id: super::StructId, | ||
18 | f: &mut fmt::Formatter<'_>, | ||
19 | ) -> Result<(), fmt::Error> { | ||
20 | let type_ctor: TypeCtor = from_chalk(self.0, TypeName::Struct(id)); | ||
21 | match type_ctor { | ||
22 | TypeCtor::Bool => write!(f, "bool")?, | ||
23 | TypeCtor::Char => write!(f, "char")?, | ||
24 | TypeCtor::Int(t) => write!(f, "{}", t)?, | ||
25 | TypeCtor::Float(t) => write!(f, "{}", t)?, | ||
26 | TypeCtor::Str => write!(f, "str")?, | ||
27 | TypeCtor::Slice => write!(f, "slice")?, | ||
28 | TypeCtor::Array => write!(f, "array")?, | ||
29 | TypeCtor::RawPtr(m) => write!(f, "*{}", m.as_keyword_for_ptr())?, | ||
30 | TypeCtor::Ref(m) => write!(f, "&{}", m.as_keyword_for_ref())?, | ||
31 | TypeCtor::Never => write!(f, "!")?, | ||
32 | TypeCtor::Tuple { .. } => { | ||
33 | write!(f, "()")?; | ||
34 | } | ||
35 | TypeCtor::FnPtr { .. } => { | ||
36 | write!(f, "fn")?; | ||
37 | } | ||
38 | TypeCtor::FnDef(def) => { | ||
39 | let name = match def { | ||
40 | CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(), | ||
41 | CallableDef::StructId(s) => self.0.struct_data(s).name.clone(), | ||
42 | CallableDef::EnumVariantId(e) => { | ||
43 | let enum_data = self.0.enum_data(e.parent); | ||
44 | enum_data.variants[e.local_id].name.clone() | ||
45 | } | ||
46 | }; | ||
47 | match def { | ||
48 | CallableDef::FunctionId(_) => write!(f, "{{fn {}}}", name)?, | ||
49 | CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => { | ||
50 | write!(f, "{{ctor {}}}", name)? | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | TypeCtor::Adt(def_id) => { | ||
55 | let name = match def_id { | ||
56 | AdtId::StructId(it) => self.0.struct_data(it).name.clone(), | ||
57 | AdtId::UnionId(it) => self.0.union_data(it).name.clone(), | ||
58 | AdtId::EnumId(it) => self.0.enum_data(it).name.clone(), | ||
59 | }; | ||
60 | write!(f, "{}", name)?; | ||
61 | } | ||
62 | TypeCtor::AssociatedType(type_alias) => { | ||
63 | let trait_ = match type_alias.lookup(self.0.upcast()).container { | ||
64 | AssocContainerId::TraitId(it) => it, | ||
65 | _ => panic!("not an associated type"), | ||
66 | }; | ||
67 | let trait_name = self.0.trait_data(trait_).name.clone(); | ||
68 | let name = self.0.type_alias_data(type_alias).name.clone(); | ||
69 | write!(f, "{}::{}", trait_name, name)?; | ||
70 | } | ||
71 | TypeCtor::Closure { def, expr } => { | ||
72 | write!(f, "{{closure {:?} in {:?}}}", expr.into_raw(), def)?; | ||
73 | } | ||
74 | } | ||
75 | Ok(()) | ||
76 | } | ||
77 | |||
78 | pub fn debug_trait_id( | ||
79 | &self, | ||
80 | id: super::TraitId, | ||
81 | fmt: &mut fmt::Formatter<'_>, | ||
82 | ) -> Result<(), fmt::Error> { | ||
83 | let trait_: hir_def::TraitId = from_chalk(self.0, id); | ||
84 | let trait_data = self.0.trait_data(trait_); | ||
85 | write!(fmt, "{}", trait_data.name) | ||
86 | } | ||
87 | |||
88 | pub fn debug_assoc_type_id( | ||
89 | &self, | ||
90 | id: super::AssocTypeId, | ||
91 | fmt: &mut fmt::Formatter<'_>, | ||
92 | ) -> Result<(), fmt::Error> { | ||
93 | let type_alias: TypeAliasId = from_chalk(self.0, id); | ||
94 | let type_alias_data = self.0.type_alias_data(type_alias); | ||
95 | let trait_ = match type_alias.lookup(self.0.upcast()).container { | ||
96 | AssocContainerId::TraitId(t) => t, | ||
97 | _ => panic!("associated type not in trait"), | ||
98 | }; | ||
99 | let trait_data = self.0.trait_data(trait_); | ||
100 | write!(fmt, "{}::{}", trait_data.name, type_alias_data.name) | ||
101 | } | ||
102 | |||
103 | pub fn debug_alias( | ||
104 | &self, | ||
105 | alias: &AliasTy<Interner>, | ||
106 | fmt: &mut fmt::Formatter<'_>, | ||
107 | ) -> Result<(), fmt::Error> { | ||
108 | let type_alias: TypeAliasId = from_chalk(self.0, alias.associated_ty_id); | ||
109 | let type_alias_data = self.0.type_alias_data(type_alias); | ||
110 | let trait_ = match type_alias.lookup(self.0.upcast()).container { | ||
111 | AssocContainerId::TraitId(t) => t, | ||
112 | _ => panic!("associated type not in trait"), | ||
113 | }; | ||
114 | let trait_data = self.0.trait_data(trait_); | ||
115 | let params = alias.substitution.parameters(&Interner); | ||
116 | write!( | ||
117 | fmt, | ||
118 | "<{:?} as {}<{:?}>>::{}", | ||
119 | ¶ms[0], | ||
120 | trait_data.name, | ||
121 | ¶ms[1..], | ||
122 | type_alias_data.name | ||
123 | ) | ||
124 | } | ||
125 | |||
126 | pub fn debug_ty( | ||
127 | &self, | ||
128 | ty: &chalk_ir::Ty<Interner>, | ||
129 | fmt: &mut fmt::Formatter<'_>, | ||
130 | ) -> Result<(), fmt::Error> { | ||
131 | write!(fmt, "{:?}", ty.data(&Interner)) | ||
132 | } | ||
133 | |||
134 | pub fn debug_lifetime( | ||
135 | &self, | ||
136 | lifetime: &Lifetime<Interner>, | ||
137 | fmt: &mut fmt::Formatter<'_>, | ||
138 | ) -> Result<(), fmt::Error> { | ||
139 | write!(fmt, "{:?}", lifetime.data(&Interner)) | ||
140 | } | ||
141 | |||
142 | pub fn debug_parameter( | ||
143 | &self, | ||
144 | parameter: &Parameter<Interner>, | ||
145 | fmt: &mut fmt::Formatter<'_>, | ||
146 | ) -> Result<(), fmt::Error> { | ||
147 | write!(fmt, "{:?}", parameter.data(&Interner).inner_debug()) | ||
148 | } | ||
149 | |||
150 | pub fn debug_goal( | ||
151 | &self, | ||
152 | goal: &Goal<Interner>, | ||
153 | fmt: &mut fmt::Formatter<'_>, | ||
154 | ) -> Result<(), fmt::Error> { | ||
155 | let goal_data = goal.data(&Interner); | ||
156 | write!(fmt, "{:?}", goal_data) | ||
157 | } | ||
158 | |||
159 | pub fn debug_goals( | ||
160 | &self, | ||
161 | goals: &Goals<Interner>, | ||
162 | fmt: &mut fmt::Formatter<'_>, | ||
163 | ) -> Result<(), fmt::Error> { | ||
164 | write!(fmt, "{:?}", goals.debug(&Interner)) | ||
165 | } | ||
166 | |||
167 | pub fn debug_program_clause_implication( | ||
168 | &self, | ||
169 | pci: &ProgramClauseImplication<Interner>, | ||
170 | fmt: &mut fmt::Formatter<'_>, | ||
171 | ) -> Result<(), fmt::Error> { | ||
172 | write!(fmt, "{:?}", pci.debug(&Interner)) | ||
173 | } | ||
174 | |||
175 | pub fn debug_application_ty( | ||
176 | &self, | ||
177 | application_ty: &chalk_ir::ApplicationTy<Interner>, | ||
178 | fmt: &mut fmt::Formatter<'_>, | ||
179 | ) -> Result<(), fmt::Error> { | ||
180 | write!(fmt, "{:?}", application_ty.debug(&Interner)) | ||
181 | } | ||
182 | |||
183 | pub fn debug_substitution( | ||
184 | &self, | ||
185 | substitution: &chalk_ir::Substitution<Interner>, | ||
186 | fmt: &mut fmt::Formatter<'_>, | ||
187 | ) -> Result<(), fmt::Error> { | ||
188 | write!(fmt, "{:?}", substitution.debug(&Interner)) | ||
189 | } | ||
190 | |||
191 | pub fn debug_separator_trait_ref( | ||
192 | &self, | ||
193 | separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>, | ||
194 | fmt: &mut fmt::Formatter<'_>, | ||
195 | ) -> Result<(), fmt::Error> { | ||
196 | write!(fmt, "{:?}", separator_trait_ref.debug(&Interner)) | ||
197 | } | ||
198 | } | ||
199 | |||
200 | mod unsafe_tls { | ||
201 | use super::DebugContext; | ||
202 | use crate::db::HirDatabase; | ||
203 | use scoped_tls::scoped_thread_local; | ||
204 | |||
205 | scoped_thread_local!(static PROGRAM: DebugContext); | ||
206 | |||
207 | pub fn with_current_program<R>( | ||
208 | op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R, | ||
209 | ) -> R { | ||
210 | if PROGRAM.is_set() { | ||
211 | PROGRAM.with(|prog| op(Some(prog))) | ||
212 | } else { | ||
213 | op(None) | ||
214 | } | ||
215 | } | ||
216 | |||
217 | pub fn set_current_program<OP, R>(p: &dyn HirDatabase, op: OP) -> R | ||
218 | where | ||
219 | OP: FnOnce() -> R, | ||
220 | { | ||
221 | let ctx = DebugContext(p); | ||
222 | // we're transmuting the lifetime in the DebugContext to static. This is | ||
223 | // fine because we only keep the reference for the lifetime of this | ||
224 | // function, *and* the only way to access the context is through | ||
225 | // `with_current_program`, which hides the lifetime through the `for` | ||
226 | // type. | ||
227 | let static_p: &DebugContext<'static> = | ||
228 | unsafe { std::mem::transmute::<&DebugContext, &DebugContext<'static>>(&ctx) }; | ||
229 | PROGRAM.set(static_p, || op()) | ||
230 | } | ||
231 | } | ||
diff --git a/crates/ra_ide/src/completion/complete_fn_param.rs b/crates/ra_ide/src/completion/complete_fn_param.rs index 62ae5ccb4..f84b559fc 100644 --- a/crates/ra_ide/src/completion/complete_fn_param.rs +++ b/crates/ra_ide/src/completion/complete_fn_param.rs | |||
@@ -1,6 +1,9 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use ra_syntax::{ast, match_ast, AstNode}; | 3 | use ra_syntax::{ |
4 | ast::{self, ModuleItemOwner}, | ||
5 | match_ast, AstNode, | ||
6 | }; | ||
4 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
5 | 8 | ||
6 | use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions}; | 9 | use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions}; |
@@ -16,11 +19,19 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
16 | 19 | ||
17 | let mut params = FxHashMap::default(); | 20 | let mut params = FxHashMap::default(); |
18 | for node in ctx.token.parent().ancestors() { | 21 | for node in ctx.token.parent().ancestors() { |
19 | match_ast! { | 22 | let items = match_ast! { |
20 | match node { | 23 | match node { |
21 | ast::SourceFile(it) => process(it, &mut params), | 24 | ast::SourceFile(it) => it.items(), |
22 | ast::ItemList(it) => process(it, &mut params), | 25 | ast::ItemList(it) => it.items(), |
23 | _ => (), | 26 | _ => continue, |
27 | } | ||
28 | }; | ||
29 | for item in items { | ||
30 | if let ast::ModuleItem::FnDef(func) = item { | ||
31 | func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| { | ||
32 | let text = param.syntax().text().to_string(); | ||
33 | params.entry(text).or_insert((0, param)).0 += 1; | ||
34 | }) | ||
24 | } | 35 | } |
25 | } | 36 | } |
26 | } | 37 | } |
@@ -39,15 +50,6 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) | |||
39 | .lookup_by(lookup) | 50 | .lookup_by(lookup) |
40 | .add_to(acc) | 51 | .add_to(acc) |
41 | }); | 52 | }); |
42 | |||
43 | fn process<N: ast::FnDefOwner>(node: N, params: &mut FxHashMap<String, (u32, ast::Param)>) { | ||
44 | node.functions().filter_map(|it| it.param_list()).flat_map(|it| it.params()).for_each( | ||
45 | |param| { | ||
46 | let text = param.syntax().text().to_string(); | ||
47 | params.entry(text).or_insert((0, param)).0 += 1; | ||
48 | }, | ||
49 | ) | ||
50 | } | ||
51 | } | 53 | } |
52 | 54 | ||
53 | #[cfg(test)] | 55 | #[cfg(test)] |
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index ded1ff3bc..fab02945c 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -35,7 +35,7 @@ use hir::{self, Docs, HasSource}; | |||
35 | use ra_assists::utils::get_missing_impl_items; | 35 | use ra_assists::utils::get_missing_impl_items; |
36 | use ra_syntax::{ | 36 | use ra_syntax::{ |
37 | ast::{self, edit, ImplDef}, | 37 | ast::{self, edit, ImplDef}, |
38 | AstNode, SyntaxKind, SyntaxNode, TextRange, | 38 | AstNode, SyntaxKind, SyntaxNode, TextRange, T, |
39 | }; | 39 | }; |
40 | use ra_text_edit::TextEdit; | 40 | use ra_text_edit::TextEdit; |
41 | 41 | ||
@@ -204,7 +204,7 @@ fn make_const_compl_syntax(const_: &ast::ConstDef) -> String { | |||
204 | let end = const_ | 204 | let end = const_ |
205 | .syntax() | 205 | .syntax() |
206 | .children_with_tokens() | 206 | .children_with_tokens() |
207 | .find(|s| s.kind() == SyntaxKind::SEMI || s.kind() == SyntaxKind::EQ) | 207 | .find(|s| s.kind() == T![;] || s.kind() == T![=]) |
208 | .map_or(const_end, |f| f.text_range().start()); | 208 | .map_or(const_end, |f| f.text_range().start()); |
209 | 209 | ||
210 | let len = end - start; | 210 | let len = end - start; |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 0e34d85db..6637afaf7 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -191,8 +191,8 @@ impl<'a> CompletionContext<'a> { | |||
191 | if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { | 191 | if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { |
192 | self.is_pat_binding_or_const = true; | 192 | self.is_pat_binding_or_const = true; |
193 | if bind_pat.at_token().is_some() | 193 | if bind_pat.at_token().is_some() |
194 | || bind_pat.ref_kw_token().is_some() | 194 | || bind_pat.ref_token().is_some() |
195 | || bind_pat.mut_kw_token().is_some() | 195 | || bind_pat.mut_token().is_some() |
196 | { | 196 | { |
197 | self.is_pat_binding_or_const = false; | 197 | self.is_pat_binding_or_const = false; |
198 | } | 198 | } |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 4b133b19b..da9f55a69 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! This module defines multiple types of inlay hints and their visibility |
2 | 2 | ||
3 | use hir::{Adt, HirDisplay, Semantics, Type}; | 3 | use hir::{Adt, HirDisplay, Semantics, Type}; |
4 | use ra_ide_db::RootDatabase; | 4 | use ra_ide_db::RootDatabase; |
@@ -235,8 +235,7 @@ fn should_show_param_hint( | |||
235 | param_name: &str, | 235 | param_name: &str, |
236 | argument: &ast::Expr, | 236 | argument: &ast::Expr, |
237 | ) -> bool { | 237 | ) -> bool { |
238 | let argument_string = argument.syntax().to_string(); | 238 | if param_name.is_empty() || is_argument_similar_to_param(argument, param_name) { |
239 | if param_name.is_empty() || argument_string.ends_with(param_name) { | ||
240 | return false; | 239 | return false; |
241 | } | 240 | } |
242 | 241 | ||
@@ -245,14 +244,37 @@ fn should_show_param_hint( | |||
245 | } else { | 244 | } else { |
246 | fn_signature.parameters.len() | 245 | fn_signature.parameters.len() |
247 | }; | 246 | }; |
247 | |||
248 | // avoid displaying hints for common functions like map, filter, etc. | 248 | // avoid displaying hints for common functions like map, filter, etc. |
249 | if parameters_len == 1 && (param_name.len() == 1 || param_name == "predicate") { | 249 | // or other obvious words used in std |
250 | if parameters_len == 1 && is_obvious_param(param_name) { | ||
250 | return false; | 251 | return false; |
251 | } | 252 | } |
252 | |||
253 | true | 253 | true |
254 | } | 254 | } |
255 | 255 | ||
256 | fn is_argument_similar_to_param(argument: &ast::Expr, param_name: &str) -> bool { | ||
257 | let argument_string = remove_ref(argument.clone()).syntax().to_string(); | ||
258 | argument_string.starts_with(¶m_name) || argument_string.ends_with(¶m_name) | ||
259 | } | ||
260 | |||
261 | fn remove_ref(expr: ast::Expr) -> ast::Expr { | ||
262 | if let ast::Expr::RefExpr(ref_expr) = &expr { | ||
263 | if let Some(inner) = ref_expr.expr() { | ||
264 | return inner; | ||
265 | } | ||
266 | } | ||
267 | expr | ||
268 | } | ||
269 | |||
270 | fn is_obvious_param(param_name: &str) -> bool { | ||
271 | let is_obvious_param_name = match param_name { | ||
272 | "predicate" | "value" | "pat" | "rhs" | "other" => true, | ||
273 | _ => false, | ||
274 | }; | ||
275 | param_name.len() == 1 || is_obvious_param_name | ||
276 | } | ||
277 | |||
256 | fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<FunctionSignature> { | 278 | fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<FunctionSignature> { |
257 | match expr { | 279 | match expr { |
258 | ast::Expr::CallExpr(expr) => { | 280 | ast::Expr::CallExpr(expr) => { |
@@ -1059,9 +1081,18 @@ impl Test { | |||
1059 | self | 1081 | self |
1060 | } | 1082 | } |
1061 | 1083 | ||
1084 | fn field(self, value: i32) -> Self { | ||
1085 | self | ||
1086 | } | ||
1087 | |||
1062 | fn no_hints_expected(&self, _: i32, test_var: i32) {} | 1088 | fn no_hints_expected(&self, _: i32, test_var: i32) {} |
1063 | } | 1089 | } |
1064 | 1090 | ||
1091 | struct Param {} | ||
1092 | |||
1093 | fn different_order(param: &Param) {} | ||
1094 | fn different_order_mut(param: &mut Param) {} | ||
1095 | |||
1065 | fn main() { | 1096 | fn main() { |
1066 | let container: TestVarContainer = TestVarContainer { test_var: 42 }; | 1097 | let container: TestVarContainer = TestVarContainer { test_var: 42 }; |
1067 | let test: Test = Test {}; | 1098 | let test: Test = Test {}; |
@@ -1069,11 +1100,20 @@ fn main() { | |||
1069 | map(22); | 1100 | map(22); |
1070 | filter(33); | 1101 | filter(33); |
1071 | 1102 | ||
1072 | let test_processed: Test = test.map(1).filter(2); | 1103 | let test_processed: Test = test.map(1).filter(2).field(3); |
1073 | 1104 | ||
1074 | let test_var: i32 = 55; | 1105 | let test_var: i32 = 55; |
1075 | test_processed.no_hints_expected(22, test_var); | 1106 | test_processed.no_hints_expected(22, test_var); |
1076 | test_processed.no_hints_expected(33, container.test_var); | 1107 | test_processed.no_hints_expected(33, container.test_var); |
1108 | |||
1109 | let param_begin: Param = Param {}; | ||
1110 | different_order(¶m_begin); | ||
1111 | different_order(&mut param_begin); | ||
1112 | |||
1113 | let a: f64 = 7.0; | ||
1114 | let b: f64 = 4.0; | ||
1115 | let _: f64 = a.div_euclid(b); | ||
1116 | let _: f64 = a.abs_sub(b); | ||
1077 | }"#, | 1117 | }"#, |
1078 | ); | 1118 | ); |
1079 | 1119 | ||
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index ad6fd50aa..7d0544ff4 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -152,7 +152,7 @@ fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Optio | |||
152 | if stmt.initializer().is_some() { | 152 | if stmt.initializer().is_some() { |
153 | let pat = stmt.pat()?; | 153 | let pat = stmt.pat()?; |
154 | if let ast::Pat::BindPat(it) = pat { | 154 | if let ast::Pat::BindPat(it) = pat { |
155 | if it.mut_kw_token().is_some() { | 155 | if it.mut_token().is_some() { |
156 | return Some(ReferenceAccess::Write); | 156 | return Some(ReferenceAccess::Write); |
157 | } | 157 | } |
158 | } | 158 | } |
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs index f58e436d1..5842ae2e8 100644 --- a/crates/ra_ide/src/syntax_tree.rs +++ b/crates/ra_ide/src/syntax_tree.rs | |||
@@ -165,7 +165,7 @@ SOURCE_FILE@[0; 60) | |||
165 | PATH_SEGMENT@[16; 22) | 165 | PATH_SEGMENT@[16; 22) |
166 | NAME_REF@[16; 22) | 166 | NAME_REF@[16; 22) |
167 | IDENT@[16; 22) "assert" | 167 | IDENT@[16; 22) "assert" |
168 | EXCL@[22; 23) "!" | 168 | BANG@[22; 23) "!" |
169 | TOKEN_TREE@[23; 57) | 169 | TOKEN_TREE@[23; 57) |
170 | L_PAREN@[23; 24) "(" | 170 | L_PAREN@[23; 24) "(" |
171 | STRING@[24; 52) "\"\n fn foo() {\n ..." | 171 | STRING@[24; 52) "\"\n fn foo() {\n ..." |
@@ -173,7 +173,7 @@ SOURCE_FILE@[0; 60) | |||
173 | WHITESPACE@[53; 54) " " | 173 | WHITESPACE@[53; 54) " " |
174 | STRING@[54; 56) "\"\"" | 174 | STRING@[54; 56) "\"\"" |
175 | R_PAREN@[56; 57) ")" | 175 | R_PAREN@[56; 57) ")" |
176 | SEMI@[57; 58) ";" | 176 | SEMICOLON@[57; 58) ";" |
177 | WHITESPACE@[58; 59) "\n" | 177 | WHITESPACE@[58; 59) "\n" |
178 | R_CURLY@[59; 60) "}" | 178 | R_CURLY@[59; 60) "}" |
179 | "# | 179 | "# |
@@ -226,7 +226,7 @@ EXPR_STMT@[16; 58) | |||
226 | PATH_SEGMENT@[16; 22) | 226 | PATH_SEGMENT@[16; 22) |
227 | NAME_REF@[16; 22) | 227 | NAME_REF@[16; 22) |
228 | IDENT@[16; 22) "assert" | 228 | IDENT@[16; 22) "assert" |
229 | EXCL@[22; 23) "!" | 229 | BANG@[22; 23) "!" |
230 | TOKEN_TREE@[23; 57) | 230 | TOKEN_TREE@[23; 57) |
231 | L_PAREN@[23; 24) "(" | 231 | L_PAREN@[23; 24) "(" |
232 | STRING@[24; 52) "\"\n fn foo() {\n ..." | 232 | STRING@[24; 52) "\"\n fn foo() {\n ..." |
@@ -234,7 +234,7 @@ EXPR_STMT@[16; 58) | |||
234 | WHITESPACE@[53; 54) " " | 234 | WHITESPACE@[53; 54) " " |
235 | STRING@[54; 56) "\"\"" | 235 | STRING@[54; 56) "\"\"" |
236 | R_PAREN@[56; 57) ")" | 236 | R_PAREN@[56; 57) ")" |
237 | SEMI@[57; 58) ";" | 237 | SEMICOLON@[57; 58) ";" |
238 | "# | 238 | "# |
239 | .trim() | 239 | .trim() |
240 | ); | 240 | ); |
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs index 71d2bcb04..f55cd3bf5 100644 --- a/crates/ra_ide/src/typing.rs +++ b/crates/ra_ide/src/typing.rs | |||
@@ -63,7 +63,7 @@ fn on_char_typed_inner( | |||
63 | fn on_eq_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChange> { | 63 | fn on_eq_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChange> { |
64 | assert_eq!(file.syntax().text().char_at(offset), Some('=')); | 64 | assert_eq!(file.syntax().text().char_at(offset), Some('=')); |
65 | let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?; | 65 | let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?; |
66 | if let_stmt.semi_token().is_some() { | 66 | if let_stmt.semicolon_token().is_some() { |
67 | return None; | 67 | return None; |
68 | } | 68 | } |
69 | if let Some(expr) = let_stmt.initializer() { | 69 | if let Some(expr) = let_stmt.initializer() { |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 8e8ae2b29..9fb5cb058 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -137,21 +137,23 @@ impl TokenMap { | |||
137 | token_id: tt::TokenId, | 137 | token_id: tt::TokenId, |
138 | open_relative_range: TextRange, | 138 | open_relative_range: TextRange, |
139 | close_relative_range: TextRange, | 139 | close_relative_range: TextRange, |
140 | ) { | 140 | ) -> usize { |
141 | let res = self.entries.len(); | ||
141 | self.entries | 142 | self.entries |
142 | .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range))); | 143 | .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range))); |
144 | res | ||
143 | } | 145 | } |
144 | 146 | ||
145 | fn update_close_delim(&mut self, token_id: tt::TokenId, close_relative_range: TextRange) { | 147 | fn update_close_delim(&mut self, idx: usize, close_relative_range: TextRange) { |
146 | if let Some(entry) = self.entries.iter_mut().find(|(tid, _)| *tid == token_id) { | 148 | let (_, token_text_range) = &mut self.entries[idx]; |
147 | if let TokenTextRange::Delimiter(dim, _) = entry.1 { | 149 | if let TokenTextRange::Delimiter(dim, _) = token_text_range { |
148 | entry.1 = TokenTextRange::Delimiter(dim, close_relative_range); | 150 | *token_text_range = TokenTextRange::Delimiter(*dim, close_relative_range); |
149 | } | ||
150 | } | 151 | } |
151 | } | 152 | } |
152 | 153 | ||
153 | fn remove_delim(&mut self, token_id: tt::TokenId) { | 154 | fn remove_delim(&mut self, idx: usize) { |
154 | self.entries.retain(|(tid, _)| *tid != token_id); | 155 | // FIXME: This could be accidently quadratic |
156 | self.entries.remove(idx); | ||
155 | } | 157 | } |
156 | } | 158 | } |
157 | 159 | ||
@@ -238,24 +240,24 @@ impl TokenIdAlloc { | |||
238 | token_id | 240 | token_id |
239 | } | 241 | } |
240 | 242 | ||
241 | fn open_delim(&mut self, open_abs_range: TextRange) -> tt::TokenId { | 243 | fn open_delim(&mut self, open_abs_range: TextRange) -> (tt::TokenId, usize) { |
242 | let token_id = tt::TokenId(self.next_id); | 244 | let token_id = tt::TokenId(self.next_id); |
243 | self.next_id += 1; | 245 | self.next_id += 1; |
244 | self.map.insert_delim( | 246 | let idx = self.map.insert_delim( |
245 | token_id, | 247 | token_id, |
246 | open_abs_range - self.global_offset, | 248 | open_abs_range - self.global_offset, |
247 | open_abs_range - self.global_offset, | 249 | open_abs_range - self.global_offset, |
248 | ); | 250 | ); |
249 | token_id | 251 | (token_id, idx) |
250 | } | 252 | } |
251 | 253 | ||
252 | fn close_delim(&mut self, id: tt::TokenId, close_abs_range: Option<TextRange>) { | 254 | fn close_delim(&mut self, idx: usize, close_abs_range: Option<TextRange>) { |
253 | match close_abs_range { | 255 | match close_abs_range { |
254 | None => { | 256 | None => { |
255 | self.map.remove_delim(id); | 257 | self.map.remove_delim(idx); |
256 | } | 258 | } |
257 | Some(close) => { | 259 | Some(close) => { |
258 | self.map.update_close_delim(id, close - self.global_offset); | 260 | self.map.update_close_delim(idx, close - self.global_offset); |
259 | } | 261 | } |
260 | } | 262 | } |
261 | } | 263 | } |
@@ -322,7 +324,7 @@ trait TokenConvertor { | |||
322 | 324 | ||
323 | if let Some((kind, closed)) = delim { | 325 | if let Some((kind, closed)) = delim { |
324 | let mut subtree = tt::Subtree::default(); | 326 | let mut subtree = tt::Subtree::default(); |
325 | let id = self.id_alloc().open_delim(range); | 327 | let (id, idx) = self.id_alloc().open_delim(range); |
326 | subtree.delimiter = Some(tt::Delimiter { kind, id }); | 328 | subtree.delimiter = Some(tt::Delimiter { kind, id }); |
327 | 329 | ||
328 | while self.peek().map(|it| it.kind() != closed).unwrap_or(false) { | 330 | while self.peek().map(|it| it.kind() != closed).unwrap_or(false) { |
@@ -331,7 +333,7 @@ trait TokenConvertor { | |||
331 | let last_range = match self.bump() { | 333 | let last_range = match self.bump() { |
332 | None => { | 334 | None => { |
333 | // For error resilience, we insert an char punct for the opening delim here | 335 | // For error resilience, we insert an char punct for the opening delim here |
334 | self.id_alloc().close_delim(id, None); | 336 | self.id_alloc().close_delim(idx, None); |
335 | let leaf: tt::Leaf = tt::Punct { | 337 | let leaf: tt::Leaf = tt::Punct { |
336 | id: self.id_alloc().alloc(range), | 338 | id: self.id_alloc().alloc(range), |
337 | char: token.to_char().unwrap(), | 339 | char: token.to_char().unwrap(), |
@@ -344,7 +346,7 @@ trait TokenConvertor { | |||
344 | } | 346 | } |
345 | Some(it) => it.1, | 347 | Some(it) => it.1, |
346 | }; | 348 | }; |
347 | self.id_alloc().close_delim(id, Some(last_range)); | 349 | self.id_alloc().close_delim(idx, Some(last_range)); |
348 | subtree.into() | 350 | subtree.into() |
349 | } else { | 351 | } else { |
350 | let spacing = match self.peek() { | 352 | let spacing = match self.peek() { |
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 1ef6f6eed..5d1274d21 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs | |||
@@ -252,7 +252,7 @@ fn test_expr_order() { | |||
252 | STAR@[11; 12) "*" | 252 | STAR@[11; 12) "*" |
253 | LITERAL@[12; 13) | 253 | LITERAL@[12; 13) |
254 | INT_NUMBER@[12; 13) "2" | 254 | INT_NUMBER@[12; 13) "2" |
255 | SEMI@[13; 14) ";" | 255 | SEMICOLON@[13; 14) ";" |
256 | R_CURLY@[14; 15) "}""#, | 256 | R_CURLY@[14; 15) "}""#, |
257 | ); | 257 | ); |
258 | } | 258 | } |
@@ -605,7 +605,7 @@ fn test_tt_to_stmts() { | |||
605 | EQ@[4; 5) "=" | 605 | EQ@[4; 5) "=" |
606 | LITERAL@[5; 6) | 606 | LITERAL@[5; 6) |
607 | INT_NUMBER@[5; 6) "0" | 607 | INT_NUMBER@[5; 6) "0" |
608 | SEMI@[6; 7) ";" | 608 | SEMICOLON@[6; 7) ";" |
609 | EXPR_STMT@[7; 14) | 609 | EXPR_STMT@[7; 14) |
610 | BIN_EXPR@[7; 13) | 610 | BIN_EXPR@[7; 13) |
611 | PATH_EXPR@[7; 8) | 611 | PATH_EXPR@[7; 8) |
@@ -620,7 +620,7 @@ fn test_tt_to_stmts() { | |||
620 | PLUS@[11; 12) "+" | 620 | PLUS@[11; 12) "+" |
621 | LITERAL@[12; 13) | 621 | LITERAL@[12; 13) |
622 | INT_NUMBER@[12; 13) "1" | 622 | INT_NUMBER@[12; 13) "1" |
623 | SEMI@[13; 14) ";" | 623 | SEMICOLON@[13; 14) ";" |
624 | EXPR_STMT@[14; 15) | 624 | EXPR_STMT@[14; 15) |
625 | PATH_EXPR@[14; 15) | 625 | PATH_EXPR@[14; 15) |
626 | PATH@[14; 15) | 626 | PATH@[14; 15) |
@@ -953,7 +953,7 @@ fn test_tt_composite2() { | |||
953 | PATH_SEGMENT@[0; 3) | 953 | PATH_SEGMENT@[0; 3) |
954 | NAME_REF@[0; 3) | 954 | NAME_REF@[0; 3) |
955 | IDENT@[0; 3) "abs" | 955 | IDENT@[0; 3) "abs" |
956 | EXCL@[3; 4) "!" | 956 | BANG@[3; 4) "!" |
957 | TOKEN_TREE@[4; 10) | 957 | TOKEN_TREE@[4; 10) |
958 | L_PAREN@[4; 5) "(" | 958 | L_PAREN@[4; 5) "(" |
959 | EQ@[5; 6) "=" | 959 | EQ@[5; 6) "=" |
@@ -1073,14 +1073,14 @@ fn test_vec() { | |||
1073 | PATH_SEGMENT@[9; 12) | 1073 | PATH_SEGMENT@[9; 12) |
1074 | NAME_REF@[9; 12) | 1074 | NAME_REF@[9; 12) |
1075 | IDENT@[9; 12) "Vec" | 1075 | IDENT@[9; 12) "Vec" |
1076 | COLONCOLON@[12; 14) "::" | 1076 | COLON2@[12; 14) "::" |
1077 | PATH_SEGMENT@[14; 17) | 1077 | PATH_SEGMENT@[14; 17) |
1078 | NAME_REF@[14; 17) | 1078 | NAME_REF@[14; 17) |
1079 | IDENT@[14; 17) "new" | 1079 | IDENT@[14; 17) "new" |
1080 | ARG_LIST@[17; 19) | 1080 | ARG_LIST@[17; 19) |
1081 | L_PAREN@[17; 18) "(" | 1081 | L_PAREN@[17; 18) "(" |
1082 | R_PAREN@[18; 19) ")" | 1082 | R_PAREN@[18; 19) ")" |
1083 | SEMI@[19; 20) ";" | 1083 | SEMICOLON@[19; 20) ";" |
1084 | EXPR_STMT@[20; 33) | 1084 | EXPR_STMT@[20; 33) |
1085 | METHOD_CALL_EXPR@[20; 32) | 1085 | METHOD_CALL_EXPR@[20; 32) |
1086 | PATH_EXPR@[20; 21) | 1086 | PATH_EXPR@[20; 21) |
@@ -1096,7 +1096,7 @@ fn test_vec() { | |||
1096 | LITERAL@[27; 31) | 1096 | LITERAL@[27; 31) |
1097 | INT_NUMBER@[27; 31) "1u32" | 1097 | INT_NUMBER@[27; 31) "1u32" |
1098 | R_PAREN@[31; 32) ")" | 1098 | R_PAREN@[31; 32) ")" |
1099 | SEMI@[32; 33) ";" | 1099 | SEMICOLON@[32; 33) ";" |
1100 | EXPR_STMT@[33; 43) | 1100 | EXPR_STMT@[33; 43) |
1101 | METHOD_CALL_EXPR@[33; 42) | 1101 | METHOD_CALL_EXPR@[33; 42) |
1102 | PATH_EXPR@[33; 34) | 1102 | PATH_EXPR@[33; 34) |
@@ -1112,7 +1112,7 @@ fn test_vec() { | |||
1112 | LITERAL@[40; 41) | 1112 | LITERAL@[40; 41) |
1113 | INT_NUMBER@[40; 41) "2" | 1113 | INT_NUMBER@[40; 41) "2" |
1114 | R_PAREN@[41; 42) ")" | 1114 | R_PAREN@[41; 42) ")" |
1115 | SEMI@[42; 43) ";" | 1115 | SEMICOLON@[42; 43) ";" |
1116 | PATH_EXPR@[43; 44) | 1116 | PATH_EXPR@[43; 44) |
1117 | PATH@[43; 44) | 1117 | PATH@[43; 44) |
1118 | PATH_SEGMENT@[43; 44) | 1118 | PATH_SEGMENT@[43; 44) |
@@ -1760,7 +1760,7 @@ fn test_no_space_after_semi_colon() { | |||
1760 | MOD_KW@[21; 24) "mod" | 1760 | MOD_KW@[21; 24) "mod" |
1761 | NAME@[24; 25) | 1761 | NAME@[24; 25) |
1762 | IDENT@[24; 25) "m" | 1762 | IDENT@[24; 25) "m" |
1763 | SEMI@[25; 26) ";" | 1763 | SEMICOLON@[25; 26) ";" |
1764 | MODULE@[26; 52) | 1764 | MODULE@[26; 52) |
1765 | ATTR@[26; 47) | 1765 | ATTR@[26; 47) |
1766 | POUND@[26; 27) "#" | 1766 | POUND@[26; 27) "#" |
@@ -1779,7 +1779,7 @@ fn test_no_space_after_semi_colon() { | |||
1779 | MOD_KW@[47; 50) "mod" | 1779 | MOD_KW@[47; 50) "mod" |
1780 | NAME@[50; 51) | 1780 | NAME@[50; 51) |
1781 | IDENT@[50; 51) "f" | 1781 | IDENT@[50; 51) "f" |
1782 | SEMI@[51; 52) ";""###, | 1782 | SEMICOLON@[51; 52) ";""###, |
1783 | ); | 1783 | ); |
1784 | } | 1784 | } |
1785 | 1785 | ||
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index c486c0211..a1bd53063 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -339,7 +339,8 @@ fn expr_bp(p: &mut Parser, mut r: Restrictions, bp: u8) -> (Option<CompletedMark | |||
339 | (Some(lhs), BlockLike::NotBlock) | 339 | (Some(lhs), BlockLike::NotBlock) |
340 | } | 340 | } |
341 | 341 | ||
342 | const LHS_FIRST: TokenSet = atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOT, MINUS]); | 342 | const LHS_FIRST: TokenSet = |
343 | atom::ATOM_EXPR_FIRST.union(token_set![T![&], T![*], T![!], T![.], T![-]]); | ||
343 | 344 | ||
344 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { | 345 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { |
345 | let m; | 346 | let m; |
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs index 386969d2d..fe1a039cb 100644 --- a/crates/ra_parser/src/grammar/types.rs +++ b/crates/ra_parser/src/grammar/types.rs | |||
@@ -3,8 +3,19 @@ | |||
3 | use super::*; | 3 | use super::*; |
4 | 4 | ||
5 | pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![ | 5 | pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![ |
6 | L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, IMPL_KW, | 6 | T!['('], |
7 | DYN_KW, L_ANGLE, | 7 | T!['['], |
8 | T![<], | ||
9 | T![!], | ||
10 | T![*], | ||
11 | T![&], | ||
12 | T![_], | ||
13 | T![fn], | ||
14 | T![unsafe], | ||
15 | T![extern], | ||
16 | T![for], | ||
17 | T![impl], | ||
18 | T![dyn], | ||
8 | ]); | 19 | ]); |
9 | 20 | ||
10 | const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA, L_DOLLAR]; | 21 | const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA, L_DOLLAR]; |
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index 004f4e564..524e7d784 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs | |||
@@ -9,7 +9,7 @@ pub enum SyntaxKind { | |||
9 | TOMBSTONE, | 9 | TOMBSTONE, |
10 | #[doc(hidden)] | 10 | #[doc(hidden)] |
11 | EOF, | 11 | EOF, |
12 | SEMI, | 12 | SEMICOLON, |
13 | COMMA, | 13 | COMMA, |
14 | L_PAREN, | 14 | L_PAREN, |
15 | R_PAREN, | 15 | R_PAREN, |
@@ -33,15 +33,15 @@ pub enum SyntaxKind { | |||
33 | PERCENT, | 33 | PERCENT, |
34 | UNDERSCORE, | 34 | UNDERSCORE, |
35 | DOT, | 35 | DOT, |
36 | DOTDOT, | 36 | DOT2, |
37 | DOTDOTDOT, | 37 | DOT3, |
38 | DOTDOTEQ, | 38 | DOT2EQ, |
39 | COLON, | 39 | COLON, |
40 | COLONCOLON, | 40 | COLON2, |
41 | EQ, | 41 | EQ, |
42 | EQEQ, | 42 | EQ2, |
43 | FAT_ARROW, | 43 | FAT_ARROW, |
44 | EXCL, | 44 | BANG, |
45 | NEQ, | 45 | NEQ, |
46 | MINUS, | 46 | MINUS, |
47 | THIN_ARROW, | 47 | THIN_ARROW, |
@@ -55,8 +55,8 @@ pub enum SyntaxKind { | |||
55 | SLASHEQ, | 55 | SLASHEQ, |
56 | STAREQ, | 56 | STAREQ, |
57 | PERCENTEQ, | 57 | PERCENTEQ, |
58 | AMPAMP, | 58 | AMP2, |
59 | PIPEPIPE, | 59 | PIPE2, |
60 | SHL, | 60 | SHL, |
61 | SHR, | 61 | SHR, |
62 | SHLEQ, | 62 | SHLEQ, |
@@ -265,12 +265,12 @@ impl SyntaxKind { | |||
265 | } | 265 | } |
266 | pub fn is_punct(self) -> bool { | 266 | pub fn is_punct(self) -> bool { |
267 | match self { | 267 | match self { |
268 | SEMI | COMMA | L_PAREN | R_PAREN | L_CURLY | R_CURLY | L_BRACK | R_BRACK | L_ANGLE | 268 | SEMICOLON | COMMA | L_PAREN | R_PAREN | L_CURLY | R_CURLY | L_BRACK | R_BRACK |
269 | | R_ANGLE | AT | POUND | TILDE | QUESTION | DOLLAR | AMP | PIPE | PLUS | STAR | 269 | | L_ANGLE | R_ANGLE | AT | POUND | TILDE | QUESTION | DOLLAR | AMP | PIPE | PLUS |
270 | | SLASH | CARET | PERCENT | UNDERSCORE | DOT | DOTDOT | DOTDOTDOT | DOTDOTEQ | 270 | | STAR | SLASH | CARET | PERCENT | UNDERSCORE | DOT | DOT2 | DOT3 | DOT2EQ | COLON |
271 | | COLON | COLONCOLON | EQ | EQEQ | FAT_ARROW | EXCL | NEQ | MINUS | THIN_ARROW | 271 | | COLON2 | EQ | EQ2 | FAT_ARROW | BANG | NEQ | MINUS | THIN_ARROW | LTEQ | GTEQ |
272 | | LTEQ | GTEQ | PLUSEQ | MINUSEQ | PIPEEQ | AMPEQ | CARETEQ | SLASHEQ | STAREQ | 272 | | PLUSEQ | MINUSEQ | PIPEEQ | AMPEQ | CARETEQ | SLASHEQ | STAREQ | PERCENTEQ | AMP2 |
273 | | PERCENTEQ | AMPAMP | PIPEPIPE | SHL | SHR | SHLEQ | SHREQ => true, | 273 | | PIPE2 | SHL | SHR | SHLEQ | SHREQ => true, |
274 | _ => false, | 274 | _ => false, |
275 | } | 275 | } |
276 | } | 276 | } |
@@ -329,7 +329,7 @@ impl SyntaxKind { | |||
329 | } | 329 | } |
330 | pub fn from_char(c: char) -> Option<SyntaxKind> { | 330 | pub fn from_char(c: char) -> Option<SyntaxKind> { |
331 | let tok = match c { | 331 | let tok = match c { |
332 | ';' => SEMI, | 332 | ';' => SEMICOLON, |
333 | ',' => COMMA, | 333 | ',' => COMMA, |
334 | '(' => L_PAREN, | 334 | '(' => L_PAREN, |
335 | ')' => R_PAREN, | 335 | ')' => R_PAREN, |
@@ -355,7 +355,7 @@ impl SyntaxKind { | |||
355 | '.' => DOT, | 355 | '.' => DOT, |
356 | ':' => COLON, | 356 | ':' => COLON, |
357 | '=' => EQ, | 357 | '=' => EQ, |
358 | '!' => EXCL, | 358 | '!' => BANG, |
359 | '-' => MINUS, | 359 | '-' => MINUS, |
360 | _ => return None, | 360 | _ => return None, |
361 | }; | 361 | }; |
@@ -363,296 +363,4 @@ impl SyntaxKind { | |||
363 | } | 363 | } |
364 | } | 364 | } |
365 | #[macro_export] | 365 | #[macro_export] |
366 | macro_rules! T { | 366 | macro_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 } ; [ lifetime ] => { $ crate :: SyntaxKind :: LIFETIME } ; [ ident ] => { $ crate :: SyntaxKind :: IDENT } ; } |
367 | ( ; ) => { | ||
368 | $crate::SyntaxKind::SEMI | ||
369 | }; | ||
370 | ( , ) => { | ||
371 | $crate::SyntaxKind::COMMA | ||
372 | }; | ||
373 | ( '(' ) => { | ||
374 | $crate::SyntaxKind::L_PAREN | ||
375 | }; | ||
376 | ( ')' ) => { | ||
377 | $crate::SyntaxKind::R_PAREN | ||
378 | }; | ||
379 | ( '{' ) => { | ||
380 | $crate::SyntaxKind::L_CURLY | ||
381 | }; | ||
382 | ( '}' ) => { | ||
383 | $crate::SyntaxKind::R_CURLY | ||
384 | }; | ||
385 | ( '[' ) => { | ||
386 | $crate::SyntaxKind::L_BRACK | ||
387 | }; | ||
388 | ( ']' ) => { | ||
389 | $crate::SyntaxKind::R_BRACK | ||
390 | }; | ||
391 | ( < ) => { | ||
392 | $crate::SyntaxKind::L_ANGLE | ||
393 | }; | ||
394 | ( > ) => { | ||
395 | $crate::SyntaxKind::R_ANGLE | ||
396 | }; | ||
397 | ( @ ) => { | ||
398 | $crate::SyntaxKind::AT | ||
399 | }; | ||
400 | ( # ) => { | ||
401 | $crate::SyntaxKind::POUND | ||
402 | }; | ||
403 | ( ~ ) => { | ||
404 | $crate::SyntaxKind::TILDE | ||
405 | }; | ||
406 | ( ? ) => { | ||
407 | $crate::SyntaxKind::QUESTION | ||
408 | }; | ||
409 | ( $ ) => { | ||
410 | $crate::SyntaxKind::DOLLAR | ||
411 | }; | ||
412 | ( & ) => { | ||
413 | $crate::SyntaxKind::AMP | ||
414 | }; | ||
415 | ( | ) => { | ||
416 | $crate::SyntaxKind::PIPE | ||
417 | }; | ||
418 | ( + ) => { | ||
419 | $crate::SyntaxKind::PLUS | ||
420 | }; | ||
421 | ( * ) => { | ||
422 | $crate::SyntaxKind::STAR | ||
423 | }; | ||
424 | ( / ) => { | ||
425 | $crate::SyntaxKind::SLASH | ||
426 | }; | ||
427 | ( ^ ) => { | ||
428 | $crate::SyntaxKind::CARET | ||
429 | }; | ||
430 | ( % ) => { | ||
431 | $crate::SyntaxKind::PERCENT | ||
432 | }; | ||
433 | ( _ ) => { | ||
434 | $crate::SyntaxKind::UNDERSCORE | ||
435 | }; | ||
436 | ( . ) => { | ||
437 | $crate::SyntaxKind::DOT | ||
438 | }; | ||
439 | ( .. ) => { | ||
440 | $crate::SyntaxKind::DOTDOT | ||
441 | }; | ||
442 | ( ... ) => { | ||
443 | $crate::SyntaxKind::DOTDOTDOT | ||
444 | }; | ||
445 | ( ..= ) => { | ||
446 | $crate::SyntaxKind::DOTDOTEQ | ||
447 | }; | ||
448 | ( : ) => { | ||
449 | $crate::SyntaxKind::COLON | ||
450 | }; | ||
451 | ( :: ) => { | ||
452 | $crate::SyntaxKind::COLONCOLON | ||
453 | }; | ||
454 | ( = ) => { | ||
455 | $crate::SyntaxKind::EQ | ||
456 | }; | ||
457 | ( == ) => { | ||
458 | $crate::SyntaxKind::EQEQ | ||
459 | }; | ||
460 | ( => ) => { | ||
461 | $crate::SyntaxKind::FAT_ARROW | ||
462 | }; | ||
463 | ( ! ) => { | ||
464 | $crate::SyntaxKind::EXCL | ||
465 | }; | ||
466 | ( != ) => { | ||
467 | $crate::SyntaxKind::NEQ | ||
468 | }; | ||
469 | ( - ) => { | ||
470 | $crate::SyntaxKind::MINUS | ||
471 | }; | ||
472 | ( -> ) => { | ||
473 | $crate::SyntaxKind::THIN_ARROW | ||
474 | }; | ||
475 | ( <= ) => { | ||
476 | $crate::SyntaxKind::LTEQ | ||
477 | }; | ||
478 | ( >= ) => { | ||
479 | $crate::SyntaxKind::GTEQ | ||
480 | }; | ||
481 | ( += ) => { | ||
482 | $crate::SyntaxKind::PLUSEQ | ||
483 | }; | ||
484 | ( -= ) => { | ||
485 | $crate::SyntaxKind::MINUSEQ | ||
486 | }; | ||
487 | ( |= ) => { | ||
488 | $crate::SyntaxKind::PIPEEQ | ||
489 | }; | ||
490 | ( &= ) => { | ||
491 | $crate::SyntaxKind::AMPEQ | ||
492 | }; | ||
493 | ( ^= ) => { | ||
494 | $crate::SyntaxKind::CARETEQ | ||
495 | }; | ||
496 | ( /= ) => { | ||
497 | $crate::SyntaxKind::SLASHEQ | ||
498 | }; | ||
499 | ( *= ) => { | ||
500 | $crate::SyntaxKind::STAREQ | ||
501 | }; | ||
502 | ( %= ) => { | ||
503 | $crate::SyntaxKind::PERCENTEQ | ||
504 | }; | ||
505 | ( && ) => { | ||
506 | $crate::SyntaxKind::AMPAMP | ||
507 | }; | ||
508 | ( || ) => { | ||
509 | $crate::SyntaxKind::PIPEPIPE | ||
510 | }; | ||
511 | ( << ) => { | ||
512 | $crate::SyntaxKind::SHL | ||
513 | }; | ||
514 | ( >> ) => { | ||
515 | $crate::SyntaxKind::SHR | ||
516 | }; | ||
517 | ( <<= ) => { | ||
518 | $crate::SyntaxKind::SHLEQ | ||
519 | }; | ||
520 | ( >>= ) => { | ||
521 | $crate::SyntaxKind::SHREQ | ||
522 | }; | ||
523 | ( as ) => { | ||
524 | $crate::SyntaxKind::AS_KW | ||
525 | }; | ||
526 | ( async ) => { | ||
527 | $crate::SyntaxKind::ASYNC_KW | ||
528 | }; | ||
529 | ( await ) => { | ||
530 | $crate::SyntaxKind::AWAIT_KW | ||
531 | }; | ||
532 | ( box ) => { | ||
533 | $crate::SyntaxKind::BOX_KW | ||
534 | }; | ||
535 | ( break ) => { | ||
536 | $crate::SyntaxKind::BREAK_KW | ||
537 | }; | ||
538 | ( const ) => { | ||
539 | $crate::SyntaxKind::CONST_KW | ||
540 | }; | ||
541 | ( continue ) => { | ||
542 | $crate::SyntaxKind::CONTINUE_KW | ||
543 | }; | ||
544 | ( crate ) => { | ||
545 | $crate::SyntaxKind::CRATE_KW | ||
546 | }; | ||
547 | ( dyn ) => { | ||
548 | $crate::SyntaxKind::DYN_KW | ||
549 | }; | ||
550 | ( else ) => { | ||
551 | $crate::SyntaxKind::ELSE_KW | ||
552 | }; | ||
553 | ( enum ) => { | ||
554 | $crate::SyntaxKind::ENUM_KW | ||
555 | }; | ||
556 | ( extern ) => { | ||
557 | $crate::SyntaxKind::EXTERN_KW | ||
558 | }; | ||
559 | ( false ) => { | ||
560 | $crate::SyntaxKind::FALSE_KW | ||
561 | }; | ||
562 | ( fn ) => { | ||
563 | $crate::SyntaxKind::FN_KW | ||
564 | }; | ||
565 | ( for ) => { | ||
566 | $crate::SyntaxKind::FOR_KW | ||
567 | }; | ||
568 | ( if ) => { | ||
569 | $crate::SyntaxKind::IF_KW | ||
570 | }; | ||
571 | ( impl ) => { | ||
572 | $crate::SyntaxKind::IMPL_KW | ||
573 | }; | ||
574 | ( in ) => { | ||
575 | $crate::SyntaxKind::IN_KW | ||
576 | }; | ||
577 | ( let ) => { | ||
578 | $crate::SyntaxKind::LET_KW | ||
579 | }; | ||
580 | ( loop ) => { | ||
581 | $crate::SyntaxKind::LOOP_KW | ||
582 | }; | ||
583 | ( macro ) => { | ||
584 | $crate::SyntaxKind::MACRO_KW | ||
585 | }; | ||
586 | ( match ) => { | ||
587 | $crate::SyntaxKind::MATCH_KW | ||
588 | }; | ||
589 | ( mod ) => { | ||
590 | $crate::SyntaxKind::MOD_KW | ||
591 | }; | ||
592 | ( move ) => { | ||
593 | $crate::SyntaxKind::MOVE_KW | ||
594 | }; | ||
595 | ( mut ) => { | ||
596 | $crate::SyntaxKind::MUT_KW | ||
597 | }; | ||
598 | ( pub ) => { | ||
599 | $crate::SyntaxKind::PUB_KW | ||
600 | }; | ||
601 | ( ref ) => { | ||
602 | $crate::SyntaxKind::REF_KW | ||
603 | }; | ||
604 | ( return ) => { | ||
605 | $crate::SyntaxKind::RETURN_KW | ||
606 | }; | ||
607 | ( self ) => { | ||
608 | $crate::SyntaxKind::SELF_KW | ||
609 | }; | ||
610 | ( static ) => { | ||
611 | $crate::SyntaxKind::STATIC_KW | ||
612 | }; | ||
613 | ( struct ) => { | ||
614 | $crate::SyntaxKind::STRUCT_KW | ||
615 | }; | ||
616 | ( super ) => { | ||
617 | $crate::SyntaxKind::SUPER_KW | ||
618 | }; | ||
619 | ( trait ) => { | ||
620 | $crate::SyntaxKind::TRAIT_KW | ||
621 | }; | ||
622 | ( true ) => { | ||
623 | $crate::SyntaxKind::TRUE_KW | ||
624 | }; | ||
625 | ( try ) => { | ||
626 | $crate::SyntaxKind::TRY_KW | ||
627 | }; | ||
628 | ( type ) => { | ||
629 | $crate::SyntaxKind::TYPE_KW | ||
630 | }; | ||
631 | ( unsafe ) => { | ||
632 | $crate::SyntaxKind::UNSAFE_KW | ||
633 | }; | ||
634 | ( use ) => { | ||
635 | $crate::SyntaxKind::USE_KW | ||
636 | }; | ||
637 | ( where ) => { | ||
638 | $crate::SyntaxKind::WHERE_KW | ||
639 | }; | ||
640 | ( while ) => { | ||
641 | $crate::SyntaxKind::WHILE_KW | ||
642 | }; | ||
643 | ( auto ) => { | ||
644 | $crate::SyntaxKind::AUTO_KW | ||
645 | }; | ||
646 | ( default ) => { | ||
647 | $crate::SyntaxKind::DEFAULT_KW | ||
648 | }; | ||
649 | ( existential ) => { | ||
650 | $crate::SyntaxKind::EXISTENTIAL_KW | ||
651 | }; | ||
652 | ( union ) => { | ||
653 | $crate::SyntaxKind::UNION_KW | ||
654 | }; | ||
655 | ( raw ) => { | ||
656 | $crate::SyntaxKind::RAW_KW | ||
657 | }; | ||
658 | } | ||
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 00ea3a9b0..2d4f68f5e 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs | |||
@@ -113,21 +113,6 @@ pub fn profile(label: Label) -> Profiler { | |||
113 | }) | 113 | }) |
114 | } | 114 | } |
115 | 115 | ||
116 | pub fn print_time(label: Label) -> impl Drop { | ||
117 | struct Guard { | ||
118 | label: Label, | ||
119 | start: Instant, | ||
120 | } | ||
121 | |||
122 | impl Drop for Guard { | ||
123 | fn drop(&mut self) { | ||
124 | eprintln!("{}: {:?}", self.label, self.start.elapsed()) | ||
125 | } | ||
126 | } | ||
127 | |||
128 | Guard { label, start: Instant::now() } | ||
129 | } | ||
130 | |||
131 | pub struct Profiler { | 116 | pub struct Profiler { |
132 | label: Option<Label>, | 117 | label: Option<Label>, |
133 | detail: Option<String>, | 118 | detail: Option<String>, |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 15a8279f3..99c6b7219 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -42,11 +42,6 @@ pub trait AstNode { | |||
42 | fn syntax(&self) -> &SyntaxNode; | 42 | fn syntax(&self) -> &SyntaxNode; |
43 | } | 43 | } |
44 | 44 | ||
45 | #[test] | ||
46 | fn assert_ast_is_object_safe() { | ||
47 | fn _f(_: &dyn AstNode, _: &dyn NameOwner) {} | ||
48 | } | ||
49 | |||
50 | /// Like `AstNode`, but wraps tokens rather than interior nodes. | 45 | /// Like `AstNode`, but wraps tokens rather than interior nodes. |
51 | pub trait AstToken { | 46 | pub trait AstToken { |
52 | fn can_cast(token: SyntaxKind) -> bool | 47 | fn can_cast(token: SyntaxKind) -> bool |
@@ -64,22 +59,6 @@ pub trait AstToken { | |||
64 | } | 59 | } |
65 | } | 60 | } |
66 | 61 | ||
67 | mod support { | ||
68 | use super::{AstChildren, AstNode, AstToken, SyntaxNode}; | ||
69 | |||
70 | pub(super) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> { | ||
71 | parent.children().find_map(N::cast) | ||
72 | } | ||
73 | |||
74 | pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> { | ||
75 | AstChildren::new(parent) | ||
76 | } | ||
77 | |||
78 | pub(super) fn token<T: AstToken>(parent: &SyntaxNode) -> Option<T> { | ||
79 | parent.children_with_tokens().filter_map(|it| it.into_token()).find_map(T::cast) | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /// An iterator over `SyntaxNode` children of a particular AST type. | 62 | /// An iterator over `SyntaxNode` children of a particular AST type. |
84 | #[derive(Debug, Clone)] | 63 | #[derive(Debug, Clone)] |
85 | pub struct AstChildren<N> { | 64 | pub struct AstChildren<N> { |
@@ -100,12 +79,25 @@ impl<N: AstNode> Iterator for AstChildren<N> { | |||
100 | } | 79 | } |
101 | } | 80 | } |
102 | 81 | ||
103 | fn child_opt<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> Option<C> { | 82 | mod support { |
104 | children(parent).next() | 83 | use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken}; |
84 | |||
85 | pub(super) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> { | ||
86 | parent.children().find_map(N::cast) | ||
87 | } | ||
88 | |||
89 | pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> { | ||
90 | AstChildren::new(parent) | ||
91 | } | ||
92 | |||
93 | pub(super) fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> { | ||
94 | parent.children_with_tokens().filter_map(|it| it.into_token()).find(|it| it.kind() == kind) | ||
95 | } | ||
105 | } | 96 | } |
106 | 97 | ||
107 | fn children<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> AstChildren<C> { | 98 | #[test] |
108 | AstChildren::new(parent.syntax()) | 99 | fn assert_ast_is_object_safe() { |
100 | fn _f(_: &dyn AstNode, _: &dyn NameOwner) {} | ||
109 | } | 101 | } |
110 | 102 | ||
111 | #[test] | 103 | #[test] |
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 069c6ee82..9e5411ee5 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -6,7 +6,7 @@ use std::{iter, ops::RangeInclusive}; | |||
6 | use arrayvec::ArrayVec; | 6 | use arrayvec::ArrayVec; |
7 | 7 | ||
8 | use crate::{ | 8 | use crate::{ |
9 | algo, | 9 | algo::{self, neighbor, SyntaxRewriter}, |
10 | ast::{ | 10 | ast::{ |
11 | self, | 11 | self, |
12 | make::{self, tokens}, | 12 | make::{self, tokens}, |
@@ -16,7 +16,6 @@ use crate::{ | |||
16 | SyntaxKind::{ATTR, COMMENT, WHITESPACE}, | 16 | SyntaxKind::{ATTR, COMMENT, WHITESPACE}, |
17 | SyntaxNode, SyntaxToken, T, | 17 | SyntaxNode, SyntaxToken, T, |
18 | }; | 18 | }; |
19 | use algo::{neighbor, SyntaxRewriter}; | ||
20 | 19 | ||
21 | impl ast::BinExpr { | 20 | impl ast::BinExpr { |
22 | #[must_use] | 21 | #[must_use] |
@@ -33,9 +32,9 @@ impl ast::FnDef { | |||
33 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); | 32 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); |
34 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { | 33 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { |
35 | old_body.syntax().clone().into() | 34 | old_body.syntax().clone().into() |
36 | } else if let Some(semi) = self.semi_token() { | 35 | } else if let Some(semi) = self.semicolon_token() { |
37 | to_insert.push(make::tokens::single_space().into()); | 36 | to_insert.push(make::tokens::single_space().into()); |
38 | semi.syntax.clone().into() | 37 | semi.into() |
39 | } else { | 38 | } else { |
40 | to_insert.push(make::tokens::single_space().into()); | 39 | to_insert.push(make::tokens::single_space().into()); |
41 | to_insert.push(body.syntax().clone().into()); | 40 | to_insert.push(body.syntax().clone().into()); |
@@ -99,7 +98,7 @@ impl ast::ItemList { | |||
99 | None => match self.l_curly_token() { | 98 | None => match self.l_curly_token() { |
100 | Some(it) => ( | 99 | Some(it) => ( |
101 | " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(), | 100 | " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(), |
102 | InsertPosition::After(it.syntax().clone().into()), | 101 | InsertPosition::After(it.into()), |
103 | ), | 102 | ), |
104 | None => return self.clone(), | 103 | None => return self.clone(), |
105 | }, | 104 | }, |
@@ -143,7 +142,7 @@ impl ast::RecordFieldList { | |||
143 | macro_rules! after_l_curly { | 142 | macro_rules! after_l_curly { |
144 | () => {{ | 143 | () => {{ |
145 | let anchor = match self.l_curly_token() { | 144 | let anchor = match self.l_curly_token() { |
146 | Some(it) => it.syntax().clone().into(), | 145 | Some(it) => it.into(), |
147 | None => return self.clone(), | 146 | None => return self.clone(), |
148 | }; | 147 | }; |
149 | InsertPosition::After(anchor) | 148 | InsertPosition::After(anchor) |
@@ -190,15 +189,15 @@ impl ast::RecordFieldList { | |||
190 | impl ast::TypeParam { | 189 | impl ast::TypeParam { |
191 | #[must_use] | 190 | #[must_use] |
192 | pub fn remove_bounds(&self) -> ast::TypeParam { | 191 | pub fn remove_bounds(&self) -> ast::TypeParam { |
193 | let colon = match self.colon() { | 192 | let colon = match self.colon_token() { |
194 | Some(it) => it, | 193 | Some(it) => it, |
195 | None => return self.clone(), | 194 | None => return self.clone(), |
196 | }; | 195 | }; |
197 | let end = match self.type_bound_list() { | 196 | let end = match self.type_bound_list() { |
198 | Some(it) => it.syntax().clone().into(), | 197 | Some(it) => it.syntax().clone().into(), |
199 | None => colon.syntax().clone().into(), | 198 | None => colon.clone().into(), |
200 | }; | 199 | }; |
201 | self.replace_children(colon.syntax().clone().into()..=end, iter::empty()) | 200 | self.replace_children(colon.into()..=end, iter::empty()) |
202 | } | 201 | } |
203 | } | 202 | } |
204 | 203 | ||
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs index 40c8fca3b..93aa3d45f 100644 --- a/crates/ra_syntax/src/ast/expr_extensions.rs +++ b/crates/ra_syntax/src/ast/expr_extensions.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Various extension methods to ast Expr Nodes, which are hard to code-generate. | 1 | //! Various extension methods to ast Expr Nodes, which are hard to code-generate. |
2 | 2 | ||
3 | use crate::{ | 3 | use crate::{ |
4 | ast::{self, child_opt, children, AstChildren, AstNode}, | 4 | ast::{self, support, AstChildren, AstNode}, |
5 | SmolStr, | 5 | SmolStr, |
6 | SyntaxKind::*, | 6 | SyntaxKind::*, |
7 | SyntaxToken, T, | 7 | SyntaxToken, T, |
@@ -36,7 +36,7 @@ impl ast::IfExpr { | |||
36 | let res = match self.blocks().nth(1) { | 36 | let res = match self.blocks().nth(1) { |
37 | Some(block) => ElseBranch::Block(block), | 37 | Some(block) => ElseBranch::Block(block), |
38 | None => { | 38 | None => { |
39 | let elif: ast::IfExpr = child_opt(self)?; | 39 | let elif: ast::IfExpr = support::child(self.syntax())?; |
40 | ElseBranch::IfExpr(elif) | 40 | ElseBranch::IfExpr(elif) |
41 | } | 41 | } |
42 | }; | 42 | }; |
@@ -44,17 +44,7 @@ impl ast::IfExpr { | |||
44 | } | 44 | } |
45 | 45 | ||
46 | fn blocks(&self) -> AstChildren<ast::BlockExpr> { | 46 | fn blocks(&self) -> AstChildren<ast::BlockExpr> { |
47 | children(self) | 47 | support::children(self.syntax()) |
48 | } | ||
49 | } | ||
50 | |||
51 | impl ast::RefExpr { | ||
52 | pub fn is_mut(&self) -> bool { | ||
53 | self.syntax().children_with_tokens().any(|n| n.kind() == T![mut]) | ||
54 | } | ||
55 | |||
56 | pub fn raw_token(&self) -> Option<SyntaxToken> { | ||
57 | None // FIXME: implement &raw | ||
58 | } | 48 | } |
59 | } | 49 | } |
60 | 50 | ||
@@ -212,15 +202,15 @@ impl ast::BinExpr { | |||
212 | } | 202 | } |
213 | 203 | ||
214 | pub fn lhs(&self) -> Option<ast::Expr> { | 204 | pub fn lhs(&self) -> Option<ast::Expr> { |
215 | children(self).next() | 205 | support::children(self.syntax()).next() |
216 | } | 206 | } |
217 | 207 | ||
218 | pub fn rhs(&self) -> Option<ast::Expr> { | 208 | pub fn rhs(&self) -> Option<ast::Expr> { |
219 | children(self).nth(1) | 209 | support::children(self.syntax()).nth(1) |
220 | } | 210 | } |
221 | 211 | ||
222 | pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) { | 212 | pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) { |
223 | let mut children = children(self); | 213 | let mut children = support::children(self.syntax()); |
224 | let first = children.next(); | 214 | let first = children.next(); |
225 | let second = children.next(); | 215 | let second = children.next(); |
226 | (first, second) | 216 | (first, second) |
@@ -275,10 +265,10 @@ impl ast::RangeExpr { | |||
275 | 265 | ||
276 | impl ast::IndexExpr { | 266 | impl ast::IndexExpr { |
277 | pub fn base(&self) -> Option<ast::Expr> { | 267 | pub fn base(&self) -> Option<ast::Expr> { |
278 | children(self).next() | 268 | support::children(self.syntax()).next() |
279 | } | 269 | } |
280 | pub fn index(&self) -> Option<ast::Expr> { | 270 | pub fn index(&self) -> Option<ast::Expr> { |
281 | children(self).nth(1) | 271 | support::children(self.syntax()).nth(1) |
282 | } | 272 | } |
283 | } | 273 | } |
284 | 274 | ||
@@ -291,11 +281,11 @@ impl ast::ArrayExpr { | |||
291 | pub fn kind(&self) -> ArrayExprKind { | 281 | pub fn kind(&self) -> ArrayExprKind { |
292 | if self.is_repeat() { | 282 | if self.is_repeat() { |
293 | ArrayExprKind::Repeat { | 283 | ArrayExprKind::Repeat { |
294 | initializer: children(self).next(), | 284 | initializer: support::children(self.syntax()).next(), |
295 | repeat: children(self).nth(1), | 285 | repeat: support::children(self.syntax()).nth(1), |
296 | } | 286 | } |
297 | } else { | 287 | } else { |
298 | ArrayExprKind::ElementList(children(self)) | 288 | ArrayExprKind::ElementList(support::children(self.syntax())) |
299 | } | 289 | } |
300 | } | 290 | } |
301 | 291 | ||
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index b50a89864..76b7655e6 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -5,9 +5,7 @@ use itertools::Itertools; | |||
5 | use ra_parser::SyntaxKind; | 5 | use ra_parser::SyntaxKind; |
6 | 6 | ||
7 | use crate::{ |