Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
function isValidChainTarget(
node: TSESTree.Node,
allowIdentifier: boolean,
): node is ValidChainTarget {
if (
node.type === AST_NODE_TYPES.MemberExpression ||
node.type === AST_NODE_TYPES.OptionalMemberExpression
) {
const isObjectValid =
ALLOWED_MEMBER_OBJECT_TYPES.has(node.object.type) &&
// make sure to validate the expression is of our expected structure
isValidChainTarget(node.object, true);
const isPropertyValid = node.computed
? ALLOWED_COMPUTED_PROP_TYPES.has(node.property.type) &&
// make sure to validate the member expression is of our expected structure
(node.property.type === AST_NODE_TYPES.MemberExpression ||
node.property.type === AST_NODE_TYPES.OptionalMemberExpression
? isValidChainTarget(node.property, allowIdentifier)
: true)
: ALLOWED_NON_COMPUTED_PROP_TYPES.has(node.property.type);
return isObjectValid && isPropertyValid;
TSQualifiedName(node: TSESTree.TSQualifiedName) {
return rules['MemberExpression, JSXMemberExpression, MetaProperty']({
type: AST_NODE_TYPES.MemberExpression,
object: node.left as any,
property: node.right as any,
// location data
parent: node.parent,
range: node.range,
loc: node.loc,
optional: false,
computed: false,
});
},
fix(fixer) {
const nodeToReplace =
node.callee.type === AST_NODE_TYPES.MemberExpression
? node.callee.object
: node.callee;
const fixedNodeName = getPreferredNodeName(nodeName, testKeyword);
return [fixer.replaceText(nodeToReplace, fixedNodeName)];
},
});
function isLessThanLengthExpression(
node: TSESTree.Node | null,
name: string,
): TSESTree.Expression | null {
if (
node !== null &&
node.type === AST_NODE_TYPES.BinaryExpression &&
node.operator === '<' &&
isMatchingIdentifier(node.left, name) &&
(node.right.type === AST_NODE_TYPES.MemberExpression ||
node.right.type === AST_NODE_TYPES.OptionalMemberExpression) &&
isMatchingIdentifier(node.right.property, 'length')
) {
return node.right.object;
}
return null;
}
function isPropertyAccessExpression(
node: TSESTree.Node,
): node is TSESTree.MemberExpression {
return node.type === AST_NODE_TYPES.MemberExpression && !node.computed;
}
CallExpression(node) {
const { callee } = node;
if (
callee.type !== AST_NODE_TYPES.MemberExpression ||
callee.property.type !== AST_NODE_TYPES.Identifier
) {
return;
}
if (callee.property.name === 'toMatchSnapshot') {
context.report({
fix(fixer) {
return [
fixer.replaceText(callee.property, 'toMatchInlineSnapshot'),
];
},
messageId: 'toMatch',
node: callee.property,
});
} else if (callee.property.name === 'toThrowErrorMatchingSnapshot') {
if (!isExpectCall(node)) {
return;
}
const {
expect: {
arguments: [argument],
},
matcher,
} = parseExpectCall(node);
if (
!matcher ||
!isParsedEqualityMatcherCall(matcher) ||
!argument ||
argument.type !== AST_NODE_TYPES.MemberExpression ||
!isSupportedAccessor(argument.property, 'length') ||
argument.property.type !== AST_NODE_TYPES.Identifier
) {
return;
}
context.report({
fix(fixer) {
const propertyDot = context
.getSourceCode()
.getFirstTokenBetween(
argument.object,
argument.property,
token => token.value === '.',
);
const isEach = (node: TSESTree.CallExpression): boolean => {
if (
node &&
node.callee &&
node.callee.type === AST_NODE_TYPES.CallExpression &&
node.callee.callee &&
node.callee.callee.type === AST_NODE_TYPES.MemberExpression &&
node.callee.callee.property &&
node.callee.callee.property.type === AST_NODE_TYPES.Identifier &&
node.callee.callee.property.name === 'each' &&
node.callee.callee.object &&
node.callee.callee.object.type === AST_NODE_TYPES.Identifier &&
TestCaseName.hasOwnProperty(node.callee.callee.object.name)
) {
return true;
}
return false;
};
'CallExpression:exit'(node: TSESTree.CallExpression) {
const top = callStack[callStack.length - 1];
if (
(((isTestCase(node) &&
node.callee.type !== AST_NODE_TYPES.MemberExpression) ||
isEach(node)) &&
top === TestCaseName.test) ||
(node.callee.type === AST_NODE_TYPES.TaggedTemplateExpression &&
top === 'template')
) {
callStack.pop();
}
},
BlockStatement(stmt) {
const isFixableIncludesCallExpression = (
node: TSESTree.Node,
): node is FixableIncludesCallExpression =>
node.type === AST_NODE_TYPES.CallExpression &&
node.callee.type === AST_NODE_TYPES.MemberExpression &&
isSupportedAccessor(node.callee.property, 'includes') &&
node.callee.property.type === AST_NODE_TYPES.Identifier &&
hasOnlyOneArgument(node);