Skip to content

Commit 0481d44

Browse files
authored
Bad callsite inferences fall back to body usage (#28235)
For parameters, the infer-from-usage codefix uses a substantially different codepath that previously only looked at call site uses. When this resulted in no inferences, or bad inferences, for a single parameter, the codefix would just use any. Only if no usages of a function were found would the codefix use the body-inference code. This commit makes parameter inference fall back to body-inference code for individual parameters when there is no inference or inference to any.
1 parent 437bc41 commit 0481d44

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

src/services/codefixes/inferFromUsage.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ namespace ts.codefix {
349349
findChildOfKind<Token<SyntaxKind.ConstructorKeyword>>(containingFunction, SyntaxKind.ConstructorKeyword, sourceFile) :
350350
containingFunction.name;
351351
if (searchToken) {
352-
return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program.getTypeChecker(), cancellationToken);
352+
return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program, cancellationToken);
353353
}
354354
}
355355
}
@@ -387,7 +387,8 @@ namespace ts.codefix {
387387
return getTypeFromUsageContext(usageContext, checker) || checker.getAnyType();
388388
}
389389

390-
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier>, declaration: FunctionLikeDeclaration, checker: TypeChecker, cancellationToken: CancellationToken): ParameterInference[] | undefined {
390+
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier>, declaration: FunctionLikeDeclaration, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
391+
const checker = program.getTypeChecker();
391392
if (references.length === 0) {
392393
return undefined;
393394
}
@@ -422,10 +423,14 @@ namespace ts.codefix {
422423
types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[parameterIndex]));
423424
}
424425
}
425-
if (!types.length) {
426-
return { declaration: parameter, type: checker.getAnyType() };
426+
427+
let type = types.length && checker.getWidenedType(checker.getUnionType(types, UnionReduction.Subtype));
428+
if ((!type || type.flags & TypeFlags.Any) && isIdentifier(parameter.name)) {
429+
type = inferTypeForVariableFromUsage(parameter.name, program, cancellationToken);
430+
}
431+
if (!type) {
432+
type = checker.getAnyType();
427433
}
428-
const type = checker.getWidenedType(checker.getUnionType(types, UnionReduction.Subtype));
429434
return {
430435
type: isRest ? checker.createArrayType(type) : type,
431436
isOptional: isOptional && !isRest,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts' />
2+
// based on acorn
3+
4+
////function isIdentifierStart([|code, astral |]) {
5+
//// if (code < 65) { return code === 36 }
6+
//// if (code < 91) { return true }
7+
//// if (code < 97) { return code === 95 }
8+
//// if (code < 123) { return true }
9+
//// if (code <= 0xffff) { return code >= 0xaa }
10+
//// if (astral === false) { return false }
11+
////}
12+
////
13+
////function isLet(nextCh: any) {
14+
//// return isIdentifierStart(nextCh, true)
15+
////};
16+
17+
18+
verify.rangeAfterCodeFix("code: number, astral: boolean",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);

0 commit comments

Comments
 (0)