mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-12 21:37:41 -06:00
infer-from-usage suggestions can't be ignored, and always do something when invoked. (#28206)
* Do not ts-ignore noImplicitAny suggestions Still need to write tests. * Add tests * More tests * Update baselines
This commit is contained in:
parent
24febc2445
commit
60efb65931
@ -13367,12 +13367,12 @@ namespace ts {
|
||||
case SyntaxKind.BinaryExpression:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
diagnostic = Diagnostics.Member_0_implicitly_has_an_1_type;
|
||||
diagnostic = noImplicitAny ? Diagnostics.Member_0_implicitly_has_an_1_type : Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage;
|
||||
break;
|
||||
case SyntaxKind.Parameter:
|
||||
diagnostic = (<ParameterDeclaration>declaration).dotDotDotToken ?
|
||||
Diagnostics.Rest_parameter_0_implicitly_has_an_any_type :
|
||||
Diagnostics.Parameter_0_implicitly_has_an_1_type;
|
||||
noImplicitAny ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage :
|
||||
noImplicitAny ? Diagnostics.Parameter_0_implicitly_has_an_1_type : Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage;
|
||||
break;
|
||||
case SyntaxKind.BindingElement:
|
||||
diagnostic = Diagnostics.Binding_element_0_implicitly_has_an_1_type;
|
||||
@ -13388,7 +13388,7 @@ namespace ts {
|
||||
error(declaration, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString);
|
||||
return;
|
||||
}
|
||||
diagnostic = Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type;
|
||||
diagnostic = noImplicitAny ? Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type : Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage;
|
||||
break;
|
||||
case SyntaxKind.MappedType:
|
||||
if (noImplicitAny) {
|
||||
@ -13396,7 +13396,7 @@ namespace ts {
|
||||
}
|
||||
return;
|
||||
default:
|
||||
diagnostic = Diagnostics.Variable_0_implicitly_has_an_1_type;
|
||||
diagnostic = noImplicitAny ? Diagnostics.Variable_0_implicitly_has_an_1_type : Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage;
|
||||
}
|
||||
errorOrSuggestion(noImplicitAny, declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString);
|
||||
}
|
||||
|
||||
@ -4041,6 +4041,39 @@
|
||||
"category": "Error",
|
||||
"code": 7042
|
||||
},
|
||||
"Variable '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.": {
|
||||
"category": "Suggestion",
|
||||
"code": 7043
|
||||
},
|
||||
"Parameter '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.": {
|
||||
"category": "Suggestion",
|
||||
"code": 7044
|
||||
},
|
||||
"Member '{0}' implicitly has an '{1}' type, but a better type may be inferred from usage.": {
|
||||
"category": "Suggestion",
|
||||
"code": 7045
|
||||
},
|
||||
"Variable '{0}' implicitly has type '{1}' in some locations, but a better type may be inferred from usage.": {
|
||||
"category": "Suggestion",
|
||||
"code": 7046
|
||||
},
|
||||
"Rest parameter '{0}' implicitly has an 'any[]' type, but a better type may be inferred from usage.": {
|
||||
"category": "Suggestion",
|
||||
"code": 7047
|
||||
},
|
||||
"Property '{0}' implicitly has type 'any', but a better type for its get accessor may be inferred from usage.": {
|
||||
"category": "Suggestion",
|
||||
"code": 7048
|
||||
},
|
||||
"Property '{0}' implicitly has type 'any', but a better type for its set accessor may be inferred from usage.": {
|
||||
"category": "Suggestion",
|
||||
"code": 7049
|
||||
},
|
||||
"'{0}' implicitly has an '{1}' return type, but a better type may be inferred from usage.": {
|
||||
"category": "Suggestion",
|
||||
"code": 7050
|
||||
},
|
||||
|
||||
"You cannot rename this element.": {
|
||||
"category": "Error",
|
||||
"code": 8000
|
||||
|
||||
@ -21,6 +21,27 @@ namespace ts.codefix {
|
||||
|
||||
// Property declarations
|
||||
Diagnostics.Member_0_implicitly_has_an_1_type.code,
|
||||
|
||||
//// Suggestions
|
||||
// Variable declarations
|
||||
Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code,
|
||||
|
||||
// Variable uses
|
||||
Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
|
||||
|
||||
// Parameter declarations
|
||||
Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
|
||||
Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code,
|
||||
|
||||
// Get Accessor declarations
|
||||
Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code,
|
||||
Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage.code,
|
||||
|
||||
// Set Accessor declarations
|
||||
Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code,
|
||||
|
||||
// Property declarations
|
||||
Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
|
||||
];
|
||||
registerCodeFix({
|
||||
errorCodes,
|
||||
@ -47,20 +68,46 @@ namespace ts.codefix {
|
||||
function getDiagnostic(errorCode: number, token: Node): DiagnosticMessage {
|
||||
switch (errorCode) {
|
||||
case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
|
||||
case Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return isSetAccessorDeclaration(getContainingFunction(token)!) ? Diagnostics.Infer_type_of_0_from_usage : Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217
|
||||
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
|
||||
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Infer_parameter_types_from_usage;
|
||||
default:
|
||||
return Diagnostics.Infer_type_of_0_from_usage;
|
||||
}
|
||||
}
|
||||
|
||||
/** Map suggestion code to error code */
|
||||
function mapSuggestionDiagnostic(errorCode: number) {
|
||||
switch (errorCode) {
|
||||
case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code;
|
||||
case Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Variable_0_implicitly_has_an_1_type.code;
|
||||
case Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Parameter_0_implicitly_has_an_1_type.code;
|
||||
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code;
|
||||
case Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code;
|
||||
case Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code;
|
||||
case Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code;
|
||||
case Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Member_0_implicitly_has_an_1_type.code;
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node, errorCode: number, program: Program, cancellationToken: CancellationToken, markSeen: NodeSeenTracker, host: LanguageServiceHost): Declaration | undefined {
|
||||
if (!isParameterPropertyModifier(token.kind) && token.kind !== SyntaxKind.Identifier && token.kind !== SyntaxKind.DotDotDotToken && token.kind !== SyntaxKind.ThisKeyword) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { parent } = token;
|
||||
errorCode = mapSuggestionDiagnostic(errorCode);
|
||||
switch (errorCode) {
|
||||
// Variable and Property declarations
|
||||
case Diagnostics.Member_0_implicitly_has_an_1_type.code:
|
||||
@ -71,7 +118,7 @@ namespace ts.codefix {
|
||||
}
|
||||
if (isPropertyAccessExpression(parent)) {
|
||||
const type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken);
|
||||
const typeNode = type && getTypeNodeIfAccessible(type, parent, program, host);
|
||||
const typeNode = getTypeNodeIfAccessible(type, parent, program, host);
|
||||
if (typeNode) {
|
||||
// Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags
|
||||
const typeTag = createJSDocTypeTag(createJSDocTypeExpression(typeNode), /*comment*/ "");
|
||||
@ -107,7 +154,7 @@ namespace ts.codefix {
|
||||
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
|
||||
if (markSeen(containingFunction)) {
|
||||
const param = cast(parent, isParameter);
|
||||
annotateParameters(changes, param, containingFunction, sourceFile, program, host, cancellationToken);
|
||||
annotateParameters(changes, sourceFile, param, containingFunction, program, host, cancellationToken);
|
||||
return param;
|
||||
}
|
||||
return undefined;
|
||||
@ -152,7 +199,7 @@ namespace ts.codefix {
|
||||
return false;
|
||||
}
|
||||
|
||||
function annotateParameters(changes: textChanges.ChangeTracker, parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, sourceFile: SourceFile, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken): void {
|
||||
function annotateParameters(changes: textChanges.ChangeTracker, sourceFile: SourceFile, parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken): void {
|
||||
if (!isIdentifier(parameterDeclaration.name) || !isApplicableFunctionForInference(containingFunction)) {
|
||||
return;
|
||||
}
|
||||
@ -160,7 +207,7 @@ namespace ts.codefix {
|
||||
const parameterInferences = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) ||
|
||||
containingFunction.parameters.map<ParameterInference>(p => ({
|
||||
declaration: p,
|
||||
type: isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : undefined
|
||||
type: isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : program.getTypeChecker().getAnyType()
|
||||
}));
|
||||
Debug.assert(containingFunction.parameters.length === parameterInferences.length);
|
||||
|
||||
@ -179,8 +226,10 @@ namespace ts.codefix {
|
||||
function annotateSetAccessor(changes: textChanges.ChangeTracker, sourceFile: SourceFile, setAccessorDeclaration: SetAccessorDeclaration, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken): void {
|
||||
const param = firstOrUndefined(setAccessorDeclaration.parameters);
|
||||
if (param && isIdentifier(setAccessorDeclaration.name) && isIdentifier(param.name)) {
|
||||
const type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken) ||
|
||||
inferTypeForVariableFromUsage(param.name, program, cancellationToken);
|
||||
let type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken);
|
||||
if (type === program.getTypeChecker().getAnyType()) {
|
||||
type = inferTypeForVariableFromUsage(param.name, program, cancellationToken);
|
||||
}
|
||||
if (isInJSFile(setAccessorDeclaration)) {
|
||||
annotateJSDocParameters(changes, sourceFile, [{ declaration: param, type }], program, host);
|
||||
}
|
||||
@ -190,8 +239,8 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function annotate(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: textChanges.TypeAnnotatable, type: Type | undefined, program: Program, host: LanguageServiceHost): void {
|
||||
const typeNode = type && getTypeNodeIfAccessible(type, declaration, program, host);
|
||||
function annotate(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: textChanges.TypeAnnotatable, type: Type, program: Program, host: LanguageServiceHost): void {
|
||||
const typeNode = getTypeNodeIfAccessible(type, declaration, program, host);
|
||||
if (typeNode) {
|
||||
if (isInJSFile(sourceFile) && declaration.kind !== SyntaxKind.PropertySignature) {
|
||||
const parent = isVariableDeclaration(declaration) ? tryCast(declaration.parent.parent, isVariableStatement) : declaration;
|
||||
@ -285,7 +334,7 @@ namespace ts.codefix {
|
||||
entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined);
|
||||
}
|
||||
|
||||
function inferTypeForVariableFromUsage(token: Identifier, program: Program, cancellationToken: CancellationToken): Type | undefined {
|
||||
function inferTypeForVariableFromUsage(token: Identifier, program: Program, cancellationToken: CancellationToken): Type {
|
||||
return InferFromReference.inferTypeFromReferences(getReferences(token, program, cancellationToken), program.getTypeChecker(), cancellationToken);
|
||||
}
|
||||
|
||||
@ -307,7 +356,7 @@ namespace ts.codefix {
|
||||
|
||||
interface ParameterInference {
|
||||
readonly declaration: ParameterDeclaration;
|
||||
readonly type?: Type;
|
||||
readonly type: Type;
|
||||
readonly isOptional?: boolean;
|
||||
}
|
||||
|
||||
@ -329,13 +378,13 @@ namespace ts.codefix {
|
||||
stringIndexContext?: UsageContext;
|
||||
}
|
||||
|
||||
export function inferTypeFromReferences(references: ReadonlyArray<Identifier>, checker: TypeChecker, cancellationToken: CancellationToken): Type | undefined {
|
||||
export function inferTypeFromReferences(references: ReadonlyArray<Identifier>, checker: TypeChecker, cancellationToken: CancellationToken): Type {
|
||||
const usageContext: UsageContext = {};
|
||||
for (const reference of references) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
inferTypeFromContext(reference, checker, usageContext);
|
||||
}
|
||||
return getTypeFromUsageContext(usageContext, checker);
|
||||
return getTypeFromUsageContext(usageContext, checker) || checker.getAnyType();
|
||||
}
|
||||
|
||||
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier>, declaration: FunctionLikeDeclaration, checker: TypeChecker, cancellationToken: CancellationToken): ParameterInference[] | undefined {
|
||||
@ -374,7 +423,7 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
if (!types.length) {
|
||||
return { declaration: parameter };
|
||||
return { declaration: parameter, type: checker.getAnyType() };
|
||||
}
|
||||
const type = checker.getWidenedType(checker.getUnionType(types, UnionReduction.Subtype));
|
||||
return {
|
||||
|
||||
@ -6,10 +6,11 @@
|
||||
|
||||
verify.getSuggestionDiagnostics([
|
||||
{ message: "JSDoc types may be moved to TypeScript types.", code: 80004 },
|
||||
{ message: "Variable 'x' implicitly has an 'any' type.", code: 7005 }]);
|
||||
{ message: "Variable 'x' implicitly has an 'any' type, but a better type may be inferred from usage.", code: 7043 }]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`/** @type {number} */
|
||||
var x: number;`,
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`/**
|
||||
* @param {?} x
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`class C {
|
||||
/**
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 9,
|
||||
newFileContent:
|
||||
`/**
|
||||
* @param {Boolean} x
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`class C {
|
||||
/**
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`class C {
|
||||
/** @param {number} value */
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 2,
|
||||
newFileContent:
|
||||
`/**
|
||||
* @template T
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 2,
|
||||
newFileContent:
|
||||
`
|
||||
/** @param {Object<string, boolean>} sb
|
||||
|
||||
@ -13,13 +13,14 @@
|
||||
const [r0, r1, r2, r3, r4] = test.ranges();
|
||||
verify.getSuggestionDiagnostics([
|
||||
{message: "JSDoc types may be moved to TypeScript types.", code: 80004, range: r0},
|
||||
{message: "Parameter 'x' implicitly has an 'any' type.", code: 7006, range: r1 },
|
||||
{message: "Parameter 'y' implicitly has an 'any' type.", code: 7006, range: r2 },
|
||||
{message: "Parameter 'alpha' implicitly has an 'any' type.", code: 7006, range: r3 },
|
||||
{message: "Parameter 'beta' implicitly has an 'any' type.", code: 7006, range: r4 }]);
|
||||
{message: "Parameter 'x' implicitly has an 'any' type, but a better type may be inferred from usage.", code: 7044, range: r1 },
|
||||
{message: "Parameter 'y' implicitly has an 'any' type, but a better type may be inferred from usage.", code: 7044, range: r2 },
|
||||
{message: "Parameter 'alpha' implicitly has an 'any' type, but a better type may be inferred from usage.", code: 7044, range: r3 },
|
||||
{message: "Parameter 'beta' implicitly has an 'any' type, but a better type may be inferred from usage.", code: 7044, range: r4 }]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
// TODO: GH#22358
|
||||
`/**
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 7,
|
||||
newFileContent:
|
||||
`/**
|
||||
* @param {*} x
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`declare class C {
|
||||
/** @type {number | null} */
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate with type from JSDoc",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`/**
|
||||
* @param {number} x
|
||||
|
||||
@ -9,4 +9,6 @@
|
||||
//// readonly [prop: K]?: any;
|
||||
//// }
|
||||
|
||||
verify.not.codeFixAvailable()
|
||||
verify.codeFixAvailable([
|
||||
{ "description": "Infer type of 'any' from usage" }
|
||||
])
|
||||
|
||||
@ -8,5 +8,6 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add 'this.' to unresolved variable",
|
||||
index: 0,
|
||||
newRangeContent: "this.foo = 10",
|
||||
});
|
||||
|
||||
11
tests/cases/fourslash/codeFixInferFromUsageAlwaysInfer.ts
Normal file
11
tests/cases/fourslash/codeFixInferFromUsageAlwaysInfer.ts
Normal file
@ -0,0 +1,11 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
// @noImplicitAny: false
|
||||
////function coll(callback) {
|
||||
////}
|
||||
verify.codeFix({
|
||||
description: "Infer parameter types from usage",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function coll(callback: any) {
|
||||
}`,
|
||||
});
|
||||
18
tests/cases/fourslash/codeFixInferFromUsageAlwaysInferJS.ts
Normal file
18
tests/cases/fourslash/codeFixInferFromUsageAlwaysInferJS.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noEmit: true
|
||||
// @noImplicitAny: false
|
||||
// @Filename: important.js
|
||||
////function coll(callback) {
|
||||
////}
|
||||
verify.codeFix({
|
||||
description: "Infer parameter types from usage",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`/**
|
||||
* @param {any} callback
|
||||
*/
|
||||
function coll(callback) {
|
||||
}`,
|
||||
});
|
||||
@ -10,4 +10,4 @@ verify.rangeAfterCodeFix(`var x: number;
|
||||
function f() {
|
||||
x++;
|
||||
}
|
||||
`, /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 1);
|
||||
`, /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 1);
|
||||
|
||||
13
tests/cases/fourslash/codeFixInferFromUsageVariable3.ts
Normal file
13
tests/cases/fourslash/codeFixInferFromUsageVariable3.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitAny: false
|
||||
////[|var x;
|
||||
////function f() {
|
||||
//// x++;
|
||||
////}|]
|
||||
|
||||
verify.rangeAfterCodeFix(`var x: number;
|
||||
function f() {
|
||||
x++;
|
||||
}
|
||||
`, /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);
|
||||
22
tests/cases/fourslash/codeFixInferFromUsageVariable3JS.ts
Normal file
22
tests/cases/fourslash/codeFixInferFromUsageVariable3JS.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noEmit: true
|
||||
// @noImplicitAny: false
|
||||
// @Filename: important.js
|
||||
|
||||
////[|function f(foo) {
|
||||
//// foo += 2
|
||||
//// return foo
|
||||
////}|]
|
||||
|
||||
|
||||
verify.rangeAfterCodeFix(`/**
|
||||
* @param {number} foo
|
||||
*/
|
||||
function f(foo) {
|
||||
foo += 2
|
||||
return foo
|
||||
}
|
||||
`);
|
||||
@ -7,9 +7,9 @@
|
||||
const [r0, r1] = test.ranges();
|
||||
verify.getSuggestionDiagnostics([
|
||||
{
|
||||
message: "Parameter 'p' implicitly has an 'any' type.",
|
||||
message: "Parameter 'p' implicitly has an 'any' type, but a better type may be inferred from usage.",
|
||||
range: r0,
|
||||
code: 7006,
|
||||
code: 7044,
|
||||
},
|
||||
{
|
||||
message: "'p' is declared but its value is never read.",
|
||||
@ -26,5 +26,9 @@ verify.getSuggestionDiagnostics([
|
||||
]);
|
||||
|
||||
verify.codeFixAvailable(
|
||||
["Remove declaration for: 'p'", "Prefix 'p' with an underscore", "Remove declaration for: 'x'"]
|
||||
.map(description => ({ description })));
|
||||
[
|
||||
"Infer parameter types from usage",
|
||||
"Remove declaration for: 'p'",
|
||||
"Prefix 'p' with an underscore",
|
||||
"Remove declaration for: 'x'"
|
||||
].map(description => ({ description })));
|
||||
|
||||
@ -6,4 +6,7 @@
|
||||
////}
|
||||
////f(
|
||||
|
||||
verify.not.codeFixAvailable();
|
||||
goTo.marker('1');
|
||||
verify.codeFixAvailable([
|
||||
{ "description": "Infer parameter types from usage" }
|
||||
]);
|
||||
|
||||
@ -3,4 +3,6 @@
|
||||
// @noImplicitAny: true
|
||||
////function f(new C(100, 3, undefined)
|
||||
|
||||
verify.codeFixAvailable([]); // Parse error, so no unused diagnostics
|
||||
verify.codeFixAvailable([
|
||||
{ "description": "Infer parameter types from usage" }
|
||||
]); // Parse error, so no unused diagnostics
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
// Only give suggestions for nodes that do NOT have parse errors
|
||||
verify.getSuggestionDiagnostics([{
|
||||
message: "Variable 'd' implicitly has an 'any' type.",
|
||||
code: 7005,
|
||||
message: "Variable 'd' implicitly has an 'any' type, but a better type may be inferred from usage.",
|
||||
code: 7043,
|
||||
range: {
|
||||
fileName: "/a.ts",
|
||||
pos: 23,
|
||||
|
||||
@ -11,5 +11,5 @@
|
||||
verify.rangeAfterCodeFix(`namespace greeter {
|
||||
export class class2 {
|
||||
}
|
||||
}`);
|
||||
}`, /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);
|
||||
|
||||
|
||||
@ -6,4 +6,4 @@
|
||||
//// use(y, z);
|
||||
////}
|
||||
|
||||
verify.rangeAfterCodeFix("var y = 0,z = 1;");
|
||||
verify.rangeAfterCodeFix("var y = 0,z = 1;", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);
|
||||
|
||||
@ -9,4 +9,4 @@
|
||||
//// }
|
||||
////}
|
||||
|
||||
verify.rangeAfterCodeFix("var y = 10;");
|
||||
verify.rangeAfterCodeFix("var y = 10;", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);
|
||||
|
||||
@ -9,4 +9,4 @@
|
||||
//// }
|
||||
////}
|
||||
|
||||
verify.rangeAfterCodeFix("var y;");
|
||||
verify.rangeAfterCodeFix("var y;", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);
|
||||
|
||||
@ -8,5 +8,6 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Remove declaration for: 'greeting'",
|
||||
index: 0,
|
||||
newRangeContent: "public greeting1;\n",
|
||||
});
|
||||
|
||||
@ -10,5 +10,6 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Remove declaration for: 'b'",
|
||||
index: 0,
|
||||
newRangeContent: 'let a = "dummy entry", c = 0;',
|
||||
});
|
||||
|
||||
@ -10,5 +10,6 @@
|
||||
|
||||
verify.codeFix({
|
||||
description: "Remove declaration for: 'c'",
|
||||
index: 0,
|
||||
newRangeContent: 'let a = "dummy entry", b;',
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user