mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 01:49:41 -05:00
textChanges: Don't crash when inserting type annotation on function with no parens (#23034)
This commit is contained in:
@@ -50,19 +50,19 @@ namespace ts.codefix {
|
||||
for (const param of decl.parameters) {
|
||||
if (!param.type) {
|
||||
const paramType = getJSDocType(param);
|
||||
if (paramType) changes.insertTypeAnnotation(sourceFile, param, transformJSDocType(paramType));
|
||||
if (paramType) changes.tryInsertTypeAnnotation(sourceFile, param, transformJSDocType(paramType));
|
||||
}
|
||||
}
|
||||
if (needParens) changes.insertNodeAfter(sourceFile, last(decl.parameters), createToken(SyntaxKind.CloseParenToken));
|
||||
if (!decl.type) {
|
||||
const returnType = getJSDocReturnType(decl);
|
||||
if (returnType) changes.insertTypeAnnotation(sourceFile, decl, transformJSDocType(returnType));
|
||||
if (returnType) changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(returnType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
const jsdocType = Debug.assertDefined(getJSDocType(decl)); // If not defined, shouldn't have been an error to fix
|
||||
Debug.assert(!decl.type); // If defined, shouldn't have been an error to fix.
|
||||
changes.insertTypeAnnotation(sourceFile, decl, transformJSDocType(jsdocType));
|
||||
changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(jsdocType));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace ts.codefix {
|
||||
|
||||
function annotate(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: textChanges.TypeAnnotatable, type: Type | undefined, program: Program): void {
|
||||
const typeNode = type && getTypeNodeIfAccessible(type, declaration, program.getTypeChecker());
|
||||
if (typeNode) changes.insertTypeAnnotation(sourceFile, declaration, typeNode);
|
||||
if (typeNode) changes.tryInsertTypeAnnotation(sourceFile, declaration, typeNode);
|
||||
}
|
||||
|
||||
function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, checker: TypeChecker): TypeNode | undefined {
|
||||
|
||||
@@ -360,12 +360,21 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
/** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */
|
||||
public insertTypeAnnotation(sourceFile: SourceFile, node: TypeAnnotatable, type: TypeNode): void {
|
||||
const end = (isFunctionLike(node)
|
||||
// If no `)`, is an arrow function `x => x`, so use the end of the first parameter
|
||||
? findChildOfKind(node, SyntaxKind.CloseParenToken, sourceFile) || first(node.parameters)
|
||||
: node.kind !== SyntaxKind.VariableDeclaration && node.questionToken ? node.questionToken : node.name).end;
|
||||
this.insertNodeAt(sourceFile, end, type, { prefix: ": " });
|
||||
public tryInsertTypeAnnotation(sourceFile: SourceFile, node: TypeAnnotatable, type: TypeNode): void {
|
||||
let endNode: Node;
|
||||
if (isFunctionLike(node)) {
|
||||
endNode = findChildOfKind(node, SyntaxKind.CloseParenToken, sourceFile);
|
||||
if (!endNode) {
|
||||
if (!isArrowFunction(node)) return; // Function missing parentheses, give up
|
||||
// If no `)`, is an arrow function `x => x`, so use the end of the first parameter
|
||||
endNode = first(node.parameters);
|
||||
}
|
||||
}
|
||||
else {
|
||||
endNode = node.kind !== SyntaxKind.VariableDeclaration && node.questionToken ? node.questionToken : node.name;
|
||||
}
|
||||
|
||||
this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " });
|
||||
}
|
||||
|
||||
public insertTypeParameters(sourceFile: SourceFile, node: SignatureDeclaration, typeParameters: ReadonlyArray<TypeParameterDeclaration>): void {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitAny: true
|
||||
// @target: esnext
|
||||
|
||||
////class C {
|
||||
//// m() { this.x * 2; }
|
||||
//// get x { return null; }
|
||||
////}
|
||||
|
||||
// Just testing that we don't crash in `insertTypeAnnotation` from inferFromUsage
|
||||
verify.not.codeFixAvailable();
|
||||
Reference in New Issue
Block a user