@@ -8,37 +8,33 @@ namespace ts.codefix {
8
8
registerCodeFix ( {
9
9
errorCodes,
10
10
getCodeActions : function getCodeActionsForStrictClassInitializationErrors ( context ) {
11
- const propertyDeclaration = getPropertyDeclaration ( context . sourceFile , context . span . start ) ;
12
- if ( ! propertyDeclaration ) return ;
13
-
14
- const result = [
15
- getActionForAddMissingUndefinedType ( context , propertyDeclaration ) ,
16
- getActionForAddMissingDefiniteAssignmentAssertion ( context , propertyDeclaration )
17
- ] ;
18
-
19
- append ( result , getActionForAddMissingInitializer ( context , propertyDeclaration ) ) ;
11
+ const info = getInfo ( context . sourceFile , context . span . start ) ;
12
+ if ( ! info ) return ;
20
13
14
+ const result : CodeFixAction [ ] = [ ] ;
15
+ append ( result , getActionForAddMissingUndefinedType ( context , info ) ) ;
16
+ append ( result , getActionForAddMissingDefiniteAssignmentAssertion ( context , info ) ) ;
17
+ append ( result , getActionForAddMissingInitializer ( context , info ) ) ;
21
18
return result ;
22
19
} ,
23
20
fixIds : [ fixIdAddDefiniteAssignmentAssertions , fixIdAddUndefinedType , fixIdAddInitializer ] ,
24
21
getAllCodeActions : context => {
25
22
return codeFixAll ( context , errorCodes , ( changes , diag ) => {
26
- const propertyDeclaration = getPropertyDeclaration ( diag . file , diag . start ) ;
27
- if ( ! propertyDeclaration ) return ;
23
+ const info = getInfo ( diag . file , diag . start ) ;
24
+ if ( ! info ) return ;
28
25
29
26
switch ( context . fixId ) {
30
27
case fixIdAddDefiniteAssignmentAssertions :
31
- addDefiniteAssignmentAssertion ( changes , diag . file , propertyDeclaration ) ;
28
+ addDefiniteAssignmentAssertion ( changes , diag . file , info . prop ) ;
32
29
break ;
33
30
case fixIdAddUndefinedType :
34
- addUndefinedType ( changes , diag . file , propertyDeclaration ) ;
31
+ addUndefinedType ( changes , diag . file , info ) ;
35
32
break ;
36
33
case fixIdAddInitializer :
37
34
const checker = context . program . getTypeChecker ( ) ;
38
- const initializer = getInitializer ( checker , propertyDeclaration ) ;
35
+ const initializer = getInitializer ( checker , info . prop ) ;
39
36
if ( ! initializer ) return ;
40
-
41
- addInitializer ( changes , diag . file , propertyDeclaration , initializer ) ;
37
+ addInitializer ( changes , diag . file , info . prop , initializer ) ;
42
38
break ;
43
39
default :
44
40
Debug . fail ( JSON . stringify ( context . fixId ) ) ;
@@ -47,14 +43,27 @@ namespace ts.codefix {
47
43
} ,
48
44
} ) ;
49
45
50
- function getPropertyDeclaration ( sourceFile : SourceFile , pos : number ) : PropertyDeclaration | undefined {
46
+ interface Info {
47
+ prop : PropertyDeclaration ;
48
+ type : TypeNode ;
49
+ isJs : boolean ;
50
+ }
51
+
52
+ function getInfo ( sourceFile : SourceFile , pos : number ) : Info | undefined {
51
53
const token = getTokenAtPosition ( sourceFile , pos ) ;
52
- return isIdentifier ( token ) ? cast ( token . parent , isPropertyDeclaration ) : undefined ;
54
+ if ( isIdentifier ( token ) && isPropertyDeclaration ( token . parent ) ) {
55
+ const type = getEffectiveTypeAnnotationNode ( token . parent ) ;
56
+ if ( type ) {
57
+ return { type, prop : token . parent , isJs : isInJSFile ( token . parent ) } ;
58
+ }
59
+ }
60
+ return undefined ;
53
61
}
54
62
55
- function getActionForAddMissingDefiniteAssignmentAssertion ( context : CodeFixContext , propertyDeclaration : PropertyDeclaration ) : CodeFixAction {
56
- const changes = textChanges . ChangeTracker . with ( context , t => addDefiniteAssignmentAssertion ( t , context . sourceFile , propertyDeclaration ) ) ;
57
- return createCodeFixAction ( fixName , changes , [ Diagnostics . Add_definite_assignment_assertion_to_property_0 , propertyDeclaration . getText ( ) ] , fixIdAddDefiniteAssignmentAssertions , Diagnostics . Add_definite_assignment_assertions_to_all_uninitialized_properties ) ;
63
+ function getActionForAddMissingDefiniteAssignmentAssertion ( context : CodeFixContext , info : Info ) : CodeFixAction | undefined {
64
+ if ( info . isJs ) return undefined ;
65
+ const changes = textChanges . ChangeTracker . with ( context , t => addDefiniteAssignmentAssertion ( t , context . sourceFile , info . prop ) ) ;
66
+ return createCodeFixAction ( fixName , changes , [ Diagnostics . Add_definite_assignment_assertion_to_property_0 , info . prop . getText ( ) ] , fixIdAddDefiniteAssignmentAssertions , Diagnostics . Add_definite_assignment_assertions_to_all_uninitialized_properties ) ;
58
67
}
59
68
60
69
function addDefiniteAssignmentAssertion ( changeTracker : textChanges . ChangeTracker , propertyDeclarationSourceFile : SourceFile , propertyDeclaration : PropertyDeclaration ) : void {
@@ -70,25 +79,32 @@ namespace ts.codefix {
70
79
changeTracker . replaceNode ( propertyDeclarationSourceFile , propertyDeclaration , property ) ;
71
80
}
72
81
73
- function getActionForAddMissingUndefinedType ( context : CodeFixContext , propertyDeclaration : PropertyDeclaration ) : CodeFixAction {
74
- const changes = textChanges . ChangeTracker . with ( context , t => addUndefinedType ( t , context . sourceFile , propertyDeclaration ) ) ;
75
- return createCodeFixAction ( fixName , changes , [ Diagnostics . Add_undefined_type_to_property_0 , propertyDeclaration . name . getText ( ) ] , fixIdAddUndefinedType , Diagnostics . Add_undefined_type_to_all_uninitialized_properties ) ;
82
+ function getActionForAddMissingUndefinedType ( context : CodeFixContext , info : Info ) : CodeFixAction {
83
+ const changes = textChanges . ChangeTracker . with ( context , t => addUndefinedType ( t , context . sourceFile , info ) ) ;
84
+ return createCodeFixAction ( fixName , changes , [ Diagnostics . Add_undefined_type_to_property_0 , info . prop . name . getText ( ) ] , fixIdAddUndefinedType , Diagnostics . Add_undefined_type_to_all_uninitialized_properties ) ;
76
85
}
77
86
78
- function addUndefinedType ( changeTracker : textChanges . ChangeTracker , propertyDeclarationSourceFile : SourceFile , propertyDeclaration : PropertyDeclaration ) : void {
87
+ function addUndefinedType ( changeTracker : textChanges . ChangeTracker , sourceFile : SourceFile , info : Info ) : void {
79
88
const undefinedTypeNode = factory . createKeywordTypeNode ( SyntaxKind . UndefinedKeyword ) ;
80
- const type = propertyDeclaration . type ! ; // TODO: GH#18217
81
- const types = isUnionTypeNode ( type ) ? type . types . concat ( undefinedTypeNode ) : [ type , undefinedTypeNode ] ;
82
- changeTracker . replaceNode ( propertyDeclarationSourceFile , type , factory . createUnionTypeNode ( types ) ) ;
89
+ const types = isUnionTypeNode ( info . type ) ? info . type . types . concat ( undefinedTypeNode ) : [ info . type , undefinedTypeNode ] ;
90
+ const unionTypeNode = factory . createUnionTypeNode ( types ) ;
91
+ if ( info . isJs ) {
92
+ changeTracker . addJSDocTags ( sourceFile , info . prop , [ factory . createJSDocTypeTag ( /*tagName*/ undefined , factory . createJSDocTypeExpression ( unionTypeNode ) ) ] ) ;
93
+ }
94
+ else {
95
+ changeTracker . replaceNode ( sourceFile , info . type , unionTypeNode ) ;
96
+ }
83
97
}
84
98
85
- function getActionForAddMissingInitializer ( context : CodeFixContext , propertyDeclaration : PropertyDeclaration ) : CodeFixAction | undefined {
99
+ function getActionForAddMissingInitializer ( context : CodeFixContext , info : Info ) : CodeFixAction | undefined {
100
+ if ( info . isJs ) return undefined ;
101
+
86
102
const checker = context . program . getTypeChecker ( ) ;
87
- const initializer = getInitializer ( checker , propertyDeclaration ) ;
103
+ const initializer = getInitializer ( checker , info . prop ) ;
88
104
if ( ! initializer ) return undefined ;
89
105
90
- const changes = textChanges . ChangeTracker . with ( context , t => addInitializer ( t , context . sourceFile , propertyDeclaration , initializer ) ) ;
91
- return createCodeFixAction ( fixName , changes , [ Diagnostics . Add_initializer_to_property_0 , propertyDeclaration . name . getText ( ) ] , fixIdAddInitializer , Diagnostics . Add_initializers_to_all_uninitialized_properties ) ;
106
+ const changes = textChanges . ChangeTracker . with ( context , t => addInitializer ( t , context . sourceFile , info . prop , initializer ) ) ;
107
+ return createCodeFixAction ( fixName , changes , [ Diagnostics . Add_initializer_to_property_0 , info . prop . name . getText ( ) ] , fixIdAddInitializer , Diagnostics . Add_initializers_to_all_uninitialized_properties ) ;
92
108
}
93
109
94
110
function addInitializer ( changeTracker : textChanges . ChangeTracker , propertyDeclarationSourceFile : SourceFile , propertyDeclaration : PropertyDeclaration , initializer : Expression ) : void {
0 commit comments