@@ -44,46 +44,55 @@ namespace ts.codefix {
44
44
} ,
45
45
} ) ;
46
46
47
- function getTarget ( file : SourceFile , pos : number ) {
47
+ // The target of the incorrect assignment
48
+ // eg
49
+ // this.definite = 1; -OR- definite = source
50
+ // ^^^^ ^^^^^^^^
51
+ // TODO: More examples here
52
+ function getTarget ( file : SourceFile , pos : number ) : MemberName | PropertyAccessExpression | undefined {
48
53
const start = getTokenAtPosition ( file , pos )
49
- if ( isPropertyAccessExpression ( start . parent ) && start . parent . expression === start ) {
50
- return start . parent
51
- }
52
- else if ( isIdentifier ( start ) || isPrivateIdentifier ( start ) ) {
53
- return start
54
- }
55
- return undefined
54
+ return isPropertyAccessExpression ( start . parent ) && start . parent . expression === start ? start . parent
55
+ : isIdentifier ( start ) || isPrivateIdentifier ( start ) ? start
56
+ : undefined ;
56
57
}
57
58
58
- function getSourceTarget ( file : SourceFile , pos : number , checker : TypeChecker ) {
59
- const target = getTarget ( file , pos )
59
+ function getSourceTarget ( target : Node | undefined , checker : TypeChecker ) : { source : Node , target : Node } | undefined {
60
60
if ( ! target ) return undefined
61
61
if ( isBinaryExpression ( target . parent ) && target . parent . operatorToken . kind === SyntaxKind . EqualsToken ) {
62
- return [ target . parent . right , target ]
62
+ return { source : target . parent . right , target : target . parent . left }
63
+ }
64
+ else if ( isVariableDeclaration ( target . parent ) && target . parent . initializer ) {
65
+ return { source : target . parent . initializer , target : target . parent . name }
63
66
}
64
67
else if ( isCallExpression ( target . parent ) ) {
65
68
const n = checker . getSymbolAtLocation ( target . parent . expression )
66
69
if ( ! n ?. valueDeclaration ) return undefined
67
- if ( ! isIdentifier ( target ) ) return undefined ;
70
+ if ( ! isExpression ( target ) ) return undefined ;
68
71
const i = target . parent . arguments . indexOf ( target )
69
72
const name = ( n . valueDeclaration as any as SignatureDeclaration ) . parameters [ i ] . name
70
- if ( isIdentifier ( name ) ) return [ target , name ]
73
+ if ( isIdentifier ( name ) ) return { source : target , target : name }
74
+ }
75
+ else if ( isPropertyAssignment ( target . parent ) && isIdentifier ( target . parent . name ) ||
76
+ isShorthandPropertyAssignment ( target . parent ) ) {
77
+ const parentTarget = getSourceTarget ( target . parent . parent , checker )
78
+ if ( ! parentTarget ) return undefined
79
+ const prop = checker . getPropertyOfType ( checker . getTypeAtLocation ( parentTarget . target ) , ( target . parent . name as Identifier ) . text )
80
+ const declaration = prop ?. declarations ?. [ 0 ]
81
+ if ( ! declaration ) return undefined
82
+ return {
83
+ source : isPropertyAssignment ( target . parent ) ? target . parent . initializer : target . parent . name ,
84
+ target : declaration
85
+ }
71
86
}
72
- // It's possible to handle destructuring by recording the path up through the structure
73
- // and following the reverse path down through the right-hand-side, but that's not worth the effort
74
87
return undefined
75
88
}
76
89
77
90
function getInfo ( file : SourceFile , pos : number , checker : TypeChecker ) : Symbol [ ] {
78
- // The target of the incorrect assignment
79
- // eg
80
- // this.definite = 1; -OR- definite = source
81
- // ^^^^ ^^^^^^^^
82
- const sourceTarget = getSourceTarget ( file , pos , checker )
91
+ const sourceTarget = getSourceTarget ( getTarget ( file , pos ) , checker )
83
92
if ( ! sourceTarget ) return [ ]
84
- const [ sourceNode , targetNode ] = sourceTarget
93
+ const { source : sourceNode , target : targetNode } = sourceTarget
85
94
const target = checker . getTypeAtLocation ( targetNode )
86
- if ( target . symbol ?. declarations ?. some ( d => getSourceFileOfNode ( d ) . fileName . match ( / ( n o d e _ m o d u l e s | ^ l i b ) / ) ) ) return [ ] ;
95
+ if ( target . symbol ?. declarations ?. some ( d => getSourceFileOfNode ( d ) . fileName . match ( / ( n o d e _ m o d u l e s | ^ l i b \. ) / ) ) ) return [ ] ;
87
96
return checker . getExactOptionalUnassignableProperties ( checker . getTypeAtLocation ( sourceNode ) , target )
88
97
}
89
98
0 commit comments