5611: Finalize attribute grammar r=matklad a=matklad



bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-07-30 18:39:09 +00:00 committed by GitHub
commit 6f5b53013c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 48 additions and 100 deletions

View file

@ -29,8 +29,8 @@ use crate::{
// } // }
// ``` // ```
pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let input = ctx.find_node_at_offset::<ast::AttrInput>()?; let attr = ctx.find_node_at_offset::<ast::Attr>()?;
let attr = input.syntax().parent().and_then(ast::Attr::cast)?; let input = attr.token_tree()?;
let attr_name = attr let attr_name = attr
.syntax() .syntax()

View file

@ -151,18 +151,15 @@ pub enum AttrInput {
impl Attr { impl Attr {
fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
let path = ModPath::from_src(ast.path()?, hygiene)?; let path = ModPath::from_src(ast.path()?, hygiene)?;
let input = match ast.input() { let input = if let Some(lit) = ast.literal() {
None => None, // FIXME: escape? raw string?
Some(ast::AttrInput::Literal(lit)) => { let value = lit.syntax().first_token()?.text().trim_matches('"').into();
// FIXME: escape? raw string? Some(AttrInput::Literal(value))
let value = lit.syntax().first_token()?.text().trim_matches('"').into(); } else if let Some(tt) = ast.token_tree() {
Some(AttrInput::Literal(value)) Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0))
} } else {
Some(ast::AttrInput::TokenTree(tt)) => { None
Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0))
}
}; };
Some(Attr { path, input }) Some(Attr { path, input })
} }
} }

View file

