]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs
6a706bdb9b2b6af133d24c63b3da2eaa57afe8f4
[rust.git] / src / test / run-pass-fulldeps / ast_stmt_expr_attr.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // ignore-cross-compile
12
13 #![feature(rustc_private)]
14
15 extern crate syntax;
16
17 use syntax::ast::*;
18 use syntax::attr::*;
19 use syntax::ast;
20 use syntax::source_map::{FilePathMapping, FileName};
21 use syntax::parse;
22 use syntax::parse::{ParseSess, PResult};
23 use syntax::parse::new_parser_from_source_str;
24 use syntax::parse::parser::Parser;
25 use syntax::parse::token;
26 use syntax::ptr::P;
27 use syntax::str::char_at;
28 use syntax::parse::attr::*;
29 use syntax::print::pprust;
30 use std::fmt;
31
32 // Copied out of syntax::util::parser_testing
33
34 pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> {
35     new_parser_from_source_str(ps, FileName::Custom("bogofile".to_owned()), source_str)
36 }
37
38 fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> PResult<'a, T> where
39     F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
40 {
41     let mut p = string_to_parser(&ps, s);
42     let x = f(&mut p);
43
44     if ps.span_diagnostic.has_errors() || p.token != token::Eof {
45         if let Err(mut e) = x {
46             e.cancel();
47         }
48         return Err(p.fatal("parse error"));
49     }
50
51     x
52 }
53
54 fn expr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, P<ast::Expr>> {
55     with_error_checking_parse(s.to_string(), ps, |p| {
56         p.parse_expr()
57     })
58 }
59
60 fn stmt<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, ast::Stmt> {
61     with_error_checking_parse(s.to_string(), ps, |p| {
62         p.parse_stmt().map(|s| s.unwrap())
63     })
64 }
65
66 fn attr<'a>(s: &str, ps: &'a ParseSess) -> PResult<'a, ast::Attribute> {
67     with_error_checking_parse(s.to_string(), ps, |p| {
68         p.parse_attribute(true)
69     })
70 }
71
72 fn str_compare<T, F: Fn(&T) -> String>(e: &str, expected: &[T], actual: &[T], f: F) {
73     let expected: Vec<_> = expected.iter().map(|e| f(e)).collect();
74     let actual: Vec<_> = actual.iter().map(|e| f(e)).collect();
75
76     if expected != actual {
77         panic!("parsed `{}` as {:?}, expected {:?}", e, actual, expected);
78     }
79 }
80
81 fn check_expr_attrs(es: &str, expected: &[&str]) {
82     let ps = ParseSess::new(FilePathMapping::empty());
83     let e = expr(es, &ps).expect("parse error");
84     let actual = &e.attrs;
85     str_compare(es,
86                 &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
87                 &actual,
88                 pprust::attribute_to_string);
89 }
90
91 fn check_stmt_attrs(es: &str, expected: &[&str]) {
92     let ps = ParseSess::new(FilePathMapping::empty());
93     let e = stmt(es, &ps).expect("parse error");
94     let actual = e.node.attrs();
95     str_compare(es,
96                 &expected.iter().map(|r| attr(r, &ps).unwrap()).collect::<Vec<_>>(),
97                 actual,
98                 pprust::attribute_to_string);
99 }
100
101 fn reject_expr_parse(es: &str) {
102     let ps = ParseSess::new(FilePathMapping::empty());
103     match expr(es, &ps) {
104         Ok(_) => panic!("parser did not reject `{}`", es),
105         Err(mut e) => e.cancel(),
106     };
107 }
108
109 fn reject_stmt_parse(es: &str) {
110     let ps = ParseSess::new(FilePathMapping::empty());
111     match stmt(es, &ps) {
112         Ok(_) => panic!("parser did not reject `{}`", es),
113         Err(mut e) => e.cancel(),
114     };
115 }
116
117 fn main() {
118     syntax::with_globals(|| run());
119 }
120
121 fn run() {
122     let both = &["#[attr]", "#![attr]"];
123     let outer = &["#[attr]"];
124     let none = &[];
125
126     check_expr_attrs("#[attr] box 0", outer);
127     reject_expr_parse("box #![attr] 0");
128
129     check_expr_attrs("#[attr] [#![attr]]", both);
130     check_expr_attrs("#[attr] [#![attr] 0]", both);
131     check_expr_attrs("#[attr] [#![attr] 0; 0]", both);
132     check_expr_attrs("#[attr] [#![attr] 0, 0, 0]", both);
133     reject_expr_parse("[#[attr]]");
134
135     check_expr_attrs("#[attr] foo()", outer);
136     check_expr_attrs("#[attr] x.foo()", outer);
137     reject_expr_parse("foo#[attr]()");
138     reject_expr_parse("foo(#![attr])");
139     reject_expr_parse("x.foo(#![attr])");
140     reject_expr_parse("x.#[attr]foo()");
141     reject_expr_parse("x.#![attr]foo()");
142
143     check_expr_attrs("#[attr] (#![attr])", both);
144     check_expr_attrs("#[attr] (#![attr] #[attr] 0,)", both);
145     check_expr_attrs("#[attr] (#![attr] #[attr] 0, 0)", both);
146
147     check_expr_attrs("#[attr] 0 + #[attr] 0", none);
148     check_expr_attrs("#[attr] 0 / #[attr] 0", none);
149     check_expr_attrs("#[attr] 0 & #[attr] 0", none);
150     check_expr_attrs("#[attr] 0 % #[attr] 0", none);
151     check_expr_attrs("#[attr] (0 + 0)", outer);
152     reject_expr_parse("0 + #![attr] 0");
153
154     check_expr_attrs("#[attr] !0", outer);
155     check_expr_attrs("#[attr] -0", outer);
156     reject_expr_parse("!#![attr] 0");
157     reject_expr_parse("-#![attr] 0");
158
159     check_expr_attrs("#[attr] false", outer);
160     check_expr_attrs("#[attr] 0", outer);
161     check_expr_attrs("#[attr] 'c'", outer);
162
163     check_expr_attrs("#[attr] x as Y", none);
164     check_expr_attrs("#[attr] (x as Y)", outer);
165     reject_expr_parse("x #![attr] as Y");
166
167     reject_expr_parse("#[attr] if false {}");
168     reject_expr_parse("if false #[attr] {}");
169     reject_expr_parse("if false {#![attr]}");
170     reject_expr_parse("if false {} #[attr] else {}");
171     reject_expr_parse("if false {} else #[attr] {}");
172     reject_expr_parse("if false {} else {#![attr]}");
173     reject_expr_parse("if false {} else #[attr] if true {}");
174     reject_expr_parse("if false {} else if true #[attr] {}");
175     reject_expr_parse("if false {} else if true {#![attr]}");
176
177     reject_expr_parse("#[attr] if let Some(false) = false {}");
178     reject_expr_parse("if let Some(false) = false #[attr] {}");
179     reject_expr_parse("if let Some(false) = false {#![attr]}");
180     reject_expr_parse("if let Some(false) = false {} #[attr] else {}");
181     reject_expr_parse("if let Some(false) = false {} else #[attr] {}");
182     reject_expr_parse("if let Some(false) = false {} else {#![attr]}");
183     reject_expr_parse("if let Some(false) = false {} else #[attr] if let Some(false) = true {}");
184     reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true #[attr] {}");
185     reject_expr_parse("if let Some(false) = false {} else if let Some(false) = true {#![attr]}");
186
187     check_expr_attrs("#[attr] while true {#![attr]}", both);
188
189     check_expr_attrs("#[attr] while let Some(false) = true {#![attr]}", both);
190
191     check_expr_attrs("#[attr] for x in y {#![attr]}", both);
192
193     check_expr_attrs("#[attr] loop {#![attr]}", both);
194
195     check_expr_attrs("#[attr] match true {#![attr] #[attr] _ => false}", both);
196
197     check_expr_attrs("#[attr]      || #[attr] foo", outer);
198     check_expr_attrs("#[attr] move || #[attr] foo", outer);
199     check_expr_attrs("#[attr]      || #[attr] { #![attr] foo }", outer);
200     check_expr_attrs("#[attr] move || #[attr] { #![attr] foo }", outer);
201     check_expr_attrs("#[attr]      || { #![attr] foo }", outer);
202     check_expr_attrs("#[attr] move || { #![attr] foo }", outer);
203     reject_expr_parse("|| #![attr] foo");
204     reject_expr_parse("move || #![attr] foo");
205     reject_expr_parse("|| #![attr] {foo}");
206     reject_expr_parse("move || #![attr] {foo}");
207
208     check_expr_attrs("#[attr] { #![attr] }", both);
209     check_expr_attrs("#[attr] { #![attr] let _ = (); }", both);
210     check_expr_attrs("#[attr] { #![attr] let _ = (); foo }", both);
211
212     check_expr_attrs("#[attr] x = y", none);
213     check_expr_attrs("#[attr] (x = y)", outer);
214
215     check_expr_attrs("#[attr] x += y", none);
216     check_expr_attrs("#[attr] (x += y)", outer);
217
218     check_expr_attrs("#[attr] foo.bar", outer);
219     check_expr_attrs("(#[attr] foo).bar", none);
220
221     check_expr_attrs("#[attr] foo.0", outer);
222     check_expr_attrs("(#[attr] foo).0", none);
223
224     check_expr_attrs("#[attr] foo[bar]", outer);
225     check_expr_attrs("(#[attr] foo)[bar]", none);
226
227     check_expr_attrs("#[attr] 0..#[attr] 0", none);
228     check_expr_attrs("#[attr] 0..", none);
229     reject_expr_parse("#[attr] ..#[attr] 0");
230     reject_expr_parse("#[attr] ..");
231
232     check_expr_attrs("#[attr] (0..0)", outer);
233     check_expr_attrs("#[attr] (0..)", outer);
234     check_expr_attrs("#[attr] (..0)", outer);
235     check_expr_attrs("#[attr] (..)", outer);
236
237     check_expr_attrs("#[attr] foo::bar::baz", outer);
238
239     check_expr_attrs("#[attr] &0", outer);
240     check_expr_attrs("#[attr] &mut 0", outer);
241     check_expr_attrs("#[attr] & #[attr] 0", outer);
242     check_expr_attrs("#[attr] &mut #[attr] 0", outer);
243     reject_expr_parse("#[attr] &#![attr] 0");
244     reject_expr_parse("#[attr] &mut #![attr] 0");
245
246     check_expr_attrs("#[attr] break", outer);
247     check_expr_attrs("#[attr] continue", outer);
248     check_expr_attrs("#[attr] return", outer);
249
250     check_expr_attrs("#[attr] foo!()", outer);
251     check_expr_attrs("#[attr] foo!(#![attr])", outer);
252     check_expr_attrs("#[attr] foo![]", outer);
253     check_expr_attrs("#[attr] foo![#![attr]]", outer);
254     check_expr_attrs("#[attr] foo!{}", outer);
255     check_expr_attrs("#[attr] foo!{#![attr]}", outer);
256
257     check_expr_attrs("#[attr] Foo { #![attr] bar: baz }", both);
258     check_expr_attrs("#[attr] Foo { #![attr] ..foo }", both);
259     check_expr_attrs("#[attr] Foo { #![attr] bar: baz, ..foo }", both);
260
261     check_expr_attrs("#[attr] (#![attr] 0)", both);
262
263     // Look at statements in their natural habitat...
264     check_expr_attrs("{
265         #[attr] let _ = 0;
266         #[attr] 0;
267         #[attr] foo!();
268         #[attr] foo!{}
269         #[attr] foo![];
270     }", none);
271
272     check_stmt_attrs("#[attr] let _ = 0", outer);
273     check_stmt_attrs("#[attr] 0",         outer);
274     check_stmt_attrs("#[attr] {#![attr]}", both);
275     check_stmt_attrs("#[attr] foo!()",    outer);
276     check_stmt_attrs("#[attr] foo![]",    outer);
277     check_stmt_attrs("#[attr] foo!{}",    outer);
278
279     reject_stmt_parse("#[attr] #![attr] let _ = 0");
280     reject_stmt_parse("#[attr] #![attr] 0");
281     reject_stmt_parse("#[attr] #![attr] foo!()");
282     reject_stmt_parse("#[attr] #![attr] foo![]");
283     reject_stmt_parse("#[attr] #![attr] foo!{}");
284
285     // FIXME: Allow attributes in pattern constexprs?
286     // would require parens in patterns to allow disambiguation...
287     // â€”which is now available under the `pattern_parentheses` feature gate
288     // (tracking issue #51087)
289
290     reject_expr_parse("match 0 {
291         0..=#[attr] 10 => ()
292     }");
293     reject_expr_parse("match 0 {
294         0..=#[attr] -10 => ()
295     }");
296     reject_expr_parse("match 0 {
297         0..=-#[attr] 10 => ()
298     }");
299     reject_expr_parse("match 0 {
300         0..=#[attr] FOO => ()
301     }");
302
303     // make sure we don't catch this bug again...
304     reject_expr_parse("{
305         fn foo() {
306             #[attr];
307         }
308     }");
309     reject_expr_parse("{
310         fn foo() {
311             #[attr]
312         }
313     }");
314 }