eslint-plugin-export-scope
Version:
Don't leak LOCAL utils, states, components into the global scope
100 lines • 4.89 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateProgram = void 0;
const scope_manager_1 = require("@typescript-eslint/scope-manager");
const utils_1 = require("@typescript-eslint/utils");
const validateJsDoc_1 = require("./validateJsDoc");
const esLintUtils_1 = require("./esLintUtils");
const validateProgram = (context, node, lintNode) => {
(0, validateJsDoc_1.validateJsDoc)(context, node);
const getModuleNames = (rootVariable, variables) => {
const moduleNames = new Set([rootVariable.name]);
const variableNameToVariableMap = new Map(variables.map((variable) => [variable.name, variable]));
const iterateRefs = (variable) => {
variable.references.forEach((ref) => {
const decl = ref.identifier.parent;
if (decl.type === utils_1.AST_NODE_TYPES.VariableDeclarator && decl.id.type === utils_1.AST_NODE_TYPES.Identifier) {
const isAlreadyAdded = moduleNames.has(decl.id.name);
moduleNames.add(decl.id.name);
if (!isAlreadyAdded) {
const variable = variableNameToVariableMap.get(decl.id.name);
if (variable)
iterateRefs(variable);
}
}
});
};
iterateRefs(rootVariable);
return moduleNames;
};
let scopeTree;
try {
scopeTree = (0, scope_manager_1.analyze)(node, { sourceType: "module" });
}
catch {
console.error("🚨 Please upgrade all @typescript-eslint/* packages to the latest mojor version 🚨");
return;
}
const globalVariables = scopeTree.globalScope?.childScopes[0]?.variables;
if (!globalVariables)
return;
const lintVariable = (variable, scopeVariables, relExportPath) => {
const variableNameToVariableMap = new Map(scopeVariables.map((variable) => [variable.name, variable]));
const moduleNames = getModuleNames(variable, scopeVariables);
const variables = Array.from(moduleNames)
.map((name) => variableNameToVariableMap.get(name))
.filter(Boolean);
variables.forEach((variable) => variable.references.forEach((ref) => lintNode(ref.identifier.parent, relExportPath)));
};
// global scope variables
globalVariables.forEach((variable) => {
const parent = variable.identifiers?.[0]?.parent;
if (parent?.type === utils_1.AST_NODE_TYPES.ImportNamespaceSpecifier) {
lintVariable(variable, globalVariables, (0, esLintUtils_1.extractPathFromImport)(parent.parent));
}
const extractPathFromVariableDeclarator = ({ init: node }) => {
if (node?.type === utils_1.AST_NODE_TYPES.AwaitExpression)
node = node.argument;
if (node?.type === utils_1.AST_NODE_TYPES.ImportExpression)
return (0, esLintUtils_1.extractPathFromImport)(node);
};
if (parent?.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
const relExportPath = extractPathFromVariableDeclarator(parent);
if (relExportPath) {
lintVariable(variable, globalVariables, relExportPath);
}
}
if (parent?.type === utils_1.AST_NODE_TYPES.Property &&
parent.parent.type === utils_1.AST_NODE_TYPES.ObjectPattern &&
parent.parent.parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
const relExportPath = extractPathFromVariableDeclarator(parent.parent.parent);
if (relExportPath) {
lintNode(parent.key, relExportPath);
}
}
});
// thenned dynamic imports
scopeTree.scopes.forEach((scope) => {
const blockParent = scope.block.parent;
if (blockParent?.type !== utils_1.AST_NODE_TYPES.CallExpression)
return;
if (blockParent.callee.type !== utils_1.AST_NODE_TYPES.MemberExpression)
return;
if (blockParent.callee.object.type !== utils_1.AST_NODE_TYPES.ImportExpression)
return;
const relExportPath = (0, esLintUtils_1.extractPathFromImport)(blockParent.callee.object);
const moduleVariable = scope.variables?.[0];
if (!moduleVariable)
return;
if (moduleVariable.identifiers?.[0]?.parent.type === utils_1.AST_NODE_TYPES.Property &&
moduleVariable.identifiers?.[0]?.parent.parent.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
const objectPattern = moduleVariable.identifiers?.[0]?.parent.parent;
lintNode(objectPattern, relExportPath);
}
else {
lintVariable(moduleVariable, scope.variables, relExportPath);
}
});
};
exports.validateProgram = validateProgram;
//# sourceMappingURL=validateProgram.js.map
;