1
1
#![ feature( rustc_private) ]
2
+ #![ feature( result_map_or_else) ]
2
3
3
4
extern crate getopts;
4
5
extern crate rustc;
5
6
extern crate rustc_codegen_utils;
6
7
extern crate rustc_driver;
7
8
extern crate rustc_errors;
9
+ extern crate rustc_interface;
8
10
extern crate rustc_metadata;
9
11
extern crate syntax;
10
12
11
13
use log:: debug;
12
14
use rustc:: { hir:: def_id:: * , middle:: cstore:: ExternCrate } ;
13
- use rustc_driver:: { driver:: CompileController , Compilation } ;
15
+ use rustc_driver:: Callbacks ;
16
+ use rustc_interface:: interface;
14
17
use semverver:: run_analysis;
15
- use std:: convert:: TryInto ;
16
18
use std:: {
17
19
path:: Path ,
18
20
process:: { exit, Command } ,
@@ -33,7 +35,7 @@ fn main() {
33
35
34
36
debug ! ( "running rust-semverver compiler driver" ) ;
35
37
exit (
36
- rustc_driver :: run ( move || {
38
+ {
37
39
use std:: env;
38
40
39
41
if std:: env:: args ( ) . any ( |a| a == "--version" || a == "-V" ) {
@@ -86,59 +88,67 @@ fn main() {
86
88
. collect ( )
87
89
} ;
88
90
89
- let verbose = std:: env:: var ( "RUST_SEMVER_VERBOSE" ) == Ok ( "true" . to_string ( ) ) ;
90
- let api_guidelines = std:: env:: var ( "RUST_SEMVER_API_GUIDELINES" ) == Ok ( "true" . to_string ( ) ) ;
91
- let version = if let Ok ( ver) = std:: env:: var ( "RUST_SEMVER_CRATE_VERSION" ) {
92
- ver
93
- } else {
94
- "no_version" . to_owned ( )
95
- } ;
96
-
97
- let mut controller = CompileController :: basic ( ) ;
98
-
99
- controller. after_analysis . callback = Box :: new ( move |state| {
100
- debug ! ( "running rust-semverver after_analysis..." ) ;
101
- let tcx = state. tcx . unwrap ( ) ;
102
-
103
- // To select the old and new crates we look at the position of the declaration in the
104
- // source file. The first one will be the `old` and the other will be `new`. This is
105
- // unfortunately a bit hacky... See issue #64 for details.
106
-
107
- let mut crates: Vec < _ > = tcx
108
- . crates ( )
109
- . iter ( )
110
- . flat_map ( |crate_num| {
111
- let def_id = DefId {
112
- krate : * crate_num,
113
- index : CRATE_DEF_INDEX ,
114
- } ;
115
-
116
- match * tcx. extern_crate ( def_id) {
117
- Some ( ExternCrate {
118
- span, direct : true , ..
119
- } ) if span. data ( ) . lo . to_usize ( ) > 0 => Some ( ( span. data ( ) . lo . to_usize ( ) , def_id) ) ,
120
- _ => None ,
91
+ struct SemverCallbacks ;
92
+
93
+ impl Callbacks for SemverCallbacks {
94
+ fn after_analysis ( & mut self , compiler : & interface:: Compiler ) -> bool {
95
+ debug ! ( "running rust-semverver after_analysis callback" ) ;
96
+
97
+ let verbose =
98
+ std:: env:: var ( "RUST_SEMVER_VERBOSE" ) == Ok ( "true" . to_string ( ) ) ;
99
+ let api_guidelines =
100
+ std:: env:: var ( "RUST_SEMVER_API_GUIDELINES" ) == Ok ( "true" . to_string ( ) ) ;
101
+ let version = if let Ok ( ver) = std:: env:: var ( "RUST_SEMVER_CRATE_VERSION" ) {
102
+ ver
103
+ } else {
104
+ "no_version" . to_owned ( )
105
+ } ;
106
+
107
+ compiler. global_ctxt ( ) . unwrap ( ) . peek_mut ( ) . enter ( |tcx| {
108
+ // To select the old and new crates we look at the position of the
109
+ // declaration in the source file. The first one will be the `old`
110
+ // and the other will be `new`. This is unfortunately a bit hacky...
111
+ // See issue #64 for details.
112
+
113
+ let mut crates: Vec < _ > = tcx
114
+ . crates ( )
115
+ . iter ( )
116
+ . flat_map ( |crate_num| {
117
+ let def_id = DefId {
118
+ krate : * crate_num,
119
+ index : CRATE_DEF_INDEX ,
120
+ } ;
121
+
122
+ match * tcx. extern_crate ( def_id) {
123
+ Some ( ExternCrate {
124
+ span, direct : true , ..
125
+ } ) if span. data ( ) . lo . to_usize ( ) > 0 =>
126
+ Some ( ( span. data ( ) . lo . to_usize ( ) , def_id) ) ,
127
+ _ => None ,
128
+ }
129
+ } )
130
+ . collect ( ) ;
131
+
132
+ crates. sort_by_key ( |& ( span_lo, _) | span_lo) ;
133
+
134
+ if let [ ( _, old_def_id) , ( _, new_def_id) ] = * crates. as_slice ( ) {
135
+ debug ! ( "running semver analysis" ) ;
136
+ let changes = run_analysis ( tcx, old_def_id, new_def_id) ;
137
+ changes. output ( tcx. sess , & version, verbose, api_guidelines) ;
138
+ } else {
139
+ tcx. sess . err ( "could not find crate old and new crates" ) ;
121
140
}
122
- } )
123
- . collect ( ) ;
141
+ } ) ;
124
142
125
- crates . sort_by_key ( | & ( span_lo , _ ) | span_lo ) ;
143
+ debug ! ( "rust-semverver after_analysis callback finished!" ) ;
126
144
127
- if let [ ( _, old_def_id) , ( _, new_def_id) ] = * crates. as_slice ( ) {
128
- debug ! ( "running semver analysis" ) ;
129
- let changes = run_analysis ( tcx, old_def_id, new_def_id) ;
130
- changes. output ( tcx. sess , & version, verbose, api_guidelines) ;
131
- } else {
132
- tcx. sess . err ( "could not find crate old and new crates" ) ;
145
+ false
133
146
}
134
-
135
- debug ! ( "running rust-semverver after_analysis finished!" ) ;
136
- } ) ;
137
- controller. after_analysis . stop = Compilation :: Stop ;
147
+ }
138
148
139
149
let args = args;
140
- rustc_driver:: run_compiler ( & args, Box :: new ( controller ) , None , None )
141
- } ) . try_into ( )
142
- . expect ( "exit code too large" ) ,
150
+ rustc_driver:: run_compiler ( & args, & mut SemverCallbacks , None , None )
151
+ }
152
+ . map_or_else ( |_| 1 , |_| 0 ) ,
143
153
)
144
154
}
0 commit comments