mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
future proof structure
This commit is contained in:
parent
5ecda802f1
commit
8e9003447c
3 changed files with 143 additions and 135 deletions
|
@ -9,10 +9,12 @@
|
||||||
//! write unit-tests (in fact, we used to do that), but that makes tests brittle
|
//! write unit-tests (in fact, we used to do that), but that makes tests brittle
|
||||||
//! and harder to understand.
|
//! and harder to understand.
|
||||||
|
|
||||||
|
mod mbe;
|
||||||
|
|
||||||
use std::{iter, ops::Range};
|
use std::{iter, ops::Range};
|
||||||
|
|
||||||
use base_db::{fixture::WithFixture, SourceDatabase};
|
use base_db::{fixture::WithFixture, SourceDatabase};
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::Expect;
|
||||||
use hir_expand::{db::AstDatabase, InFile, MacroFile};
|
use hir_expand::{db::AstDatabase, InFile, MacroFile};
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
|
@ -113,137 +115,3 @@ fn pretty_print_macro_expansion(expn: SyntaxNode) -> String {
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn wrong_nesting_level() {
|
|
||||||
check(
|
|
||||||
r#"
|
|
||||||
macro_rules! m {
|
|
||||||
($($i:ident);*) => ($i)
|
|
||||||
}
|
|
||||||
m!{a}
|
|
||||||
"#,
|
|
||||||
expect![[r#"
|
|
||||||
macro_rules! m {
|
|
||||||
($($i:ident);*) => ($i)
|
|
||||||
}
|
|
||||||
/* error: expected simple binding, found nested binding `i` */
|
|
||||||
"#]],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn expansion_does_not_parse_as_expression() {
|
|
||||||
check(
|
|
||||||
r#"
|
|
||||||
macro_rules! stmts {
|
|
||||||
() => { let _ = 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn f() { let _ = stmts!(); }
|
|
||||||
"#,
|
|
||||||
expect![[r#"
|
|
||||||
macro_rules! stmts {
|
|
||||||
() => { let _ = 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn f() { let _ = /* error: could not convert tokens */; }
|
|
||||||
"#]],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn round_trips_compound_tokens() {
|
|
||||||
check(
|
|
||||||
r#"
|
|
||||||
macro_rules! m {
|
|
||||||
() => { type qual: ::T = qual::T; }
|
|
||||||
}
|
|
||||||
m!();
|
|
||||||
"#,
|
|
||||||
expect![[r#"
|
|
||||||
macro_rules! m {
|
|
||||||
() => { type qual: ::T = qual::T; }
|
|
||||||
}
|
|
||||||
type qual: ::T = qual::T;
|
|
||||||
"#]],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn round_trips_literals() {
|
|
||||||
check(
|
|
||||||
r#"
|
|
||||||
macro_rules! m {
|
|
||||||
() => {
|
|
||||||
let _ = 'c';
|
|
||||||
let _ = 1000;
|
|
||||||
let _ = 12E+99_f64;
|
|
||||||
let _ = "rust1";
|
|
||||||
let _ = -92;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn f() {
|
|
||||||
m!()
|
|
||||||
}
|
|
||||||
"#,
|
|
||||||
expect![[r#"
|
|
||||||
macro_rules! m {
|
|
||||||
() => {
|
|
||||||
let _ = 'c';
|
|
||||||
let _ = 1000;
|
|
||||||
let _ = 12E+99_f64;
|
|
||||||
let _ = "rust1";
|
|
||||||
let _ = -92;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn f() {
|
|
||||||
let_ = 'c';
|
|
||||||
let_ = 1000;
|
|
||||||
let_ = 12E+99_f64;
|
|
||||||
let_ = "rust1";
|
|
||||||
let_ = -92;
|
|
||||||
}
|
|
||||||
"#]],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn broken_parenthesis_sequence() {
|
|
||||||
check(
|
|
||||||
r#"
|
|
||||||
macro_rules! m1 { ($x:ident) => { ($x } }
|
|
||||||
macro_rules! m2 { ($x:ident) => {} }
|
|
||||||
|
|
||||||
m1!();
|
|
||||||
m2!(x
|
|
||||||
"#,
|
|
||||||
expect![[r#"
|
|
||||||
macro_rules! m1 { ($x:ident) => { ($x } }
|
|
||||||
macro_rules! m2 { ($x:ident) => {} }
|
|
||||||
|
|
||||||
/* error: Failed to find macro definition */
|
|
||||||
/* error: Failed to lower macro args to token tree */
|
|
||||||
"#]],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn unary_minus_is_a_literal() {
|
|
||||||
check(
|
|
||||||
r#"
|
|
||||||
macro_rules! m { ($x:literal) => (literal!()); ($x:tt) => (not_a_literal!()); }
|
|
||||||
m!(92);
|
|
||||||
m!(-92);
|
|
||||||
m!(-9.2);
|
|
||||||
m!(--92);
|
|
||||||
"#,
|
|
||||||
expect![[r#"
|
|
||||||
macro_rules! m { ($x:literal) => (literal!()); ($x:tt) => (not_a_literal!()); }
|
|
||||||
literal!()
|
|
||||||
literal!()
|
|
||||||
literal!()
|
|
||||||
/* error: leftover tokens */not_a_literal!()
|
|
||||||
"#]],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
137
crates/hir_def/src/macro_expansion_tests/mbe.rs
Normal file
137
crates/hir_def/src/macro_expansion_tests/mbe.rs
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
use expect_test::expect;
|
||||||
|
|
||||||
|
use crate::macro_expansion_tests::check;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wrong_nesting_level() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
macro_rules! m {
|
||||||
|
($($i:ident);*) => ($i)
|
||||||
|
}
|
||||||
|
m!{a}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
macro_rules! m {
|
||||||
|
($($i:ident);*) => ($i)
|
||||||
|
}
|
||||||
|
/* error: expected simple binding, found nested binding `i` */
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expansion_does_not_parse_as_expression() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
macro_rules! stmts {
|
||||||
|
() => { let _ = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() { let _ = stmts!(); }
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
macro_rules! stmts {
|
||||||
|
() => { let _ = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() { let _ = /* error: could not convert tokens */; }
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn round_trips_compound_tokens() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
macro_rules! m {
|
||||||
|
() => { type qual: ::T = qual::T; }
|
||||||
|
}
|
||||||
|
m!();
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
macro_rules! m {
|
||||||
|
() => { type qual: ::T = qual::T; }
|
||||||
|
}
|
||||||
|
type qual: ::T = qual::T;
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn round_trips_literals() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
macro_rules! m {
|
||||||
|
() => {
|
||||||
|
let _ = 'c';
|
||||||
|
let _ = 1000;
|
||||||
|
let _ = 12E+99_f64;
|
||||||
|
let _ = "rust1";
|
||||||
|
let _ = -92;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn f() {
|
||||||
|
m!()
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
macro_rules! m {
|
||||||
|
() => {
|
||||||
|
let _ = 'c';
|
||||||
|
let _ = 1000;
|
||||||
|
let _ = 12E+99_f64;
|
||||||
|
let _ = "rust1";
|
||||||
|
let _ = -92;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn f() {
|
||||||
|
let_ = 'c';
|
||||||
|
let_ = 1000;
|
||||||
|
let_ = 12E+99_f64;
|
||||||
|
let_ = "rust1";
|
||||||
|
let_ = -92;
|
||||||
|
}
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn broken_parenthesis_sequence() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
macro_rules! m1 { ($x:ident) => { ($x } }
|
||||||
|
macro_rules! m2 { ($x:ident) => {} }
|
||||||
|
|
||||||
|
m1!();
|
||||||
|
m2!(x
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
macro_rules! m1 { ($x:ident) => { ($x } }
|
||||||
|
macro_rules! m2 { ($x:ident) => {} }
|
||||||
|
|
||||||
|
/* error: Failed to find macro definition */
|
||||||
|
/* error: Failed to lower macro args to token tree */
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unary_minus_is_a_literal() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
macro_rules! m { ($x:literal) => (literal!()); ($x:tt) => (not_a_literal!()); }
|
||||||
|
m!(92);
|
||||||
|
m!(-92);
|
||||||
|
m!(-9.2);
|
||||||
|
m!(--92);
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
macro_rules! m { ($x:literal) => (literal!()); ($x:tt) => (not_a_literal!()); }
|
||||||
|
literal!()
|
||||||
|
literal!()
|
||||||
|
literal!()
|
||||||
|
/* error: leftover tokens */not_a_literal!()
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
|
@ -2,6 +2,9 @@
|
||||||
//! `macro_rules` macros. It uses `TokenTree` (from `tt` package) as the
|
//! `macro_rules` macros. It uses `TokenTree` (from `tt` package) as the
|
||||||
//! interface, although it contains some code to bridge `SyntaxNode`s and
|
//! interface, although it contains some code to bridge `SyntaxNode`s and
|
||||||
//! `TokenTree`s as well!
|
//! `TokenTree`s as well!
|
||||||
|
//!
|
||||||
|
//! The tes for this functionality live in another crate:
|
||||||
|
//! `hir_def::macro_expansion_tests::mbe`.
|
||||||
|
|
||||||
mod parser;
|
mod parser;
|
||||||
mod expander;
|
mod expander;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue