feat: add support for feature attributes in struct literal
Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
This commit is contained in:
commit
c1317d6923
28 changed files with 7648 additions and 8155 deletions
|
@ -1,5 +1,5 @@
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode, NameOwner, TypeParamsOwner},
|
ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner},
|
||||||
TextUnit,
|
TextUnit,
|
||||||
};
|
};
|
||||||
use stdx::{format_to, SepBy};
|
use stdx::{format_to, SepBy};
|
||||||
|
@ -42,7 +42,7 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> {
|
||||||
if let Some(type_params) = type_params {
|
if let Some(type_params) = type_params {
|
||||||
let lifetime_params = type_params
|
let lifetime_params = type_params
|
||||||
.lifetime_params()
|
.lifetime_params()
|
||||||
.filter_map(|it| it.lifetime_token())
|
.filter_map(|it| it.lifetime())
|
||||||
.map(|it| it.text().clone());
|
.map(|it| it.text().clone());
|
||||||
let type_params =
|
let type_params =
|
||||||
type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
|
type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use hir::Adt;
|
use hir::Adt;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{
|
ast::{
|
||||||
self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner,
|
self, AstNode, AstToken, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner,
|
||||||
|
VisibilityOwner,
|
||||||
},
|
},
|
||||||
TextUnit, T,
|
TextUnit, T,
|
||||||
};
|
};
|
||||||
|
@ -105,7 +106,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
|
||||||
if let Some(type_params) = type_params {
|
if let Some(type_params) = type_params {
|
||||||
let lifetime_params = type_params
|
let lifetime_params = type_params
|
||||||
.lifetime_params()
|
.lifetime_params()
|
||||||
.filter_map(|it| it.lifetime_token())
|
.filter_map(|it| it.lifetime())
|
||||||
.map(|it| it.text().clone());
|
.map(|it| it.text().clone());
|
||||||
let type_params =
|
let type_params =
|
||||||
type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
|
type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
|
||||||
|
|
|
@ -124,7 +124,7 @@ fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ast::Stmt::cast(node.clone()).is_some() {
|
if ast::Stmt::cast(node.clone().into()).is_some() {
|
||||||
return Some((node, false));
|
return Some((node, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::iter::successors;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::{neighbor, SyntaxRewriter},
|
algo::{neighbor, SyntaxRewriter},
|
||||||
ast::{self, edit::AstNodeEdit, make},
|
ast::{self, edit::AstNodeEdit, make},
|
||||||
AstNode, Direction, InsertPosition, SyntaxElement, T,
|
AstNode, AstToken, Direction, InsertPosition, SyntaxElement, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Assist, AssistCtx, AssistId};
|
use crate::{Assist, AssistCtx, AssistId};
|
||||||
|
@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTre
|
||||||
.filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']),
|
.filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']),
|
||||||
);
|
);
|
||||||
let use_tree_list = lhs.use_tree_list()?;
|
let use_tree_list = lhs.use_tree_list()?;
|
||||||
let pos = InsertPosition::Before(use_tree_list.r_curly()?.into());
|
let pos = InsertPosition::Before(use_tree_list.r_curly()?.syntax().clone().into());
|
||||||
let use_tree_list = use_tree_list.insert_children(pos, to_insert);
|
let use_tree_list = use_tree_list.insert_children(pos, to_insert);
|
||||||
Some(lhs.with_use_tree_list(use_tree_list))
|
Some(lhs.with_use_tree_list(use_tree_list))
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,10 +60,10 @@ pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
|
||||||
} else {
|
} else {
|
||||||
// Unwrap `{ continue; }`
|
// Unwrap `{ continue; }`
|
||||||
let (stmt,) = block.statements().next_tuple()?;
|
let (stmt,) = block.statements().next_tuple()?;
|
||||||
if has_anything_else(stmt.syntax()) {
|
if let ast::Stmt::ExprStmt(expr_stmt) = stmt {
|
||||||
|
if has_anything_else(expr_stmt.syntax()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
if let ast::Stmt::ExprStmt(expr_stmt) = stmt {
|
|
||||||
let expr = expr_stmt.expr()?;
|
let expr = expr_stmt.expr()?;
|
||||||
match expr.syntax().kind() {
|
match expr.syntax().kind() {
|
||||||
CONTINUE_EXPR | BREAK_EXPR | RETURN_EXPR => return Some(expr),
|
CONTINUE_EXPR | BREAK_EXPR | RETURN_EXPR => return Some(expr),
|
||||||
|
|
|
@ -497,14 +497,16 @@ impl ExprCollector<'_> {
|
||||||
self.collect_block_items(&block);
|
self.collect_block_items(&block);
|
||||||
let statements = block
|
let statements = block
|
||||||
.statements()
|
.statements()
|
||||||
.map(|s| match s {
|
.filter_map(|s| match s {
|
||||||
ast::Stmt::LetStmt(stmt) => {
|
ast::Stmt::LetStmt(stmt) => {
|
||||||
let pat = self.collect_pat_opt(stmt.pat());
|
let pat = self.collect_pat_opt(stmt.pat());
|
||||||
let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
|
let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
|
||||||
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
|
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
|
||||||
Statement::Let { pat, type_ref, initializer }
|
Some(Statement::Let { pat, type_ref, initializer })
|
||||||
|
}
|
||||||
|
ast::Stmt::ExprStmt(stmt) => {
|
||||||
|
Some(Statement::Expr(self.collect_expr_opt(stmt.expr())))
|
||||||
}
|
}
|
||||||
ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let tail = block.expr().map(|e| self.collect_expr(e));
|
let tail = block.expr().map(|e| self.collect_expr(e));
|
||||||
|
@ -556,6 +558,7 @@ impl ExprCollector<'_> {
|
||||||
let ast_id = self.expander.ast_id(&def);
|
let ast_id = self.expander.ast_id(&def);
|
||||||
(TraitLoc { container, ast_id }.intern(self.db).into(), def.name())
|
(TraitLoc { container, ast_id }.intern(self.db).into(), def.name())
|
||||||
}
|
}
|
||||||
|
ast::ModuleItem::ExternBlock(_) => continue, // FIXME: collect from extern blocks
|
||||||
ast::ModuleItem::ImplDef(_)
|
ast::ModuleItem::ImplDef(_)
|
||||||
| ast::ModuleItem::UseItem(_)
|
| ast::ModuleItem::UseItem(_)
|
||||||
| ast::ModuleItem::ExternCrateItem(_)
|
| ast::ModuleItem::ExternCrateItem(_)
|
||||||
|
|
|
@ -266,6 +266,10 @@ impl RawItemsCollector {
|
||||||
self.add_macro(current_module, it);
|
self.add_macro(current_module, it);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ast::ModuleItem::ExternBlock(_) => {
|
||||||
|
// FIXME: add extern block
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
let name = name.as_name();
|
let name = name.as_name();
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
|
||||||
loop {
|
loop {
|
||||||
let segment = path.segment()?;
|
let segment = path.segment()?;
|
||||||
|
|
||||||
if segment.has_colon_colon() {
|
if segment.coloncolon().is_some() {
|
||||||
kind = PathKind::Abs;
|
kind = PathKind::Abs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub(crate) fn lower_use_tree(
|
||||||
let alias = tree.alias().map(|a| {
|
let alias = tree.alias().map(|a| {
|
||||||
a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
|
a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
|
||||||
});
|
});
|
||||||
let is_glob = tree.has_star();
|
let is_glob = tree.star().is_some();
|
||||||
if let Some(ast_path) = tree.path() {
|
if let Some(ast_path) = tree.path() {
|
||||||
// Handle self in a path.
|
// Handle self in a path.
|
||||||
// E.g. `use something::{self, <...>}`
|
// E.g. `use something::{self, <...>}`
|
||||||
|
|
|
@ -84,6 +84,10 @@ impl RawVisibility {
|
||||||
let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
|
let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
|
||||||
RawVisibility::Module(path)
|
RawVisibility::Module(path)
|
||||||
}
|
}
|
||||||
|
ast::VisibilityKind::PubSelf => {
|
||||||
|
let path = ModPath { kind: PathKind::Plain, segments: Vec::new() };
|
||||||
|
RawVisibility::Module(path)
|
||||||
|
}
|
||||||
ast::VisibilityKind::Pub => RawVisibility::Public,
|
ast::VisibilityKind::Pub => RawVisibility::Public,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ use insta::assert_snapshot;
|
||||||
use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
|
use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo,
|
algo,
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode, AstToken},
|
||||||
};
|
};
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
|
||||||
let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db));
|
let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db));
|
||||||
|
|
||||||
let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
|
let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
|
||||||
(self_param.self_kw_token().text_range(), "self".to_string())
|
(self_param.self_kw().unwrap().syntax().text_range(), "self".to_string())
|
||||||
} else {
|
} else {
|
||||||
(src_ptr.value.range(), node.text().to_string().replace("\n", " "))
|
(src_ptr.value.range(), node.text().to_string().replace("\n", " "))
|
||||||
};
|
};
|
||||||
|
|
|
@ -245,7 +245,7 @@ fn opt_fn_ret_type(p: &mut Parser) -> bool {
|
||||||
if p.at(T![->]) {
|
if p.at(T![->]) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
p.bump(T![->]);
|
p.bump(T![->]);
|
||||||
types::type_(p);
|
types::type_no_bounds(p);
|
||||||
m.complete(p, RET_TYPE);
|
m.complete(p, RET_TYPE);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -105,6 +105,7 @@ pub enum SyntaxKind {
|
||||||
DEFAULT_KW,
|
DEFAULT_KW,
|
||||||
EXISTENTIAL_KW,
|
EXISTENTIAL_KW,
|
||||||
UNION_KW,
|
UNION_KW,
|
||||||
|
RAW_KW,
|
||||||
INT_NUMBER,
|
INT_NUMBER,
|
||||||
FLOAT_NUMBER,
|
FLOAT_NUMBER,
|
||||||
CHAR,
|
CHAR,
|
||||||
|
@ -258,7 +259,7 @@ impl SyntaxKind {
|
||||||
| IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
|
| IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
|
||||||
| MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW
|
| MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW
|
||||||
| TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW
|
| TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW
|
||||||
| AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW => true,
|
| AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -651,4 +652,7 @@ macro_rules! T {
|
||||||
( union ) => {
|
( union ) => {
|
||||||
$crate::SyntaxKind::UNION_KW
|
$crate::SyntaxKind::UNION_KW
|
||||||
};
|
};
|
||||||
|
( raw ) => {
|
||||||
|
$crate::SyntaxKind::RAW_KW
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::{
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ra_text_edit::TextEditBuilder;
|
use ra_text_edit::TextEditBuilder;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken,
|
AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken,
|
||||||
|
@ -72,8 +72,18 @@ pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxEleme
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> {
|
pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> {
|
||||||
let u_ancestors = u.ancestors().collect::<FxHashSet<SyntaxNode>>();
|
if u == v {
|
||||||
v.ancestors().find(|it| u_ancestors.contains(it))
|
return Some(u.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
let u_depth = u.ancestors().count();
|
||||||
|
let v_depth = v.ancestors().count();
|
||||||
|
let keep = u_depth.min(v_depth);
|
||||||
|
|
||||||
|
let u_candidates = u.ancestors().skip(u_depth - keep);
|
||||||
|
let v_canidates = v.ancestors().skip(v_depth - keep);
|
||||||
|
let (res, _) = u_candidates.zip(v_canidates).find(|(x, y)| x == y)?;
|
||||||
|
Some(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> {
|
pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> {
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub use self::{
|
||||||
AttrKind, FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind,
|
AttrKind, FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind,
|
||||||
TypeBoundKind, VisibilityKind,
|
TypeBoundKind, VisibilityKind,
|
||||||
},
|
},
|
||||||
generated::*,
|
generated::{nodes::*, tokens::*},
|
||||||
tokens::*,
|
tokens::*,
|
||||||
traits::*,
|
traits::*,
|
||||||
};
|
};
|
||||||
|
@ -64,6 +64,22 @@ pub trait AstToken {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod support {
|
||||||
|
use super::{AstChildren, AstNode, AstToken, SyntaxNode};
|
||||||
|
|
||||||
|
pub(super) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {
|
||||||
|
parent.children().find_map(N::cast)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
|
||||||
|
AstChildren::new(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn token<T: AstToken>(parent: &SyntaxNode) -> Option<T> {
|
||||||
|
parent.children_with_tokens().filter_map(|it| it.into_token()).find_map(T::cast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An iterator over `SyntaxNode` children of a particular AST type.
|
/// An iterator over `SyntaxNode` children of a particular AST type.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AstChildren<N> {
|
pub struct AstChildren<N> {
|
||||||
|
@ -271,7 +287,7 @@ where
|
||||||
let pred = predicates.next().unwrap();
|
let pred = predicates.next().unwrap();
|
||||||
let mut bounds = pred.type_bound_list().unwrap().bounds();
|
let mut bounds = pred.type_bound_list().unwrap().bounds();
|
||||||
|
|
||||||
assert_eq!("'a", pred.lifetime_token().unwrap().text());
|
assert_eq!("'a", pred.lifetime().unwrap().text());
|
||||||
|
|
||||||
assert_bound("'b", bounds.next());
|
assert_bound("'b", bounds.next());
|
||||||
assert_bound("'c", bounds.next());
|
assert_bound("'c", bounds.next());
|
||||||
|
|
|
@ -99,7 +99,7 @@ impl ast::ItemList {
|
||||||
None => match self.l_curly() {
|
None => match self.l_curly() {
|
||||||
Some(it) => (
|
Some(it) => (
|
||||||
" ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
|
" ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
|
||||||
InsertPosition::After(it),
|
InsertPosition::After(it.syntax().clone().into()),
|
||||||
),
|
),
|
||||||
None => return self.clone(),
|
None => return self.clone(),
|
||||||
},
|
},
|
||||||
|
@ -109,10 +109,6 @@ impl ast::ItemList {
|
||||||
[ws.ws().into(), item.syntax().clone().into()].into();
|
[ws.ws().into(), item.syntax().clone().into()].into();
|
||||||
self.insert_children(position, to_insert)
|
self.insert_children(position, to_insert)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn l_curly(&self) -> Option<SyntaxElement> {
|
|
||||||
self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::RecordFieldList {
|
impl ast::RecordFieldList {
|
||||||
|
@ -147,7 +143,7 @@ impl ast::RecordFieldList {
|
||||||
macro_rules! after_l_curly {
|
macro_rules! after_l_curly {
|
||||||
() => {{
|
() => {{
|
||||||
let anchor = match self.l_curly() {
|
let anchor = match self.l_curly() {
|
||||||
Some(it) => it,
|
Some(it) => it.syntax().clone().into(),
|
||||||
None => return self.clone(),
|
None => return self.clone(),
|
||||||
};
|
};
|
||||||
InsertPosition::After(anchor)
|
InsertPosition::After(anchor)
|
||||||
|
@ -189,24 +185,20 @@ impl ast::RecordFieldList {
|
||||||
|
|
||||||
self.insert_children(position, to_insert)
|
self.insert_children(position, to_insert)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn l_curly(&self) -> Option<SyntaxElement> {
|
|
||||||
self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::TypeParam {
|
impl ast::TypeParam {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn remove_bounds(&self) -> ast::TypeParam {
|
pub fn remove_bounds(&self) -> ast::TypeParam {
|
||||||
let colon = match self.colon_token() {
|
let colon = match self.colon() {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return self.clone(),
|
None => return self.clone(),
|
||||||
};
|
};
|
||||||
let end = match self.type_bound_list() {
|
let end = match self.type_bound_list() {
|
||||||
Some(it) => it.syntax().clone().into(),
|
Some(it) => it.syntax().clone().into(),
|
||||||
None => colon.clone().into(),
|
None => colon.syntax().clone().into(),
|
||||||
};
|
};
|
||||||
self.replace_children(colon.into()..=end, iter::empty())
|
self.replace_children(colon.syntax().clone().into()..=end, iter::empty())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,8 +297,12 @@ impl ast::UseTree {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return self.clone(),
|
None => return self.clone(),
|
||||||
};
|
};
|
||||||
let use_tree =
|
let use_tree = make::use_tree(
|
||||||
make::use_tree(suffix.clone(), self.use_tree_list(), self.alias(), self.has_star());
|
suffix.clone(),
|
||||||
|
self.use_tree_list(),
|
||||||
|
self.alias(),
|
||||||
|
self.star().is_some(),
|
||||||
|
);
|
||||||
let nested = make::use_tree_list(iter::once(use_tree));
|
let nested = make::use_tree_list(iter::once(use_tree));
|
||||||
return make::use_tree(prefix.clone(), Some(nested), None, false);
|
return make::use_tree(prefix.clone(), Some(nested), None, false);
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,10 @@ impl ast::RefExpr {
|
||||||
pub fn is_mut(&self) -> bool {
|
pub fn is_mut(&self) -> bool {
|
||||||
self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
|
self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn raw_token(&self) -> Option<SyntaxToken> {
|
||||||
|
None // FIXME: implement &raw
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, child_opt, children, AstNode, AttrInput, NameOwner, SyntaxNode},
|
ast::{
|
||||||
|
self, child_opt, children, support, AstNode, AstToken, AttrInput, NameOwner, SyntaxNode,
|
||||||
|
},
|
||||||
SmolStr, SyntaxElement,
|
SmolStr, SyntaxElement,
|
||||||
SyntaxKind::*,
|
SyntaxKind::*,
|
||||||
SyntaxToken, T,
|
SyntaxToken, T,
|
||||||
|
@ -130,13 +132,6 @@ impl ast::PathSegment {
|
||||||
};
|
};
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_colon_colon(&self) -> bool {
|
|
||||||
match self.syntax.first_child_or_token().map(|s| s.kind()) {
|
|
||||||
Some(T![::]) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::Path {
|
impl ast::Path {
|
||||||
|
@ -154,12 +149,6 @@ impl ast::Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::UseTree {
|
|
||||||
pub fn has_star(&self) -> bool {
|
|
||||||
self.syntax().children_with_tokens().any(|it| it.kind() == T![*])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ast::UseTreeList {
|
impl ast::UseTreeList {
|
||||||
pub fn parent_use_tree(&self) -> ast::UseTree {
|
pub fn parent_use_tree(&self) -> ast::UseTree {
|
||||||
self.syntax()
|
self.syntax()
|
||||||
|
@ -167,20 +156,6 @@ impl ast::UseTreeList {
|
||||||
.and_then(ast::UseTree::cast)
|
.and_then(ast::UseTree::cast)
|
||||||
.expect("UseTreeLists are always nested in UseTrees")
|
.expect("UseTreeLists are always nested in UseTrees")
|
||||||
}
|
}
|
||||||
pub fn l_curly(&self) -> Option<SyntaxToken> {
|
|
||||||
self.token(T!['{'])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn r_curly(&self) -> Option<SyntaxToken> {
|
|
||||||
self.token(T!['}'])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
|
|
||||||
self.syntax()
|
|
||||||
.children_with_tokens()
|
|
||||||
.filter_map(|it| it.into_token())
|
|
||||||
.find(|it| it.kind() == kind)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::ImplDef {
|
impl ast::ImplDef {
|
||||||
|
@ -387,24 +362,9 @@ pub enum SelfParamKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::SelfParam {
|
impl ast::SelfParam {
|
||||||
pub fn self_kw_token(&self) -> SyntaxToken {
|
|
||||||
self.syntax()
|
|
||||||
.children_with_tokens()
|
|
||||||
.filter_map(|it| it.into_token())
|
|
||||||
.find(|it| it.kind() == T![self])
|
|
||||||
.expect("invalid tree: self param must have self")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> SelfParamKind {
|
pub fn kind(&self) -> SelfParamKind {
|
||||||
let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == T![&]);
|
if self.amp().is_some() {
|
||||||
if borrowed {
|
if self.amp_mut_kw().is_some() {
|
||||||
// check for a `mut` coming after the & -- `mut &self` != `&mut self`
|
|
||||||
if self
|
|
||||||
.syntax()
|
|
||||||
.children_with_tokens()
|
|
||||||
.skip_while(|n| n.kind() != T![&])
|
|
||||||
.any(|n| n.kind() == T![mut])
|
|
||||||
{
|
|
||||||
SelfParamKind::MutRef
|
SelfParamKind::MutRef
|
||||||
} else {
|
} else {
|
||||||
SelfParamKind::Ref
|
SelfParamKind::Ref
|
||||||
|
@ -413,32 +373,23 @@ impl ast::SelfParam {
|
||||||
SelfParamKind::Owned
|
SelfParamKind::Owned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ast::LifetimeParam {
|
/// the "mut" in "mut self", not the one in "&mut self"
|
||||||
pub fn lifetime_token(&self) -> Option<SyntaxToken> {
|
pub fn mut_kw(&self) -> Option<ast::MutKw> {
|
||||||
self.syntax()
|
self.syntax()
|
||||||
.children_with_tokens()
|
.children_with_tokens()
|
||||||
.filter_map(|it| it.into_token())
|
.filter_map(|it| it.into_token())
|
||||||
.find(|it| it.kind() == LIFETIME)
|
.take_while(|it| it.kind() != T![&])
|
||||||
}
|
.find_map(ast::MutKw::cast)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::TypeParam {
|
/// the "mut" in "&mut self", not the one in "mut self"
|
||||||
pub fn colon_token(&self) -> Option<SyntaxToken> {
|
pub fn amp_mut_kw(&self) -> Option<ast::MutKw> {
|
||||||
self.syntax()
|
self.syntax()
|
||||||
.children_with_tokens()
|
.children_with_tokens()
|
||||||
.filter_map(|it| it.into_token())
|
.filter_map(|it| it.into_token())
|
||||||
.find(|it| it.kind() == T![:])
|
.skip_while(|it| it.kind() != T![&])
|
||||||
}
|
.find_map(ast::MutKw::cast)
|
||||||
}
|
|
||||||
|
|
||||||
impl ast::WherePred {
|
|
||||||
pub fn lifetime_token(&self) -> Option<SyntaxToken> {
|
|
||||||
self.syntax()
|
|
||||||
.children_with_tokens()
|
|
||||||
.filter_map(|it| it.into_token())
|
|
||||||
.find(|it| it.kind() == LIFETIME)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +400,7 @@ pub enum TypeBoundKind {
|
||||||
/// for<'a> ...
|
/// for<'a> ...
|
||||||
ForType(ast::ForType),
|
ForType(ast::ForType),
|
||||||
/// 'a
|
/// 'a
|
||||||
Lifetime(ast::SyntaxToken),
|
Lifetime(ast::Lifetime),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::TypeBound {
|
impl ast::TypeBound {
|
||||||
|
@ -465,21 +416,28 @@ impl ast::TypeBound {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lifetime(&self) -> Option<SyntaxToken> {
|
pub fn has_question_mark(&self) -> bool {
|
||||||
self.syntax()
|
self.question().is_some()
|
||||||
.children_with_tokens()
|
|
||||||
.filter_map(|it| it.into_token())
|
|
||||||
.find(|it| it.kind() == LIFETIME)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn question_mark_token(&self) -> Option<SyntaxToken> {
|
pub fn const_question(&self) -> Option<ast::Question> {
|
||||||
self.syntax()
|
self.syntax()
|
||||||
.children_with_tokens()
|
.children_with_tokens()
|
||||||
.filter_map(|it| it.into_token())
|
.filter_map(|it| it.into_token())
|
||||||
.find(|it| it.kind() == T![?])
|
.take_while(|it| it.kind() != T![const])
|
||||||
|
.find_map(ast::Question::cast)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn question(&self) -> Option<ast::Question> {
|
||||||
|
if self.const_kw().is_some() {
|
||||||
|
self.syntax()
|
||||||
|
.children_with_tokens()
|
||||||
|
.filter_map(|it| it.into_token())
|
||||||
|
.skip_while(|it| it.kind() != T![const])
|
||||||
|
.find_map(ast::Question::cast)
|
||||||
|
} else {
|
||||||
|
support::token(&self.syntax)
|
||||||
}
|
}
|
||||||
pub fn has_question_mark(&self) -> bool {
|
|
||||||
self.question_mark_token().is_some()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,6 +451,7 @@ pub enum VisibilityKind {
|
||||||
In(ast::Path),
|
In(ast::Path),
|
||||||
PubCrate,
|
PubCrate,
|
||||||
PubSuper,
|
PubSuper,
|
||||||
|
PubSelf,
|
||||||
Pub,
|
Pub,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,6 +463,8 @@ impl ast::Visibility {
|
||||||
VisibilityKind::PubCrate
|
VisibilityKind::PubCrate
|
||||||
} else if self.is_pub_super() {
|
} else if self.is_pub_super() {
|
||||||
VisibilityKind::PubSuper
|
VisibilityKind::PubSuper
|
||||||
|
} else if self.is_pub_self() {
|
||||||
|
VisibilityKind::PubSuper
|
||||||
} else {
|
} else {
|
||||||
VisibilityKind::Pub
|
VisibilityKind::Pub
|
||||||
}
|
}
|
||||||
|
@ -516,6 +477,10 @@ impl ast::Visibility {
|
||||||
fn is_pub_super(&self) -> bool {
|
fn is_pub_super(&self) -> bool {
|
||||||
self.syntax().children_with_tokens().any(|it| it.kind() == T![super])
|
self.syntax().children_with_tokens().any(|it| it.kind() == T![super])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_pub_self(&self) -> bool {
|
||||||
|
self.syntax().children_with_tokens().any(|it| it.kind() == T![self])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::MacroCall {
|
impl ast::MacroCall {
|
||||||
|
@ -528,3 +493,41 @@ impl ast::MacroCall {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ast::LifetimeParam {
|
||||||
|
pub fn lifetime_bounds(&self) -> impl Iterator<Item = ast::Lifetime> {
|
||||||
|
self.syntax()
|
||||||
|
.children_with_tokens()
|
||||||
|
.filter_map(|it| it.into_token())
|
||||||
|
.skip_while(|x| x.kind() != T![:])
|
||||||
|
.filter_map(ast::Lifetime::cast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ast::RangePat {
|
||||||
|
pub fn start(&self) -> Option<ast::Pat> {
|
||||||
|
self.syntax()
|
||||||
|
.children_with_tokens()
|
||||||
|
.take_while(|it| !ast::RangeSeparator::can_cast(it.kind()))
|
||||||
|
.filter_map(|it| it.into_node())
|
||||||
|
.find_map(ast::Pat::cast)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end(&self) -> Option<ast::Pat> {
|
||||||
|
self.syntax()
|
||||||
|
.children_with_tokens()
|
||||||
|
.skip_while(|it| !ast::RangeSeparator::can_cast(it.kind()))
|
||||||
|
.filter_map(|it| it.into_node())
|
||||||
|
.find_map(ast::Pat::cast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ast::TokenTree {
|
||||||
|
pub fn left_delimiter(&self) -> Option<ast::LeftDelimiter> {
|
||||||
|
self.syntax().first_child_or_token()?.into_token().and_then(ast::LeftDelimiter::cast)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right_delimiter(&self) -> Option<ast::RightDelimiter> {
|
||||||
|
self.syntax().last_child_or_token()?.into_token().and_then(ast::RightDelimiter::cast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
4177
crates/ra_syntax/src/ast/generated/nodes.rs
Normal file
4177
crates/ra_syntax/src/ast/generated/nodes.rs
Normal file
File diff suppressed because it is too large
Load diff
2808
crates/ra_syntax/src/ast/generated/tokens.rs
Normal file
2808
crates/ra_syntax/src/ast/generated/tokens.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,7 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, child_opt, children, AstChildren, AstNode, AstToken},
|
ast::{self, child_opt, children, support, AstChildren, AstNode, AstToken},
|
||||||
syntax_node::SyntaxElementChildren,
|
syntax_node::SyntaxElementChildren,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@ pub trait LoopBodyOwner: AstNode {
|
||||||
fn loop_body(&self) -> Option<ast::BlockExpr> {
|
fn loop_body(&self) -> Option<ast::BlockExpr> {
|
||||||
child_opt(self)
|
child_opt(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn label(&self) -> Option<ast::Label> {
|
||||||
|
child_opt(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ArgListOwner: AstNode {
|
pub trait ArgListOwner: AstNode {
|
||||||
|
@ -65,6 +69,10 @@ pub trait TypeBoundsOwner: AstNode {
|
||||||
fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
|
fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
|
||||||
child_opt(self)
|
child_opt(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn colon(&self) -> Option<ast::Colon> {
|
||||||
|
support::token(self.syntax())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AttrsOwner: AstNode {
|
pub trait AttrsOwner: AstNode {
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
SOURCE_FILE@[0; 40)
|
||||||
|
FN_DEF@[0; 39)
|
||||||
|
FN_KW@[0; 2) "fn"
|
||||||
|
WHITESPACE@[2; 3) " "
|
||||||
|
NAME@[3; 4)
|
||||||
|
IDENT@[3; 4) "f"
|
||||||
|
TYPE_PARAM_LIST@[4; 7)
|
||||||
|
L_ANGLE@[4; 5) "<"
|
||||||
|
TYPE_PARAM@[5; 6)
|
||||||
|
NAME@[5; 6)
|
||||||
|
IDENT@[5; 6) "T"
|
||||||
|
R_ANGLE@[6; 7) ">"
|
||||||
|
PARAM_LIST@[7; 9)
|
||||||
|
L_PAREN@[7; 8) "("
|
||||||
|
R_PAREN@[8; 9) ")"
|
||||||
|
WHITESPACE@[9; 10) " "
|
||||||
|
WHERE_CLAUSE@[10; 36)
|
||||||
|
WHERE_KW@[10; 15) "where"
|
||||||
|
WHITESPACE@[15; 16) " "
|
||||||
|
WHERE_PRED@[16; 36)
|
||||||
|
PATH_TYPE@[16; 17)
|
||||||
|
PATH@[16; 17)
|
||||||
|
PATH_SEGMENT@[16; 17)
|
||||||
|
NAME_REF@[16; 17)
|
||||||
|
IDENT@[16; 17) "T"
|
||||||
|
COLON@[17; 18) ":"
|
||||||
|
WHITESPACE@[18; 19) " "
|
||||||
|
TYPE_BOUND_LIST@[19; 36)
|
||||||
|
TYPE_BOUND@[19; 29)
|
||||||
|
PATH_TYPE@[19; 29)
|
||||||
|
PATH@[19; 29)
|
||||||
|
PATH_SEGMENT@[19; 29)
|
||||||
|
NAME_REF@[19; 21)
|
||||||
|
IDENT@[19; 21) "Fn"
|
||||||
|
PARAM_LIST@[21; 23)
|
||||||
|
L_PAREN@[21; 22) "("
|
||||||
|
R_PAREN@[22; 23) ")"
|
||||||
|
WHITESPACE@[23; 24) " "
|
||||||
|
RET_TYPE@[24; 29)
|
||||||
|
THIN_ARROW@[24; 26) "->"
|
||||||
|
WHITESPACE@[26; 27) " "
|
||||||
|
PATH_TYPE@[27; 29)
|
||||||
|
PATH@[27; 29)
|
||||||
|
PATH_SEGMENT@[27; 29)
|
||||||
|
NAME_REF@[27; 29)
|
||||||
|
IDENT@[27; 29) "u8"
|
||||||
|
WHITESPACE@[29; 30) " "
|
||||||
|
PLUS@[30; 31) "+"
|
||||||
|
WHITESPACE@[31; 32) " "
|
||||||
|
TYPE_BOUND@[32; 36)
|
||||||
|
PATH_TYPE@[32; 36)
|
||||||
|
PATH@[32; 36)
|
||||||
|
PATH_SEGMENT@[32; 36)
|
||||||
|
NAME_REF@[32; 36)
|
||||||
|
IDENT@[32; 36) "Send"
|
||||||
|
WHITESPACE@[36; 37) " "
|
||||||
|
BLOCK_EXPR@[37; 39)
|
||||||
|
BLOCK@[37; 39)
|
||||||
|
L_CURLY@[37; 38) "{"
|
||||||
|
R_CURLY@[38; 39) "}"
|
||||||
|
WHITESPACE@[39; 40) "\n"
|
|
@ -0,0 +1 @@
|
||||||
|
fn f<T>() where T: Fn() -> u8 + Send {}
|
|
@ -70,7 +70,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
|
||||||
"match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super",
|
"match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super",
|
||||||
"trait", "true", "try", "type", "unsafe", "use", "where", "while",
|
"trait", "true", "try", "type", "unsafe", "use", "where", "while",
|
||||||
],
|
],
|
||||||
contextual_keywords: &["auto", "default", "existential", "union"],
|
contextual_keywords: &["auto", "default", "existential", "union", "raw"],
|
||||||
literals: &[
|
literals: &[
|
||||||
"INT_NUMBER",
|
"INT_NUMBER",
|
||||||
"FLOAT_NUMBER",
|
"FLOAT_NUMBER",
|
||||||
|
@ -227,6 +227,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
|
||||||
pub(crate) struct AstSrc<'a> {
|
pub(crate) struct AstSrc<'a> {
|
||||||
pub(crate) nodes: &'a [AstNodeSrc<'a>],
|
pub(crate) nodes: &'a [AstNodeSrc<'a>],
|
||||||
pub(crate) enums: &'a [AstEnumSrc<'a>],
|
pub(crate) enums: &'a [AstEnumSrc<'a>],
|
||||||
|
pub(crate) token_enums: &'a [AstEnumSrc<'a>],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct AstNodeSrc<'a> {
|
pub(crate) struct AstNodeSrc<'a> {
|
||||||
|
@ -297,235 +298,310 @@ macro_rules! ast_enums {
|
||||||
|
|
||||||
pub(crate) const AST_SRC: AstSrc = AstSrc {
|
pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
nodes: &ast_nodes! {
|
nodes: &ast_nodes! {
|
||||||
struct SourceFile: ModuleItemOwner, FnDefOwner {
|
struct SourceFile: ModuleItemOwner, FnDefOwner, AttrsOwner {
|
||||||
modules: [Module],
|
modules: [Module],
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner {
|
struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner {
|
||||||
|
Abi,
|
||||||
|
ConstKw,
|
||||||
|
DefaultKw,
|
||||||
|
AsyncKw,
|
||||||
|
UnsafeKw,
|
||||||
|
FnKw,
|
||||||
ParamList,
|
ParamList,
|
||||||
RetType,
|
RetType,
|
||||||
body: BlockExpr,
|
body: BlockExpr,
|
||||||
|
Semi
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RetType { TypeRef }
|
struct RetType { ThinArrow, TypeRef }
|
||||||
|
|
||||||
struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
|
struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
|
||||||
|
StructKw,
|
||||||
|
FieldDefList,
|
||||||
|
Semi
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
|
struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
|
||||||
|
UnionKw,
|
||||||
RecordFieldDefList,
|
RecordFieldDefList,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RecordFieldDefList { fields: [RecordFieldDef] }
|
struct RecordFieldDefList { LCurly, fields: [RecordFieldDef], RCurly }
|
||||||
struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { }
|
struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { }
|
||||||
|
|
||||||
struct TupleFieldDefList { fields: [TupleFieldDef] }
|
struct TupleFieldDefList { LParen, fields: [TupleFieldDef], RParen }
|
||||||
struct TupleFieldDef: VisibilityOwner, AttrsOwner {
|
struct TupleFieldDef: VisibilityOwner, AttrsOwner {
|
||||||
TypeRef,
|
TypeRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
|
struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
|
||||||
|
EnumKw,
|
||||||
variant_list: EnumVariantList,
|
variant_list: EnumVariantList,
|
||||||
}
|
}
|
||||||
struct EnumVariantList {
|
struct EnumVariantList {
|
||||||
|
LCurly,
|
||||||
variants: [EnumVariant],
|
variants: [EnumVariant],
|
||||||
|
RCurly
|
||||||
}
|
}
|
||||||
struct EnumVariant: NameOwner, DocCommentsOwner, AttrsOwner {
|
struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner {
|
||||||
|
FieldDefList,
|
||||||
|
Eq,
|
||||||
Expr
|
Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner {
|
struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner {
|
||||||
|
UnsafeKw,
|
||||||
|
AutoKw,
|
||||||
|
TraitKw,
|
||||||
ItemList,
|
ItemList,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner {
|
struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner {
|
||||||
|
ModKw,
|
||||||
ItemList,
|
ItemList,
|
||||||
|
Semi
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ItemList: FnDefOwner, ModuleItemOwner {
|
struct ItemList: FnDefOwner, ModuleItemOwner {
|
||||||
|
LCurly,
|
||||||
impl_items: [ImplItem],
|
impl_items: [ImplItem],
|
||||||
|
RCurly
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
|
struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
|
||||||
|
DefaultKw,
|
||||||
|
ConstKw,
|
||||||
|
Eq,
|
||||||
body: Expr,
|
body: Expr,
|
||||||
|
Semi
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
|
struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
|
||||||
|
StaticKw,
|
||||||
|
MutKw,
|
||||||
|
Eq,
|
||||||
body: Expr,
|
body: Expr,
|
||||||
|
Semi
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner {
|
struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner {
|
||||||
|
DefaultKw,
|
||||||
|
TypeKw,
|
||||||
|
Eq,
|
||||||
TypeRef,
|
TypeRef,
|
||||||
|
Semi
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ImplDef: TypeParamsOwner, AttrsOwner {
|
struct ImplDef: TypeParamsOwner, AttrsOwner {
|
||||||
|
DefaultKw,
|
||||||
|
ConstKw,
|
||||||
|
UnsafeKw,
|
||||||
|
ImplKw,
|
||||||
|
Excl,
|
||||||
|
ForKw,
|
||||||
ItemList,
|
ItemList,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ParenType { TypeRef }
|
struct ParenType { LParen, TypeRef, RParen }
|
||||||
struct TupleType { fields: [TypeRef] }
|
struct TupleType { LParen, fields: [TypeRef], RParen }
|
||||||
struct NeverType { }
|
struct NeverType { Excl }
|
||||||
struct PathType { Path }
|
struct PathType { Path }
|
||||||
struct PointerType { TypeRef }
|
struct PointerType { Star, ConstKw, TypeRef }
|
||||||
struct ArrayType { TypeRef, Expr }
|
struct ArrayType { LBrack, TypeRef, Semi, Expr, RBrack }
|
||||||
struct SliceType { TypeRef }
|
struct SliceType { LBrack, TypeRef, RBrack }
|
||||||
struct ReferenceType { TypeRef }
|
struct ReferenceType { Amp, Lifetime, MutKw, TypeRef }
|
||||||
struct PlaceholderType { }
|
struct PlaceholderType { Underscore }
|
||||||
struct FnPointerType { ParamList, RetType }
|
struct FnPointerType { Abi, UnsafeKw, FnKw, ParamList, RetType }
|
||||||
struct ForType { TypeRef }
|
struct ForType { ForKw, TypeParamList, TypeRef }
|
||||||
struct ImplTraitType: TypeBoundsOwner {}
|
struct ImplTraitType: TypeBoundsOwner { ImplKw }
|
||||||
struct DynTraitType: TypeBoundsOwner {}
|
struct DynTraitType: TypeBoundsOwner { DynKw }
|
||||||
|
|
||||||
struct TupleExpr { exprs: [Expr] }
|
struct TupleExpr: AttrsOwner { LParen, exprs: [Expr], RParen }
|
||||||
struct ArrayExpr { exprs: [Expr] }
|
struct ArrayExpr: AttrsOwner { LBrack, exprs: [Expr], Semi, RBrack }
|
||||||
struct ParenExpr { Expr }
|
struct ParenExpr: AttrsOwner { LParen, Expr, RParen }
|
||||||
struct PathExpr { Path }
|
struct PathExpr { Path }
|
||||||
struct LambdaExpr {
|
struct LambdaExpr: AttrsOwner {
|
||||||
|
StaticKw,
|
||||||
|
AsyncKw,
|
||||||
|
MoveKw,
|
||||||
ParamList,
|
ParamList,
|
||||||
RetType,
|
RetType,
|
||||||
body: Expr,
|
body: Expr,
|
||||||
}
|
}
|
||||||
struct IfExpr { Condition }
|
struct IfExpr: AttrsOwner { IfKw, Condition }
|
||||||
struct LoopExpr: LoopBodyOwner { }
|
struct LoopExpr: AttrsOwner, LoopBodyOwner { LoopKw }
|
||||||
struct TryBlockExpr { body: BlockExpr }
|
struct TryBlockExpr: AttrsOwner { TryKw, body: BlockExpr }
|
||||||
struct ForExpr: LoopBodyOwner {
|
struct ForExpr: AttrsOwner, LoopBodyOwner {
|
||||||
|
ForKw,
|
||||||
Pat,
|
Pat,
|
||||||
|
InKw,
|
||||||
iterable: Expr,
|
iterable: Expr,
|
||||||
}
|
}
|
||||||
struct WhileExpr: LoopBodyOwner { Condition }
|
struct WhileExpr: AttrsOwner, LoopBodyOwner { WhileKw, Condition }
|
||||||
struct ContinueExpr {}
|
struct ContinueExpr: AttrsOwner { ContinueKw, Lifetime }
|
||||||
struct BreakExpr { Expr }
|
struct BreakExpr: AttrsOwner { BreakKw, Lifetime, Expr }
|
||||||
struct Label {}
|
struct Label { Lifetime }
|
||||||
struct BlockExpr { Block }
|
struct BlockExpr: AttrsOwner { Label, UnsafeKw, Block }
|
||||||
struct ReturnExpr { Expr }
|
struct ReturnExpr: AttrsOwner { Expr }
|
||||||
struct CallExpr: ArgListOwner { Expr }
|
struct CallExpr: ArgListOwner { Expr }
|
||||||
struct MethodCallExpr: ArgListOwner {
|
struct MethodCallExpr: AttrsOwner, ArgListOwner {
|
||||||
Expr, NameRef, TypeArgList,
|
Expr, Dot, NameRef, TypeArgList,
|
||||||
}
|
}
|
||||||
struct IndexExpr {}
|
struct IndexExpr: AttrsOwner { LBrack, RBrack }
|
||||||
struct FieldExpr { Expr, NameRef }
|
struct FieldExpr: AttrsOwner { Expr, Dot, NameRef }
|
||||||
struct AwaitExpr { Expr }
|
struct AwaitExpr: AttrsOwner { Expr, Dot, AwaitKw }
|
||||||
struct TryExpr { Expr }
|
struct TryExpr: AttrsOwner { TryKw, Expr }
|
||||||
struct CastExpr { Expr, TypeRef }
|
struct CastExpr: AttrsOwner { Expr, AsKw, TypeRef }
|
||||||
struct RefExpr { Expr }
|
struct RefExpr: AttrsOwner { Amp, RawKw, MutKw, Expr }
|
||||||
struct PrefixExpr { Expr }
|
struct PrefixExpr: AttrsOwner { PrefixOp, Expr }
|
||||||
struct BoxExpr { Expr }
|
struct BoxExpr: AttrsOwner { BoxKw, Expr }
|
||||||
struct RangeExpr {}
|
struct RangeExpr: AttrsOwner { RangeOp }
|
||||||
struct BinExpr {}
|
struct BinExpr: AttrsOwner { BinOp }
|
||||||
struct Literal {}
|
struct Literal { LiteralToken }
|
||||||
|
|
||||||
struct MatchExpr { Expr, MatchArmList }
|
struct MatchExpr: AttrsOwner { MatchKw, Expr, MatchArmList }
|
||||||
struct MatchArmList: AttrsOwner { arms: [MatchArm] }
|
struct MatchArmList: AttrsOwner { LCurly, arms: [MatchArm], RCurly }
|
||||||
struct MatchArm: AttrsOwner {
|
struct MatchArm: AttrsOwner {
|
||||||
pat: Pat,
|
pat: Pat,
|
||||||
guard: MatchGuard,
|
guard: MatchGuard,
|
||||||
|
FatArrow,
|
||||||
Expr,
|
Expr,
|
||||||
}
|
}
|
||||||
struct MatchGuard { Expr }
|
struct MatchGuard { IfKw, Expr }
|
||||||
|
|
||||||
struct RecordLit { Path, RecordFieldList}
|
struct RecordLit { Path, RecordFieldList}
|
||||||
struct RecordFieldList {
|
struct RecordFieldList {
|
||||||
|
LCurly,
|
||||||
fields: [RecordField],
|
fields: [RecordField],
|
||||||
|
Dotdot,
|
||||||
spread: Expr,
|
spread: Expr,
|
||||||
|
RCurly
|
||||||
}
|
}
|
||||||
struct RecordField { NameRef, Expr }
|
struct RecordField: AttrsOwner { NameRef, Colon, Expr }
|
||||||
|
|
||||||
struct OrPat { pats: [Pat] }
|
struct OrPat { pats: [Pat] }
|
||||||
struct ParenPat { Pat }
|
struct ParenPat { LParen, Pat, RParen }
|
||||||
struct RefPat { Pat }
|
struct RefPat { Amp, MutKw, Pat }
|
||||||
struct BoxPat { Pat }
|
struct BoxPat { BoxKw, Pat }
|
||||||
struct BindPat: NameOwner { Pat }
|
struct BindPat: AttrsOwner, NameOwner { RefKw, MutKw, Pat }
|
||||||
struct PlaceholderPat { }
|
struct PlaceholderPat { Underscore }
|
||||||
struct DotDotPat { }
|
struct DotDotPat { Dotdot }
|
||||||
struct PathPat { Path }
|
struct PathPat { Path }
|
||||||
struct SlicePat { args: [Pat] }
|
struct SlicePat { LBrack, args: [Pat], RBrack }
|
||||||
struct RangePat {}
|
struct RangePat { RangeSeparator }
|
||||||
struct LiteralPat { Literal }
|
struct LiteralPat { Literal }
|
||||||
struct MacroPat { MacroCall }
|
struct MacroPat { MacroCall }
|
||||||
|
|
||||||
struct RecordPat { RecordFieldPatList, Path }
|
struct RecordPat { RecordFieldPatList, Path }
|
||||||
struct RecordFieldPatList {
|
struct RecordFieldPatList {
|
||||||
|
LCurly,
|
||||||
|
pats: [RecordInnerPat],
|
||||||
record_field_pats: [RecordFieldPat],
|
record_field_pats: [RecordFieldPat],
|
||||||
bind_pats: [BindPat],
|
bind_pats: [BindPat],
|
||||||
|
Dotdot,
|
||||||
|
RCurly
|
||||||
}
|
}
|
||||||
struct RecordFieldPat: NameOwner { Pat }
|
struct RecordFieldPat: AttrsOwner, NameOwner { Colon, Pat }
|
||||||
|
|
||||||
struct TupleStructPat { Path, args: [Pat] }
|
struct TupleStructPat { Path, LParen, args: [Pat], RParen }
|
||||||
struct TuplePat { args: [Pat] }
|
struct TuplePat { LParen, args: [Pat], RParen }
|
||||||
|
|
||||||
struct Visibility {}
|
struct Visibility { PubKw, SuperKw, SelfKw, CrateKw }
|
||||||
struct Name {}
|
struct Name { Ident }
|
||||||
struct NameRef {}
|
struct NameRef { NameRefToken }
|
||||||
|
|
||||||
struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner {
|
struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner {
|
||||||
TokenTree, Path
|
Path, Excl, TokenTree, Semi
|
||||||
}
|
}
|
||||||
struct Attr { Path, input: AttrInput }
|
struct Attr { Pound, Excl, LBrack, Path, Eq, input: AttrInput, RBrack }
|
||||||
struct TokenTree {}
|
struct TokenTree {}
|
||||||
struct TypeParamList {
|
struct TypeParamList {
|
||||||
|
LAngle,
|
||||||
|
generic_params: [GenericParam],
|
||||||
type_params: [TypeParam],
|
type_params: [TypeParam],
|
||||||
lifetime_params: [LifetimeParam],
|
lifetime_params: [LifetimeParam],
|
||||||
|
const_params: [ConstParam],
|
||||||
|
RAngle
|
||||||
}
|
}
|
||||||
struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner {
|
struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner {
|
||||||
|
Eq,
|
||||||
default_type: TypeRef,
|
default_type: TypeRef,
|
||||||
}
|
}
|
||||||
struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner {
|
struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner {
|
||||||
|
Eq,
|
||||||
default_val: Expr,
|
default_val: Expr,
|
||||||
}
|
}
|
||||||
struct LifetimeParam: AttrsOwner { }
|
struct LifetimeParam: AttrsOwner { Lifetime}
|
||||||
struct TypeBound { TypeRef}
|
struct TypeBound { Lifetime, /* Question, */ ConstKw, /* Question, */ TypeRef}
|
||||||
struct TypeBoundList { bounds: [TypeBound] }
|
struct TypeBoundList { bounds: [TypeBound] }
|
||||||
struct WherePred: TypeBoundsOwner { TypeRef }
|
struct WherePred: TypeBoundsOwner { Lifetime, TypeRef }
|
||||||
struct WhereClause { predicates: [WherePred] }
|
struct WhereClause { WhereKw, predicates: [WherePred] }
|
||||||
struct ExprStmt { Expr }
|
struct Abi { String }
|
||||||
struct LetStmt: TypeAscriptionOwner {
|
struct ExprStmt: AttrsOwner { Expr, Semi }
|
||||||
|
struct LetStmt: AttrsOwner, TypeAscriptionOwner {
|
||||||
|
LetKw,
|
||||||
Pat,
|
Pat,
|
||||||
|
Eq,
|
||||||
initializer: Expr,
|
initializer: Expr,
|
||||||
}
|
}
|
||||||
struct Condition { Pat, Expr }
|
struct Condition { LetKw, Pat, Eq, Expr }
|
||||||
struct Block: AttrsOwner, ModuleItemOwner {
|
struct Block: AttrsOwner, ModuleItemOwner {
|
||||||
|
LCurly,
|
||||||
statements: [Stmt],
|
statements: [Stmt],
|
||||||
Expr,
|
Expr,
|
||||||
|
RCurly,
|
||||||
}
|
}
|
||||||
struct ParamList {
|
struct ParamList {
|
||||||
|
LParen,
|
||||||
SelfParam,
|
SelfParam,
|
||||||
params: [Param],
|
params: [Param],
|
||||||
|
RParen
|
||||||
}
|
}
|
||||||
struct SelfParam: TypeAscriptionOwner, AttrsOwner { }
|
struct SelfParam: TypeAscriptionOwner, AttrsOwner { Amp, Lifetime, SelfKw }
|
||||||
struct Param: TypeAscriptionOwner, AttrsOwner {
|
struct Param: TypeAscriptionOwner, AttrsOwner {
|
||||||
Pat,
|
Pat,
|
||||||
|
Dotdotdot
|
||||||
}
|
}
|
||||||
struct UseItem: AttrsOwner, VisibilityOwner {
|
struct UseItem: AttrsOwner, VisibilityOwner {
|
||||||
|
UseKw,
|
||||||
UseTree,
|
UseTree,
|
||||||
}
|
}
|
||||||
struct UseTree {
|
struct UseTree {
|
||||||
Path, UseTreeList, Alias
|
Path, Star, UseTreeList, Alias
|
||||||
}
|
}
|
||||||
struct Alias: NameOwner { }
|
struct Alias: NameOwner { AsKw }
|
||||||
struct UseTreeList { use_trees: [UseTree] }
|
struct UseTreeList { LCurly, use_trees: [UseTree], RCurly }
|
||||||
struct ExternCrateItem: AttrsOwner, VisibilityOwner {
|
struct ExternCrateItem: AttrsOwner, VisibilityOwner {
|
||||||
NameRef, Alias,
|
ExternKw, CrateKw, NameRef, Alias,
|
||||||
}
|
}
|
||||||
struct ArgList {
|
struct ArgList {
|
||||||
|
LParen,
|
||||||
args: [Expr],
|
args: [Expr],
|
||||||
|
RParen
|
||||||
}
|
}
|
||||||
struct Path {
|
struct Path {
|
||||||
segment: PathSegment,
|
segment: PathSegment,
|
||||||
qualifier: Path,
|
qualifier: Path,
|
||||||
}
|
}
|
||||||
struct PathSegment {
|
struct PathSegment {
|
||||||
NameRef, TypeArgList, ParamList, RetType, PathType,
|
Coloncolon, LAngle, NameRef, TypeArgList, ParamList, RetType, PathType, RAngle
|
||||||
}
|
}
|
||||||
struct TypeArgList {
|
struct TypeArgList {
|
||||||
|
Coloncolon,
|
||||||
|
LAngle,
|
||||||
|
generic_args: [GenericArg],
|
||||||
type_args: [TypeArg],
|
type_args: [TypeArg],
|
||||||
lifetime_args: [LifetimeArg],
|
lifetime_args: [LifetimeArg],
|
||||||
assoc_type_args: [AssocTypeArg],
|
assoc_type_args: [AssocTypeArg],
|
||||||
const_arg: [ConstArg],
|
const_args: [ConstArg],
|
||||||
|
RAngle
|
||||||
}
|
}
|
||||||
struct TypeArg { TypeRef }
|
struct TypeArg { TypeRef }
|
||||||
struct AssocTypeArg { NameRef, TypeRef }
|
struct AssocTypeArg : TypeBoundsOwner { NameRef, Eq, TypeRef }
|
||||||
struct LifetimeArg {}
|
struct LifetimeArg { Lifetime }
|
||||||
struct ConstArg { Literal, BlockExpr }
|
struct ConstArg { Literal, Eq, BlockExpr }
|
||||||
|
|
||||||
struct MacroItems: ModuleItemOwner, FnDefOwner { }
|
struct MacroItems: ModuleItemOwner, FnDefOwner { }
|
||||||
|
|
||||||
|
@ -533,12 +609,44 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
statements: [Stmt],
|
statements: [Stmt],
|
||||||
Expr,
|
Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ExternItemList: FnDefOwner, ModuleItemOwner {
|
||||||
|
LCurly,
|
||||||
|
extern_items: [ExternItem],
|
||||||
|
RCurly
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ExternBlock {
|
||||||
|
Abi,
|
||||||
|
ExternItemList
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MetaItem {
|
||||||
|
Path, Eq, AttrInput, nested_meta_items: [MetaItem]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MacroDef {
|
||||||
|
Name, TokenTree
|
||||||
|
}
|
||||||
},
|
},
|
||||||
enums: &ast_enums! {
|
enums: &ast_enums! {
|
||||||
enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner {
|
enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner {
|
||||||
StructDef, EnumDef, UnionDef,
|
StructDef, EnumDef, UnionDef,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum GenericParam {
|
||||||
|
LifetimeParam,
|
||||||
|
TypeParam,
|
||||||
|
ConstParam
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GenericArg {
|
||||||
|
LifetimeArg,
|
||||||
|
TypeArg,
|
||||||
|
ConstArg,
|
||||||
|
AssocTypeArg
|
||||||
|
}
|
||||||
|
|
||||||
enum TypeRef {
|
enum TypeRef {
|
||||||
ParenType,
|
ParenType,
|
||||||
TupleType,
|
TupleType,
|
||||||
|
@ -555,7 +663,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
DynTraitType,
|
DynTraitType,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ModuleItem: AttrsOwner, VisibilityOwner {
|
enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner {
|
||||||
StructDef,
|
StructDef,
|
||||||
UnionDef,
|
UnionDef,
|
||||||
EnumDef,
|
EnumDef,
|
||||||
|
@ -569,13 +677,20 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
StaticDef,
|
StaticDef,
|
||||||
Module,
|
Module,
|
||||||
MacroCall,
|
MacroCall,
|
||||||
|
ExternBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ImplItem: AttrsOwner {
|
/* impl blocks can also contain MacroCall */
|
||||||
FnDef, TypeAliasDef, ConstDef,
|
enum ImplItem: NameOwner, AttrsOwner {
|
||||||
|
FnDef, TypeAliasDef, ConstDef
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Expr {
|
/* extern blocks can also contain MacroCall */
|
||||||
|
enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner {
|
||||||
|
FnDef, StaticDef
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Expr: AttrsOwner {
|
||||||
TupleExpr,
|
TupleExpr,
|
||||||
ArrayExpr,
|
ArrayExpr,
|
||||||
ParenExpr,
|
ParenExpr,
|
||||||
|
@ -627,7 +742,88 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
MacroPat,
|
MacroPat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum RecordInnerPat {
|
||||||
|
RecordFieldPat,
|
||||||
|
BindPat
|
||||||
|
}
|
||||||
|
|
||||||
enum AttrInput { Literal, TokenTree }
|
enum AttrInput { Literal, TokenTree }
|
||||||
enum Stmt { ExprStmt, LetStmt }
|
enum Stmt {
|
||||||
|
LetStmt,
|
||||||
|
ExprStmt,
|
||||||
|
// macro calls are parsed as expression statements */
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FieldDefList {
|
||||||
|
RecordFieldDefList,
|
||||||
|
TupleFieldDefList,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
token_enums: &ast_enums! {
|
||||||
|
enum LeftDelimiter { LParen, LBrack, LCurly }
|
||||||
|
enum RightDelimiter { RParen, RBrack, RCurly }
|
||||||
|
enum RangeSeparator { Dotdot, Dotdotdot, Dotdoteq}
|
||||||
|
|
||||||
|
enum BinOp {
|
||||||
|
Pipepipe,
|
||||||
|
Ampamp,
|
||||||
|
Eqeq,
|
||||||
|
Neq,
|
||||||
|
Lteq,
|
||||||
|
Gteq,
|
||||||
|
LAngle,
|
||||||
|
RAngle,
|
||||||
|
Plus,
|
||||||
|
Star,
|
||||||
|
Minus,
|
||||||
|
Slash,
|
||||||
|
Percent,
|
||||||
|
Shl,
|
||||||
|
Shr,
|
||||||
|
Caret,
|
||||||
|
Pipe,
|
||||||
|
Amp,
|
||||||
|
Eq,
|
||||||
|
Pluseq,
|
||||||
|
Slasheq,
|
||||||
|
Stareq,
|
||||||
|
Percenteq,
|
||||||
|
Shreq,
|
||||||
|
Shleq,
|
||||||
|
Minuseq,
|
||||||
|
Pipeeq,
|
||||||
|
Ampeq,
|
||||||
|
Careteq,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PrefixOp {
|
||||||
|
Minus,
|
||||||
|
Excl,
|
||||||
|
Star
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RangeOp {
|
||||||
|
Dotdot,
|
||||||
|
Dotdoteq
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LiteralToken {
|
||||||
|
IntNumber,
|
||||||
|
FloatNumber,
|
||||||
|
String,
|
||||||
|
RawString,
|
||||||
|
TrueKw,
|
||||||
|
FalseKw,
|
||||||
|
ByteString,
|
||||||
|
RawByteString,
|
||||||
|
Char,
|
||||||
|
Byte
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NameRefToken {
|
||||||
|
Ident,
|
||||||
|
IntNumber
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,8 +22,9 @@ const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar";
|
||||||
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok";
|
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok";
|
||||||
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err";
|
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err";
|
||||||
|
|
||||||
pub const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs";
|
const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs";
|
||||||
pub const AST: &str = "crates/ra_syntax/src/ast/generated.rs";
|
const AST_NODES: &str = "crates/ra_syntax/src/ast/generated/nodes.rs";
|
||||||
|
const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs";
|
||||||
|
|
||||||
const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers";
|
const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers";
|
||||||
const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs";
|
const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs";
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
//! Specifically, it generates the `SyntaxKind` enum and a number of newtype
|
//! Specifically, it generates the `SyntaxKind` enum and a number of newtype
|
||||||
//! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`.
|
//! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
collections::{BTreeSet, HashSet},
|
||||||
|
};
|
||||||
|
|
||||||
use proc_macro2::{Punct, Spacing};
|
use proc_macro2::{Punct, Spacing};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC},
|
ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC},
|
||||||
|
@ -19,9 +22,13 @@ pub fn generate_syntax(mode: Mode) -> Result<()> {
|
||||||
let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?;
|
let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?;
|
||||||
update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
|
update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
|
||||||
|
|
||||||
let ast_file = project_root().join(codegen::AST);
|
let ast_nodes_file = project_root().join(codegen::AST_NODES);
|
||||||
let ast = generate_ast(KINDS_SRC, AST_SRC)?;
|
let contents = generate_nodes(KINDS_SRC, AST_SRC)?;
|
||||||
update(ast_file.as_path(), &ast, mode)?;
|
update(ast_nodes_file.as_path(), &contents, mode)?;
|
||||||
|
|
||||||
|
let ast_tokens_file = project_root().join(codegen::AST_TOKENS);
|
||||||
|
let contents = generate_tokens(KINDS_SRC, AST_SRC)?;
|
||||||
|
update(ast_tokens_file.as_path(), &contents, mode)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -33,7 +40,7 @@ struct ElementKinds {
|
||||||
has_tokens: bool,
|
has_tokens: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
let all_token_kinds: Vec<_> = kinds
|
let all_token_kinds: Vec<_> = kinds
|
||||||
.punct
|
.punct
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -51,46 +58,6 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
.chain(kinds.tokens.into_iter().copied().map(|x| x.into()))
|
.chain(kinds.tokens.into_iter().copied().map(|x| x.into()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut element_kinds_map = HashMap::new();
|
|
||||||
for kind in &all_token_kinds {
|
|
||||||
let kind = &**kind;
|
|
||||||
let name = to_pascal_case(kind);
|
|
||||||
element_kinds_map.insert(
|
|
||||||
name,
|
|
||||||
ElementKinds {
|
|
||||||
kinds: Some(format_ident!("{}", kind)).into_iter().collect(),
|
|
||||||
has_nodes: false,
|
|
||||||
has_tokens: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for kind in kinds.nodes {
|
|
||||||
let name = to_pascal_case(kind);
|
|
||||||
element_kinds_map.insert(
|
|
||||||
name,
|
|
||||||
ElementKinds {
|
|
||||||
kinds: Some(format_ident!("{}", *kind)).into_iter().collect(),
|
|
||||||
has_nodes: true,
|
|
||||||
has_tokens: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for en in grammar.enums {
|
|
||||||
let mut element_kinds: ElementKinds = Default::default();
|
|
||||||
for variant in en.variants {
|
|
||||||
if let Some(variant_element_kinds) = element_kinds_map.get(*variant) {
|
|
||||||
element_kinds.kinds.extend(variant_element_kinds.kinds.iter().cloned());
|
|
||||||
element_kinds.has_tokens |= variant_element_kinds.has_tokens;
|
|
||||||
element_kinds.has_nodes |= variant_element_kinds.has_nodes;
|
|
||||||
} else {
|
|
||||||
panic!("Enum variant has type that does not exist or was not declared before the enum: {}", *variant);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
element_kinds_map.insert(en.name.to_string(), element_kinds);
|
|
||||||
}
|
|
||||||
|
|
||||||
let tokens = all_token_kinds.iter().map(|kind_str| {
|
let tokens = all_token_kinds.iter().map(|kind_str| {
|
||||||
let kind_str = &**kind_str;
|
let kind_str = &**kind_str;
|
||||||
let kind = format_ident!("{}", kind_str);
|
let kind = format_ident!("{}", kind_str);
|
||||||
|
@ -108,12 +75,7 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstToken for #name {
|
impl AstToken for #name {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool {
|
fn can_cast(kind: SyntaxKind) -> bool { kind == #kind }
|
||||||
match kind {
|
|
||||||
#kind => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
||||||
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
||||||
}
|
}
|
||||||
|
@ -122,6 +84,99 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let enums = grammar.token_enums.iter().map(|en| {
|
||||||
|
let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>();
|
||||||
|
let name = format_ident!("{}", en.name);
|
||||||
|
let kinds = variants
|
||||||
|
.iter()
|
||||||
|
.map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
assert!(en.traits.is_empty());
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum #name {
|
||||||
|
#(#variants(#variants),)*
|
||||||
|
}
|
||||||
|
|
||||||
|
#(
|
||||||
|
impl From<#variants> for #name {
|
||||||
|
fn from(node: #variants) -> #name {
|
||||||
|
#name::#variants(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
impl std::fmt::Display for #name {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AstToken for #name {
|
||||||
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
|
match kind {
|
||||||
|
#(#kinds)|* => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
||||||
|
let res = match syntax.kind() {
|
||||||
|
#(
|
||||||
|
#kinds => #name::#variants(#variants { syntax }),
|
||||||
|
)*
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxToken {
|
||||||
|
match self {
|
||||||
|
#(
|
||||||
|
#name::#variants(it) => &it.syntax,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
crate::reformat(quote! {
|
||||||
|
use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken};
|
||||||
|
|
||||||
|
#(#tokens)*
|
||||||
|
#(#enums)*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
|
let all_token_kinds: Vec<_> = kinds
|
||||||
|
.punct
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, kind)| kind)
|
||||||
|
.copied()
|
||||||
|
.map(|x| x.into())
|
||||||
|
.chain(
|
||||||
|
kinds
|
||||||
|
.keywords
|
||||||
|
.into_iter()
|
||||||
|
.chain(kinds.contextual_keywords.into_iter())
|
||||||
|
.map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))),
|
||||||
|
)
|
||||||
|
.chain(kinds.literals.into_iter().copied().map(|x| x.into()))
|
||||||
|
.chain(kinds.tokens.into_iter().copied().map(|x| x.into()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut token_kinds = HashSet::new();
|
||||||
|
for kind in &all_token_kinds {
|
||||||
|
let kind = &**kind;
|
||||||
|
let name = to_pascal_case(kind);
|
||||||
|
token_kinds.insert(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for en in grammar.token_enums {
|
||||||
|
token_kinds.insert(en.name.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
let nodes = grammar.nodes.iter().map(|node| {
|
let nodes = grammar.nodes.iter().map(|node| {
|
||||||
let name = format_ident!("{}", node.name);
|
let name = format_ident!("{}", node.name);
|
||||||
let kind = format_ident!("{}", to_upper_snake_case(&name.to_string()));
|
let kind = format_ident!("{}", to_upper_snake_case(&name.to_string()));
|
||||||
|
@ -146,14 +201,23 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
FieldSrc::Many(_) => {
|
FieldSrc::Many(_) => {
|
||||||
quote! {
|
quote! {
|
||||||
pub fn #method_name(&self) -> AstChildren<#ty> {
|
pub fn #method_name(&self) -> AstChildren<#ty> {
|
||||||
AstChildren::new(&self.syntax)
|
support::children(&self.syntax)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FieldSrc::Optional(_) | FieldSrc::Shorthand => {
|
FieldSrc::Optional(_) | FieldSrc::Shorthand => {
|
||||||
|
let is_token = token_kinds.contains(&ty.to_string());
|
||||||
|
if is_token {
|
||||||
quote! {
|
quote! {
|
||||||
pub fn #method_name(&self) -> Option<#ty> {
|
pub fn #method_name(&self) -> Option<#ty> {
|
||||||
AstChildren::new(&self.syntax).next()
|
support::token(&self.syntax)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
pub fn #method_name(&self) -> Option<#ty> {
|
||||||
|
support::child(&self.syntax)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,18 +230,9 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for #name {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AstNode for #name {
|
impl AstNode for #name {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool {
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
match kind {
|
kind == #kind
|
||||||
#kind => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
||||||
|
@ -219,12 +274,6 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|
||||||
impl std::fmt::Display for #name {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AstNode for #name {
|
impl AstNode for #name {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool {
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -249,10 +298,26 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#traits)*
|
#(#traits)*
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let displays = grammar
|
||||||
|
.enums
|
||||||
|
.iter()
|
||||||
|
.map(|it| format_ident!("{}", it.name))
|
||||||
|
.chain(grammar.nodes.iter().map(|it| format_ident!("{}", it.name)))
|
||||||
|
.map(|name| {
|
||||||
|
quote! {
|
||||||
|
impl std::fmt::Display for #name {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let defined_nodes: HashSet<_> = grammar.nodes.iter().map(|node| node.name).collect();
|
let defined_nodes: HashSet<_> = grammar.nodes.iter().map(|node| node.name).collect();
|
||||||
|
|
||||||
for node in kinds
|
for node in kinds
|
||||||
|
@ -265,15 +330,16 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let ast = quote! {
|
let ast = quote! {
|
||||||
#[allow(unused_imports)]
|
|
||||||
use crate::{
|
use crate::{
|
||||||
SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *},
|
SyntaxNode, SyntaxKind::{self, *},
|
||||||
ast::{self, AstNode, AstToken, AstChildren},
|
ast::{self, AstNode, AstChildren, support},
|
||||||
};
|
};
|
||||||
|
|
||||||
#(#tokens)*
|
use super::tokens::*;
|
||||||
|
|
||||||
#(#nodes)*
|
#(#nodes)*
|
||||||
#(#enums)*
|
#(#enums)*
|
||||||
|
#(#displays)*
|
||||||
};
|
};
|
||||||
|
|
||||||
let pretty = crate::reformat(ast)?;
|
let pretty = crate::reformat(ast)?;
|
||||||
|
|
|
@ -67,6 +67,7 @@ fn reformat(text: impl std::fmt::Display) -> Result<String> {
|
||||||
let mut rustfmt = Command::new("rustup")
|
let mut rustfmt = Command::new("rustup")
|
||||||
.args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"])
|
.args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"])
|
||||||
.arg(project_root().join("rustfmt.toml"))
|
.arg(project_root().join("rustfmt.toml"))
|
||||||
|
.args(&["--config", "fn_single_line=true"])
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
|
|
Loading…
Reference in a new issue