Implement support for indicating the stability of items.
There are 6 new compiler recognised attributes: deprecated, experimental,
unstable, stable, frozen, locked (these levels are taken directly from
Node's "stability index"[1]). These indicate the stability of the
item to which they are attached; e.g. `#[deprecated] fn foo() { .. }`
says that `foo` is deprecated.
This comes with 3 lints for the first 3 levels (with matching names) that
will detect the use of items marked with them (the `unstable` lint
includes items with no stability attribute). The attributes can be given
a short text note that will be displayed by the lint. An example:
#[warn(unstable)]; // `allow` by default
#[deprecated="use `bar`"]
fn foo() { }
#[stable]
fn bar() { }
fn baz() { }
fn main() {
foo(); // "warning: use of deprecated item: use `bar`"
bar(); // all fine
baz(); // "warning: use of unmarked item"
}
The lints currently only check the "edges" of the AST: i.e. functions,
methods[2], structs and enum variants. Any stability attributes on modules,
enums, traits and impls are not checked.
[1]: http://nodejs.org/api/documentation.html
[2]: the method check is currently incorrect and doesn't work.
This commit is contained in:
parent
7048e05d5f
commit
506f69aed7
8 changed files with 745 additions and 3 deletions
|
|
@ -80,6 +80,26 @@ pub enum ast_node {
|
|||
node_callee_scope(@Expr)
|
||||
}
|
||||
|
||||
impl ast_node {
|
||||
pub fn with_attrs<T>(&self, f: &fn(Option<&[Attribute]>) -> T) -> T {
|
||||
let attrs = match *self {
|
||||
node_item(i, _) => Some(i.attrs.as_slice()),
|
||||
node_foreign_item(fi, _, _, _) => Some(fi.attrs.as_slice()),
|
||||
node_trait_method(tm, _, _) => match *tm {
|
||||
required(ref type_m) => Some(type_m.attrs.as_slice()),
|
||||
provided(m) => Some(m.attrs.as_slice())
|
||||
},
|
||||
node_method(m, _, _) => Some(m.attrs.as_slice()),
|
||||
node_variant(ref v, _, _) => Some(v.node.attrs.as_slice()),
|
||||
// unit/tuple structs take the attributes straight from
|
||||
// the struct definition.
|
||||
node_struct_ctor(_, strct, _) => Some(strct.attrs.as_slice()),
|
||||
_ => None
|
||||
};
|
||||
f(attrs)
|
||||
}
|
||||
}
|
||||
|
||||
pub type map = @mut HashMap<NodeId, ast_node>;
|
||||
|
||||
pub struct Ctx {
|
||||
|
|
|
|||
|
|
@ -313,6 +313,44 @@ pub fn test_cfg<AM: AttrMetaMethods, It: Iterator<AM>>
|
|||
no_cfgs || some_cfg_matches
|
||||
}
|
||||
|
||||
/// Represents the #[deprecated="foo"] (etc) attributes.
|
||||
pub struct Stability {
|
||||
level: StabilityLevel,
|
||||
text: Option<@str>
|
||||
}
|
||||
|
||||
/// The available stability levels.
|
||||
#[deriving(Eq,Ord,Clone)]
|
||||
pub enum StabilityLevel {
|
||||
Deprecated,
|
||||
Experimental,
|
||||
Unstable,
|
||||
Stable,
|
||||
Frozen,
|
||||
Locked
|
||||
}
|
||||
|
||||
/// Find the first stability attribute. `None` if none exists.
|
||||
pub fn find_stability<AM: AttrMetaMethods, It: Iterator<AM>>(mut metas: It) -> Option<Stability> {
|
||||
for m in metas {
|
||||
let level = match m.name().as_slice() {
|
||||
"deprecated" => Deprecated,
|
||||
"experimental" => Experimental,
|
||||
"unstable" => Unstable,
|
||||
"stable" => Stable,
|
||||
"frozen" => Frozen,
|
||||
"locked" => Locked,
|
||||
_ => loop // not a stability level
|
||||
};
|
||||
|
||||
return Some(Stability {
|
||||
level: level,
|
||||
text: m.value_str()
|
||||
});
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn require_unique_names(diagnostic: @mut span_handler,
|
||||
metas: &[@MetaItem]) {
|
||||
let mut set = HashSet::new();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue