@@ -10,14 +10,15 @@ namespace ts.codefix {
1010 Diagnostics . Property_0_is_missing_in_type_1_but_required_in_type_2 . code ,
1111 Diagnostics . Type_0_is_missing_the_following_properties_from_type_1_Colon_2 . code ,
1212 Diagnostics . Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more . code ,
13+ Diagnostics . Argument_of_type_0_is_not_assignable_to_parameter_of_type_1 . code ,
1314 Diagnostics . Cannot_find_name_0 . code
1415 ] ;
1516
1617 registerCodeFix ( {
1718 errorCodes,
1819 getCodeActions ( context ) {
1920 const typeChecker = context . program . getTypeChecker ( ) ;
20- const info = getInfo ( context . sourceFile , context . span . start , typeChecker , context . program ) ;
21+ const info = getInfo ( context . sourceFile , context . span . start , context . errorCode , typeChecker , context . program ) ;
2122 if ( ! info ) {
2223 return undefined ;
2324 }
@@ -44,7 +45,7 @@ namespace ts.codefix {
4445
4546 return createCombinedCodeActions ( textChanges . ChangeTracker . with ( context , changes => {
4647 eachDiagnostic ( context , errorCodes , diag => {
47- const info = getInfo ( diag . file , diag . start , checker , context . program ) ;
48+ const info = getInfo ( diag . file , diag . start , diag . code , checker , context . program ) ;
4849 if ( ! info || ! addToSeen ( seen , getNodeId ( info . parentDeclaration ) + "#" + info . token . text ) ) {
4950 return ;
5051 }
@@ -135,38 +136,48 @@ namespace ts.codefix {
135136 readonly token : Identifier ;
136137 readonly properties : Symbol [ ] ;
137138 readonly parentDeclaration : ObjectLiteralExpression ;
139+ readonly indentation ?: number ;
138140 }
139141
140- function getInfo ( sourceFile : SourceFile , tokenPos : number , checker : TypeChecker , program : Program ) : Info | undefined {
142+ function getInfo ( sourceFile : SourceFile , tokenPos : number , errorCode : number , checker : TypeChecker , program : Program ) : Info | undefined {
141143 // The identifier of the missing property. eg:
142144 // this.missing = 1;
143145 // ^^^^^^^
144146 const token = getTokenAtPosition ( sourceFile , tokenPos ) ;
145- if ( ! isIdentifier ( token ) && ! isPrivateIdentifier ( token ) ) {
146- return undefined ;
147+ const parent = token . parent ;
148+
149+ if ( errorCode === Diagnostics . Argument_of_type_0_is_not_assignable_to_parameter_of_type_1 . code ) {
150+ if ( ! ( token . kind === SyntaxKind . OpenBraceToken && isObjectLiteralExpression ( parent ) && isCallExpression ( parent . parent ) ) ) return undefined ;
151+
152+ const argIndex = findIndex ( parent . parent . arguments , arg => arg === parent ) ;
153+ if ( argIndex < 0 ) return undefined ;
154+
155+ const signature = singleOrUndefined ( checker . getSignaturesOfType ( checker . getTypeAtLocation ( parent . parent . expression ) , SignatureKind . Call ) ) ;
156+ if ( ! ( signature && signature . declaration && signature . parameters [ argIndex ] ) ) return undefined ;
157+
158+ const param = signature . parameters [ argIndex ] . valueDeclaration ;
159+ if ( ! ( param && isParameter ( param ) && isIdentifier ( param . name ) ) ) return undefined ;
160+
161+ const properties = arrayFrom ( checker . getUnmatchedProperties ( checker . getTypeAtLocation ( parent ) , checker . getTypeAtLocation ( param ) , /* requireOptionalProperties */ false , /* matchDiscriminantProperties */ false ) ) ;
162+ return length ( properties ) ? { kind : InfoKind . ObjectLiteral , token : param . name , properties, indentation : 0 , parentDeclaration : parent } : undefined ; ;
147163 }
148164
149- const { parent } = token ;
165+ if ( ! isMemberName ( token ) ) return undefined ;
166+
150167 if ( isIdentifier ( token ) && hasInitializer ( parent ) && parent . initializer && isObjectLiteralExpression ( parent . initializer ) ) {
151168 const properties = arrayFrom ( checker . getUnmatchedProperties ( checker . getTypeAtLocation ( parent . initializer ) , checker . getTypeAtLocation ( token ) , /* requireOptionalProperties */ false , /* matchDiscriminantProperties */ false ) ) ;
152- if ( length ( properties ) ) {
153- return { kind : InfoKind . ObjectLiteral , token, properties, parentDeclaration : parent . initializer } ;
154- }
169+ return length ( properties ) ? { kind : InfoKind . ObjectLiteral , token, properties, indentation : undefined , parentDeclaration : parent . initializer } : undefined ;
155170 }
156171
157172 if ( isIdentifier ( token ) && isCallExpression ( parent ) ) {
158173 return { kind : InfoKind . Function , token, call : parent , sourceFile, modifierFlags : ModifierFlags . None , parentDeclaration : sourceFile } ;
159174 }
160175
161- if ( ! isPropertyAccessExpression ( parent ) ) {
162- return undefined ;
163- }
176+ if ( ! isPropertyAccessExpression ( parent ) ) return undefined ;
164177
165178 const leftExpressionType = skipConstraint ( checker . getTypeAtLocation ( parent . expression ) ) ;
166- const { symbol } = leftExpressionType ;
167- if ( ! symbol || ! symbol . declarations ) {
168- return undefined ;
169- }
179+ const symbol = leftExpressionType . symbol ;
180+ if ( ! symbol || ! symbol . declarations ) return undefined ;
170181
171182 if ( isIdentifier ( token ) && isCallExpression ( parent . parent ) ) {
172183 const moduleDeclaration = find ( symbol . declarations , isModuleDeclaration ) ;
@@ -176,9 +187,7 @@ namespace ts.codefix {
176187 }
177188
178189 const moduleSourceFile = find ( symbol . declarations , isSourceFile ) ;
179- if ( sourceFile . commonJsModuleIndicator ) {
180- return ;
181- }
190+ if ( sourceFile . commonJsModuleIndicator ) return undefined ;
182191
183192 if ( moduleSourceFile && ! program . isSourceFileFromExternalLibrary ( moduleSourceFile ) ) {
184193 return { kind : InfoKind . Function , token, call : parent . parent , sourceFile : moduleSourceFile , modifierFlags : ModifierFlags . Export , parentDeclaration : moduleSourceFile } ;
@@ -187,17 +196,13 @@ namespace ts.codefix {
187196
188197 const classDeclaration = find ( symbol . declarations , isClassLike ) ;
189198 // Don't suggest adding private identifiers to anything other than a class.
190- if ( ! classDeclaration && isPrivateIdentifier ( token ) ) {
191- return undefined ;
192- }
199+ if ( ! classDeclaration && isPrivateIdentifier ( token ) ) return undefined ;
193200
194201 // Prefer to change the class instead of the interface if they are merged
195202 const classOrInterface = classDeclaration || find ( symbol . declarations , isInterfaceDeclaration ) ;
196203 if ( classOrInterface && ! program . isSourceFileFromExternalLibrary ( classOrInterface . getSourceFile ( ) ) ) {
197204 const makeStatic = ( ( leftExpressionType as TypeReference ) . target || leftExpressionType ) !== checker . getDeclaredTypeOfSymbol ( symbol ) ;
198- if ( makeStatic && ( isPrivateIdentifier ( token ) || isInterfaceDeclaration ( classOrInterface ) ) ) {
199- return undefined ;
200- }
205+ if ( makeStatic && ( isPrivateIdentifier ( token ) || isInterfaceDeclaration ( classOrInterface ) ) ) return undefined ;
201206
202207 const declSourceFile = classOrInterface . getSourceFile ( ) ;
203208 const modifierFlags = ( makeStatic ? ModifierFlags . Static : 0 ) | ( startsWithUnderscore ( token . text ) ? ModifierFlags . Private : 0 ) ;
@@ -438,7 +443,12 @@ namespace ts.codefix {
438443 const initializer = prop . valueDeclaration ? tryGetInitializerValueFromType ( context , checker , importAdder , quotePreference , checker . getTypeAtLocation ( prop . valueDeclaration ) ) : createUndefined ( ) ;
439444 return factory . createPropertyAssignment ( prop . name , initializer ) ;
440445 } ) ;
441- changes . replaceNode ( context . sourceFile , info . parentDeclaration , factory . createObjectLiteralExpression ( [ ...info . parentDeclaration . properties , ...props ] , /*multiLine*/ true ) ) ;
446+ const options = {
447+ leadingTriviaOption : textChanges . LeadingTriviaOption . Exclude ,
448+ trailingTriviaOption : textChanges . TrailingTriviaOption . Exclude ,
449+ indentation : info . indentation
450+ } ;
451+ changes . replaceNode ( context . sourceFile , info . parentDeclaration , factory . createObjectLiteralExpression ( [ ...info . parentDeclaration . properties , ...props ] , /*multiLine*/ true ) , options ) ;
442452 }
443453
444454 function tryGetInitializerValueFromType ( context : CodeFixContextBase , checker : TypeChecker , importAdder : ImportAdder , quotePreference : QuotePreference , type : Type ) : Expression {
0 commit comments