migrate ra_syntax to the new rowan API

This commit is contained in:
Aleksey Kladov
2019-07-18 19:23:05 +03:00
parent 58d4983ba5
commit d402974aa0
20 changed files with 1189 additions and 2352 deletions

View File

@@ -8,20 +8,20 @@ use crate::{
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ElseBranch<'a> {
Block(&'a ast::Block),
IfExpr(&'a ast::IfExpr),
pub enum ElseBranch {
Block(ast::Block),
IfExpr(ast::IfExpr),
}
impl ast::IfExpr {
pub fn then_branch(&self) -> Option<&ast::Block> {
pub fn then_branch(&self) -> Option<ast::Block> {
self.blocks().nth(0)
}
pub fn else_branch(&self) -> Option<ElseBranch> {
let res = match self.blocks().nth(1) {
Some(block) => ElseBranch::Block(block),
None => {
let elif: &ast::IfExpr = child_opt(self)?;
let elif: ast::IfExpr = child_opt(self)?;
ElseBranch::IfExpr(elif)
}
};
@@ -60,7 +60,7 @@ impl ast::PrefixExpr {
}
pub fn op_token(&self) -> Option<SyntaxToken> {
self.syntax().first_child_or_token()?.as_token()
self.syntax().first_child_or_token()?.as_token().cloned()
}
}
@@ -132,7 +132,7 @@ pub enum BinOp {
impl ast::BinExpr {
fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
self.syntax().children_with_tokens().filter_map(|it| it.as_token()).find_map(|c| {
self.syntax().children_with_tokens().filter_map(|it| it.as_token().cloned()).find_map(|c| {
match c.kind() {
T![||] => Some((c, BinOp::BooleanOr)),
T![&&] => Some((c, BinOp::BooleanAnd)),
@@ -178,15 +178,15 @@ impl ast::BinExpr {
self.op_details().map(|t| t.0)
}
pub fn lhs(&self) -> Option<&ast::Expr> {
pub fn lhs(&self) -> Option<ast::Expr> {
children(self).nth(0)
}
pub fn rhs(&self) -> Option<&ast::Expr> {
pub fn rhs(&self) -> Option<ast::Expr> {
children(self).nth(1)
}
pub fn sub_exprs(&self) -> (Option<&ast::Expr>, Option<&ast::Expr>) {
pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) {
let mut children = children(self);
let first = children.next();
let second = children.next();
@@ -194,9 +194,9 @@ impl ast::BinExpr {
}
}
pub enum ArrayExprKind<'a> {
Repeat { initializer: Option<&'a ast::Expr>, repeat: Option<&'a ast::Expr> },
ElementList(AstChildren<'a, ast::Expr>),
pub enum ArrayExprKind {
Repeat { initializer: Option<ast::Expr>, repeat: Option<ast::Expr> },
ElementList(AstChildren<ast::Expr>),
}
impl ast::ArrayExpr {
@@ -275,12 +275,12 @@ impl ast::Literal {
#[test]
fn test_literal_with_attr() {
let parse = ast::SourceFile::parse(r#"const _: &str = { #[attr] "Hello" };"#);
let lit = parse.tree.syntax().descendants().find_map(ast::Literal::cast).unwrap();
let lit = parse.tree().syntax().descendants().find_map(ast::Literal::cast).unwrap();
assert_eq!(lit.token().text(), r#""Hello""#);
}
impl ast::NamedField {
pub fn parent_struct_lit(&self) -> &ast::StructLit {
pub fn parent_struct_lit(&self) -> ast::StructLit {
self.syntax().ancestors().find_map(ast::StructLit::cast).unwrap()
}
}

View File

@@ -4,7 +4,7 @@
use itertools::Itertools;
use crate::{
ast::{self, child_opt, children, AstNode},
ast::{self, child_opt, children, AstNode, SyntaxNode},
SmolStr, SyntaxElement,
SyntaxKind::*,
SyntaxToken, T,
@@ -13,15 +13,20 @@ use ra_parser::SyntaxKind;
impl ast::Name {
pub fn text(&self) -> &SmolStr {
let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap();
ident.text()
text_of_first_token(self.syntax())
}
}
impl ast::NameRef {
pub fn text(&self) -> &SmolStr {
let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap();
ident.text()
text_of_first_token(self.syntax())
}
}
fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {
match node.0.green().children().first() {
Some(rowan::GreenElement::Token(it)) => it.text(),
_ => panic!(),
}
}
@@ -50,10 +55,10 @@ impl ast::Attr {
}
}
pub fn as_call(&self) -> Option<(SmolStr, &ast::TokenTree)> {
pub fn as_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
let tt = self.value()?;
let (_bra, attr, args, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
let args = ast::TokenTree::cast(args.as_node()?)?;
let args = ast::TokenTree::cast(args.as_node()?.clone())?;
if attr.kind() == IDENT {
Some((attr.as_token()?.text().clone(), args))
} else {
@@ -86,16 +91,16 @@ impl ast::Attr {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PathSegmentKind<'a> {
Name(&'a ast::NameRef),
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PathSegmentKind {
Name(ast::NameRef),
SelfKw,
SuperKw,
CrateKw,
}
impl ast::PathSegment {
pub fn parent_path(&self) -> &ast::Path {
pub fn parent_path(&self) -> ast::Path {
self.syntax()
.parent()
.and_then(ast::Path::cast)
@@ -125,7 +130,7 @@ impl ast::PathSegment {
}
impl ast::Path {
pub fn parent_path(&self) -> Option<&ast::Path> {
pub fn parent_path(&self) -> Option<ast::Path> {
self.syntax().parent().and_then(ast::Path::cast)
}
}
@@ -146,7 +151,7 @@ impl ast::UseTree {
}
impl ast::UseTreeList {
pub fn parent_use_tree(&self) -> &ast::UseTree {
pub fn parent_use_tree(&self) -> ast::UseTree {
self.syntax()
.parent()
.and_then(ast::UseTree::cast)
@@ -155,21 +160,21 @@ impl ast::UseTreeList {
}
impl ast::ImplBlock {
pub fn target_type(&self) -> Option<&ast::TypeRef> {
pub fn target_type(&self) -> Option<ast::TypeRef> {
match self.target() {
(Some(t), None) | (_, Some(t)) => Some(t),
_ => None,
}
}
pub fn target_trait(&self) -> Option<&ast::TypeRef> {
pub fn target_trait(&self) -> Option<ast::TypeRef> {
match self.target() {
(Some(t), Some(_)) => Some(t),
_ => None,
}
}
fn target(&self) -> (Option<&ast::TypeRef>, Option<&ast::TypeRef>) {
fn target(&self) -> (Option<ast::TypeRef>, Option<ast::TypeRef>) {
let mut types = children(self);
let first = types.next();
let second = types.next();
@@ -182,13 +187,13 @@ impl ast::ImplBlock {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StructKind<'a> {
Tuple(&'a ast::PosFieldDefList),
Named(&'a ast::NamedFieldDefList),
pub enum StructKind {
Tuple(ast::PosFieldDefList),
Named(ast::NamedFieldDefList),
Unit,
}
impl StructKind<'_> {
impl StructKind {
fn from_node<N: AstNode>(node: &N) -> StructKind {
if let Some(nfdl) = child_opt::<_, ast::NamedFieldDefList>(node) {
StructKind::Named(nfdl)
@@ -218,7 +223,7 @@ impl ast::StructDef {
}
impl ast::EnumVariant {
pub fn parent_enum(&self) -> &ast::EnumDef {
pub fn parent_enum(&self) -> ast::EnumDef {
self.syntax()
.parent()
.and_then(|it| it.parent())
@@ -231,10 +236,10 @@ impl ast::EnumVariant {
}
impl ast::FnDef {
pub fn semicolon_token(&self) -> Option<SyntaxToken<'_>> {
pub fn semicolon_token(&self) -> Option<SyntaxToken> {
self.syntax()
.last_child_or_token()
.and_then(|it| it.as_token())
.and_then(|it| it.as_token().cloned())
.filter(|it| it.kind() == T![;])
}
}
@@ -258,9 +263,9 @@ impl ast::ExprStmt {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FieldKind<'a> {
Name(&'a ast::NameRef),
Index(SyntaxToken<'a>),
pub enum FieldKind {
Name(ast::NameRef),
Index(SyntaxToken),
}
impl ast::FieldExpr {
@@ -271,6 +276,7 @@ impl ast::FieldExpr {
.find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
.as_ref()
.and_then(SyntaxElement::as_token)
.cloned()
}
pub fn field_access(&self) -> Option<FieldKind> {
@@ -326,7 +332,7 @@ impl ast::SelfParam {
pub fn self_kw_token(&self) -> SyntaxToken {
self.syntax()
.children_with_tokens()
.filter_map(|it| it.as_token())
.filter_map(|it| it.as_token().cloned())
.find(|it| it.kind() == T![self])
.expect("invalid tree: self param must have self")
}
@@ -355,7 +361,7 @@ impl ast::LifetimeParam {
pub fn lifetime_token(&self) -> Option<SyntaxToken> {
self.syntax()
.children_with_tokens()
.filter_map(|it| it.as_token())
.filter_map(|it| it.as_token().cloned())
.find(|it| it.kind() == LIFETIME)
}
}
@@ -364,7 +370,7 @@ impl ast::WherePred {
pub fn lifetime_token(&self) -> Option<SyntaxToken> {
self.syntax()
.children_with_tokens()
.filter_map(|it| it.as_token())
.filter_map(|it| it.as_token().cloned())
.find(|it| it.kind() == LIFETIME)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -11,94 +11,73 @@ the below applies to the result of this template
#![cfg_attr(rustfmt, rustfmt_skip)]
use rowan::TransparentNewType;
use crate::{
SyntaxNode, SyntaxKind::*,
syntax_node::{TreeArc},
ast::{self, AstNode},
};
{% for node, methods in ast %}
// {{ node }}
{%- if methods.enum %}
#[derive(Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct {{ node }} {
pub(crate) syntax: SyntaxNode,
}
unsafe impl TransparentNewType for {{ node }} {
type Repr = rowan::SyntaxNode;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum {{ node }}Kind<'a> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum {{ node }}Kind {
{%- for kind in methods.enum %}
{{ kind }}(&'a {{ kind }}),
{{ kind }}({{ kind }}),
{%- endfor %}
}
{%- for kind in methods.enum %}
impl<'a> From<&'a {{ kind }}> for &'a {{ node }} {
fn from(n: &'a {{ kind }}) -> &'a {{ node }} {
{{ node }}::cast(&n.syntax).unwrap()
impl From<{{ kind }}> for {{ node }} {
fn from(n: {{ kind }}) -> {{ node }} {
{{ node }}::cast(n.syntax).unwrap()
}
}
{%- endfor %}
impl AstNode for {{ node }} {
fn cast(syntax: &SyntaxNode) -> Option<&Self> {
fn cast(syntax: SyntaxNode) -> Option<Self> {
match syntax.kind() {
{%- for kind in methods.enum %}
| {{ kind | SCREAM }}
{%- endfor %} => Some({{ node }}::from_repr(syntax.into_repr())),
{%- endfor %} => Some({{ node }} { syntax }),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl ToOwned for {{ node }} {
type Owned = TreeArc<{{ node }}>;
fn to_owned(&self) -> TreeArc<{{ node }}> { TreeArc::cast(self.syntax.to_owned()) }
}
impl {{ node }} {
pub fn kind(&self) -> {{ node }}Kind {
match self.syntax.kind() {
{%- for kind in methods.enum %}
{{ kind | SCREAM }} => {{ node }}Kind::{{ kind }}({{ kind }}::cast(&self.syntax).unwrap()),
{{ kind | SCREAM }} => {{ node }}Kind::{{ kind }}({{ kind }}::cast(self.syntax.clone()).unwrap()),
{%- endfor %}
_ => unreachable!(),
}
}
}
{% else %}
#[derive(Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct {{ node }} {
pub(crate) syntax: SyntaxNode,
}
unsafe impl TransparentNewType for {{ node }} {
type Repr = rowan::SyntaxNode;
}
impl AstNode for {{ node }} {
fn cast(syntax: &SyntaxNode) -> Option<&Self> {
fn cast(syntax: SyntaxNode) -> Option<Self> {
match syntax.kind() {
{{ node | SCREAM }} => Some({{ node }}::from_repr(syntax.into_repr())),
{{ node | SCREAM }} => Some({{ node }} { syntax }),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl ToOwned for {{ node }} {
type Owned = TreeArc<{{ node }}>;
fn to_owned(&self) -> TreeArc<{{ node }}> { TreeArc::cast(self.syntax.to_owned()) }
}
{% endif %}
{% if methods.traits -%}
@@ -113,7 +92,7 @@ impl {{ node }} {
{%- for m in methods.collections -%}
{%- set method_name = m.0 -%}
{%- set ChildName = m.1 %}
pub fn {{ method_name }}(&self) -> impl Iterator<Item = &{{ ChildName }}> {
pub fn {{ method_name }}(&self) -> impl Iterator<Item = {{ ChildName }}> {
super::children(self)
}
{% endfor -%}
@@ -129,7 +108,7 @@ impl {{ node }} {
{%- set method_name = m.0 -%}
{%- set ChildName = m.1 %}
{%- endif %}
pub fn {{ method_name }}(&self) -> Option<&{{ ChildName }}> {
pub fn {{ method_name }}(&self) -> Option<{{ ChildName }}> {
super::child_opt(self)
}
{% endfor -%}

View File

@@ -6,23 +6,23 @@ use crate::{
SyntaxToken,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Comment<'a>(SyntaxToken<'a>);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Comment(SyntaxToken);
impl<'a> AstToken<'a> for Comment<'a> {
fn cast(token: SyntaxToken<'a>) -> Option<Self> {
impl AstToken for Comment {
fn cast(token: SyntaxToken) -> Option<Self> {
if token.kind() == COMMENT {
Some(Comment(token))
} else {
None
}
}
fn syntax(&self) -> SyntaxToken<'a> {
self.0
fn syntax(&self) -> &SyntaxToken {
&self.0
}
}
impl<'a> Comment<'a> {
impl Comment {
pub fn kind(&self) -> CommentKind {
kind_by_prefix(self.text())
}
@@ -90,22 +90,22 @@ fn prefix_by_kind(kind: CommentKind) -> &'static str {
unreachable!()
}
pub struct Whitespace<'a>(SyntaxToken<'a>);
pub struct Whitespace(SyntaxToken);
impl<'a> AstToken<'a> for Whitespace<'a> {
fn cast(token: SyntaxToken<'a>) -> Option<Self> {
impl AstToken for Whitespace {
fn cast(token: SyntaxToken) -> Option<Self> {
if token.kind() == WHITESPACE {
Some(Whitespace(token))
} else {
None
}
}
fn syntax(&self) -> SyntaxToken<'a> {
self.0
fn syntax(&self) -> &SyntaxToken {
&self.0
}
}
impl<'a> Whitespace<'a> {
impl Whitespace {
pub fn spans_multiple_lines(&self) -> bool {
let text = self.text();
text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n'))

View File

@@ -10,37 +10,37 @@ use crate::{
};
pub trait TypeAscriptionOwner: AstNode {
fn ascribed_type(&self) -> Option<&ast::TypeRef> {
fn ascribed_type(&self) -> Option<ast::TypeRef> {
child_opt(self)
}
}
pub trait NameOwner: AstNode {
fn name(&self) -> Option<&ast::Name> {
fn name(&self) -> Option<ast::Name> {
child_opt(self)
}
}
pub trait VisibilityOwner: AstNode {
fn visibility(&self) -> Option<&ast::Visibility> {
fn visibility(&self) -> Option<ast::Visibility> {
child_opt(self)
}
}
pub trait LoopBodyOwner: AstNode {
fn loop_body(&self) -> Option<&ast::Block> {
fn loop_body(&self) -> Option<ast::Block> {
child_opt(self)
}
}
pub trait TryBlockBodyOwner: AstNode {
fn try_body(&self) -> Option<&ast::Block> {
fn try_body(&self) -> Option<ast::Block> {
child_opt(self)
}
}
pub trait ArgListOwner: AstNode {
fn arg_list(&self) -> Option<&ast::ArgList> {
fn arg_list(&self) -> Option<ast::ArgList> {
child_opt(self)
}
}
@@ -51,10 +51,10 @@ pub trait FnDefOwner: AstNode {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ItemOrMacro<'a> {
Item(&'a ast::ModuleItem),
Macro(&'a ast::MacroCall),
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ItemOrMacro {
Item(ast::ModuleItem),
Macro(ast::MacroCall),
}
pub trait ModuleItemOwner: AstNode {
@@ -67,14 +67,14 @@ pub trait ModuleItemOwner: AstNode {
}
#[derive(Debug)]
pub struct ItemOrMacroIter<'a>(SyntaxNodeChildren<'a>);
pub struct ItemOrMacroIter(SyntaxNodeChildren);
impl<'a> Iterator for ItemOrMacroIter<'a> {
type Item = ItemOrMacro<'a>;
fn next(&mut self) -> Option<ItemOrMacro<'a>> {
impl Iterator for ItemOrMacroIter {
type Item = ItemOrMacro;
fn next(&mut self) -> Option<ItemOrMacro> {
loop {
let n = self.0.next()?;
if let Some(item) = ast::ModuleItem::cast(n) {
if let Some(item) = ast::ModuleItem::cast(n.clone()) {
return Some(ItemOrMacro::Item(item));
}
if let Some(call) = ast::MacroCall::cast(n) {
@@ -85,17 +85,17 @@ impl<'a> Iterator for ItemOrMacroIter<'a> {
}
pub trait TypeParamsOwner: AstNode {
fn type_param_list(&self) -> Option<&ast::TypeParamList> {
fn type_param_list(&self) -> Option<ast::TypeParamList> {
child_opt(self)
}
fn where_clause(&self) -> Option<&ast::WhereClause> {
fn where_clause(&self) -> Option<ast::WhereClause> {
child_opt(self)
}
}
pub trait TypeBoundsOwner: AstNode {
fn type_bound_list(&self) -> Option<&ast::TypeBoundList> {
fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
child_opt(self)
}
}
@@ -148,19 +148,19 @@ pub trait DocCommentsOwner: AstNode {
}
}
pub struct CommentIter<'a> {
iter: SyntaxElementChildren<'a>,
pub struct CommentIter {
iter: SyntaxElementChildren,
}
impl<'a> Iterator for CommentIter<'a> {
type Item = ast::Comment<'a>;
fn next(&mut self) -> Option<ast::Comment<'a>> {
self.iter.by_ref().find_map(|el| el.as_token().and_then(ast::Comment::cast))
impl Iterator for CommentIter {
type Item = ast::Comment;
fn next(&mut self) -> Option<ast::Comment> {
self.iter.by_ref().find_map(|el| el.as_token().cloned().and_then(ast::Comment::cast))
}
}
pub trait DefaultTypeParamOwner: AstNode {
fn default_type(&self) -> Option<&ast::PathType> {
fn default_type(&self) -> Option<ast::PathType> {
child_opt(self)
}
}