@@ -5,25 +5,68 @@ namespace ts.codefix {
5
5
registerCodeFix ( {
6
6
errorCodes,
7
7
getCodeActions ( context ) {
8
- const changes = textChanges . ChangeTracker . with ( context , t => doChange ( t , context . sourceFile , context . span . start , context . program ) ) ;
8
+ const info = getInfo ( context . sourceFile , context . program , context . span . start ) ;
9
+ if ( ! info ) {
10
+ return undefined ;
11
+ }
12
+ const changes = textChanges . ChangeTracker . with ( context , t => doChange ( t , context . sourceFile , info ) ) ;
9
13
return [ createCodeFixAction ( fixId , changes , Diagnostics . Convert_require_to_import , fixId , Diagnostics . Convert_all_require_to_import ) ] ;
10
14
} ,
11
15
fixIds : [ fixId ] ,
12
- getAllCodeActions : context => codeFixAll ( context , errorCodes , ( changes , diag ) => doChange ( changes , diag . file , diag . start , context . program ) ) ,
16
+ getAllCodeActions : context => codeFixAll ( context , errorCodes , ( changes , diag ) => {
17
+ const info = getInfo ( diag . file , context . program , diag . start ) ;
18
+ if ( info ) {
19
+ doChange ( changes , context . sourceFile , info ) ;
20
+ }
21
+ } ) ,
13
22
} ) ;
14
23
15
- function doChange ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , pos : number , program : Program ) {
16
- const { statement , name , required } = getInfo ( sourceFile , pos ) ;
17
- changes . replaceNode ( sourceFile , statement , getAllowSyntheticDefaultImports ( program . getCompilerOptions ( ) )
18
- ? createImportDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , createImportClause ( name , /*namedBindings*/ undefined ) , required )
19
- : createImportEqualsDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , name , createExternalModuleReference ( required ) ) ) ;
24
+ function doChange ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , info : Info ) {
25
+ const { allowSyntheticDefaults , defaultImportName , namedImports , statement , required } = info ;
26
+ changes . replaceNode ( sourceFile , statement , defaultImportName && ! allowSyntheticDefaults
27
+ ? createImportEqualsDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , defaultImportName , createExternalModuleReference ( required ) )
28
+ : createImportDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , createImportClause ( defaultImportName , namedImports ) , required ) ) ;
20
29
}
21
30
22
- interface Info { readonly statement : VariableStatement ; readonly name : Identifier ; readonly required : StringLiteralLike ; }
23
- function getInfo ( sourceFile : SourceFile , pos : number ) : Info {
31
+ interface Info {
32
+ readonly allowSyntheticDefaults : boolean ;
33
+ readonly defaultImportName : Identifier | undefined ;
34
+ readonly namedImports : NamedImports | undefined ;
35
+ readonly statement : VariableStatement ;
36
+ readonly required : StringLiteralLike ;
37
+ }
38
+
39
+ function getInfo ( sourceFile : SourceFile , program : Program , pos : number ) : Info | undefined {
24
40
const { parent } = getTokenAtPosition ( sourceFile , pos ) ;
25
- if ( ! isRequireCall ( parent , /*checkArgumentIsStringLiteralLike*/ true ) ) throw Debug . failBadSyntaxKind ( parent ) ;
41
+ if ( ! isRequireCall ( parent , /*checkArgumentIsStringLiteralLike*/ true ) ) {
42
+ throw Debug . failBadSyntaxKind ( parent ) ;
43
+ }
44
+
26
45
const decl = cast ( parent . parent , isVariableDeclaration ) ;
27
- return { statement : cast ( decl . parent . parent , isVariableStatement ) , name : cast ( decl . name , isIdentifier ) , required : parent . arguments [ 0 ] } ;
46
+ const defaultImportName = tryCast ( decl . name , isIdentifier ) ;
47
+ const namedImports = isObjectBindingPattern ( decl . name ) ? tryCreateNamedImportsFromObjectBindingPattern ( decl . name ) : undefined ;
48
+ if ( defaultImportName || namedImports ) {
49
+ return {
50
+ allowSyntheticDefaults : getAllowSyntheticDefaultImports ( program . getCompilerOptions ( ) ) ,
51
+ defaultImportName,
52
+ namedImports,
53
+ statement : cast ( decl . parent . parent , isVariableStatement ) ,
54
+ required : first ( parent . arguments )
55
+ } ;
56
+ }
57
+ }
58
+
59
+ function tryCreateNamedImportsFromObjectBindingPattern ( node : ObjectBindingPattern ) : NamedImports | undefined {
60
+ const importSpecifiers : ImportSpecifier [ ] = [ ] ;
61
+ for ( const element of node . elements ) {
62
+ if ( ! isIdentifier ( element . name ) || element . initializer ) {
63
+ return undefined ;
64
+ }
65
+ importSpecifiers . push ( createImportSpecifier ( tryCast ( element . propertyName , isIdentifier ) , element . name ) ) ;
66
+ }
67
+
68
+ if ( importSpecifiers . length ) {
69
+ return createNamedImports ( importSpecifiers ) ;
70
+ }
28
71
}
29
72
}
0 commit comments