1
1
import reflect = require( 'jsii-reflect' ) ;
2
2
import log4js = require( 'log4js' ) ;
3
3
import { Analysis , FailedAnalysis , isSuperType } from './type-analysis' ;
4
- import { ComparisonContext , shouldInspect } from './types' ;
4
+ import { ComparisonContext } from './types' ;
5
5
6
6
const LOG = log4js . getLogger ( 'jsii-diff' ) ;
7
7
@@ -14,28 +14,36 @@ const LOG = log4js.getLogger('jsii-diff');
14
14
export function compareReferenceType < T extends reflect . ReferenceType > ( original : T , updated : T , context : ComparisonContext ) {
15
15
if ( original . isClassType ( ) && updated . isClassType ( ) ) {
16
16
if ( updated . abstract && ! original . abstract ) {
17
- context . mismatches . report ( original , 'has gone from non-abstract to abstract' ) ;
17
+ context . mismatches . report ( {
18
+ ruleKey : 'made-abstract' ,
19
+ message : 'has gone from non-abstract to abstract' ,
20
+ violator : original ,
21
+ } ) ;
18
22
}
19
23
20
24
// JSII assembler has already taken care of inheritance here
21
25
if ( original . initializer && updated . initializer ) {
22
- compareMethod ( original , original . initializer , updated . initializer , context ) ;
26
+ compareMethod ( original . initializer , updated . initializer , context ) ;
23
27
}
24
28
}
25
29
26
30
if ( original . docs . subclassable && ! updated . docs . subclassable ) {
27
- context . mismatches . report ( original , 'has gone from @subclassable to non-@subclassable' ) ;
31
+ context . mismatches . report ( {
32
+ ruleKey : `remove-subclassable` ,
33
+ message : 'has gone from @subclassable to non-@subclassable' ,
34
+ violator : original ,
35
+ } ) ;
28
36
}
29
37
30
38
for ( const [ origMethod , updatedElement ] of memberPairs ( original , original . allMethods , updated , context ) ) {
31
39
if ( reflect . isMethod ( origMethod ) && reflect . isMethod ( updatedElement ) ) {
32
- compareMethod ( original , origMethod , updatedElement , context ) ;
40
+ compareMethod ( origMethod , updatedElement , context ) ;
33
41
}
34
42
}
35
43
36
44
for ( const [ origProp , updatedElement ] of memberPairs ( original , original . allProperties , updated , context ) ) {
37
45
if ( reflect . isProperty ( origProp ) && reflect . isProperty ( updatedElement ) ) {
38
- compareProperty ( original , origProp , updatedElement , context ) ;
46
+ compareProperty ( origProp , updatedElement , context ) ;
39
47
}
40
48
}
41
49
@@ -67,7 +75,11 @@ function noNewAbstractMembers<T extends reflect.ReferenceType>(original: T, upda
67
75
const originalMemberNames = new Set ( original . allMembers . map ( m => m . name ) ) ;
68
76
for ( const name of absMemberNames ) {
69
77
if ( ! originalMemberNames . has ( name ) ) {
70
- context . mismatches . report ( original , `adds requirement for subclasses to implement '${ name } '.` ) ;
78
+ context . mismatches . report ( {
79
+ ruleKey : 'new-abstract-member' ,
80
+ message : `adds requirement for subclasses to implement '${ name } '.` ,
81
+ violator : updated . getMembers ( true ) [ name ]
82
+ } ) ;
71
83
}
72
84
}
73
85
}
@@ -83,7 +95,6 @@ function describeOptionalValueMatchingFailure(origType: reflect.OptionalValue, u
83
95
}
84
96
85
97
function compareMethod < T extends ( reflect . Method | reflect . Initializer ) > (
86
- origClass : reflect . Type ,
87
98
original : T ,
88
99
updated : T ,
89
100
context : ComparisonContext ) {
@@ -92,41 +103,65 @@ function compareMethod<T extends (reflect.Method | reflect.Initializer)>(
92
103
if ( original . static !== updated . static ) {
93
104
const origQual = original . static ? 'static' : 'not static' ;
94
105
const updQual = updated . static ? 'static' : 'not static' ;
95
- context . mismatches . report ( origClass , `${ original . kind } ${ original . name } was ${ origQual } , is now ${ updQual } .` ) ;
106
+ context . mismatches . report ( {
107
+ ruleKey : 'changed-static' ,
108
+ violator : original ,
109
+ message : `was ${ origQual } , is now ${ updQual } .`
110
+ } ) ;
96
111
}
97
112
98
113
if ( original . async !== updated . async ) {
99
114
const origQual = original . async ? 'asynchronous' : 'synchronous' ;
100
115
const updQual = updated . async ? 'asynchronous' : 'synchronous' ;
101
- context . mismatches . report ( origClass , `${ original . kind } ${ original . name } was ${ origQual } , is now ${ updQual } ` ) ;
116
+ context . mismatches . report ( {
117
+ ruleKey : 'changed-async' ,
118
+ violator : original ,
119
+ message : `was ${ origQual } , is now ${ updQual } `
120
+ } ) ;
102
121
}
103
122
}
104
123
105
124
if ( original . variadic && ! updated . variadic ) {
106
125
// Once variadic, can never be made non-variadic anymore (because I could always have been passing N+1 arguments)
107
- context . mismatches . report ( origClass , `${ original . kind } ${ original . name } used to be variadic, not variadic anymore.` ) ;
126
+ context . mismatches . report ( {
127
+ ruleKey : 'changed-variadic' ,
128
+ violator : original ,
129
+ message : `used to be variadic, not variadic anymore.`
130
+ } ) ;
108
131
}
109
132
110
133
if ( reflect . isMethod ( original ) && reflect . isMethod ( updated ) ) {
111
134
const retAna = isCompatibleReturnType ( original . returns , updated . returns ) ;
112
135
if ( ! retAna . success ) {
113
136
// tslint:disable-next-line:max-line-length
114
- context . mismatches . report ( origClass , `${ original . kind } ${ original . name } , returns ${ describeOptionalValueMatchingFailure ( original . returns , updated . returns , retAna ) } ` ) ;
137
+ context . mismatches . report ( {
138
+ ruleKey : 'change-return-type' ,
139
+ violator : original ,
140
+ message : `returns ${ describeOptionalValueMatchingFailure ( original . returns , updated . returns , retAna ) } `
141
+ } ) ;
115
142
}
116
143
}
117
144
118
145
// Check that every original parameter can still be mapped to a parameter in the updated method
119
146
original . parameters . forEach ( ( param , i ) => {
120
147
const updatedParam = findParam ( updated . parameters , i ) ;
121
148
if ( updatedParam === undefined ) {
122
- context . mismatches . report ( origClass , `${ original . kind } ${ original . name } argument ${ param . name } , not accepted anymore.` ) ;
149
+ context . mismatches . report ( {
150
+ ruleKey : 'removed-argument' ,
151
+ violator : original ,
152
+ message : `argument ${ param . name } , not accepted anymore.`
153
+ } ) ;
123
154
return ;
124
155
}
125
156
126
157
const argAna = isCompatibleArgumentType ( param . type , updatedParam . type ) ;
127
158
if ( ! argAna . success ) {
128
- // tslint:disable-next-line:max-line-length
129
- context . mismatches . report ( origClass , `${ original . kind } ${ original . name } argument ${ param . name } , takes ${ describeOptionalValueMatchingFailure ( param , updatedParam , argAna ) } ` ) ;
159
+ context . mismatches . report ( {
160
+ ruleKey : 'incompatible-argument' ,
161
+ violator : original ,
162
+ // tslint:disable-next-line:max-line-length
163
+ message : `argument ${ param . name } , takes ${ describeOptionalValueMatchingFailure ( param , updatedParam , argAna ) } `
164
+ } ) ;
130
165
return ;
131
166
}
132
167
} ) ;
@@ -137,7 +172,11 @@ function compareMethod<T extends (reflect.Method | reflect.Initializer)>(
137
172
138
173
const origParam = findParam ( original . parameters , i ) ;
139
174
if ( ! origParam || origParam . optional ) {
140
- context . mismatches . report ( origClass , `${ original . kind } ${ original . name } argument ${ param . name } , newly required argument.` ) ;
175
+ context . mismatches . report ( {
176
+ ruleKey : 'new-argument' ,
177
+ violator : original ,
178
+ message : `argument ${ param . name } , newly required argument.`
179
+ } ) ;
141
180
}
142
181
} ) ;
143
182
}
@@ -161,39 +200,63 @@ function findParam(parameters: reflect.Parameter[], i: number): reflect.Paramete
161
200
return undefined ;
162
201
}
163
202
164
- function compareProperty ( origClass : reflect . Type , original : reflect . Property , updated : reflect . Property , context : ComparisonContext ) {
203
+ function compareProperty ( original : reflect . Property , updated : reflect . Property , context : ComparisonContext ) {
165
204
if ( original . static !== updated . static ) {
166
205
// tslint:disable-next-line:max-line-length
167
- context . mismatches . report ( origClass , `property ${ original . name } , used to be ${ original . static ? 'static' : 'not static' } , is now ${ updated . static ? 'static' : 'not static' } ` ) ;
206
+ context . mismatches . report ( {
207
+ ruleKey : 'changed-static' ,
208
+ violator : original ,
209
+ message : `used to be ${ original . static ? 'static' : 'not static' } , is now ${ updated . static ? 'static' : 'not static' } `
210
+ } ) ;
168
211
}
169
212
170
213
const ana = isCompatibleReturnType ( original , updated ) ;
171
214
if ( ! ana . success ) {
172
- context . mismatches . report ( origClass , `property ${ original . name } , type ${ describeOptionalValueMatchingFailure ( original , updated , ana ) } ` ) ;
215
+ context . mismatches . report ( {
216
+ ruleKey : 'changed-type' ,
217
+ violator : original ,
218
+ message : `type ${ describeOptionalValueMatchingFailure ( original , updated , ana ) } `
219
+ } ) ;
173
220
}
174
221
175
222
if ( updated . immutable && ! original . immutable ) {
176
- context . mismatches . report ( origClass , `property ${ original . name } , used to be mutable, is now immutable` ) ;
223
+ context . mismatches . report ( {
224
+ ruleKey : 'removed-mutability' ,
225
+ violator : original ,
226
+ message : `used to be mutable, is now immutable`
227
+ } ) ;
177
228
}
178
229
}
179
230
180
231
// tslint:disable-next-line:max-line-length
181
232
function * memberPairs < T extends reflect . TypeMember , U extends reflect . ReferenceType > ( origClass : U , xs : T [ ] , updatedClass : U , context : ComparisonContext ) : IterableIterator < [ T , reflect . TypeMember ] > {
182
- for ( const origMember of xs . filter ( shouldInspect ( context ) ) ) {
233
+ for ( const origMember of xs ) {
183
234
LOG . trace ( `${ origClass . fqn } #${ origMember . name } ` ) ;
184
235
185
236
const updatedMember = updatedClass . allMembers . find ( m => m . name === origMember . name ) ;
186
237
if ( ! updatedMember ) {
187
- context . mismatches . report ( origClass , `member ${ origMember . name } has been removed` ) ;
238
+ context . mismatches . report ( {
239
+ ruleKey : 'removed' ,
240
+ violator : origMember ,
241
+ message : `has been removed`
242
+ } ) ;
188
243
continue ;
189
244
}
190
245
191
246
if ( origMember . kind !== updatedMember . kind ) {
192
- context . mismatches . report ( origClass , `member ${ origMember . name } changed from ${ origMember . kind } to ${ updatedMember . kind } ` ) ;
247
+ context . mismatches . report ( {
248
+ ruleKey : 'changed-kind' ,
249
+ violator : origMember ,
250
+ message : `changed from ${ origMember . kind } to ${ updatedMember . kind } `
251
+ } ) ;
193
252
}
194
253
195
254
if ( ! origMember . protected && updatedMember . protected ) {
196
- context . mismatches . report ( origClass , `member ${ origMember . name } changed from 'public' to 'protected'` ) ;
255
+ context . mismatches . report ( {
256
+ ruleKey : 'hidden' ,
257
+ violator : origMember ,
258
+ message : `changed from 'public' to 'protected'`
259
+ } ) ;
197
260
}
198
261
199
262
yield [ origMember , updatedMember ] ;
0 commit comments