Skip to content

Commit d846afd

Browse files
committed
check top level entry point invariants
1 parent fa049d9 commit d846afd

File tree

5 files changed

+42
-12
lines changed

5 files changed

+42
-12
lines changed

crates/hir_def/src/macro_expansion_tests/mbe/tt_conversion.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,21 +105,21 @@ macro_rules! m2 { ($x:ident) => {} }
105105

106106
#[test]
107107
fn expansion_does_not_parse_as_expression() {
108-
cov_mark::check!(expansion_does_not_parse_as_expression);
109108
check(
110109
r#"
111110
macro_rules! stmts {
112111
() => { let _ = 0; }
113112
}
114113
115-
fn f() { let _ = stmts!(); }
114+
fn f() { let _ = stmts!/*+errors*/(); }
116115
"#,
117116
expect![[r#"
118117
macro_rules! stmts {
119118
() => { let _ = 0; }
120119
}
121120
122-
fn f() { let _ = /* error: could not convert tokens */; }
121+
fn f() { let _ = /* parse error: expected expression */
122+
let _ = 0;; }
123123
"#]],
124124
)
125125
}

crates/ide/src/hover/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ fn foo() { let a = id!([0u32, bar($0)] ); }
11481148
fn test_hover_through_literal_string_in_macro() {
11491149
check(
11501150
r#"
1151-
macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } }
1151+
macro_rules! arr { ($($tt:tt)*) => { [$($tt)*] } }
11521152
fn foo() {
11531153
let mastered_for_itunes = "";
11541154
let _ = arr!("Tr$0acks", &mastered_for_itunes);

crates/mbe/src/syntax_bridge.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Conversions between [`SyntaxNode`] and [`tt::TokenTree`].
22
33
use rustc_hash::{FxHashMap, FxHashSet};
4-
use stdx::non_empty_vec::NonEmptyVec;
4+
use stdx::{never, non_empty_vec::NonEmptyVec};
55
use syntax::{
66
ast::{self, make::tokens::doc_comment},
77
AstToken, Parse, PreorderWithTokens, SmolStr, SyntaxElement, SyntaxKind,
@@ -66,8 +66,7 @@ pub fn token_tree_to_syntax_node(
6666
parser::Step::Error { msg } => tree_sink.error(msg.to_string()),
6767
}
6868
}
69-
if tree_sink.roots.len() != 1 {
70-
cov_mark::hit!(expansion_does_not_parse_as_expression);
69+
if never!(tree_sink.roots.len() != 1) {
7170
return Err(ExpandError::ConversionError);
7271
}
7372
//FIXME: would be cool to report errors

crates/parser/src/grammar.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,19 @@ pub(crate) mod entry {
148148
}
149149
m.complete(p, ERROR);
150150
}
151+
152+
pub(crate) fn meta_item(p: &mut Parser) {
153+
let m = p.start();
154+
attributes::meta(p);
155+
if p.at(EOF) {
156+
m.abandon(p);
157+
return;
158+
}
159+
while !p.at(EOF) {
160+
p.bump_any();
161+
}
162+
m.complete(p, ERROR);
163+
}
151164
}
152165
}
153166

crates/parser/src/lib.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,11 @@ impl PrefixEntryPoint {
9999
/// ```
100100
///
101101
/// the input to the macro will be parsed with [`PrefixEntryPoint::Item`], and
102-
/// the result will be [`TopEntryPoint::Items`].
102+
/// the result will be [`TopEntryPoint::MacroItems`].
103103
///
104-
/// This *should* (but currently doesn't) guarantee that all input is consumed.
104+
/// [`TopEntryPoint::parse`] makes a guarantee that
105+
/// * all input is consumed
106+
/// * the result is a valid tree (there's one root node)
105107
#[derive(Debug)]
106108
pub enum TopEntryPoint {
107109
SourceFile,
@@ -124,13 +126,29 @@ impl TopEntryPoint {
124126
TopEntryPoint::Pattern => grammar::entry::top::pattern,
125127
TopEntryPoint::Type => grammar::entry::top::type_,
126128
TopEntryPoint::Expr => grammar::entry::top::expr,
127-
// FIXME
128-
TopEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
129+
TopEntryPoint::MetaItem => grammar::entry::top::meta_item,
129130
};
130131
let mut p = parser::Parser::new(input);
131132
entry_point(&mut p);
132133
let events = p.finish();
133-
event::process(events)
134+
let res = event::process(events);
135+
136+
if cfg!(debug_assertions) {
137+
let mut depth = 0;
138+
let mut first = true;
139+
for step in res.iter() {
140+
assert!(depth > 0 || first);
141+
first = false;
142+
match step {
143+
Step::Enter { .. } => depth += 1,
144+
Step::Exit => depth -= 1,
145+
Step::Token { .. } | Step::Error { .. } => (),
146+
}
147+
}
148+
assert!(!first, "no tree at all");
149+
}
150+
151+
res
134152
}
135153
}
136154

0 commit comments

Comments
 (0)