astro-ghostcms/.pnpm-store/v3/files/c6/9b9ff33584eb7cc9504fab08bdd...

241 lines
8.6 KiB
Plaintext

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ancestorHasReturnType = exports.isValidFunctionExpressionReturnType = exports.isTypedFunctionExpression = exports.doesImmediatelyReturnFunctionExpression = exports.checkFunctionReturnType = exports.checkFunctionExpressionReturnType = void 0;
const utils_1 = require("@typescript-eslint/utils");
const astUtils_1 = require("./astUtils");
const getFunctionHeadLoc_1 = require("./getFunctionHeadLoc");
/**
* Checks if a node is a variable declarator with a type annotation.
* ```
* const x: Foo = ...
* ```
*/
function isVariableDeclaratorWithTypeAnnotation(node) {
return (node.type === utils_1.AST_NODE_TYPES.VariableDeclarator && !!node.id.typeAnnotation);
}
/**
* Checks if a node is a class property with a type annotation.
* ```
* public x: Foo = ...
* ```
*/
function isPropertyDefinitionWithTypeAnnotation(node) {
return (node.type === utils_1.AST_NODE_TYPES.PropertyDefinition && !!node.typeAnnotation);
}
/**
* Checks if a node belongs to:
* ```
* foo(() => 1)
* ```
*/
function isFunctionArgument(parent, callee) {
return (parent.type === utils_1.AST_NODE_TYPES.CallExpression &&
// make sure this isn't an IIFE
parent.callee !== callee);
}
/**
* Checks if a node is type-constrained in JSX
* ```
* <Foo x={() => {}} />
* <Bar>{() => {}}</Bar>
* <Baz {...props} />
* ```
*/
function isTypedJSX(node) {
return (node.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer ||
node.type === utils_1.AST_NODE_TYPES.JSXSpreadAttribute);
}
function isTypedParent(parent, callee) {
return ((0, astUtils_1.isTypeAssertion)(parent) ||
isVariableDeclaratorWithTypeAnnotation(parent) ||
isPropertyDefinitionWithTypeAnnotation(parent) ||
isFunctionArgument(parent, callee) ||
isTypedJSX(parent));
}
/**
* Checks if a node belongs to:
* ```
* new Foo(() => {})
* ^^^^^^^^
* ```
*/
function isConstructorArgument(node) {
return node.type === utils_1.AST_NODE_TYPES.NewExpression;
}
/**
* Checks if a node is a property or a nested property of a typed object:
* ```
* const x: Foo = { prop: () => {} }
* const x = { prop: () => {} } as Foo
* const x = <Foo>{ prop: () => {} }
* const x: Foo = { bar: { prop: () => {} } }
* ```
*/
function isPropertyOfObjectWithType(property) {
if (!property || property.type !== utils_1.AST_NODE_TYPES.Property) {
return false;
}
const objectExpr = property.parent;
if (objectExpr.type !== utils_1.AST_NODE_TYPES.ObjectExpression) {
return false;
}
const parent = objectExpr.parent;
return isTypedParent(parent) || isPropertyOfObjectWithType(parent);
}
/**
* Checks if a function belongs to:
* ```
* () => () => ...
* () => function () { ... }
* () => { return () => ... }
* () => { return function () { ... } }
* function fn() { return () => ... }
* function fn() { return function() { ... } }
* ```
*/
function doesImmediatelyReturnFunctionExpression({ body, }) {
// Check if body is a block with a single statement
if (body.type === utils_1.AST_NODE_TYPES.BlockStatement && body.body.length === 1) {
const [statement] = body.body;
// Check if that statement is a return statement with an argument
if (statement.type === utils_1.AST_NODE_TYPES.ReturnStatement &&
!!statement.argument) {
// If so, check that returned argument as body
body = statement.argument;
}
}
// Check if the body being returned is a function expression
return (body.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
body.type === utils_1.AST_NODE_TYPES.FunctionExpression);
}
exports.doesImmediatelyReturnFunctionExpression = doesImmediatelyReturnFunctionExpression;
/**
* Checks if a function belongs to:
* ```
* () => ({ action: 'xxx' } as const)
* ```
*/
function returnsConstAssertionDirectly(node) {
const { body } = node;
if ((0, astUtils_1.isTypeAssertion)(body)) {
const { typeAnnotation } = body;
if (typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeReference) {
const { typeName } = typeAnnotation;
if (typeName.type === utils_1.AST_NODE_TYPES.Identifier &&
typeName.name === 'const') {
return true;
}
}
}
return false;
}
/**
* True when the provided function expression is typed.
*/
function isTypedFunctionExpression(node, options) {
const parent = utils_1.ESLintUtils.nullThrows(node.parent, utils_1.ESLintUtils.NullThrowsReasons.MissingParent);
if (!options.allowTypedFunctionExpressions) {
return false;
}
return (isTypedParent(parent, node) ||
isPropertyOfObjectWithType(parent) ||
isConstructorArgument(parent));
}
exports.isTypedFunctionExpression = isTypedFunctionExpression;
/**
* Check whether the function expression return type is either typed or valid
* with the provided options.
*/
function isValidFunctionExpressionReturnType(node, options) {
if (isTypedFunctionExpression(node, options)) {
return true;
}
const parent = utils_1.ESLintUtils.nullThrows(node.parent, utils_1.ESLintUtils.NullThrowsReasons.MissingParent);
if (options.allowExpressions &&
parent.type !== utils_1.AST_NODE_TYPES.VariableDeclarator &&
parent.type !== utils_1.AST_NODE_TYPES.MethodDefinition &&
parent.type !== utils_1.AST_NODE_TYPES.ExportDefaultDeclaration &&
parent.type !== utils_1.AST_NODE_TYPES.PropertyDefinition) {
return true;
}
// https://github.com/typescript-eslint/typescript-eslint/issues/653
return (options.allowDirectConstAssertionInArrowFunctions === true &&
node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression &&
returnsConstAssertionDirectly(node));
}
exports.isValidFunctionExpressionReturnType = isValidFunctionExpressionReturnType;
/**
* Check that the function expression or declaration is valid.
*/
function isValidFunctionReturnType(node, options) {
if (options.allowHigherOrderFunctions &&
doesImmediatelyReturnFunctionExpression(node)) {
return true;
}
return (node.returnType != null ||
(0, astUtils_1.isConstructor)(node.parent) ||
(0, astUtils_1.isSetter)(node.parent));
}
/**
* Checks if a function declaration/expression has a return type.
*/
function checkFunctionReturnType(node, options, sourceCode, report) {
if (isValidFunctionReturnType(node, options)) {
return;
}
report((0, getFunctionHeadLoc_1.getFunctionHeadLoc)(node, sourceCode));
}
exports.checkFunctionReturnType = checkFunctionReturnType;
/**
* Checks if a function declaration/expression has a return type.
*/
function checkFunctionExpressionReturnType(node, options, sourceCode, report) {
if (isValidFunctionExpressionReturnType(node, options)) {
return;
}
checkFunctionReturnType(node, options, sourceCode, report);
}
exports.checkFunctionExpressionReturnType = checkFunctionExpressionReturnType;
/**
* Check whether any ancestor of the provided function has a valid return type.
*/
function ancestorHasReturnType(node) {
let ancestor = node.parent;
if (ancestor.type === utils_1.AST_NODE_TYPES.Property) {
ancestor = ancestor.value;
}
// if the ancestor is not a return, then this function was not returned at all, so we can exit early
const isReturnStatement = ancestor.type === utils_1.AST_NODE_TYPES.ReturnStatement;
const isBodylessArrow = ancestor.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression &&
ancestor.body.type !== utils_1.AST_NODE_TYPES.BlockStatement;
if (!isReturnStatement && !isBodylessArrow) {
return false;
}
while (ancestor) {
switch (ancestor.type) {
case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
case utils_1.AST_NODE_TYPES.FunctionExpression:
case utils_1.AST_NODE_TYPES.FunctionDeclaration:
if (ancestor.returnType) {
return true;
}
break;
// const x: Foo = () => {};
// Assume that a typed variable types the function expression
case utils_1.AST_NODE_TYPES.VariableDeclarator:
if (ancestor.id.typeAnnotation) {
return true;
}
break;
case utils_1.AST_NODE_TYPES.PropertyDefinition:
if (ancestor.typeAnnotation) {
return true;
}
break;
}
ancestor = ancestor.parent;
}
return false;
}
exports.ancestorHasReturnType = ancestorHasReturnType;
//# sourceMappingURL=explicitReturnTypeUtils.js.map