mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-24 02:21:30 -05:00
Enable strictFunctionTypes (#49929)
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
isJSDocIndexSignature,
|
||||
isOptionalJSDocPropertyLikeTag,
|
||||
isParameter,
|
||||
isTypeNode,
|
||||
JSDocFunctionType,
|
||||
JSDocNonNullableType,
|
||||
JSDocNullableType,
|
||||
@@ -35,7 +36,6 @@ import {
|
||||
SyntaxKind,
|
||||
textChanges,
|
||||
tryCast,
|
||||
TypeNode,
|
||||
TypeReferenceNode,
|
||||
VariableDeclaration,
|
||||
visitEachChild,
|
||||
@@ -100,19 +100,19 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, de
|
||||
for (const param of decl.parameters) {
|
||||
if (!param.type) {
|
||||
const paramType = getJSDocType(param);
|
||||
if (paramType) changes.tryInsertTypeAnnotation(sourceFile, param, transformJSDocType(paramType));
|
||||
if (paramType) changes.tryInsertTypeAnnotation(sourceFile, param, visitNode(paramType, transformJSDocType, isTypeNode));
|
||||
}
|
||||
}
|
||||
if (needParens) changes.insertNodeAfter(sourceFile, last(decl.parameters), factory.createToken(SyntaxKind.CloseParenToken));
|
||||
if (!decl.type) {
|
||||
const returnType = getJSDocReturnType(decl);
|
||||
if (returnType) changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(returnType));
|
||||
if (returnType) changes.tryInsertTypeAnnotation(sourceFile, decl, visitNode(returnType, transformJSDocType, isTypeNode));
|
||||
}
|
||||
}
|
||||
else {
|
||||
const jsdocType = Debug.checkDefined(getJSDocType(decl), "A JSDocType for this declaration should exist"); // If not defined, shouldn't have been an error to fix
|
||||
Debug.assert(!decl.type, "The JSDocType decl should have a type"); // If defined, shouldn't have been an error to fix.
|
||||
changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(jsdocType));
|
||||
changes.tryInsertTypeAnnotation(sourceFile, decl, visitNode(jsdocType, transformJSDocType, isTypeNode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ function isDeclarationWithType(node: Node): node is DeclarationWithType {
|
||||
node.kind === SyntaxKind.PropertyDeclaration;
|
||||
}
|
||||
|
||||
function transformJSDocType(node: TypeNode): TypeNode {
|
||||
function transformJSDocType(node: Node): Node {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JSDocAllType:
|
||||
case SyntaxKind.JSDocUnknownType:
|
||||
@@ -155,21 +155,21 @@ function transformJSDocTypeLiteral(node: JSDocTypeLiteral) {
|
||||
/*modifiers*/ undefined,
|
||||
isIdentifier(tag.name) ? tag.name : tag.name.right,
|
||||
isOptionalJSDocPropertyLikeTag(tag) ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
|
||||
tag.typeExpression && visitNode(tag.typeExpression.type, transformJSDocType) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword))));
|
||||
tag.typeExpression && visitNode(tag.typeExpression.type, transformJSDocType, isTypeNode) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword))));
|
||||
setEmitFlags(typeNode, EmitFlags.SingleLine);
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
function transformJSDocOptionalType(node: JSDocOptionalType) {
|
||||
return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType), factory.createTypeReferenceNode("undefined", emptyArray)]);
|
||||
return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType, isTypeNode), factory.createTypeReferenceNode("undefined", emptyArray)]);
|
||||
}
|
||||
|
||||
function transformJSDocNullableType(node: JSDocNullableType) {
|
||||
return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType), factory.createTypeReferenceNode("null", emptyArray)]);
|
||||
return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType, isTypeNode), factory.createTypeReferenceNode("null", emptyArray)]);
|
||||
}
|
||||
|
||||
function transformJSDocVariadicType(node: JSDocVariadicType) {
|
||||
return factory.createArrayTypeNode(visitNode(node.type, transformJSDocType));
|
||||
return factory.createArrayTypeNode(visitNode(node.type, transformJSDocType, isTypeNode));
|
||||
}
|
||||
|
||||
function transformJSDocFunctionType(node: JSDocFunctionType) {
|
||||
@@ -183,7 +183,7 @@ function transformJSDocParameter(node: ParameterDeclaration) {
|
||||
const isRest = node.type!.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; // TODO: GH#18217
|
||||
const name = node.name || (isRest ? "rest" : "arg" + index);
|
||||
const dotdotdot = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken;
|
||||
return factory.createParameterDeclaration(node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer);
|
||||
return factory.createParameterDeclaration(node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType, isTypeNode), node.initializer);
|
||||
}
|
||||
|
||||
function transformJSDocTypeReference(node: TypeReferenceNode) {
|
||||
@@ -212,7 +212,7 @@ function transformJSDocTypeReference(node: TypeReferenceNode) {
|
||||
args = factory.createNodeArray([factory.createTypeReferenceNode("any", emptyArray)]);
|
||||
}
|
||||
else {
|
||||
args = visitNodes(node.typeArguments, transformJSDocType);
|
||||
args = visitNodes(node.typeArguments, transformJSDocType, isTypeNode);
|
||||
}
|
||||
}
|
||||
return factory.createTypeReferenceNode(name, args);
|
||||
|
||||
@@ -51,6 +51,7 @@ import {
|
||||
isPropertyAssignment,
|
||||
isSetAccessorDeclaration,
|
||||
isStringLiteral,
|
||||
isTypeNode,
|
||||
isYieldExpression,
|
||||
LanguageServiceHost,
|
||||
length,
|
||||
@@ -100,6 +101,7 @@ import {
|
||||
UserPreferences,
|
||||
visitEachChild,
|
||||
visitNode,
|
||||
visitNodes,
|
||||
} from "../_namespaces/ts";
|
||||
import { ImportAdder } from "../_namespaces/ts.codefix";
|
||||
|
||||
@@ -852,12 +854,11 @@ export function findJsonProperty(obj: ObjectLiteralExpression, name: string): Pr
|
||||
*/
|
||||
export function tryGetAutoImportableReferenceFromTypeNode(importTypeNode: TypeNode | undefined, scriptTarget: ScriptTarget) {
|
||||
let symbols: Symbol[] | undefined;
|
||||
const typeNode = visitNode(importTypeNode, visit);
|
||||
const typeNode = visitNode(importTypeNode, visit, isTypeNode);
|
||||
if (symbols && typeNode) {
|
||||
return { typeNode, symbols };
|
||||
}
|
||||
|
||||
function visit(node: TypeNode): TypeNode;
|
||||
function visit(node: Node): Node {
|
||||
if (isLiteralImportTypeNode(node) && node.qualifier) {
|
||||
// Symbol for the left-most thing after the dot
|
||||
@@ -868,7 +869,7 @@ export function tryGetAutoImportableReferenceFromTypeNode(importTypeNode: TypeNo
|
||||
: node.qualifier;
|
||||
|
||||
symbols = append(symbols, firstIdentifier.symbol);
|
||||
const typeArguments = node.typeArguments?.map(visit);
|
||||
const typeArguments = visitNodes(node.typeArguments, visit, isTypeNode);
|
||||
return factory.createTypeReferenceNode(qualifier, typeArguments);
|
||||
}
|
||||
return visitEachChild(node, visit, nullTransformationContext);
|
||||
|
||||
@@ -1002,9 +1002,13 @@ function getUmdSymbol(token: Node, checker: TypeChecker): Symbol | undefined {
|
||||
|
||||
// The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`.
|
||||
const { parent } = token;
|
||||
return (isJsxOpeningLikeElement(parent) && parent.tagName === token) || isJsxOpeningFragment(parent)
|
||||
? tryCast(checker.resolveName(checker.getJsxNamespace(parent), isJsxOpeningLikeElement(parent) ? token : parent, SymbolFlags.Value, /*excludeGlobals*/ false), isUMDExportSymbol)
|
||||
: undefined;
|
||||
if ((isJsxOpeningLikeElement(parent) && parent.tagName === token) || isJsxOpeningFragment(parent)) {
|
||||
const parentSymbol = checker.resolveName(checker.getJsxNamespace(parent), isJsxOpeningLikeElement(parent) ? token : parent, SymbolFlags.Value, /*excludeGlobals*/ false);
|
||||
if (isUMDExportSymbol(parentSymbol)) {
|
||||
return parentSymbol;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1595,7 +1595,7 @@ function transformFunctionBody(body: Node, exposedVariableDeclarations: readonly
|
||||
const statements = factory.createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : factory.createReturnStatement(skipParentheses(body as Expression))]);
|
||||
// rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
|
||||
if (hasWritesOrVariableDeclarations || substitutions.size) {
|
||||
const rewrittenStatements = visitNodes(statements, visitor).slice();
|
||||
const rewrittenStatements = visitNodes(statements, visitor, isStatement).slice();
|
||||
if (hasWritesOrVariableDeclarations && !hasReturn && isStatement(body)) {
|
||||
// add return at the end to propagate writes back in case if control flow falls out of the function body
|
||||
// it is ok to know that range has at least one return since it we only allow unconditional returns
|
||||
@@ -1620,7 +1620,7 @@ function transformFunctionBody(body: Node, exposedVariableDeclarations: readonly
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = "__return";
|
||||
}
|
||||
assignments.unshift(factory.createPropertyAssignment(returnValueProperty, visitNode(node.expression, visitor)));
|
||||
assignments.unshift(factory.createPropertyAssignment(returnValueProperty, visitNode(node.expression, visitor, isExpression)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return factory.createReturnStatement(assignments[0].name as Expression);
|
||||
|
||||
@@ -1342,11 +1342,18 @@ export function assignPositionsToNode(node: Node): Node {
|
||||
return newNode;
|
||||
}
|
||||
|
||||
function assignPositionsToNodeArray(nodes: NodeArray<any>, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) {
|
||||
function assignPositionsToNodeArray(
|
||||
nodes: NodeArray<Node> | undefined,
|
||||
visitor: Visitor,
|
||||
test?: (node: Node) => boolean,
|
||||
start?: number,
|
||||
count?: number,
|
||||
): NodeArray<Node> | undefined {
|
||||
const visited = visitNodes(nodes, visitor, test, start, count);
|
||||
if (!visited) {
|
||||
return visited;
|
||||
}
|
||||
Debug.assert(nodes);
|
||||
// clone nodearray if necessary
|
||||
const nodeArray = visited === nodes ? factory.createNodeArray(visited.slice(0)) : visited;
|
||||
setTextRangePosEnd(nodeArray, getPos(nodes), getEnd(nodes));
|
||||
|
||||
@@ -3069,10 +3069,10 @@ export function getSynthesizedDeepCloneWithReplacements<T extends Node>(
|
||||
}
|
||||
|
||||
function getSynthesizedDeepCloneWorker<T extends Node>(node: T, replaceNode?: (node: Node) => Node | undefined): T {
|
||||
const nodeClone: (n: T) => T = replaceNode
|
||||
const nodeClone: <T extends Node>(n: T) => T = replaceNode
|
||||
? n => getSynthesizedDeepCloneWithReplacements(n, /*includeTrivia*/ true, replaceNode)
|
||||
: getSynthesizedDeepClone;
|
||||
const nodesClone: (ns: NodeArray<T>) => NodeArray<T> = replaceNode
|
||||
const nodesClone: <T extends Node>(ns: NodeArray<T> | undefined) => NodeArray<T> | undefined = replaceNode
|
||||
? ns => ns && getSynthesizedDeepClonesWithReplacements(ns, /*includeTrivia*/ true, replaceNode)
|
||||
: ns => ns && getSynthesizedDeepClones(ns);
|
||||
const visited =
|
||||
@@ -3964,7 +3964,7 @@ export function isNonGlobalDeclaration(declaration: Declaration) {
|
||||
return false;
|
||||
}
|
||||
// If the file is a module written in TypeScript, it still might be in a `declare global` augmentation
|
||||
return isInJSFile(declaration) || !findAncestor(declaration, isGlobalScopeAugmentation);
|
||||
return isInJSFile(declaration) || !findAncestor(declaration, d => isModuleDeclaration(d) && isGlobalScopeAugmentation(d));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
Reference in New Issue
Block a user