Parse extended_key_value_attributes

This commit is contained in:
Lukas Wirth 2021-03-18 22:25:10 +01:00
parent 816bc73895
commit 4771a56791
7 changed files with 32 additions and 41 deletions

4
Cargo.lock generated
View file

@ -1809,9 +1809,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]] [[package]]
name = "ungrammar" name = "ungrammar"
version = "1.12.2" version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df6586a7c530704efe803d49a0b4132dcbdb4063163df39110548e6b5f2373ba" checksum = "76760314176cc2b94047af2f921b92c39f11a34dc05c43a3c2b0fc91cb22959f"
[[package]] [[package]]
name = "unicase" name = "unicase"

View file

@ -414,7 +414,7 @@ pub enum AttrInput {
impl Attr { impl Attr {
fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> {
let path = ModPath::from_src(ast.path()?, hygiene)?; let path = ModPath::from_src(ast.path()?, hygiene)?;
let input = if let Some(lit) = ast.literal() { let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
let value = match lit.kind() { let value = match lit.kind() {
ast::LiteralKind::String(string) => string.value()?.into(), ast::LiteralKind::String(string) => string.value()?.into(),
_ => lit.syntax().first_token()?.text().trim_matches('"').into(), _ => lit.syntax().first_token()?.text().trim_matches('"').into(),

View file

@ -277,9 +277,9 @@ pub(super) fn doc_comment(hl: &mut Highlights, sema: &Semantics<RootDatabase>, n
} }
fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::String> { fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::String> {
match it.literal() { match it.expr() {
// #[doc = lit] // #[doc = lit]
Some(lit) => match lit.kind() { Some(ast::Expr::Literal(lit)) => match lit.kind() {
ast::LiteralKind::String(it) => Some(it), ast::LiteralKind::String(it) => Some(it),
_ => None, _ => None,
}, },
@ -297,6 +297,7 @@ fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::Stri
string.text().get(1..string.text().len() - 1).map_or(false, |it| it == text) string.text().get(1..string.text().len() - 1).map_or(false, |it| it == text)
}) })
} }
_ => return None,
} }
} }

View file

@ -30,8 +30,8 @@ fn attr(p: &mut Parser, inner: bool) {
match p.current() { match p.current() {
T![=] => { T![=] => {
p.bump(T![=]); p.bump(T![=]);
if expressions::literal(p).is_none() { if expressions::expr(p).0.is_none() {
p.error("expected literal"); p.error("expected expression");
} }
} }
T!['('] | T!['['] | T!['{'] => items::token_tree(p), T!['('] | T!['['] | T!['{'] => items::token_tree(p),

View file

@ -152,7 +152,7 @@ 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 literal(&self) -> Option<Literal> { support::child(&self.syntax) } pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
pub fn token_tree(&self) -> Option<TokenTree> { 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![']']) }
} }
@ -632,12 +632,6 @@ impl WherePred {
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) } pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Literal {
pub(crate) syntax: SyntaxNode,
}
impl ast::AttrsOwner for Literal {}
impl Literal {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ExprStmt { pub struct ExprStmt {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
@ -805,6 +799,12 @@ impl IndexExpr {
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)]
pub struct Literal {
pub(crate) syntax: SyntaxNode,
}
impl ast::AttrsOwner for Literal {}
impl Literal {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct LoopExpr { pub struct LoopExpr {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
@ -2072,17 +2072,6 @@ impl AstNode for WherePred {
} }
fn syntax(&self) -> &SyntaxNode { &self.syntax } fn syntax(&self) -> &SyntaxNode { &self.syntax }
} }
impl AstNode for Literal {
fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for ExprStmt { impl AstNode for ExprStmt {
fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT } fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT }
fn cast(syntax: SyntaxNode) -> Option<Self> { fn cast(syntax: SyntaxNode) -> Option<Self> {
@ -2259,6 +2248,17 @@ impl AstNode for IndexExpr {
} }
fn syntax(&self) -> &SyntaxNode { &self.syntax } fn syntax(&self) -> &SyntaxNode { &self.syntax }
} }
impl AstNode for Literal {
fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for LoopExpr { impl AstNode for LoopExpr {
fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR } fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR }
fn cast(syntax: SyntaxNode) -> Option<Self> { fn cast(syntax: SyntaxNode) -> Option<Self> {
@ -3887,11 +3887,6 @@ impl std::fmt::Display for WherePred {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ExprStmt { impl std::fmt::Display for ExprStmt {
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)
@ -3972,6 +3967,11 @@ impl std::fmt::Display for IndexExpr {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for LoopExpr { impl std::fmt::Display for LoopExpr {
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

@ -109,16 +109,6 @@ impl ast::Attr {
Some((self.simple_name()?, tt)) Some((self.simple_name()?, tt))
} }
pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> {
let lit = self.literal()?;
let key = self.simple_name()?;
let value_token = lit.syntax().first_token()?;
let value: SmolStr = ast::String::cast(value_token)?.value()?.into();
Some((key, value))
}
pub fn simple_name(&self) -> Option<SmolStr> { pub fn simple_name(&self) -> Option<SmolStr> {
let path = self.path()?; let path = self.path()?;
match (path.segment(), path.qualifier()) { match (path.segment(), path.qualifier()) {

View file

@ -11,7 +11,7 @@ anyhow = "1.0.26"
flate2 = "1.0" flate2 = "1.0"
proc-macro2 = "1.0.8" proc-macro2 = "1.0.8"
quote = "1.0.2" quote = "1.0.2"
ungrammar = "=1.12" ungrammar = "=1.13"
walkdir = "2.3.1" walkdir = "2.3.1"
write-json = "0.1.0" write-json = "0.1.0"
xshell = "0.1" xshell = "0.1"