@@ -6,89 +6,51 @@ namespace ts.codefix {
6
6
7
7
type FixableDeclaration = InterfaceDeclaration | TypeAliasDeclaration ;
8
8
9
- interface Info {
10
- indexSignature : IndexSignatureDeclaration ;
11
- container : FixableDeclaration ;
12
- otherMembers : ReadonlyArray < TypeElement > ;
13
- parameterName : Identifier ;
14
- parameterType : TypeNode ;
15
- }
16
-
17
9
registerCodeFix ( {
18
10
errorCodes,
19
11
getCodeActions : context => {
20
12
const { sourceFile, span } = context ;
21
- const info = getFixableSignatureAtPosition ( sourceFile , span . start ) ;
22
- if ( ! info ) return ;
23
- const { indexSignature, container, otherMembers, parameterName, parameterType } = info ;
24
-
25
- const changes = textChanges . ChangeTracker . with ( context , t => doChange ( t , sourceFile , indexSignature , container , otherMembers , parameterName , parameterType ) ) ;
26
- return [ createCodeFixAction ( fixId , changes , [ Diagnostics . Convert_0_to_mapped_object_type , idText ( container . name ) ] , fixId , [ Diagnostics . Convert_0_to_mapped_object_type , idText ( container . name ) ] ) ] ;
13
+ const info = getInfo ( sourceFile , span . start ) ;
14
+ if ( ! info ) return undefined ;
15
+ const changes = textChanges . ChangeTracker . with ( context , t => doChange ( t , sourceFile , info ) ) ;
16
+ const name = idText ( info . container . name ) ;
17
+ return [ createCodeFixAction ( fixId , changes , [ Diagnostics . Convert_0_to_mapped_object_type , name ] , fixId , [ Diagnostics . Convert_0_to_mapped_object_type , name ] ) ] ;
27
18
} ,
28
19
fixIds : [ fixId ] ,
29
20
getAllCodeActions : context => codeFixAll ( context , errorCodes , ( changes , diag ) => {
30
- const info = getFixableSignatureAtPosition ( diag . file , diag . start ) ;
31
- if ( ! info ) return ;
32
- const { indexSignature, container, otherMembers, parameterName, parameterType } = info ;
33
-
34
- doChange ( changes , context . sourceFile , indexSignature , container , otherMembers , parameterName , parameterType ) ;
21
+ const info = getInfo ( diag . file , diag . start ) ;
22
+ if ( info ) doChange ( changes , diag . file , info ) ;
35
23
} )
36
24
} ) ;
37
25
38
- function isFixableParameterName ( node : Node ) : boolean {
39
- return node && node . parent && node . parent . parent && node . parent . parent . parent && ! isClassDeclaration ( node . parent . parent . parent ) ;
40
- }
41
-
42
- function getFixableSignatureAtPosition ( sourceFile : SourceFile , pos : number ) : Info | undefined {
26
+ interface Info { readonly indexSignature : IndexSignatureDeclaration ; readonly container : FixableDeclaration ; }
27
+ function getInfo ( sourceFile : SourceFile , pos : number ) : Info | undefined {
43
28
const token = getTokenAtPosition ( sourceFile , pos , /*includeJsDocComment*/ false ) ;
44
- if ( ! isFixableParameterName ( token ) ) return undefined ;
45
-
46
- const indexSignature = < IndexSignatureDeclaration > token . parent . parent ;
47
- const container = isInterfaceDeclaration ( indexSignature . parent ) ? indexSignature . parent : < TypeAliasDeclaration > indexSignature . parent . parent ;
48
- const members = isInterfaceDeclaration ( container ) ? container . members : ( < TypeLiteralNode > container . type ) . members ;
49
- const otherMembers = filter ( members , member => ! isIndexSignatureDeclaration ( member ) ) ;
50
- const parameter = first ( indexSignature . parameters ) ;
51
-
52
- return {
53
- indexSignature,
54
- container,
55
- otherMembers,
56
- parameterName : < Identifier > parameter . name ,
57
- parameterType : parameter . type !
58
- } ;
29
+ const indexSignature = cast ( token . parent . parent , isIndexSignatureDeclaration ) ;
30
+ if ( isClassDeclaration ( indexSignature . parent ) ) return undefined ;
31
+ const container = isInterfaceDeclaration ( indexSignature . parent ) ? indexSignature . parent : cast ( indexSignature . parent . parent , isTypeAliasDeclaration ) ;
32
+ return { indexSignature, container } ;
59
33
}
60
34
61
- function getInterfaceHeritageClauses ( declaration : FixableDeclaration ) : NodeArray < ExpressionWithTypeArguments > | undefined {
62
- if ( ! isInterfaceDeclaration ( declaration ) ) return undefined ;
63
-
64
- const heritageClause = getHeritageClause ( declaration . heritageClauses , SyntaxKind . ExtendsKeyword ) ;
65
- return heritageClause && heritageClause . types ;
35
+ function createTypeAliasFromInterface ( declaration : FixableDeclaration , type : TypeNode ) : TypeAliasDeclaration {
36
+ return createTypeAliasDeclaration ( declaration . decorators , declaration . modifiers , declaration . name , declaration . typeParameters , type ) ;
66
37
}
67
38
68
- function createTypeAliasFromInterface ( indexSignature : IndexSignatureDeclaration , declaration : FixableDeclaration , otherMembers : ReadonlyArray < TypeElement > , parameterName : Identifier , parameterType : TypeNode ) {
69
- const heritageClauses = getInterfaceHeritageClauses ( declaration ) ;
70
- const mappedTypeParameter = createTypeParameterDeclaration ( parameterName , parameterType ) ;
39
+ function doChange ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , { indexSignature, container } : Info ) : void {
40
+ const members = isInterfaceDeclaration ( container ) ? container . members : ( < TypeLiteralNode > container . type ) . members ;
41
+ const otherMembers = members . filter ( member => ! isIndexSignatureDeclaration ( member ) ) ;
42
+ const parameter = first ( indexSignature . parameters ) ;
43
+ const mappedTypeParameter = createTypeParameterDeclaration ( cast ( parameter . name , isIdentifier ) , parameter . type ) ;
71
44
const mappedIntersectionType = createMappedTypeNode (
72
45
hasReadonlyModifier ( indexSignature ) ? createModifier ( SyntaxKind . ReadonlyKeyword ) : undefined ,
73
46
mappedTypeParameter ,
74
47
indexSignature . questionToken ,
75
48
indexSignature . type ) ;
76
-
77
- return createTypeAliasDeclaration (
78
- declaration . decorators ,
79
- declaration . modifiers ,
80
- declaration . name ,
81
- declaration . typeParameters ,
82
- createIntersectionTypeNode (
83
- concatenate (
84
- heritageClauses ,
85
- append < TypeNode > ( [ mappedIntersectionType ] , otherMembers . length ? createTypeLiteralNode ( otherMembers ) : undefined )
86
- )
87
- )
88
- ) ;
89
- }
90
-
91
- function doChange ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , indexSignature : IndexSignatureDeclaration , declaration : FixableDeclaration , otherMembers : ReadonlyArray < TypeElement > , parameterName : Identifier , parameterType : TypeNode ) {
92
- changes . replaceNode ( sourceFile , declaration , createTypeAliasFromInterface ( indexSignature , declaration , otherMembers , parameterName , parameterType ) ) ;
49
+ const intersectionType = createIntersectionTypeNode ( [
50
+ ...getAllSuperTypeNodes ( container ) ,
51
+ mappedIntersectionType ,
52
+ ...( otherMembers . length ? [ createTypeLiteralNode ( otherMembers ) ] : emptyArray ) ,
53
+ ] ) ;
54
+ changes . replaceNode ( sourceFile , container , createTypeAliasFromInterface ( container , intersectionType ) ) ;
93
55
}
94
56
}
0 commit comments