Finalize attribute grammar
This commit is contained in:
parent
e28ea81b2b
commit
fcce07d2d1
@ -29,8 +29,8 @@
|
|||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
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()
|
||||||
|
@ -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 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,20 +13,18 @@
|
|||||||
|
|
||||||
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(())
|
||||||
|
@ -24,7 +24,8 @@ pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T
|
|||||||
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)]
|
||||||
@ -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),
|
||||||
@ -3342,34 +3338,6 @@ fn syntax(&self) -> &SyntaxNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 @@ 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 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)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
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> {
|
||||||
|
@ -182,10 +182,7 @@ Visibility =
|
|||||||
')')?
|
')')?
|
||||||
|
|
||||||
Attr =
|
Attr =
|
||||||
'#' '!'? '[' Path ('=' input:AttrInput)? ']'
|
'#' '!'? '[' Path ('=' Literal | TokenTree)? ']'
|
||||||
|
|
||||||
AttrInput =
|
|
||||||
Literal | TokenTree
|
|
||||||
|
|
||||||
ParenType =
|
ParenType =
|
||||||
'(' TypeRef ')'
|
'(' TypeRef ')'
|
||||||
|
Loading…
Reference in New Issue
Block a user