rust/src/libsyntax/parse/obsolete.rs

340 lines
12 KiB
Rust
Raw Normal View History

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
Support for parsing unsupported, old syntaxes, for the
purpose of reporting errors. Parsing of these syntaxes
is tested by compile-test/obsolete-syntax.rs.
Obsolete syntax that becomes too hard to parse can be
removed.
*/
use ast::{expr, expr_lit, lit_nil, Attribute};
use ast;
2013-01-30 09:56:33 -08:00
use codemap::{span, respan};
use parse::parser::Parser;
use parse::token::{keywords, Token};
use parse::token;
2013-06-24 20:40:33 -04:00
use std::str;
use std::to_bytes;
/// The specific types of unsupported syntax
#[deriving(Eq)]
pub enum ObsoleteSyntax {
ObsoleteLet,
ObsoleteFieldTerminator,
2012-09-10 17:26:20 -07:00
ObsoleteWith,
ObsoleteClassTraits,
ObsoletePrivSection,
ObsoleteModeInFnType,
ObsoleteMoveInit,
ObsoleteBinaryMove,
ObsoleteSwap,
ObsoleteUnsafeBlock,
ObsoleteUnenforcedBound,
ObsoleteImplSyntax,
2013-02-25 15:54:13 -08:00
ObsoleteMutOwnedPointer,
ObsoleteMutVector,
ObsoleteImplVisibility,
ObsoleteRecordType,
ObsoleteRecordPattern,
ObsoletePostFnTySigil,
ObsoleteBareFnType,
2013-03-07 18:59:00 -08:00
ObsoleteNewtypeEnum,
ObsoleteMode,
ObsoleteImplicitSelf,
ObsoleteLifetimeNotation,
ObsoletePurity,
ObsoleteStaticMethod,
2013-03-22 14:51:35 -07:00
ObsoleteConstItem,
2013-03-22 19:22:12 -07:00
ObsoleteFixedLengthVectorType,
ObsoleteNamedExternModule,
ObsoleteMultipleLocalDecl,
ObsoleteMutWithMultipleBindings,
ObsoleteExternVisibility,
ObsoleteUnsafeExternFn,
ObsoletePrivVisibility,
ObsoleteTraitFuncVisibility,
ObsoleteConstPointer,
}
2013-05-02 18:33:33 -04:00
impl to_bytes::IterBytes for ObsoleteSyntax {
#[inline]
2013-05-02 18:33:33 -04:00
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
(*self as uint).iter_bytes(lsb0, f)
}
}
pub trait ParserObsoleteMethods {
/// Reports an obsolete syntax non-fatal error.
fn obsolete(&self, sp: span, kind: ObsoleteSyntax);
// Reports an obsolete syntax non-fatal error, and returns
// a placeholder expression
fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr;
fn report(&self,
sp: span,
kind: ObsoleteSyntax,
kind_str: &str,
desc: &str);
fn token_is_obsolete_ident(&self, ident: &str, token: &Token) -> bool;
fn is_obsolete_ident(&self, ident: &str) -> bool;
fn eat_obsolete_ident(&self, ident: &str) -> bool;
fn try_parse_obsolete_with(&self) -> bool;
fn try_parse_obsolete_priv_section(&self, attrs: &[Attribute]) -> bool;
}
impl ParserObsoleteMethods for Parser {
/// Reports an obsolete syntax non-fatal error.
fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
let (kind_str, desc) = match kind {
ObsoleteLet => (
"`let` in field declaration",
"declare fields as `field: Type`"
),
ObsoleteFieldTerminator => (
"field declaration terminated with semicolon",
"fields are now separated by commas"
),
ObsoleteWith => (
"with",
"record update is done with `..`, e.g. \
`MyStruct { foo: bar, .. baz }`"
),
2012-09-10 18:00:03 -07:00
ObsoleteClassTraits => (
"class traits",
"implemented traits are specified on the impl, as in \
`impl foo : bar {`"
),
ObsoletePrivSection => (
"private section",
"the `priv` keyword is applied to individual items, methods, \
and fields"
),
ObsoleteModeInFnType => (
"mode without identifier in fn type",
"to use a (deprecated) mode in a fn type, you should \
give the argument an explicit name (like `&&v: int`)"
),
ObsoleteMoveInit => (
"initializer-by-move",
"Write `let foo = move bar` instead"
),
ObsoleteBinaryMove => (
"binary move",
"Write `foo = move bar` instead"
),
ObsoleteSwap => (
"swap",
2013-06-24 20:40:33 -04:00
"Use std::util::{swap, replace} instead"
),
ObsoleteUnsafeBlock => (
"non-standalone unsafe block",
"use an inner `unsafe { ... }` block instead"
),
ObsoleteUnenforcedBound => (
"unenforced type parameter bound",
"use trait bounds on the functions that take the type as \
arguments, not on the types themselves"
),
ObsoleteImplSyntax => (
"colon-separated impl syntax",
"write `impl Trait for Type`"
),
2013-02-25 15:54:13 -08:00
ObsoleteMutOwnedPointer => (
"const or mutable owned pointer",
2013-02-25 15:54:13 -08:00
"mutability inherits through `~` pointers; place the `~` box
in a mutable location, like a mutable local variable or an \
`@mut` box"
),
ObsoleteMutVector => (
"const or mutable vector",
"mutability inherits through `~` pointers; place the vector \
in a mutable location, like a mutable local variable or an \
`@mut` box"
),
ObsoleteImplVisibility => (
"visibility-qualified implementation",
"`pub` or `priv` goes on individual functions; remove the \
`pub` or `priv`"
),
ObsoleteRecordType => (
"structural record type",
"use a structure instead"
),
ObsoleteRecordPattern => (
"structural record pattern",
"use a structure instead"
),
ObsoletePostFnTySigil => (
"fn sigil in postfix position",
"Rather than `fn@`, `fn~`, or `fn&`, \
write `@fn`, `~fn`, and `&fn` respectively"
),
ObsoleteBareFnType => (
"bare function type",
"use `&fn` or `extern fn` instead"
),
2013-03-07 18:59:00 -08:00
ObsoleteNewtypeEnum => (
"newtype enum",
"instead of `enum Foo = int`, write `struct Foo(int)`"
),
ObsoleteMode => (
"obsolete argument mode",
"replace `-` or `++` mode with `+`"
),
ObsoleteImplicitSelf => (
"implicit self",
"use an explicit `self` declaration or declare the method as \
static"
),
ObsoleteLifetimeNotation => (
"`/` lifetime notation",
"instead of `&foo/bar`, write `&'foo bar`; instead of \
`bar/&foo`, write `&bar<'foo>"
),
ObsoletePurity => (
"pure function",
"remove `pure`"
),
ObsoleteStaticMethod => (
"`static` notation",
"`static` is superfluous; remove it"
),
2013-03-22 14:51:35 -07:00
ObsoleteConstItem => (
"`const` item",
"`const` items are now `static` items; replace `const` with \
`static`"
),
2013-03-22 19:22:12 -07:00
ObsoleteFixedLengthVectorType => (
"fixed-length vector notation",
"instead of `[T * N]`, write `[T, ..N]`"
),
ObsoleteNamedExternModule => (
"named external module",
"instead of `extern mod foo { ... }`, write `mod foo { \
extern { ... } }`"
),
ObsoleteMultipleLocalDecl => (
"declaration of multiple locals at once",
"instead of e.g. `let a = 1, b = 2`, write \
`let (a, b) = (1, 2)`."
),
ObsoleteMutWithMultipleBindings => (
"`mut` with multiple bindings",
"use multiple local declarations instead of e.g. `let mut \
(x, y) = ...`."
),
ObsoleteExternVisibility => (
"`pub extern` or `priv extern`",
"place the `pub` or `priv` on the individual external items \
instead"
),
ObsoleteUnsafeExternFn => (
"unsafe external function",
"external functions are always unsafe; remove the `unsafe` \
keyword"
),
ObsoletePrivVisibility => (
"`priv` not necessary",
"an item without a visibility qualifier is private by default"
),
ObsoleteTraitFuncVisibility => (
"visibility not necessary",
"trait functions inherit the visibility of the trait itself"
),
ObsoleteConstPointer => (
"const pointer",
"instead of `&const Foo` or `@const Foo`, write `&Foo` or \
`@Foo`"
),
};
self.report(sp, kind, kind_str, desc);
}
// Reports an obsolete syntax non-fatal error, and returns
// a placeholder expression
fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr {
self.obsolete(sp, kind);
self.mk_expr(sp.lo, sp.hi, expr_lit(@respan(sp, lit_nil)))
}
fn report(&self,
sp: span,
kind: ObsoleteSyntax,
kind_str: &str,
desc: &str) {
self.span_err(sp, fmt!("obsolete syntax: %s", kind_str));
2013-03-21 15:41:37 -04:00
if !self.obsolete_set.contains(&kind) {
self.sess.span_diagnostic.handler().note(fmt!("%s", desc));
2013-03-21 15:41:37 -04:00
self.obsolete_set.insert(kind);
}
}
fn token_is_obsolete_ident(&self, ident: &str, token: &Token)
-> bool {
match *token {
token::IDENT(sid, _) => {
str::eq_slice(self.id_to_str(sid), ident)
}
_ => false
}
}
fn is_obsolete_ident(&self, ident: &str) -> bool {
self.token_is_obsolete_ident(ident, self.token)
}
fn eat_obsolete_ident(&self, ident: &str) -> bool {
if self.is_obsolete_ident(ident) {
self.bump();
true
} else {
false
}
}
fn try_parse_obsolete_with(&self) -> bool {
if *self.token == token::COMMA
2013-07-02 12:47:32 -07:00
&& self.look_ahead(1,
|t| self.token_is_obsolete_ident("with", t)) {
self.bump();
}
if self.eat_obsolete_ident("with") {
self.obsolete(*self.last_span, ObsoleteWith);
self.parse_expr();
true
} else {
false
}
}
fn try_parse_obsolete_priv_section(&self, attrs: &[Attribute])
-> bool {
2013-07-02 12:47:32 -07:00
if self.is_keyword(keywords::Priv) &&
self.look_ahead(1, |t| *t == token::LBRACE) {
self.obsolete(*self.span, ObsoletePrivSection);
self.eat_keyword(keywords::Priv);
self.bump();
while *self.token != token::RBRACE {
self.parse_single_struct_field(ast::private, attrs.to_owned());
}
self.bump();
true
} else {
false
}
}
}