]>
git.proxmox.com Git - rustc.git/blob - src/tools/tidy/src/features.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.
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.
11 //! Tidy check to ensure that unstable features are all in order
13 //! This check will ensure properties like:
15 //! * All stability attributes look reasonably well formed
16 //! * The set of library features is disjoint from the set of language features
17 //! * Library features have at most one stability level
18 //! * Library features have at most one `since` value
20 use std
::collections
::HashMap
;
23 use std
::io
::prelude
::*;
32 impl fmt
::Display
for Status
{
33 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
34 let as_str
= match *self {
35 Status
::Stable
=> "stable",
36 Status
::Unstable
=> "unstable",
38 fmt
::Display
::fmt(as_str
, f
)
54 pub fn check(path
: &Path
, bad
: &mut bool
) {
55 let features
= collect_lang_features(&path
.join("libsyntax/feature_gate.rs"));
56 assert
!(!features
.is_empty());
57 let mut lib_features
= HashMap
::<String
, LibFeature
>::new();
59 let mut contents
= String
::new();
61 &mut |path
| super::filter_dirs(path
) || path
.ends_with("src/test"),
63 let filename
= file
.file_name().unwrap().to_string_lossy();
64 if !filename
.ends_with(".rs") || filename
== "features.rs" ||
65 filename
== "diagnostic_list.rs" {
70 t
!(t
!(File
::open(&file
), &file
).read_to_string(&mut contents
));
72 for (i
, line
) in contents
.lines().enumerate() {
73 let mut err
= |msg
: &str| {
74 println
!("{}:{}: {}", file
.display(), i
+ 1, msg
);
77 let level
= if line
.contains("[unstable(") {
79 } else if line
.contains("[stable(") {
84 let feature_name
= match find_attr_val(line
, "feature") {
87 err("malformed stability attribute");
91 let since
= match find_attr_val(line
, "since") {
93 None
if level
== Status
::Stable
=> {
94 err("malformed stability attribute");
100 if features
.iter().any(|f
| f
.name
== feature_name
) {
101 err("duplicating a lang feature");
103 if let Some(ref s
) = lib_features
.get(feature_name
) {
104 if s
.level
!= level
{
105 err("different stability level than before");
107 if s
.since
!= since
{
108 err("different `since` than before");
112 lib_features
.insert(feature_name
.to_owned(),
115 since
: since
.to_owned(),
124 let mut lines
= Vec
::new();
125 for feature
in features
{
126 lines
.push(format
!("{:<32} {:<8} {:<12} {:<8}",
132 for (name
, feature
) in lib_features
{
133 lines
.push(format
!("{:<32} {:<8} {:<12} {:<8}",
142 println
!("* {}", line
);
146 fn find_attr_val
<'a
>(line
: &'a
str, attr
: &str) -> Option
<&'a
str> {
148 .and_then(|i
| line
[i
..].find('
"').map(|j| i + j + 1))
149 .and_then(|i| line[i..].find('"'
).map(|j
| (i
, i
+ j
)))
150 .map(|(i
, j
)| &line
[i
..j
])
153 fn collect_lang_features(path
: &Path
) -> Vec
<Feature
> {
154 let mut contents
= String
::new();
155 t
!(t
!(File
::open(path
)).read_to_string(&mut contents
));
159 let mut parts
= line
.trim().split(",");
160 let level
= match parts
.next().map(|l
| l
.trim().trim_left_matches('
('
)) {
161 Some("active") => Status
::Unstable
,
162 Some("removed") => Status
::Unstable
,
163 Some("accepted") => Status
::Stable
,
166 let name
= parts
.next().unwrap().trim();
167 let since
= parts
.next().unwrap().trim().trim_matches('
"');
169 name: name.to_owned(),
171 since: since.to_owned(),