From 23fde40feddaca9359414dc90cc446d8adabe0dd Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Sun, 12 Nov 2023 11:20:14 +0800 Subject: [PATCH 1/2] fix `PathSegment` grammar --- crates/syntax/rust.ungram | 2 +- crates/syntax/src/ast/generated/nodes.rs | 93 ++++++++++++------------ crates/syntax/src/ast/node_ext.rs | 12 +++ 3 files changed, 60 insertions(+), 47 deletions(-) diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 3603560d35c3..c3010d090c6b 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -36,7 +36,7 @@ PathSegment = '::'? NameRef | NameRef GenericArgList? | NameRef ParamList RetType? -| '<' PathType ('as' PathType)? '>' +| '<' Type ('as' PathType)? '>' GenericArgList = '::'? '<' (GenericArg (',' GenericArg)* ','?)? '>' diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 7ba0d4dc656f..6c86e591044a 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -59,8 +59,9 @@ impl PathSegment { pub fn param_list(&self) -> Option { support::child(&self.syntax) } pub fn ret_type(&self) -> Option { support::child(&self.syntax) } pub fn l_angle_token(&self) -> Option { support::token(&self.syntax, T![<]) } - pub fn path_type(&self) -> Option { support::child(&self.syntax) } + pub fn ty(&self) -> Option { support::child(&self.syntax) } pub fn as_token(&self) -> Option { support::token(&self.syntax, T![as]) } + pub fn path_type(&self) -> Option { support::child(&self.syntax) } pub fn r_angle_token(&self) -> Option { support::token(&self.syntax, T![>]) } } @@ -1576,14 +1577,6 @@ impl RecordPatField { pub fn pat(&self) -> Option { support::child(&self.syntax) } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum GenericArg { - TypeArg(TypeArg), - AssocTypeArg(AssocTypeArg), - LifetimeArg(LifetimeArg), - ConstArg(ConstArg), -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Type { ArrayType(ArrayType), @@ -1602,6 +1595,14 @@ pub enum Type { TupleType(TupleType), } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum GenericArg { + TypeArg(TypeArg), + AssocTypeArg(AssocTypeArg), + LifetimeArg(LifetimeArg), + ConstArg(ConstArg), +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Expr { ArrayExpr(ArrayExpr), @@ -3319,41 +3320,6 @@ impl AstNode for RecordPatField { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } -impl From for GenericArg { - fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) } -} -impl From for GenericArg { - fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) } -} -impl From for GenericArg { - fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) } -} -impl From for GenericArg { - fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) } -} -impl AstNode for GenericArg { - fn can_cast(kind: SyntaxKind) -> bool { - matches!(kind, TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG) - } - fn cast(syntax: SyntaxNode) -> Option { - let res = match syntax.kind() { - TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }), - ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }), - LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }), - CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }), - _ => return None, - }; - Some(res) - } - fn syntax(&self) -> &SyntaxNode { - match self { - GenericArg::TypeArg(it) => &it.syntax, - GenericArg::AssocTypeArg(it) => &it.syntax, - GenericArg::LifetimeArg(it) => &it.syntax, - GenericArg::ConstArg(it) => &it.syntax, - } - } -} impl From for Type { fn from(node: ArrayType) -> Type { Type::ArrayType(node) } } @@ -3455,6 +3421,41 @@ impl AstNode for Type { } } } +impl From for GenericArg { + fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) } +} +impl From for GenericArg { + fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) } +} +impl From for GenericArg { + fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) } +} +impl From for GenericArg { + fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) } +} +impl AstNode for GenericArg { + fn can_cast(kind: SyntaxKind) -> bool { + matches!(kind, TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG) + } + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }), + ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }), + LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }), + CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + GenericArg::TypeArg(it) => &it.syntax, + GenericArg::AssocTypeArg(it) => &it.syntax, + GenericArg::LifetimeArg(it) => &it.syntax, + GenericArg::ConstArg(it) => &it.syntax, + } + } +} impl From for Expr { fn from(node: ArrayExpr) -> Expr { Expr::ArrayExpr(node) } } @@ -4340,12 +4341,12 @@ impl AstNode for AnyHasVisibility { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } -impl std::fmt::Display for GenericArg { +impl std::fmt::Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for Type { +impl std::fmt::Display for GenericArg { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 691d0c618f38..457c3c1996fe 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -361,6 +361,18 @@ impl ast::Impl { } } +// for `PathSegment` '', call `first_path_type` will get `i32` and `last_path_type` will get `core::ops::Add` +// for '<&i32 as core::ops::Add>', call `first_path_type` and `last_path_type` will both get `core::ops::Add` cause `&i32` is `Type(RefType)` +impl ast::PathSegment { + pub fn first_path_type(&self) -> Option { + self.syntax().children().find_map(ast::PathType::cast) + } + + pub fn last_path_type(&self) -> Option { + self.syntax().children().filter_map(ast::PathType::cast).last() + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum StructKind { Record(ast::RecordFieldList), From 3e5bc9a9c8bfd01e827e7f4062356e484e33387a Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Mon, 13 Nov 2023 18:14:00 +0800 Subject: [PATCH 2/2] impl `qualifying_trait` for `PathSegment` --- crates/syntax/src/ast/node_ext.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 457c3c1996fe..be5b954ad345 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -361,15 +361,12 @@ impl ast::Impl { } } -// for `PathSegment` '', call `first_path_type` will get `i32` and `last_path_type` will get `core::ops::Add` -// for '<&i32 as core::ops::Add>', call `first_path_type` and `last_path_type` will both get `core::ops::Add` cause `&i32` is `Type(RefType)` +// [#15778](https://github.com/rust-lang/rust-analyzer/issues/15778) impl ast::PathSegment { - pub fn first_path_type(&self) -> Option { - self.syntax().children().find_map(ast::PathType::cast) - } - - pub fn last_path_type(&self) -> Option { - self.syntax().children().filter_map(ast::PathType::cast).last() + pub fn qualifying_trait(&self) -> Option { + let mut path_types = support::children(self.syntax()); + let first = path_types.next()?; + path_types.next().or(Some(first)) } }