@@ -6,89 +6,51 @@ namespace ts.codefix {
66
77 type FixableDeclaration = InterfaceDeclaration | TypeAliasDeclaration ;
88
9- interface Info {
10- indexSignature : IndexSignatureDeclaration ;
11- container : FixableDeclaration ;
12- otherMembers : ReadonlyArray < TypeElement > ;
13- parameterName : Identifier ;
14- parameterType : TypeNode ;
15- }
16-
179 registerCodeFix ( {
1810 errorCodes,
1911 getCodeActions : context => {
2012 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 ] ) ] ;
2718 } ,
2819 fixIds : [ fixId ] ,
2920 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 ) ;
3523 } )
3624 } ) ;
3725
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 {
4328 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 } ;
5933 }
6034
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 ) ;
6637 }
6738
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 ) ;
7144 const mappedIntersectionType = createMappedTypeNode (
7245 hasReadonlyModifier ( indexSignature ) ? createModifier ( SyntaxKind . ReadonlyKeyword ) : undefined ,
7346 mappedTypeParameter ,
7447 indexSignature . questionToken ,
7548 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 ) ) ;
9355 }
9456}
0 commit comments