Skip to content

Commit 6ac3e66

Browse files
9217: internal: Don't stringify and reparse `cfg_attr`-gated attributes r=jonas-schievink a=jonas-schievink Bumps ungrammar to include rust-analyzer/ungrammar#33 bors r+ Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
2 parents 5f69420 + 99d40e7 commit 6ac3e66

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+819
-680
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir_def/src/attr.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ impl RawAttrs {
106106
) -> Self {
107107
let entries = collect_attrs(owner)
108108
.flat_map(|(id, attr)| match attr {
109-
Either::Left(attr) => Attr::from_src(db, attr, hygiene, id),
109+
Either::Left(attr) => {
110+
attr.meta().and_then(|meta| Attr::from_src(db, meta, hygiene, id))
111+
}
110112
Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
111113
id,
112114
input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))),
@@ -172,10 +174,9 @@ impl RawAttrs {
172174
let index = attr.id;
173175
let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
174176
let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
175-
let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
176177
// FIXME hygiene
177178
let hygiene = Hygiene::new_unhygienic();
178-
Attr::from_src(db, attr, &hygiene, index)
179+
Attr::from_tt(db, &tree, &hygiene, index)
179180
});
180181

181182
let cfg_options = &crate_graph[krate].cfg_options;
@@ -664,7 +665,7 @@ impl fmt::Display for AttrInput {
664665
impl Attr {
665666
fn from_src(
666667
db: &dyn DefDatabase,
667-
ast: ast::Attr,
668+
ast: ast::Meta,
668669
hygiene: &Hygiene,
669670
id: AttrId,
670671
) -> Option<Attr> {
@@ -683,6 +684,19 @@ impl Attr {
683684
Some(Attr { id, path, input })
684685
}
685686

687+
fn from_tt(
688+
db: &dyn DefDatabase,
689+
tt: &tt::Subtree,
690+
hygiene: &Hygiene,
691+
id: AttrId,
692+
) -> Option<Attr> {
693+
let (parse, _) =
694+
mbe::token_tree_to_syntax_node(tt, hir_expand::FragmentKind::MetaItem).ok()?;
695+
let ast = ast::Meta::cast(parse.syntax_node())?;
696+
697+
Self::from_src(db, ast, hygiene, id)
698+
}
699+
686700
/// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
687701
/// to derive macros.
688702
///

crates/ide/src/hover.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ pub(crate) fn hover(
208208
}
209209

210210
fn try_hover_for_attribute(token: &SyntaxToken) -> Option<RangeInfo<HoverResult>> {
211-
let attr = token.ancestors().nth(1).and_then(ast::Attr::cast)?;
211+
let attr = token.ancestors().find_map(ast::Attr::cast)?;
212212
let (path, tt) = attr.as_simple_call()?;
213213
if !tt.syntax().text_range().contains(token.text_range().start()) {
214214
return None;

crates/ide_db/src/defs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ impl NameRefClass {
369369
}
370370

371371
if let Some(resolved) = sema.resolve_path(&path) {
372-
if path.syntax().parent().and_then(ast::Attr::cast).is_some() {
372+
if path.syntax().ancestors().find_map(ast::Attr::cast).is_some() {
373373
if let PathResolution::Def(ModuleDef::Function(func)) = resolved {
374374
if func.attrs(sema.db).by_key("proc_macro_attribute").exists() {
375375
return Some(NameRefClass::Definition(resolved.into()));

crates/mbe/src/tests/expand.rs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,16 +1846,17 @@ fn test_no_space_after_semi_colon() {
18461846
ATTR@0..21
18471847
POUND@0..1 "#"
18481848
L_BRACK@1..2 "["
1849-
PATH@2..5
1850-
PATH_SEGMENT@2..5
1851-
NAME_REF@2..5
1852-
IDENT@2..5 "cfg"
1853-
TOKEN_TREE@5..20
1854-
L_PAREN@5..6 "("
1855-
IDENT@6..13 "feature"
1856-
EQ@13..14 "="
1857-
STRING@14..19 "\"std\""
1858-
R_PAREN@19..20 ")"
1849+
META@2..20
1850+
PATH@2..5
1851+
PATH_SEGMENT@2..5
1852+
NAME_REF@2..5
1853+
IDENT@2..5 "cfg"
1854+
TOKEN_TREE@5..20
1855+
L_PAREN@5..6 "("
1856+
IDENT@6..13 "feature"
1857+
EQ@13..14 "="
1858+
STRING@14..19 "\"std\""
1859+
R_PAREN@19..20 ")"
18591860
R_BRACK@20..21 "]"
18601861
MOD_KW@21..24 "mod"
18611862
NAME@24..25
@@ -1865,16 +1866,17 @@ fn test_no_space_after_semi_colon() {
18651866
ATTR@26..47
18661867
POUND@26..27 "#"
18671868
L_BRACK@27..28 "["
1868-
PATH@28..31
1869-
PATH_SEGMENT@28..31
1870-
NAME_REF@28..31
1871-
IDENT@28..31 "cfg"
1872-
TOKEN_TREE@31..46
1873-
L_PAREN@31..32 "("
1874-
IDENT@32..39 "feature"
1875-
EQ@39..40 "="
1876-
STRING@40..45 "\"std\""
1877-
R_PAREN@45..46 ")"
1869+
META@28..46
1870+
PATH@28..31
1871+
PATH_SEGMENT@28..31
1872+
NAME_REF@28..31
1873+
IDENT@28..31 "cfg"
1874+
TOKEN_TREE@31..46
1875+
L_PAREN@31..32 "("
1876+
IDENT@32..39 "feature"
1877+
EQ@39..40 "="
1878+
STRING@40..45 "\"std\""
1879+
R_PAREN@45..46 ")"
18781880
R_BRACK@46..47 "]"
18791881
MOD_KW@47..50 "mod"
18801882
NAME@50..51

crates/parser/src/grammar/attributes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub(super) fn outer_attrs(p: &mut Parser) {
1313
}
1414

1515
pub(super) fn meta(p: &mut Parser) {
16+
let meta = p.start();
1617
paths::use_path(p);
1718

1819
match p.current() {
@@ -25,6 +26,8 @@ pub(super) fn meta(p: &mut Parser) {
2526
T!['('] | T!['['] | T!['{'] => items::token_tree(p),
2627
_ => {}
2728
}
29+
30+
meta.complete(p, META);
2831
}
2932

3033
fn attr(p: &mut Parser, inner: bool) {

crates/parser/src/syntax_kind/generated.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ pub enum SyntaxKind {
220220
ITEM_LIST,
221221
ASSOC_ITEM_LIST,
222222
ATTR,
223-
META_ITEM,
223+
META,
224224
USE_TREE,
225225
USE_TREE_LIST,
226226
PATH,

crates/syntax/src/ast/generated/nodes.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,7 @@ impl Attr {
150150
pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
151151
pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
152152
pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
153-
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
154-
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
155-
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
156-
pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
153+
pub fn meta(&self) -> Option<Meta> { support::child(&self.syntax) }
157154
pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
158155
}
159156
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -632,6 +629,16 @@ impl WherePred {
632629
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
633630
}
634631
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
632+
pub struct Meta {
633+
pub(crate) syntax: SyntaxNode,
634+
}
635+
impl Meta {
636+
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
637+
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
638+
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
639+
pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
640+
}
641+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
635642
pub struct ExprStmt {
636643
pub(crate) syntax: SyntaxNode,
637644
}
@@ -2072,6 +2079,17 @@ impl AstNode for WherePred {
20722079
}
20732080
fn syntax(&self) -> &SyntaxNode { &self.syntax }
20742081
}
2082+
impl AstNode for Meta {
2083+
fn can_cast(kind: SyntaxKind) -> bool { kind == META }
2084+
fn cast(syntax: SyntaxNode) -> Option<Self> {
2085+
if Self::can_cast(syntax.kind()) {
2086+
Some(Self { syntax })
2087+
} else {
2088+
None
2089+
}
2090+
}
2091+
fn syntax(&self) -> &SyntaxNode { &self.syntax }
2092+
}
20752093
impl AstNode for ExprStmt {
20762094
fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT }
20772095
fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3887,6 +3905,11 @@ impl std::fmt::Display for WherePred {
38873905
std::fmt::Display::fmt(self.syntax(), f)
38883906
}
38893907
}
3908+
impl std::fmt::Display for Meta {
3909+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3910+
std::fmt::Display::fmt(self.syntax(), f)
3911+
}
3912+
}
38903913
impl std::fmt::Display for ExprStmt {
38913914
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38923915
std::fmt::Display::fmt(self.syntax(), f)

crates/syntax/src/ast/node_ext.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,19 +144,20 @@ impl AttrKind {
144144

145145
impl ast::Attr {
146146
pub fn as_simple_atom(&self) -> Option<SmolStr> {
147-
if self.eq_token().is_some() || self.token_tree().is_some() {
147+
let meta = self.meta()?;
148+
if meta.eq_token().is_some() || meta.token_tree().is_some() {
148149
return None;
149150
}
150151
self.simple_name()
151152
}
152153

153154
pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
154-
let tt = self.token_tree()?;
155+
let tt = self.meta()?.token_tree()?;
155156
Some((self.simple_name()?, tt))
156157
}
157158

158159
pub fn simple_name(&self) -> Option<SmolStr> {
159-
let path = self.path()?;
160+
let path = self.meta()?.path()?;
160161
match (path.segment(), path.qualifier()) {
161162
(Some(segment), None) => Some(segment.syntax().first_token()?.text().into()),
162163
_ => None,
@@ -174,6 +175,18 @@ impl ast::Attr {
174175
_ => AttrKind::Outer,
175176
}
176177
}
178+
179+
pub fn path(&self) -> Option<ast::Path> {
180+
self.meta()?.path()
181+
}
182+
183+
pub fn expr(&self) -> Option<ast::Expr> {
184+
self.meta()?.expr()
185+
}
186+
187+
pub fn token_tree(&self) -> Option<ast::TokenTree> {
188+
self.meta()?.token_tree()
189+
}
177190
}
178191

179192
#[derive(Debug, Clone, PartialEq, Eq)]

crates/syntax/test_data/parser/err/0005_attribute_recover.rast

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@ SOURCE_FILE@0..54
33
ATTR@0..18
44
POUND@0..1 "#"
55
L_BRACK@1..2 "["
6-
PATH@2..5
7-
PATH_SEGMENT@2..5
8-
NAME_REF@2..5
9-
IDENT@2..5 "foo"
10-
TOKEN_TREE@5..17
11-
L_PAREN@5..6 "("
12-
IDENT@6..9 "foo"
13-
COMMA@9..10 ","
14-
WHITESPACE@10..11 " "
15-
PLUS@11..12 "+"
16-
COMMA@12..13 ","
17-
WHITESPACE@13..14 " "
18-
INT_NUMBER@14..16 "92"
19-
R_PAREN@16..17 ")"
6+
META@2..17
7+
PATH@2..5
8+
PATH_SEGMENT@2..5
9+
NAME_REF@2..5
10+
IDENT@2..5 "foo"
11+
TOKEN_TREE@5..17
12+
L_PAREN@5..6 "("
13+
IDENT@6..9 "foo"
14+
COMMA@9..10 ","
15+
WHITESPACE@10..11 " "
16+
PLUS@11..12 "+"
17+
COMMA@12..13 ","
18+
WHITESPACE@13..14 " "
19+
INT_NUMBER@14..16 "92"
20+
R_PAREN@16..17 ")"
2021
R_BRACK@17..18 "]"
2122
WHITESPACE@18..19 "\n"
2223
FN_KW@19..21 "fn"
@@ -35,24 +36,25 @@ SOURCE_FILE@0..54
3536
ATTR@34..53
3637
POUND@34..35 "#"
3738
L_BRACK@35..36 "["
38-
PATH@36..39
39-
PATH_SEGMENT@36..39
40-
NAME_REF@36..39
41-
IDENT@36..39 "foo"
42-
TOKEN_TREE@39..53
43-
L_PAREN@39..40 "("
44-
WHITESPACE@40..41 "\n"
45-
FN_KW@41..43 "fn"
46-
WHITESPACE@43..44 " "
47-
IDENT@44..47 "foo"
48-
TOKEN_TREE@47..49
49-
L_PAREN@47..48 "("
50-
R_PAREN@48..49 ")"
51-
WHITESPACE@49..50 " "
52-
TOKEN_TREE@50..53
53-
L_CURLY@50..51 "{"
54-
WHITESPACE@51..52 "\n"
55-
R_CURLY@52..53 "}"
39+
META@36..53
40+
PATH@36..39
41+
PATH_SEGMENT@36..39
42+
NAME_REF@36..39
43+
IDENT@36..39 "foo"
44+
TOKEN_TREE@39..53
45+
L_PAREN@39..40 "("
46+
WHITESPACE@40..41 "\n"
47+
FN_KW@41..43 "fn"
48+
WHITESPACE@43..44 " "
49+
IDENT@44..47 "foo"
50+
TOKEN_TREE@47..49
51+
L_PAREN@47..48 "("
52+
R_PAREN@48..49 ")"
53+
WHITESPACE@49..50 " "
54+
TOKEN_TREE@50..53
55+
L_CURLY@50..51 "{"
56+
WHITESPACE@51..52 "\n"
57+
R_CURLY@52..53 "}"
5658
WHITESPACE@53..54 "\n"
5759
error 53..53: expected R_PAREN
5860
error 53..53: expected `]`

0 commit comments

Comments
 (0)