eslint-plugin-mocha
Version:
Eslint rules for mocha.
92 lines • 4.62 kB
JavaScript
import { findVariable } from '@eslint-community/eslint-utils';
import { flatMapWithArgs, mapWithArgs } from '../list.js';
import { extractMemberExpressionPath, getIdentifierName, isConstantPath } from './member-expression.js';
import { isAssignmentProperty, isIdentifierPattern, isObjectPattern, isVariableDeclarator } from './node-types.js';
import { findParentNodeAndPathForIdentifier } from './resolved-reference.js';
function isAliasConstAssignment(node) {
if (isVariableDeclarator(node) && node.parent.type === 'VariableDeclaration') {
return node.parent.kind === 'const';
}
return false;
}
function extractIdentifiersFromObjectPattern(node, currentPath) {
return node.properties.flatMap((property) => {
if (!isAssignmentProperty(property)) {
return [];
}
if (property.value.type === 'Identifier') {
return [{ identifier: property.value, path: [...currentPath, getIdentifierName(property.key)] }];
}
if (property.value.type === 'ObjectPattern') {
return extractIdentifiersFromObjectPattern(property.value, [
...currentPath,
getIdentifierName(property.key)
]);
}
return [];
});
}
function getDeclaredIdentifiers(sourceCode, node) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- bad typing in eslint core
const path = extractMemberExpressionPath(sourceCode, node.init);
if (isIdentifierPattern(node.id)) {
return [{ identifier: node.id, fullPath: path, leftHandSidePath: [], rightHandSidePath: path }];
}
if (isObjectPattern(node.id)) {
const allPatternIdentifiers = extractIdentifiersFromObjectPattern(node.id, []);
return allPatternIdentifiers.map((patternIdentifiers) => {
return {
identifier: patternIdentifiers.identifier,
fullPath: [...path, ...patternIdentifiers.path],
leftHandSidePath: patternIdentifiers.path,
rightHandSidePath: path
};
});
}
return [];
}
// eslint-disable-next-line complexity -- no good idea how to refactor
function extendPath(parentReference, originalPath, identifierPath) {
const extendedPath = [...parentReference.resolvedPath, ...originalPath, ...identifierPath.slice(1)];
if (isConstantPath(identifierPath) && identifierPath.length === 1 && identifierPath.at(0)?.endsWith('()') === true) {
const lastElement = extendedPath.at(-1);
if (lastElement !== undefined) {
extendedPath[extendedPath.length - 1] = typeof lastElement === 'string'
? `${lastElement}()`
: lastElement;
}
}
return extendedPath;
}
function aliasReferenceToResolvedReference(reference, sourceCode, parentReference, originalPath) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- bad typings in eslint core
const { node, path } = findParentNodeAndPathForIdentifier(sourceCode, reference.identifier);
return { node, path, resolvedPath: extendPath(parentReference, originalPath, path) };
}
function isNonInitReference(reference) {
return !reference.init;
}
// eslint-disable-next-line max-statements -- no good idea how to split this function
function resolveAliasReferencesRecursively(reference, sourceCode) {
const { node } = reference;
const result = [reference];
if (isAliasConstAssignment(node)) {
const declaratedIdentifiers = getDeclaredIdentifiers(sourceCode, node);
for (const { identifier, leftHandSidePath: identifierPath } of declaratedIdentifiers) {
const aliasedVariable = findVariable(sourceCode.getScope(node), identifier.name);
if (aliasedVariable !== null) {
const aliasReferencesWithoutInit = aliasedVariable.references.filter(isNonInitReference);
const aliasedResolvedReferences = mapWithArgs(aliasReferencesWithoutInit, aliasReferenceToResolvedReference, sourceCode, reference, identifierPath);
result.push(...flatMapWithArgs(aliasedResolvedReferences, resolveAliasReferencesRecursively, sourceCode));
}
}
}
return result;
}
function hasConstantResolvedPath(resolvedReference) {
return isConstantPath(resolvedReference.resolvedPath);
}
export function resolveAliasedReferences(sourceCode, originalResolvedReferences) {
return flatMapWithArgs(originalResolvedReferences, resolveAliasReferencesRecursively, sourceCode).filter(hasConstantResolvedPath);
}
//# sourceMappingURL=alias-references.js.map