@@ -23,6 +23,9 @@ use std::{
23
23
use syntax:: symbol:: Symbol ;
24
24
use syntax_pos:: Span ;
25
25
26
+ use serde:: Serialize ;
27
+ use serde:: ser:: { Serializer , SerializeStruct } ;
28
+
26
29
/// The categories we use when analyzing changes between crate versions.
27
30
///
28
31
/// These directly correspond to the semantic versioning spec, with the exception that some
@@ -31,7 +34,7 @@ use syntax_pos::Span;
31
34
/// exotic and/or unlikely scenarios, while we have a separate category for them.
32
35
///
33
36
/// [1]: https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md
34
- #[ derive( Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
37
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord , Serialize ) ]
35
38
pub enum ChangeCategory {
36
39
/// A patch-level change - no change to the public API of a crate.
37
40
Patch ,
@@ -64,33 +67,60 @@ impl<'a> fmt::Display for ChangeCategory {
64
67
}
65
68
}
66
69
70
+ pub struct RSymbol ( pub Symbol ) ;
71
+
72
+ impl Serialize for RSymbol {
73
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
74
+ where S : Serializer ,
75
+ {
76
+ serializer. serialize_str ( & format ! ( "{}" , self . 0 ) )
77
+ }
78
+ }
79
+
67
80
/// Different ways to refer to a changed item.
68
81
///
69
82
/// Used in the header of a change description to identify an item that was subject to change.
70
83
pub enum Name {
71
84
/// The changed item's name.
72
- Symbol ( Symbol ) ,
85
+ Symbol ( RSymbol ) ,
73
86
/// A textutal description of the item, used for trait impls.
74
87
ImplDesc ( String ) ,
75
88
}
76
89
77
- impl < ' a > fmt:: Display for Name {
90
+ impl Name {
91
+ pub fn symbol ( symbol : Symbol ) -> Self {
92
+ Name :: Symbol ( RSymbol ( symbol) )
93
+ }
94
+ }
95
+
96
+ impl fmt:: Display for Name {
78
97
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
79
98
match * self {
80
- Name :: Symbol ( name) => write ! ( f, "`{}`" , name) ,
99
+ Name :: Symbol ( ref name) => write ! ( f, "`{}`" , name. 0 ) ,
81
100
Name :: ImplDesc ( ref desc) => write ! ( f, "`{}`" , desc) ,
82
101
}
83
102
}
84
103
}
85
104
105
+ impl Serialize for Name {
106
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
107
+ where S : Serializer ,
108
+ {
109
+ match * self {
110
+ Name :: Symbol ( ref name) => serializer. serialize_str ( & format ! ( "{}" , name. 0 ) ) ,
111
+ Name :: ImplDesc ( ref desc) => serializer. serialize_str ( & format ! ( "{}" , desc) ) ,
112
+ }
113
+ }
114
+ }
115
+
86
116
/// A change record of newly introduced or removed paths to an item.
87
117
///
88
118
/// NB: `Eq` and `Ord` instances are constructed to only regard the span of the associated item
89
119
/// definition. All other spans are only present for later display of the change record.
90
120
pub struct PathChange {
91
121
/// The name of the item - this doesn't use `Name` because this change structure only gets
92
122
/// generated for removals and additions of named items, not impls.
93
- name : Symbol ,
123
+ name : RSymbol ,
94
124
/// The definition span of the item.
95
125
def_span : Span ,
96
126
/// The set of spans of added exports of the item.
@@ -103,7 +133,7 @@ impl PathChange {
103
133
/// Construct a new empty path change record for an item.
104
134
fn new ( name : Symbol , def_span : Span ) -> Self {
105
135
Self {
106
- name,
136
+ name : RSymbol ( name ) ,
107
137
def_span,
108
138
additions : BTreeSet :: new ( ) ,
109
139
removals : BTreeSet :: new ( ) ,
@@ -142,7 +172,7 @@ impl PathChange {
142
172
return ;
143
173
}
144
174
145
- let msg = format ! ( "path changes to `{}`" , self . name) ;
175
+ let msg = format ! ( "path changes to `{}`" , self . name. 0 ) ;
146
176
let mut builder = if cat == Breaking {
147
177
session. struct_span_err ( self . def_span , & msg)
148
178
} else {
@@ -189,6 +219,18 @@ impl Ord for PathChange {
189
219
}
190
220
}
191
221
222
+ impl Serialize for PathChange {
223
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
224
+ where S : Serializer ,
225
+ {
226
+ let mut state = serializer. serialize_struct ( "PathChange" , 3 ) ?;
227
+ state. serialize_field ( "name" , & self . name ) ?;
228
+ state. serialize_field ( "additions" , & !self . additions . is_empty ( ) ) ?;
229
+ state. serialize_field ( "removals" , & !self . removals . is_empty ( ) ) ?;
230
+ state. end ( )
231
+ }
232
+ }
233
+
192
234
/// The types of changes we identify between items present in both crate versions.
193
235
#[ derive( Clone , Debug ) ]
194
236
pub enum ChangeType < ' tcx > {
@@ -605,6 +647,14 @@ impl<'a> fmt::Display for ChangeType<'a> {
605
647
}
606
648
}
607
649
650
+ impl < ' tcx > Serialize for ChangeType < ' tcx > {
651
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
652
+ where S : Serializer ,
653
+ {
654
+ serializer. serialize_str ( & format ! ( "{}" , self ) )
655
+ }
656
+ }
657
+
608
658
/// A change record of an item present in both crate versions.
609
659
///
610
660
/// NB: `Eq` and `Ord` instances are constucted to only regard the *new* span of the associated
@@ -758,6 +808,21 @@ impl<'tcx> Ord for Change<'tcx> {
758
808
}
759
809
}
760
810
811
+ impl < ' tcx > Serialize for Change < ' tcx > {
812
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
813
+ where S : Serializer ,
814
+ {
815
+ let mut state = serializer. serialize_struct ( "Change" , 3 ) ?;
816
+ state. serialize_field ( "name" , & self . name ) ?;
817
+ state. serialize_field ( "max_category" , & self . max ) ?;
818
+
819
+ let changes: Vec < _ > = self . changes . iter ( ) . map ( |( t, _) | t. clone ( ) ) . collect ( ) ;
820
+
821
+ state. serialize_field ( "changes" , & changes) ?;
822
+ state. end ( )
823
+ }
824
+ }
825
+
761
826
/// The total set of changes recorded for two crate versions.
762
827
#[ derive( Default ) ]
763
828
pub struct ChangeSet < ' tcx > {
@@ -811,7 +876,7 @@ impl<'tcx> ChangeSet<'tcx> {
811
876
new_span : Span ,
812
877
output : bool ,
813
878
) {
814
- let change = Change :: new ( Name :: Symbol ( name) , new_span, output) ;
879
+ let change = Change :: new ( Name :: symbol ( name) , new_span, output) ;
815
880
816
881
self . spans . insert ( old_span, old_def_id) ;
817
882
self . spans . insert ( new_span, new_def_id) ;
@@ -874,15 +939,7 @@ impl<'tcx> ChangeSet<'tcx> {
874
939
. map_or ( false , Change :: trait_item_breaking)
875
940
}
876
941
877
- /// Format the contents of a change set for user output.
878
- pub fn output (
879
- & self ,
880
- session : & Session ,
881
- version : & str ,
882
- verbose : bool ,
883
- compact : bool ,
884
- api_guidelines : bool ,
885
- ) {
942
+ fn get_new_version ( & self , version : & str ) -> Option < String > {
886
943
if let Ok ( mut new_version) = Version :: parse ( version) {
887
944
if new_version. major == 0 {
888
945
new_version. increment_patch ( ) ;
@@ -894,6 +951,41 @@ impl<'tcx> ChangeSet<'tcx> {
894
951
}
895
952
}
896
953
954
+ Some ( format ! ( "{}" , new_version) )
955
+ } else {
956
+ None
957
+ }
958
+ }
959
+
960
+ pub fn output_json ( & self , version : & str ) {
961
+ #[ derive( Serialize ) ]
962
+ struct Output < ' a , ' tcx > {
963
+ old_version : String ,
964
+ new_version : String ,
965
+ changes : & ' a ChangeSet < ' tcx > ,
966
+ }
967
+
968
+ let new_version = self . get_new_version ( version) . unwrap_or_else ( || "parse error" . to_owned ( ) ) ;
969
+
970
+ let output = Output {
971
+ old_version : version. to_owned ( ) ,
972
+ new_version,
973
+ changes : self ,
974
+ } ;
975
+
976
+ println ! ( "{}" , serde_json:: to_string( & output) . unwrap( ) ) ;
977
+ }
978
+
979
+ /// Format the contents of a change set for user output.
980
+ pub fn output (
981
+ & self ,
982
+ session : & Session ,
983
+ version : & str ,
984
+ verbose : bool ,
985
+ compact : bool ,
986
+ api_guidelines : bool ,
987
+ ) {
988
+ if let Some ( new_version) = self . get_new_version ( version) {
897
989
if compact {
898
990
println ! ( "{}" , new_version) ;
899
991
} else {
@@ -932,6 +1024,23 @@ impl<'tcx> ChangeSet<'tcx> {
932
1024
}
933
1025
}
934
1026
1027
+ impl < ' tcx > Serialize for ChangeSet < ' tcx > {
1028
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
1029
+ where S : Serializer ,
1030
+ {
1031
+ let mut state = serializer. serialize_struct ( "ChangeSet" , 3 ) ?;
1032
+
1033
+ let path_changes: Vec < _ > = self . path_changes . values ( ) . collect ( ) ;
1034
+ state. serialize_field ( "path_changes" , & path_changes) ?;
1035
+
1036
+ let changes: Vec < _ > = self . changes . values ( ) . filter ( |c| c. output && !c. changes . is_empty ( ) ) . collect ( ) ;
1037
+ state. serialize_field ( "changes" , & changes) ?;
1038
+
1039
+ state. serialize_field ( "max_category" , & self . max ) ?;
1040
+ state. end ( )
1041
+ }
1042
+ }
1043
+
935
1044
#[ cfg( test) ]
936
1045
pub mod tests {
937
1046
pub use super :: * ;
@@ -1150,7 +1259,7 @@ pub mod tests {
1150
1259
changes : Vec < ( ChangeType_ , Option < Span_ > ) > ,
1151
1260
) -> Change < ' a > {
1152
1261
let mut interner = Interner :: default ( ) ;
1153
- let mut change = Change :: new ( Name :: Symbol ( interner. intern ( "test" ) ) , s1, output) ;
1262
+ let mut change = Change :: new ( Name :: Symbol ( RSymbol ( interner. intern ( "test" ) ) ) , s1, output) ;
1154
1263
1155
1264
for ( type_, span) in changes {
1156
1265
change. insert ( type_. inner ( ) , span. map ( |s| s. inner ( ) ) ) ;
0 commit comments