]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/obsolete.rs
Forbid `priv` where it has no effect
[rust.git] / src / libsyntax / parse / obsolete.rs
1 // Copyright 2012 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 /*!
12 Support for parsing unsupported, old syntaxes, for the
13 purpose of reporting errors. Parsing of these syntaxes
14 is tested by compile-test/obsolete-syntax.rs.
15
16 Obsolete syntax that becomes too hard to parse can be
17 removed.
18 */
19
20 use ast::{expr, expr_lit, lit_nil, Attribute};
21 use ast;
22 use codemap::{span, respan};
23 use parse::parser::Parser;
24 use parse::token::{keywords, Token};
25 use parse::token;
26
27 use std::str;
28 use std::to_bytes;
29
30 /// The specific types of unsupported syntax
31 #[deriving(Eq)]
32 pub enum ObsoleteSyntax {
33     ObsoleteLet,
34     ObsoleteFieldTerminator,
35     ObsoleteStructCtor,
36     ObsoleteWith,
37     ObsoleteClassTraits,
38     ObsoletePrivSection,
39     ObsoleteModeInFnType,
40     ObsoleteMoveInit,
41     ObsoleteBinaryMove,
42     ObsoleteSwap,
43     ObsoleteUnsafeBlock,
44     ObsoleteUnenforcedBound,
45     ObsoleteImplSyntax,
46     ObsoleteMutOwnedPointer,
47     ObsoleteMutVector,
48     ObsoleteImplVisibility,
49     ObsoleteRecordType,
50     ObsoleteRecordPattern,
51     ObsoletePostFnTySigil,
52     ObsoleteBareFnType,
53     ObsoleteNewtypeEnum,
54     ObsoleteMode,
55     ObsoleteImplicitSelf,
56     ObsoleteLifetimeNotation,
57     ObsoleteConstManagedPointer,
58     ObsoletePurity,
59     ObsoleteStaticMethod,
60     ObsoleteConstItem,
61     ObsoleteFixedLengthVectorType,
62     ObsoleteNamedExternModule,
63     ObsoleteMultipleLocalDecl,
64     ObsoleteMutWithMultipleBindings,
65     ObsoleteExternVisibility,
66     ObsoleteUnsafeExternFn,
67     ObsoletePrivVisibility,
68 }
69
70 impl to_bytes::IterBytes for ObsoleteSyntax {
71     #[inline]
72     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
73         (*self as uint).iter_bytes(lsb0, f)
74     }
75 }
76
77 pub trait ParserObsoleteMethods {
78     /// Reports an obsolete syntax non-fatal error.
79     fn obsolete(&self, sp: span, kind: ObsoleteSyntax);
80     // Reports an obsolete syntax non-fatal error, and returns
81     // a placeholder expression
82     fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr;
83     fn report(&self,
84               sp: span,
85               kind: ObsoleteSyntax,
86               kind_str: &str,
87               desc: &str);
88     fn token_is_obsolete_ident(&self, ident: &str, token: &Token) -> bool;
89     fn is_obsolete_ident(&self, ident: &str) -> bool;
90     fn eat_obsolete_ident(&self, ident: &str) -> bool;
91     fn try_parse_obsolete_struct_ctor(&self) -> bool;
92     fn try_parse_obsolete_with(&self) -> bool;
93     fn try_parse_obsolete_priv_section(&self, attrs: &[Attribute]) -> bool;
94 }
95
96 impl ParserObsoleteMethods for Parser {
97     /// Reports an obsolete syntax non-fatal error.
98     pub fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
99         let (kind_str, desc) = match kind {
100             ObsoleteLet => (
101                 "`let` in field declaration",
102                 "declare fields as `field: Type`"
103             ),
104             ObsoleteFieldTerminator => (
105                 "field declaration terminated with semicolon",
106                 "fields are now separated by commas"
107             ),
108             ObsoleteStructCtor => (
109                 "struct constructor",
110                 "structs are now constructed with `MyStruct { foo: val }` \
111                  syntax. Structs with private fields cannot be created \
112                  outside of their defining module"
113             ),
114             ObsoleteWith => (
115                 "with",
116                 "record update is done with `..`, e.g. \
117                  `MyStruct { foo: bar, .. baz }`"
118             ),
119             ObsoleteClassTraits => (
120                 "class traits",
121                 "implemented traits are specified on the impl, as in \
122                  `impl foo : bar {`"
123             ),
124             ObsoletePrivSection => (
125                 "private section",
126                 "the `priv` keyword is applied to individual items, methods, \
127                  and fields"
128             ),
129             ObsoleteModeInFnType => (
130                 "mode without identifier in fn type",
131                 "to use a (deprecated) mode in a fn type, you should \
132                  give the argument an explicit name (like `&&v: int`)"
133             ),
134             ObsoleteMoveInit => (
135                 "initializer-by-move",
136                 "Write `let foo = move bar` instead"
137             ),
138             ObsoleteBinaryMove => (
139                 "binary move",
140                 "Write `foo = move bar` instead"
141             ),
142             ObsoleteSwap => (
143                 "swap",
144                 "Use std::util::{swap, replace} instead"
145             ),
146             ObsoleteUnsafeBlock => (
147                 "non-standalone unsafe block",
148                 "use an inner `unsafe { ... }` block instead"
149             ),
150             ObsoleteUnenforcedBound => (
151                 "unenforced type parameter bound",
152                 "use trait bounds on the functions that take the type as \
153                  arguments, not on the types themselves"
154             ),
155             ObsoleteImplSyntax => (
156                 "colon-separated impl syntax",
157                 "write `impl Trait for Type`"
158             ),
159             ObsoleteMutOwnedPointer => (
160                 "const or mutable owned pointer",
161                 "mutability inherits through `~` pointers; place the `~` box
162                  in a mutable location, like a mutable local variable or an \
163                  `@mut` box"
164             ),
165             ObsoleteMutVector => (
166                 "const or mutable vector",
167                 "mutability inherits through `~` pointers; place the vector \
168                  in a mutable location, like a mutable local variable or an \
169                  `@mut` box"
170             ),
171             ObsoleteImplVisibility => (
172                 "visibility-qualified implementation",
173                 "`pub` or `priv` goes on individual functions; remove the \
174                  `pub` or `priv`"
175             ),
176             ObsoleteRecordType => (
177                 "structural record type",
178                 "use a structure instead"
179             ),
180             ObsoleteRecordPattern => (
181                 "structural record pattern",
182                 "use a structure instead"
183             ),
184             ObsoletePostFnTySigil => (
185                 "fn sigil in postfix position",
186                 "Rather than `fn@`, `fn~`, or `fn&`, \
187                  write `@fn`, `~fn`, and `&fn` respectively"
188             ),
189             ObsoleteBareFnType => (
190                 "bare function type",
191                 "use `&fn` or `extern fn` instead"
192             ),
193             ObsoleteNewtypeEnum => (
194                 "newtype enum",
195                 "instead of `enum Foo = int`, write `struct Foo(int)`"
196             ),
197             ObsoleteMode => (
198                 "obsolete argument mode",
199                 "replace `-` or `++` mode with `+`"
200             ),
201             ObsoleteImplicitSelf => (
202                 "implicit self",
203                 "use an explicit `self` declaration or declare the method as \
204                  static"
205             ),
206             ObsoleteLifetimeNotation => (
207                 "`/` lifetime notation",
208                 "instead of `&foo/bar`, write `&'foo bar`; instead of \
209                  `bar/&foo`, write `&bar<'foo>"
210             ),
211             ObsoleteConstManagedPointer => (
212                 "const `@` pointer",
213                 "instead of `@const Foo`, write `@Foo`"
214             ),
215             ObsoletePurity => (
216                 "pure function",
217                 "remove `pure`"
218             ),
219             ObsoleteStaticMethod => (
220                 "`static` notation",
221                 "`static` is superfluous; remove it"
222             ),
223             ObsoleteConstItem => (
224                 "`const` item",
225                 "`const` items are now `static` items; replace `const` with \
226                  `static`"
227             ),
228             ObsoleteFixedLengthVectorType => (
229                 "fixed-length vector notation",
230                 "instead of `[T * N]`, write `[T, ..N]`"
231             ),
232             ObsoleteNamedExternModule => (
233                 "named external module",
234                 "instead of `extern mod foo { ... }`, write `mod foo { \
235                  extern { ... } }`"
236             ),
237             ObsoleteMultipleLocalDecl => (
238                 "declaration of multiple locals at once",
239                 "instead of e.g. `let a = 1, b = 2`, write \
240                  `let (a, b) = (1, 2)`."
241             ),
242             ObsoleteMutWithMultipleBindings => (
243                 "`mut` with multiple bindings",
244                 "use multiple local declarations instead of e.g. `let mut \
245                  (x, y) = ...`."
246             ),
247             ObsoleteExternVisibility => (
248                 "`pub extern` or `priv extern`",
249                 "place the `pub` or `priv` on the individual external items \
250                  instead"
251             ),
252             ObsoleteUnsafeExternFn => (
253                 "unsafe external function",
254                 "external functions are always unsafe; remove the `unsafe` \
255                  keyword"
256             ),
257             ObsoletePrivVisibility => (
258                 "`priv` not necessary",
259                 "an item without a visibility qualifier is private by default"
260             ),
261         };
262
263         self.report(sp, kind, kind_str, desc);
264     }
265
266     // Reports an obsolete syntax non-fatal error, and returns
267     // a placeholder expression
268     pub fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr {
269         self.obsolete(sp, kind);
270         self.mk_expr(sp.lo, sp.hi, expr_lit(@respan(sp, lit_nil)))
271     }
272
273     fn report(&self,
274               sp: span,
275               kind: ObsoleteSyntax,
276               kind_str: &str,
277               desc: &str) {
278         self.span_err(sp, fmt!("obsolete syntax: %s", kind_str));
279
280         if !self.obsolete_set.contains(&kind) {
281             self.sess.span_diagnostic.handler().note(fmt!("%s", desc));
282             self.obsolete_set.insert(kind);
283         }
284     }
285
286     pub fn token_is_obsolete_ident(&self, ident: &str, token: &Token)
287                                    -> bool {
288         match *token {
289             token::IDENT(sid, _) => {
290                 str::eq_slice(self.id_to_str(sid), ident)
291             }
292             _ => false
293         }
294     }
295
296     pub fn is_obsolete_ident(&self, ident: &str) -> bool {
297         self.token_is_obsolete_ident(ident, self.token)
298     }
299
300     pub fn eat_obsolete_ident(&self, ident: &str) -> bool {
301         if self.is_obsolete_ident(ident) {
302             self.bump();
303             true
304         } else {
305             false
306         }
307     }
308
309     pub fn try_parse_obsolete_struct_ctor(&self) -> bool {
310         if self.eat_obsolete_ident("new") {
311             self.obsolete(*self.last_span, ObsoleteStructCtor);
312             self.parse_fn_decl();
313             self.parse_block();
314             true
315         } else {
316             false
317         }
318     }
319
320     pub fn try_parse_obsolete_with(&self) -> bool {
321         if *self.token == token::COMMA
322             && self.look_ahead(1,
323                                |t| self.token_is_obsolete_ident("with", t)) {
324             self.bump();
325         }
326         if self.eat_obsolete_ident("with") {
327             self.obsolete(*self.last_span, ObsoleteWith);
328             self.parse_expr();
329             true
330         } else {
331             false
332         }
333     }
334
335     pub fn try_parse_obsolete_priv_section(&self, attrs: &[Attribute])
336                                            -> bool {
337         if self.is_keyword(keywords::Priv) &&
338                 self.look_ahead(1, |t| *t == token::LBRACE) {
339             self.obsolete(*self.span, ObsoletePrivSection);
340             self.eat_keyword(keywords::Priv);
341             self.bump();
342             while *self.token != token::RBRACE {
343                 self.parse_single_struct_field(ast::private, attrs.to_owned());
344             }
345             self.bump();
346             true
347         } else {
348             false
349         }
350     }
351
352 }