eslint-plugin-mocha
Version:
Eslint rules for mocha.
72 lines • 3.56 kB
JavaScript
import { filterWithArgs, flatMapWithArgs, mapWithArgs } from '../list.js';
import { getUniqueBaseNames } from '../mocha/path.js';
import { isConstantPath } from './member-expression.js';
import { findParentNodeAndPathForIdentifier } from './resolved-reference.js';
function isLiteralWithValue(node, expectedValue) {
return node.type === 'Literal' && node.value === expectedValue;
}
function isExclusiveNamedImportBindingWithMatchingSource(variable, expectedSource) {
const importDef = variable.defs[0];
return (importDef !== undefined &&
importDef.type === 'ImportBinding' &&
isLiteralWithValue(importDef.parent.source, expectedSource));
}
function getAllNamedImportBindingVariables(moduleScope, expectedSource) {
return filterWithArgs(moduleScope.variables, isExclusiveNamedImportBindingWithMatchingSource, expectedSource);
}
function isNonAssignmentReference(reference) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- bad eslint core typings
const node = reference.identifier;
return (node.parent.type !== 'AssignmentExpression' ||
node.parent.left !== node);
}
function isBindingConstant(variable) {
return variable.references.every(isNonAssignmentReference);
}
function replaceFirstSegment(path, replacement) {
if (isConstantPath(path)) {
const [firstSegment, ...remainingPath] = path;
const suffix = firstSegment?.endsWith('()') === true ? '()' : '';
return [`${replacement}${suffix}`, ...remainingPath];
}
return path;
}
function resolveImportPathWithOriginalName(reference, sourceCode, originalName) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- bad eslint core typings
const { node, path } = findParentNodeAndPathForIdentifier(sourceCode, reference.identifier);
return {
node,
path,
resolvedPath: replaceFirstSegment(path, originalName)
};
}
function resolveReferencesForNamedImport(variable, sourceCode, identifierNames) {
const importDef = variable.defs[0];
if (importDef !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access -- ok
const originalName = importDef.node.imported.name;
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- ok
if (identifierNames.includes(originalName)) {
return mapWithArgs(variable.references, resolveImportPathWithOriginalName, sourceCode, originalName);
}
}
return [];
}
function processNamedImports(sourceCode, moduleScope, identifierNames, importSource) {
const namedImportVariables = getAllNamedImportBindingVariables(moduleScope, importSource);
const constantNamedImports = namedImportVariables.filter(isBindingConstant);
return flatMapWithArgs(constantNamedImports, resolveReferencesForNamedImport, sourceCode, identifierNames);
}
export function findImportReferencesByName(context, nameDetailsList, importSource) {
const { sourceCode } = context;
const { globalScope } = sourceCode.scopeManager;
const [maybeModuleScope] = globalScope?.childScopes ?? [];
if (maybeModuleScope?.type !== 'module') {
return [];
}
const identifierNames = getUniqueBaseNames(nameDetailsList);
const moduleScope = maybeModuleScope;
const namedImportReferences = processNamedImports(sourceCode, moduleScope, identifierNames, importSource);
return namedImportReferences;
}
//# sourceMappingURL=find-import-references.js.map