@@ -5,14 +5,16 @@ namespace ts.codefix {
5
5
registerCodeFix ( {
6
6
errorCodes,
7
7
getCodeActions ( context : CodeFixContext ) {
8
- const changes = textChanges . ChangeTracker . with ( context , t => doChange ( t , context . sourceFile , context . span . start , context . program . getTypeChecker ( ) ) ) ;
8
+ const changes = textChanges . ChangeTracker . with ( context , t =>
9
+ doChange ( t , context . sourceFile , context . span . start , context . program . getTypeChecker ( ) , context . preferences , context . program . getCompilerOptions ( ) ) ) ;
9
10
return [ createCodeFixAction ( fixId , changes , Diagnostics . Convert_function_to_an_ES2015_class , fixId , Diagnostics . Convert_all_constructor_functions_to_classes ) ] ;
10
11
} ,
11
12
fixIds : [ fixId ] ,
12
- getAllCodeActions : context => codeFixAll ( context , errorCodes , ( changes , err ) => doChange ( changes , err . file , err . start , context . program . getTypeChecker ( ) ) ) ,
13
+ getAllCodeActions : context => codeFixAll ( context , errorCodes , ( changes , err ) =>
14
+ doChange ( changes , err . file , err . start , context . program . getTypeChecker ( ) , context . preferences , context . program . getCompilerOptions ( ) ) ) ,
13
15
} ) ;
14
16
15
- function doChange ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , position : number , checker : TypeChecker ) : void {
17
+ function doChange ( changes : textChanges . ChangeTracker , sourceFile : SourceFile , position : number , checker : TypeChecker , preferences : UserPreferences , compilerOptions : CompilerOptions ) : void {
16
18
const ctorSymbol = checker . getSymbolAtLocation ( getTokenAtPosition ( sourceFile , position ) ) ! ;
17
19
if ( ! ctorSymbol || ! ( ctorSymbol . flags & ( SymbolFlags . Function | SymbolFlags . Variable ) ) ) {
18
20
// Bad input
@@ -86,12 +88,12 @@ namespace ts.codefix {
86
88
87
89
return memberElements ;
88
90
89
- function shouldConvertDeclaration ( _target : PropertyAccessExpression | ObjectLiteralExpression , source : Expression ) {
91
+ function shouldConvertDeclaration ( _target : AccessExpression | ObjectLiteralExpression , source : Expression ) {
90
92
// Right now the only thing we can convert are function expressions, get/set accessors and methods
91
93
// other values like normal value fields ({a: 1}) shouldn't get transformed.
92
94
// We can update this once ES public class properties are available.
93
- if ( isPropertyAccessExpression ( _target ) ) {
94
- if ( isConstructorAssignment ( _target ) ) return true ;
95
+ if ( isAccessExpression ( _target ) ) {
96
+ if ( isPropertyAccessExpression ( _target ) && isConstructorAssignment ( _target ) ) return true ;
95
97
return isFunctionLike ( source ) ;
96
98
}
97
99
else {
@@ -115,10 +117,9 @@ namespace ts.codefix {
115
117
return members ;
116
118
}
117
119
118
- const memberDeclaration = symbol . valueDeclaration as PropertyAccessExpression | ObjectLiteralExpression ;
120
+ const memberDeclaration = symbol . valueDeclaration as AccessExpression | ObjectLiteralExpression ;
119
121
const assignmentBinaryExpression = memberDeclaration . parent as BinaryExpression ;
120
122
const assignmentExpr = assignmentBinaryExpression . right ;
121
-
122
123
if ( ! shouldConvertDeclaration ( memberDeclaration , assignmentExpr ) ) {
123
124
return members ;
124
125
}
@@ -135,8 +136,13 @@ namespace ts.codefix {
135
136
}
136
137
137
138
// f.x = expr
138
- if ( isPropertyAccessExpression ( memberDeclaration ) && ( isFunctionExpression ( assignmentExpr ) || isArrowFunction ( assignmentExpr ) ) ) {
139
- return createFunctionLikeExpressionMember ( members , assignmentExpr , memberDeclaration . name ) ;
139
+ if ( isAccessExpression ( memberDeclaration ) && ( isFunctionExpression ( assignmentExpr ) || isArrowFunction ( assignmentExpr ) ) ) {
140
+ const quotePreference = getQuotePreference ( sourceFile , preferences ) ;
141
+ const name = tryGetPropertyName ( memberDeclaration , compilerOptions , quotePreference ) ;
142
+ if ( name ) {
143
+ return createFunctionLikeExpressionMember ( members , assignmentExpr , name ) ;
144
+ }
145
+ return members ;
140
146
}
141
147
// f.prototype = { ... }
142
148
else if ( isObjectLiteralExpression ( assignmentExpr ) ) {
@@ -166,22 +172,20 @@ namespace ts.codefix {
166
172
return members ;
167
173
}
168
174
169
- type MethodName = Parameters < typeof factory . createMethodDeclaration > [ 3 ] ;
170
-
171
- function createFunctionLikeExpressionMember ( members : readonly ClassElement [ ] , expression : FunctionExpression | ArrowFunction , name : MethodName ) {
175
+ function createFunctionLikeExpressionMember ( members : readonly ClassElement [ ] , expression : FunctionExpression | ArrowFunction , name : PropertyName ) {
172
176
if ( isFunctionExpression ( expression ) ) return createFunctionExpressionMember ( members , expression , name ) ;
173
177
else return createArrowFunctionExpressionMember ( members , expression , name ) ;
174
178
}
175
179
176
- function createFunctionExpressionMember ( members : readonly ClassElement [ ] , functionExpression : FunctionExpression , name : MethodName ) {
180
+ function createFunctionExpressionMember ( members : readonly ClassElement [ ] , functionExpression : FunctionExpression , name : PropertyName ) {
177
181
const fullModifiers = concatenate ( modifiers , getModifierKindFromSource ( functionExpression , SyntaxKind . AsyncKeyword ) ) ;
178
182
const method = factory . createMethodDeclaration ( /*decorators*/ undefined , fullModifiers , /*asteriskToken*/ undefined , name , /*questionToken*/ undefined ,
179
183
/*typeParameters*/ undefined , functionExpression . parameters , /*type*/ undefined , functionExpression . body ) ;
180
184
copyLeadingComments ( assignmentBinaryExpression , method , sourceFile ) ;
181
185
return members . concat ( method ) ;
182
186
}
183
187
184
- function createArrowFunctionExpressionMember ( members : readonly ClassElement [ ] , arrowFunction : ArrowFunction , name : MethodName ) {
188
+ function createArrowFunctionExpressionMember ( members : readonly ClassElement [ ] , arrowFunction : ArrowFunction , name : PropertyName ) {
185
189
const arrowFunctionBody = arrowFunction . body ;
186
190
let bodyBlock : Block ;
187
191
@@ -243,4 +247,23 @@ namespace ts.codefix {
243
247
if ( isIdentifier ( x . name ) && x . name . text === "constructor" ) return true ;
244
248
return false ;
245
249
}
250
+
251
+ function tryGetPropertyName ( node : AccessExpression , compilerOptions : CompilerOptions , quotePreference : QuotePreference ) : PropertyName | undefined {
252
+ if ( isPropertyAccessExpression ( node ) ) {
253
+ return node . name ;
254
+ }
255
+
256
+ const propName = node . argumentExpression ;
257
+ if ( isNumericLiteral ( propName ) ) {
258
+ return propName ;
259
+ }
260
+
261
+ if ( isStringLiteralLike ( propName ) ) {
262
+ return isIdentifierText ( propName . text , compilerOptions . target ) ? factory . createIdentifier ( propName . text )
263
+ : isNoSubstitutionTemplateLiteral ( propName ) ? factory . createStringLiteral ( propName . text , quotePreference === QuotePreference . Single )
264
+ : propName ;
265
+ }
266
+
267
+ return undefined ;
268
+ }
246
269
}
0 commit comments