about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2013-08-31 17:13:57 +1000
committerHuon Wilson <dbau.pp+github@gmail.com>2013-09-04 00:12:27 +1000
commit506f69aed7e2f5dfdd2134ae0c74e47559e1c649 (patch)
tree4358920c7b2fe144f6a00a92875d629e09580eff /src/libsyntax
parent7048e05d5fb6aae8647494148a89bd902e5a913f (diff)
downloadrust-506f69aed7e2f5dfdd2134ae0c74e47559e1c649.tar.gz
rust-506f69aed7e2f5dfdd2134ae0c74e47559e1c649.zip
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.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast_map.rs20
-rw-r--r--src/libsyntax/attr.rs38
2 files changed, 58 insertions, 0 deletions
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index ccaadcbad4d..e3023b919f8 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -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 {
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 2ed03040fa1..fd0887de722 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -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();