Skip to content

Commit c1317d6

Browse files
committed
feat: add support for feature attributes in struct literal
Signed-off-by: Benjamin Coenen <[email protected]>
2 parents fc70cf9 + 30f0ad1 commit c1317d6

File tree

28 files changed

+7651
-8158
lines changed

28 files changed

+7651
-8158
lines changed

crates/ra_assists/src/handlers/add_impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use ra_syntax::{
2-
ast::{self, AstNode, NameOwner, TypeParamsOwner},
2+
ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner},
33
TextUnit,
44
};
55
use stdx::{format_to, SepBy};
@@ -42,7 +42,7 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> {
4242
if let Some(type_params) = type_params {
4343
let lifetime_params = type_params
4444
.lifetime_params()
45-
.filter_map(|it| it.lifetime_token())
45+
.filter_map(|it| it.lifetime())
4646
.map(|it| it.text().clone());
4747
let type_params =
4848
type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());

crates/ra_assists/src/handlers/add_new.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use hir::Adt;
22
use ra_syntax::{
33
ast::{
4-
self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner,
4+
self, AstNode, AstToken, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner,
5+
VisibilityOwner,
56
},
67
TextUnit, T,
78
};
@@ -105,7 +106,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
105106
if let Some(type_params) = type_params {
106107
let lifetime_params = type_params
107108
.lifetime_params()
108-
.filter_map(|it| it.lifetime_token())
109+
.filter_map(|it| it.lifetime())
109110
.map(|it| it.text().clone());
110111
let type_params =
111112
type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());

crates/ra_assists/src/handlers/introduce_variable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
124124
}
125125
}
126126

127-
if ast::Stmt::cast(node.clone()).is_some() {
127+
if ast::Stmt::cast(node.clone().into()).is_some() {
128128
return Some((node, false));
129129
}
130130

crates/ra_assists/src/handlers/merge_imports.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::iter::successors;
33
use ra_syntax::{
44
algo::{neighbor, SyntaxRewriter},
55
ast::{self, edit::AstNodeEdit, make},
6-
AstNode, Direction, InsertPosition, SyntaxElement, T,
6+
AstNode, AstToken, Direction, InsertPosition, SyntaxElement, T,
77
};
88

99
use crate::{Assist, AssistCtx, AssistId};
@@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTre
8282
.filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']),
8383
);
8484
let use_tree_list = lhs.use_tree_list()?;
85-
let pos = InsertPosition::Before(use_tree_list.r_curly()?.into());
85+
let pos = InsertPosition::Before(use_tree_list.r_curly()?.syntax().clone().into());
8686
let use_tree_list = use_tree_list.insert_children(pos, to_insert);
8787
Some(lhs.with_use_tree_list(use_tree_list))
8888
}

crates/ra_fmt/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
6060
} else {
6161
// Unwrap `{ continue; }`
6262
let (stmt,) = block.statements().next_tuple()?;
63-
if has_anything_else(stmt.syntax()) {
64-
return None;
65-
}
6663
if let ast::Stmt::ExprStmt(expr_stmt) = stmt {
64+
if has_anything_else(expr_stmt.syntax()) {
65+
return None;
66+
}
6767
let expr = expr_stmt.expr()?;
6868
match expr.syntax().kind() {
6969
CONTINUE_EXPR | BREAK_EXPR | RETURN_EXPR => return Some(expr),

crates/ra_hir_def/src/body/lower.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -497,14 +497,16 @@ impl ExprCollector<'_> {
497497
self.collect_block_items(&block);
498498
let statements = block
499499
.statements()
500-
.map(|s| match s {
500+
.filter_map(|s| match s {
501501
ast::Stmt::LetStmt(stmt) => {
502502
let pat = self.collect_pat_opt(stmt.pat());
503503
let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
504504
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
505-
Statement::Let { pat, type_ref, initializer }
505+
Some(Statement::Let { pat, type_ref, initializer })
506+
}
507+
ast::Stmt::ExprStmt(stmt) => {
508+
Some(Statement::Expr(self.collect_expr_opt(stmt.expr())))
506509
}
507-
ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
508510
})
509511
.collect();
510512
let tail = block.expr().map(|e| self.collect_expr(e));
@@ -556,6 +558,7 @@ impl ExprCollector<'_> {
556558
let ast_id = self.expander.ast_id(&def);
557559
(TraitLoc { container, ast_id }.intern(self.db).into(), def.name())
558560
}
561+
ast::ModuleItem::ExternBlock(_) => continue, // FIXME: collect from extern blocks
559562
ast::ModuleItem::ImplDef(_)
560563
| ast::ModuleItem::UseItem(_)
561564
| ast::ModuleItem::ExternCrateItem(_)

crates/ra_hir_def/src/nameres/raw.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ impl RawItemsCollector {
266266
self.add_macro(current_module, it);
267267
return;
268268
}
269+
ast::ModuleItem::ExternBlock(_) => {
270+
// FIXME: add extern block
271+
return;
272+
}
269273
};
270274
if let Some(name) = name {
271275
let name = name.as_name();

crates/ra_hir_def/src/path/lower.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
2828
loop {
2929
let segment = path.segment()?;
3030

31-
if segment.has_colon_colon() {
31+
if segment.coloncolon().is_some() {
3232
kind = PathKind::Abs;
3333
}
3434

crates/ra_hir_def/src/path/lower/lower_use.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub(crate) fn lower_use_tree(
3434
let alias = tree.alias().map(|a| {
3535
a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
3636
});
37-
let is_glob = tree.has_star();
37+
let is_glob = tree.star().is_some();
3838
if let Some(ast_path) = tree.path() {
3939
// Handle self in a path.
4040
// E.g. `use something::{self, <...>}`

crates/ra_hir_def/src/visibility.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ impl RawVisibility {
8484
let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
8585
RawVisibility::Module(path)
8686
}
87+
ast::VisibilityKind::PubSelf => {
88+
let path = ModPath { kind: PathKind::Plain, segments: Vec::new() };
89+
RawVisibility::Module(path)
90+
}
8791
ast::VisibilityKind::Pub => RawVisibility::Public,
8892
}
8993
}

crates/ra_hir_ty/src/tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use insta::assert_snapshot;
2323
use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
2424
use ra_syntax::{
2525
algo,
26-
ast::{self, AstNode},
26+
ast::{self, AstNode, AstToken},
2727
};
2828
use stdx::format_to;
2929

@@ -101,7 +101,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
101101
let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db));
102102

103103
let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
104-
(self_param.self_kw_token().text_range(), "self".to_string())
104+
(self_param.self_kw().unwrap().syntax().text_range(), "self".to_string())
105105
} else {
106106
(src_ptr.value.range(), node.text().to_string().replace("\n", " "))
107107
};
@@ -367,7 +367,7 @@ fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() {
367367
fn new(foo: u32) -> Self {
368368
Self { foo }
369369
}
370-
#[cfg(not(feature = "foo"))]
370+
#[cfg(not(feature = "foo"))]
371371
fn new(bar: u32) -> Self {
372372
Self { bar }
373373
}

crates/ra_parser/src/grammar.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ fn opt_fn_ret_type(p: &mut Parser) -> bool {
245245
if p.at(T![->]) {
246246
let m = p.start();
247247
p.bump(T![->]);
248-
types::type_(p);
248+
types::type_no_bounds(p);
249249
m.complete(p, RET_TYPE);
250250
true
251251
} else {

crates/ra_parser/src/syntax_kind/generated.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ pub enum SyntaxKind {
105105
DEFAULT_KW,
106106
EXISTENTIAL_KW,
107107
UNION_KW,
108+
RAW_KW,
108109
INT_NUMBER,
109110
FLOAT_NUMBER,
110111
CHAR,
@@ -258,7 +259,7 @@ impl SyntaxKind {
258259
| IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
259260
| MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW
260261
| TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW
261-
| AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW => true,
262+
| AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW => true,
262263
_ => false,
263264
}
264265
}
@@ -651,4 +652,7 @@ macro_rules! T {
651652
( union ) => {
652653
$crate::SyntaxKind::UNION_KW
653654
};
655+
( raw ) => {
656+
$crate::SyntaxKind::RAW_KW
657+
};
654658
}

crates/ra_syntax/src/algo.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77

88
use itertools::Itertools;
99
use ra_text_edit::TextEditBuilder;
10-
use rustc_hash::{FxHashMap, FxHashSet};
10+
use rustc_hash::FxHashMap;
1111

1212
use crate::{
1313
AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken,
@@ -72,8 +72,18 @@ pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxEleme
7272
}
7373

7474
pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> {
75-
let u_ancestors = u.ancestors().collect::<FxHashSet<SyntaxNode>>();
76-
v.ancestors().find(|it| u_ancestors.contains(it))
75+
if u == v {
76+
return Some(u.clone());
77+
}
78+
79+
let u_depth = u.ancestors().count();
80+
let v_depth = v.ancestors().count();
81+
let keep = u_depth.min(v_depth);
82+
83+
let u_candidates = u.ancestors().skip(u_depth - keep);
84+
let v_canidates = v.ancestors().skip(v_depth - keep);
85+
let (res, _) = u_candidates.zip(v_canidates).find(|(x, y)| x == y)?;
86+
Some(res)
7787
}
7888

7989
pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> {

crates/ra_syntax/src/ast.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub use self::{
2121
AttrKind, FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind,
2222
TypeBoundKind, VisibilityKind,
2323
},
24-
generated::*,
24+
generated::{nodes::*, tokens::*},
2525
tokens::*,
2626
traits::*,
2727
};
@@ -64,6 +64,22 @@ pub trait AstToken {
6464
}
6565
}
6666

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+
6783
/// An iterator over `SyntaxNode` children of a particular AST type.
6884
#[derive(Debug, Clone)]
6985
pub struct AstChildren<N> {
@@ -271,7 +287,7 @@ where
271287
let pred = predicates.next().unwrap();
272288
let mut bounds = pred.type_bound_list().unwrap().bounds();
273289

274-
assert_eq!("'a", pred.lifetime_token().unwrap().text());
290+
assert_eq!("'a", pred.lifetime().unwrap().text());
275291

276292
assert_bound("'b", bounds.next());
277293
assert_bound("'c", bounds.next());

crates/ra_syntax/src/ast/edit.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl ast::ItemList {
9999
None => match self.l_curly() {
100100
Some(it) => (
101101
" ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
102-
InsertPosition::After(it),
102+
InsertPosition::After(it.syntax().clone().into()),
103103
),
104104
None => return self.clone(),
105105
},
@@ -109,10 +109,6 @@ impl ast::ItemList {
109109
[ws.ws().into(), item.syntax().clone().into()].into();
110110
self.insert_children(position, to_insert)
111111
}
112-
113-
fn l_curly(&self) -> Option<SyntaxElement> {
114-
self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
115-
}
116112
}
117113

118114
impl ast::RecordFieldList {
@@ -147,7 +143,7 @@ impl ast::RecordFieldList {
147143
macro_rules! after_l_curly {
148144
() => {{
149145
let anchor = match self.l_curly() {
150-
Some(it) => it,
146+
Some(it) => it.syntax().clone().into(),
151147
None => return self.clone(),
152148
};
153149
InsertPosition::After(anchor)
@@ -189,24 +185,20 @@ impl ast::RecordFieldList {
189185

190186
self.insert_children(position, to_insert)
191187
}
192-
193-
fn l_curly(&self) -> Option<SyntaxElement> {
194-
self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
195-
}
196188
}
197189

198190
impl ast::TypeParam {
199191
#[must_use]
200192
pub fn remove_bounds(&self) -> ast::TypeParam {
201-
let colon = match self.colon_token() {
193+
let colon = match self.colon() {
202194
Some(it) => it,
203195
None => return self.clone(),
204196
};
205197
let end = match self.type_bound_list() {
206198
Some(it) => it.syntax().clone().into(),
207-
None => colon.clone().into(),
199+
None => colon.syntax().clone().into(),
208200
};
209-
self.replace_children(colon.into()..=end, iter::empty())
201+
self.replace_children(colon.syntax().clone().into()..=end, iter::empty())
210202
}
211203
}
212204

@@ -305,8 +297,12 @@ impl ast::UseTree {
305297
Some(it) => it,
306298
None => return self.clone(),
307299
};
308-
let use_tree =
309-
make::use_tree(suffix.clone(), self.use_tree_list(), self.alias(), self.has_star());
300+
let use_tree = make::use_tree(
301+
suffix.clone(),
302+
self.use_tree_list(),
303+
self.alias(),
304+
self.star().is_some(),
305+
);
310306
let nested = make::use_tree_list(iter::once(use_tree));
311307
return make::use_tree(prefix.clone(), Some(nested), None, false);
312308

crates/ra_syntax/src/ast/expr_extensions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ impl ast::RefExpr {
5252
pub fn is_mut(&self) -> bool {
5353
self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
5454
}
55+
56+
pub fn raw_token(&self) -> Option<SyntaxToken> {
57+
None // FIXME: implement &raw
58+
}
5559
}
5660

5761
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]

0 commit comments

Comments
 (0)