@@ -12,14 +12,16 @@ namespace ts.codefix {
1212 const info = getInfo ( context . sourceFile , context . span . start , context . program . getTypeChecker ( ) ) ;
1313 if ( ! info ) return undefined ;
1414
15- if ( isEnumInfo ( info ) ) {
16- return singleElementArray ( getActionForEnumMemberDeclaration ( context , info . enumDeclarationSourceFile , info . declaration , info . token ) ) ;
15+ if ( info . kind === InfoKind . enum ) {
16+ const { token, enumDeclaration } = info ;
17+ const changes = textChanges . ChangeTracker . with ( context , t => addEnumMemberDeclaration ( t , context . program . getTypeChecker ( ) , token , enumDeclaration ) ) ;
18+ return singleElementArray ( createCodeFixAction ( fixName , changes , [ Diagnostics . Add_missing_enum_member_0 , token . text ] , fixId , Diagnostics . Add_all_missing_enum_members ) ) ;
1719 }
18- const { declaration , classDeclarationSourceFile, inJs, makeStatic, token, call } = info ;
19- const methodCodeAction = call && getActionForMethodDeclaration ( context , classDeclarationSourceFile , declaration , token , call , makeStatic , inJs , context . preferences ) ;
20+ const { classDeclaration , classDeclarationSourceFile, inJs, makeStatic, token, call } = info ;
21+ const methodCodeAction = call && getActionForMethodDeclaration ( context , classDeclarationSourceFile , classDeclaration , token , call , makeStatic , inJs , context . preferences ) ;
2022 const addMember = inJs ?
21- singleElementArray ( getActionsForAddMissingMemberInJavaScriptFile ( context , classDeclarationSourceFile , declaration , token . text , makeStatic ) ) :
22- getActionsForAddMissingMemberInTypeScriptFile ( context , classDeclarationSourceFile , declaration , token , makeStatic ) ;
23+ singleElementArray ( getActionsForAddMissingMemberInJavaScriptFile ( context , classDeclarationSourceFile , classDeclaration , token . text , makeStatic ) ) :
24+ getActionsForAddMissingMemberInTypeScriptFile ( context , classDeclarationSourceFile , classDeclaration , token , makeStatic ) ;
2325 return concatenate ( singleElementArray ( methodCodeAction ) , addMember ) ;
2426 } ,
2527 fixIds : [ fixId ] ,
@@ -33,38 +35,35 @@ namespace ts.codefix {
3335 return ;
3436 }
3537
36- if ( isEnumInfo ( info ) ) {
37- const { token, declaration , enumDeclarationSourceFile } = info ;
38- addEnumMemberDeclaration ( changes , checker , token , declaration , enumDeclarationSourceFile ) ;
38+ if ( info . kind === InfoKind . enum ) {
39+ const { token, enumDeclaration } = info ;
40+ addEnumMemberDeclaration ( changes , checker , token , enumDeclaration ) ;
3941 }
4042 else {
41- const { declaration , classDeclarationSourceFile, inJs, makeStatic, token, call } = info ;
43+ const { classDeclaration , classDeclarationSourceFile, inJs, makeStatic, token, call } = info ;
4244 // Always prefer to add a method declaration if possible.
4345 if ( call ) {
44- addMethodDeclaration ( context , changes , classDeclarationSourceFile , declaration , token , call , makeStatic , inJs , preferences ) ;
46+ addMethodDeclaration ( context , changes , classDeclarationSourceFile , classDeclaration , token , call , makeStatic , inJs , preferences ) ;
4547 }
4648 else {
4749 if ( inJs ) {
48- addMissingMemberInJs ( changes , classDeclarationSourceFile , declaration , token . text , makeStatic ) ;
50+ addMissingMemberInJs ( changes , classDeclarationSourceFile , classDeclaration , token . text , makeStatic ) ;
4951 }
5052 else {
51- const typeNode = getTypeNode ( program . getTypeChecker ( ) , declaration , token ) ;
52- addPropertyDeclaration ( changes , classDeclarationSourceFile , declaration , token . text , typeNode , makeStatic ) ;
53+ const typeNode = getTypeNode ( program . getTypeChecker ( ) , classDeclaration , token ) ;
54+ addPropertyDeclaration ( changes , classDeclarationSourceFile , classDeclaration , token . text , typeNode , makeStatic ) ;
5355 }
5456 }
5557 }
5658 } ) ;
5759 } ,
5860 } ) ;
5961
60- interface EnumInfo { token : Identifier ; declaration : EnumDeclaration ; enumDeclarationSourceFile : SourceFile ; }
61- interface ClassInfo { token : Identifier ; declaration : ClassLikeDeclaration ; makeStatic : boolean ; classDeclarationSourceFile : SourceFile ; inJs : boolean ; call : CallExpression | undefined ; }
62+ enum InfoKind { enum , class }
63+ interface EnumInfo { kind : InfoKind . enum ; token : Identifier ; enumDeclaration : EnumDeclaration ; }
64+ interface ClassInfo { kind : InfoKind . class ; token : Identifier ; classDeclaration : ClassLikeDeclaration ; makeStatic : boolean ; classDeclarationSourceFile : SourceFile ; inJs : boolean ; call : CallExpression | undefined ; }
6265 type Info = EnumInfo | ClassInfo ;
6366
64- function isEnumInfo ( info : Info ) : info is EnumInfo {
65- return isEnumDeclaration ( info . declaration ) ;
66- }
67-
6867 function getInfo ( tokenSourceFile : SourceFile , tokenPos : number , checker : TypeChecker ) : Info | undefined {
6968 // The identifier of the missing property. eg:
7069 // this.missing = 1;
@@ -87,11 +86,11 @@ namespace ts.codefix {
8786 const classDeclarationSourceFile = classDeclaration . getSourceFile ( ) ;
8887 const inJs = isSourceFileJavaScript ( classDeclarationSourceFile ) ;
8988 const call = tryCast ( parent . parent , isCallExpression ) ;
90- return { token , declaration : classDeclaration , makeStatic, classDeclarationSourceFile, inJs, call } ;
89+ return { kind : InfoKind . class , token , classDeclaration, makeStatic, classDeclarationSourceFile, inJs, call } ;
9190 }
9291 const enumDeclaration = find ( symbol . declarations , isEnumDeclaration ) ;
9392 if ( enumDeclaration ) {
94- return { token , declaration : enumDeclaration , enumDeclarationSourceFile : enumDeclaration . getSourceFile ( ) } ;
93+ return { kind : InfoKind . enum , token , enumDeclaration } ;
9594 }
9695 return undefined ;
9796 }
@@ -211,16 +210,6 @@ namespace ts.codefix {
211210 return createCodeFixAction ( fixName , changes , [ makeStatic ? Diagnostics . Declare_static_method_0 : Diagnostics . Declare_method_0 , token . text ] , fixId , Diagnostics . Add_all_missing_members ) ;
212211 }
213212
214- function getActionForEnumMemberDeclaration (
215- context : CodeFixContext ,
216- enumDeclarationSourceFile : SourceFile ,
217- enumDeclaration : EnumDeclaration ,
218- token : Identifier
219- ) : CodeFixAction | undefined {
220- const changes = textChanges . ChangeTracker . with ( context , t => addEnumMemberDeclaration ( t , context . program . getTypeChecker ( ) , token , enumDeclaration , enumDeclarationSourceFile ) ) ;
221- return createCodeFixAction ( fixName , changes , [ Diagnostics . Add_missing_enum_member_0 , token . text ] , fixId , Diagnostics . Add_all_missing_enum_members ) ;
222- }
223-
224213 function addMethodDeclaration (
225214 context : CodeFixContextBase ,
226215 changeTracker : textChanges . ChangeTracker ,
@@ -243,26 +232,19 @@ namespace ts.codefix {
243232 }
244233 }
245234
246- function createEnumMemberFromEnumDeclaration ( checker : TypeChecker , token : Identifier , enumDeclaration : EnumDeclaration ) {
235+ function addEnumMemberDeclaration ( changes : textChanges . ChangeTracker , checker : TypeChecker , token : Identifier , enumDeclaration : EnumDeclaration ) {
247236 /**
248- * create initializer only string enum.
237+ * create initializer only literal enum that has string initializer .
249238 * value of initializer is a string literal that equal to name of enum member.
250- * literal enum or empty enum will not create initializer.
239+ * numeric enum or empty enum will not create initializer.
251240 */
252- const firstMember = firstOrUndefined ( enumDeclaration . members ) ;
253- let enumMemberInitializer : Expression | undefined ;
254- if ( firstMember && firstMember . initializer ) {
255- const memberType = checker . getTypeAtLocation ( firstMember . initializer ) ;
256- if ( memberType && memberType . flags & TypeFlags . StringLike ) {
257- enumMemberInitializer = createStringLiteral ( token . text ) ;
258- }
259- }
260- return createEnumMember ( token , enumMemberInitializer ) ;
261- }
241+ const hasStringInitializer = some ( enumDeclaration . members , member => {
242+ const type = checker . getTypeAtLocation ( member ) ;
243+ return ! ! ( type && type . flags & ( TypeFlags . StringLike | TypeFlags . Enum ) ) ;
244+ } ) ;
262245
263- function addEnumMemberDeclaration ( changes : textChanges . ChangeTracker , checker : TypeChecker , token : Identifier , enumDeclaration : EnumDeclaration , file : SourceFile ) {
264- const enumMember = createEnumMemberFromEnumDeclaration ( checker , token , enumDeclaration ) ;
265- changes . replaceNode ( file , enumDeclaration , updateEnumDeclaration (
246+ const enumMember = createEnumMember ( token , hasStringInitializer ? createStringLiteral ( token . text ) : undefined ) ;
247+ changes . replaceNode ( enumDeclaration . getSourceFile ( ) , enumDeclaration , updateEnumDeclaration (
266248 enumDeclaration ,
267249 enumDeclaration . decorators ,
268250 enumDeclaration . modifiers ,
0 commit comments