18
18
//! * Library features have at most one `since` value
19
19
20
20
use std:: collections:: HashMap ;
21
+ use std:: fmt;
21
22
use std:: fs:: File ;
22
23
use std:: io:: prelude:: * ;
23
24
use std:: path:: Path ;
24
25
25
- const STATUSES : & ' static [ & ' static str ] = & [
26
- "Active" , "Deprecated" , "Removed" , "Accepted" ,
27
- ] ;
26
+ #[ derive( PartialEq ) ]
27
+ enum Status {
28
+ Stable ,
29
+ Unstable ,
30
+ }
31
+
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" ,
37
+ } ;
38
+ fmt:: Display :: fmt ( as_str, f)
39
+ }
40
+ }
41
+
28
42
29
43
struct Feature {
30
44
name : String ,
45
+ level : Status ,
31
46
since : String ,
32
- status : String ,
33
47
}
34
48
35
49
struct LibFeature {
36
- level : String ,
50
+ level : Status ,
37
51
since : String ,
38
52
}
39
53
40
54
pub fn check ( path : & Path , bad : & mut bool ) {
41
55
let features = collect_lang_features ( & path. join ( "libsyntax/feature_gate.rs" ) ) ;
56
+ assert ! ( !features. is_empty( ) ) ;
42
57
let mut lib_features = HashMap :: < String , LibFeature > :: new ( ) ;
43
58
44
59
let mut contents = String :: new ( ) ;
@@ -48,7 +63,7 @@ pub fn check(path: &Path, bad: &mut bool) {
48
63
let filename = file. file_name ( ) . unwrap ( ) . to_string_lossy ( ) ;
49
64
if !filename. ends_with ( ".rs" ) || filename == "features.rs" ||
50
65
filename == "diagnostic_list.rs" {
51
- return
66
+ return ;
52
67
}
53
68
54
69
contents. truncate ( 0 ) ;
@@ -60,24 +75,24 @@ pub fn check(path: &Path, bad: &mut bool) {
60
75
* bad = true ;
61
76
} ;
62
77
let level = if line. contains ( "[unstable(" ) {
63
- "unstable"
78
+ Status :: Unstable
64
79
} else if line. contains ( "[stable(" ) {
65
- "stable"
80
+ Status :: Stable
66
81
} else {
67
- continue
82
+ continue ;
68
83
} ;
69
84
let feature_name = match find_attr_val ( line, "feature" ) {
70
85
Some ( name) => name,
71
86
None => {
72
87
err ( "malformed stability attribute" ) ;
73
- continue
88
+ continue ;
74
89
}
75
90
} ;
76
91
let since = match find_attr_val ( line, "since" ) {
77
92
Some ( name) => name,
78
- None if level == "stable" => {
93
+ None if level == Status :: Stable => {
79
94
err ( "malformed stability attribute" ) ;
80
- continue
95
+ continue ;
81
96
}
82
97
None => "None" ,
83
98
} ;
@@ -92,27 +107,34 @@ pub fn check(path: &Path, bad: &mut bool) {
92
107
if s. since != since {
93
108
err ( "different `since` than before" ) ;
94
109
}
95
- continue
110
+ continue ;
96
111
}
97
- lib_features. insert ( feature_name. to_owned ( ) , LibFeature {
98
- level : level. to_owned ( ) ,
99
- since : since. to_owned ( ) ,
100
- } ) ;
112
+ lib_features. insert ( feature_name. to_owned ( ) ,
113
+ LibFeature {
114
+ level : level,
115
+ since : since. to_owned ( ) ,
116
+ } ) ;
101
117
}
102
118
} ) ;
103
119
104
120
if * bad {
105
- return
121
+ return ;
106
122
}
107
123
108
124
let mut lines = Vec :: new ( ) ;
109
125
for feature in features {
110
126
lines. push ( format ! ( "{:<32} {:<8} {:<12} {:<8}" ,
111
- feature. name, "lang" , feature. status, feature. since) ) ;
127
+ feature. name,
128
+ "lang" ,
129
+ feature. level,
130
+ feature. since) ) ;
112
131
}
113
132
for ( name, feature) in lib_features {
114
133
lines. push ( format ! ( "{:<32} {:<8} {:<12} {:<8}" ,
115
- name, "lib" , feature. level, feature. since) ) ;
134
+ name,
135
+ "lib" ,
136
+ feature. level,
137
+ feature. since) ) ;
116
138
}
117
139
118
140
lines. sort ( ) ;
@@ -122,39 +144,32 @@ pub fn check(path: &Path, bad: &mut bool) {
122
144
}
123
145
124
146
fn find_attr_val < ' a > ( line : & ' a str , attr : & str ) -> Option < & ' a str > {
125
- line. find ( attr) . and_then ( |i| {
126
- line[ i..] . find ( "\" " ) . map ( |j| i + j + 1 )
127
- } ) . and_then ( |i| {
128
- line[ i..] . find ( "\" " ) . map ( |j| ( i, i + j) )
129
- } ) . map ( |( i, j) | {
130
- & line[ i..j]
131
- } )
147
+ line. find ( attr)
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] )
132
151
}
133
152
134
153
fn collect_lang_features ( path : & Path ) -> Vec < Feature > {
135
154
let mut contents = String :: new ( ) ;
136
155
t ! ( t!( File :: open( path) ) . read_to_string( & mut contents) ) ;
137
156
138
- let mut features = Vec :: new ( ) ;
139
- for line in contents. lines ( ) . map ( |l| l. trim ( ) ) {
140
- if !STATUSES . iter ( ) . any ( |s| line. starts_with ( & format ! ( "({}" , s) ) ) {
141
- continue
142
- }
143
- let mut parts = line. split ( "," ) ;
144
- let status = match & parts. next ( ) . unwrap ( ) . trim ( ) . replace ( "(" , "" ) [ ..] {
145
- "active" => "unstable" ,
146
- "removed" => "unstable" ,
147
- "accepted" => "stable" ,
148
- s => panic ! ( "unknown status: {}" , s) ,
149
- } ;
150
- let name = parts. next ( ) . unwrap ( ) . trim ( ) . to_owned ( ) ;
151
- let since = parts. next ( ) . unwrap ( ) . trim ( ) . replace ( "\" " , "" ) ;
152
-
153
- features. push ( Feature {
154
- name : name,
155
- since : since,
156
- status : status. to_owned ( ) ,
157
- } ) ;
158
- }
159
- return features
157
+ contents. lines ( )
158
+ . filter_map ( |line| {
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 ,
164
+ _ => return None ,
165
+ } ;
166
+ let name = parts. next ( ) . unwrap ( ) . trim ( ) ;
167
+ let since = parts. next ( ) . unwrap ( ) . trim ( ) . trim_matches ( '"' ) ;
168
+ Some ( Feature {
169
+ name : name. to_owned ( ) ,
170
+ level : level,
171
+ since : since. to_owned ( ) ,
172
+ } )
173
+ } )
174
+ . collect ( )
160
175
}
0 commit comments