1
- import stringify = require( 'json-stringify-safe' )
2
1
import { uniqBy } from 'lodash'
2
+ import { Options } from '.'
3
+ import { generateType } from './generator'
3
4
import { AST , T_ANY , T_UNKNOWN } from './types/AST'
4
5
import { log } from './utils'
5
6
6
- export function optimize ( ast : AST , processed = new Set < AST > ( ) ) : AST {
7
- log ( 'cyan' , 'optimizer' , ast , processed . has ( ast ) ? '(FROM CACHE)' : '' )
8
-
7
+ export function optimize ( ast : AST , options : Options , processed = new Set < AST > ( ) ) : AST {
9
8
if ( processed . has ( ast ) ) {
10
9
return ast
11
10
}
@@ -15,7 +14,7 @@ export function optimize(ast: AST, processed = new Set<AST>()): AST {
15
14
switch ( ast . type ) {
16
15
case 'INTERFACE' :
17
16
return Object . assign ( ast , {
18
- params : ast . params . map ( _ => Object . assign ( _ , { ast : optimize ( _ . ast , processed ) } ) )
17
+ params : ast . params . map ( _ => Object . assign ( _ , { ast : optimize ( _ . ast , options , processed ) } ) )
19
18
} )
20
19
case 'INTERSECTION' :
21
20
case 'UNION' :
@@ -31,25 +30,40 @@ export function optimize(ast: AST, processed = new Set<AST>()): AST {
31
30
return T_UNKNOWN
32
31
}
33
32
33
+ // [A (named), A] -> [A (named)]
34
+ if (
35
+ ast . params . every ( _ => {
36
+ const a = generateType ( omitStandaloneName ( _ ) , options )
37
+ const b = generateType ( omitStandaloneName ( ast . params [ 0 ] ) , options )
38
+ return a === b
39
+ } ) &&
40
+ ast . params . some ( _ => _ . standaloneName !== undefined )
41
+ ) {
42
+ log ( 'cyan' , 'optimizer' , '[A, B, B] -> [A, B]' , ast )
43
+ ast . params = ast . params . filter ( _ => _ . standaloneName !== undefined )
44
+ }
45
+
34
46
// [A, B, B] -> [A, B]
35
- const shouldTakeStandaloneNameIntoAccount = ast . params . filter ( _ => _ . standaloneName ) . length > 1
36
- const params = uniqBy (
37
- ast . params ,
38
- _ => `
39
- ${ _ . type } -
40
- ${ shouldTakeStandaloneNameIntoAccount ? _ . standaloneName : '' } -
41
- ${ stringify ( ( _ as any ) . params ) }
42
- `
43
- )
47
+ const params = uniqBy ( ast . params , _ => `${ _ . standaloneName } :${ generateType ( _ , options ) } ` )
44
48
if ( params . length !== ast . params . length ) {
45
49
log ( 'cyan' , 'optimizer' , '[A, B, B] -> [A, B]' , ast )
46
50
ast . params = params
47
51
}
48
52
49
53
return Object . assign ( ast , {
50
- params : ast . params . map ( _ => optimize ( _ , processed ) )
54
+ params : ast . params . map ( _ => optimize ( _ , options , processed ) )
51
55
} )
52
56
default :
53
57
return ast
54
58
}
55
59
}
60
+
61
+ // TODO: More clearly disambiguate standalone names vs. aliased names instead.
62
+ function omitStandaloneName < A extends AST > ( ast : A ) : A {
63
+ switch ( ast . type ) {
64
+ case 'ENUM' :
65
+ return ast
66
+ default :
67
+ return { ...ast , standaloneName : undefined }
68
+ }
69
+ }
0 commit comments