@ -13,20 +13,18 @@ use crate::completion::{
pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
let attribute = ctx.attribute_under_caret.as_ref()?; let attribute = ctx.attribute_under_caret.as_ref()?;
match (attribute.path(), attribute.input()) { match (attribute.path(), attribute.token_tree()) {
(Some(path), Some(ast::AttrInput::TokenTree(token_tree))) (Some(path), Some(token_tree)) if path.to_string() == "derive" => {
if path.to_string() == "derive" =>
{
complete_derive(acc, ctx, token_tree) complete_derive(acc, ctx, token_tree)
} }
(Some(path), Some(ast::AttrInput::TokenTree(token_tree))) (Some(path), Some(token_tree))
if ["allow", "warn", "deny", "forbid"] if ["allow", "warn", "deny", "forbid"]
.iter() .iter()
.any(|lint_level| lint_level == &path.to_string()) => .any(|lint_level| lint_level == &path.to_string()) =>
{ {
complete_lint(acc, ctx, token_tree) complete_lint(acc, ctx, token_tree)
} }
(_, Some(ast::AttrInput::TokenTree(_token_tree))) => {} (_, Some(_token_tree)) => {}
_ => complete_attribute_start(acc, ctx, attribute), _ => complete_attribute_start(acc, ctx, attribute),
} }
Some(()) Some(())

View file

@ -24,7 +24,8 @@ impl Attr {
pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
pub fn input(&self) -> Option<AttrInput> { support::child(&self.syntax) } pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -321,9 +322,9 @@ pub struct ParamList {
} }
impl ParamList { impl ParamList {
pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) } pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) }
pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) } pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -356,17 +357,6 @@ impl BlockExpr {
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Param {
pub(crate) syntax: SyntaxNode,
}
impl ast::AttrsOwner for Param {}
impl ast::TypeAscriptionOwner for Param {}
impl Param {
pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SelfParam { pub struct SelfParam {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
@ -382,6 +372,17 @@ impl SelfParam {
pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Param {
pub(crate) syntax: SyntaxNode,
}
impl ast::AttrsOwner for Param {}
impl ast::TypeAscriptionOwner for Param {}
impl Param {
pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypeBoundList { pub struct TypeBoundList {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
@ -1378,11 +1379,6 @@ pub enum GenericParam {
} }
impl ast::AttrsOwner for GenericParam {} impl ast::AttrsOwner for GenericParam {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum AttrInput {
Literal(Literal),
TokenTree(TokenTree),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Stmt { pub enum Stmt {
LetStmt(LetStmt), LetStmt(LetStmt),
ExprStmt(ExprStmt), ExprStmt(ExprStmt),
@ -1728,8 +1724,8 @@ impl AstNode for BlockExpr {
} }
fn syntax(&self) -> &SyntaxNode { &self.syntax } fn syntax(&self) -> &SyntaxNode { &self.syntax }
} }
impl AstNode for Param { impl AstNode for SelfParam {
fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM } fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM }
fn cast(syntax: SyntaxNode) -> Option<Self> { fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) { if Self::can_cast(syntax.kind()) {
Some(Self { syntax }) Some(Self { syntax })
@ -1739,8 +1735,8 @@ impl AstNode for Param {
} }
fn syntax(&self) -> &SyntaxNode { &self.syntax } fn syntax(&self) -> &SyntaxNode { &self.syntax }
} }
impl AstNode for SelfParam { impl AstNode for Param {
fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM } fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM }
fn cast(syntax: SyntaxNode) -> Option<Self> { fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) { if Self::can_cast(syntax.kind()) {
Some(Self { syntax }) Some(Self { syntax })
@ -3342,34 +3338,6 @@ impl AstNode for GenericParam {
} }
} }
} }
impl From<Literal> for AttrInput {
fn from(node: Literal) -> AttrInput { AttrInput::Literal(node) }
}
impl From<TokenTree> for AttrInput {
fn from(node: TokenTree) -> AttrInput { AttrInput::TokenTree(node) }
}
impl AstNode for AttrInput {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
LITERAL | TOKEN_TREE => true,
_ => false,
}
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
let res = match syntax.kind() {
LITERAL => AttrInput::Literal(Literal { syntax }),
TOKEN_TREE => AttrInput::TokenTree(TokenTree { syntax }),
_ => return None,
};
Some(res)
}
fn syntax(&self) -> &SyntaxNode {
match self {
AttrInput::Literal(it) => &it.syntax,
AttrInput::TokenTree(it) => &it.syntax,
}
}
}
impl From<LetStmt> for Stmt { impl From<LetStmt> for Stmt {
fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) } fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) }
} }
@ -3471,11 +3439,6 @@ impl std::fmt::Display for GenericParam {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for AttrInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for Stmt { impl std::fmt::Display for Stmt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
@ -3636,12 +3599,12 @@ impl std::fmt::Display for BlockExpr {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for Param { impl std::fmt::Display for SelfParam {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for SelfParam { impl std::fmt::Display for Param {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }

View file

@ -7,7 +7,7 @@ use itertools::Itertools;
use ra_parser::SyntaxKind; use ra_parser::SyntaxKind;
use crate::{ use crate::{
ast::{self, support, AstNode, AttrInput, NameOwner, SyntaxNode}, ast::{self, support, AstNode, NameOwner, SyntaxNode},
SmolStr, SyntaxElement, SyntaxToken, T, SmolStr, SyntaxElement, SyntaxToken, T,
}; };
@ -39,29 +39,23 @@ pub enum AttrKind {
impl ast::Attr { impl ast::Attr {
pub fn as_simple_atom(&self) -> Option<SmolStr> { pub fn as_simple_atom(&self) -> Option<SmolStr> {
match self.input() { if self.eq_token().is_some() || self.token_tree().is_some() {
None => self.simple_name(), return None;
Some(_) => None,
} }
self.simple_name()
} }
pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> { pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
match self.input() { let tt = self.token_tree()?;
Some(AttrInput::TokenTree(tt)) => Some((self.simple_name()?, tt)), Some((self.simple_name()?, tt))
_ => None,
}
} }
pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> { pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> {
match self.input() { let lit = self.literal()?;
Some(AttrInput::Literal(lit)) => { let key = self.simple_name()?;
let key = self.simple_name()?; // FIXME: escape? raw string?
// FIXME: escape? raw string? let value = lit.syntax().first_token()?.text().trim_matches('"').into();
let value = lit.syntax().first_token()?.text().trim_matches('"').into(); Some((key, value))
Some((key, value))
}
_ => None,
}
} }
pub fn simple_name(&self) -> Option<SmolStr> { pub fn simple_name(&self) -> Option<SmolStr> {

View file

@ -54,9 +54,8 @@ Abi =
ParamList = ParamList =
'('( '('(
(Param (',' Param)* ','?)? SelfParam
| SelfParam ','? | (SelfParam ',')? (Param (',' Param)* ','?)?
| SelfParam ',' (Param (',' Param)* ','?)
)')' )')'
SelfParam = SelfParam =
@ -182,10 +181,7 @@ Visibility =
')')? ')')?
Attr = Attr =
'#' '!'? '[' Path ('=' input:AttrInput)? ']' '#' '!'? '[' Path ('=' Literal | TokenTree)? ']'
AttrInput =
Literal | TokenTree
ParenType = ParenType =
'(' TypeRef ')' '(' TypeRef ')'