123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- "use strict"
- function getStaticPropertyName(node) {
- let prop = null
- switch (node && node.type) {
- case "Property":
- case "MethodDefinition":
- prop = node.key
- break
- case "MemberExpression":
- prop = node.property
- break
-
- }
- switch (prop && prop.type) {
- case "Literal":
- return String(prop.value)
- case "TemplateLiteral":
- if (prop.expressions.length === 0 && prop.quasis.length === 1) {
- return prop.quasis[0].value.cooked
- }
- break
- case "Identifier":
- if (!node.computed) {
- return prop.name
- }
- break
-
- }
- return null
- }
- function isAssignee(node) {
- return (
- node.parent.type === "AssignmentExpression" && node.parent.left === node
- )
- }
- function getTopAssignment(leafNode) {
- let node = leafNode
-
- while (
- node.parent.type === "MemberExpression" &&
- node.parent.object === node
- ) {
- node = node.parent
- }
-
- if (!isAssignee(node)) {
- return null
- }
-
- while (node.parent.type === "AssignmentExpression") {
- node = node.parent
- }
- return node
- }
- function createAssignmentList(nodes) {
- return nodes.map(getTopAssignment).filter(Boolean)
- }
- function getModuleExportsNodes(scope) {
- const variable = scope.set.get("module")
- if (variable == null) {
- return []
- }
- return variable.references
- .map(reference => reference.identifier.parent)
- .filter(
- node =>
- node.type === "MemberExpression" &&
- getStaticPropertyName(node) === "exports"
- )
- }
- function getExportsNodes(scope) {
- const variable = scope.set.get("exports")
- if (variable == null) {
- return []
- }
- return variable.references.map(reference => reference.identifier)
- }
- module.exports = {
- meta: {
- docs: {
- description: "enforce either `module.exports` or `exports`",
- category: "Stylistic Issues",
- recommended: false,
- url:
- "https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/exports-style.md",
- },
- type: "suggestion",
- fixable: null,
- schema: [
- {
-
- enum: ["module.exports", "exports"],
- },
- {
- type: "object",
- properties: { allowBatchAssign: { type: "boolean" } },
- additionalProperties: false,
- },
- ],
- },
- create(context) {
- const mode = context.options[0] || "module.exports"
- const batchAssignAllowed = Boolean(
- context.options[1] != null && context.options[1].allowBatchAssign
- )
- const sourceCode = context.getSourceCode()
-
- function getLocation(node) {
- const token = sourceCode.getTokenAfter(node)
- return {
- start: node.loc.start,
- end: token.loc.end,
- }
- }
-
- function enforceModuleExports() {
- const globalScope = context.getScope()
- const exportsNodes = getExportsNodes(globalScope)
- const assignList = batchAssignAllowed
- ? createAssignmentList(getModuleExportsNodes(globalScope))
- : []
- for (const node of exportsNodes) {
-
- if (
- assignList.length > 0 &&
- assignList.indexOf(getTopAssignment(node)) !== -1
- ) {
- continue
- }
-
- context.report({
- node,
- loc: getLocation(node),
- message:
- "Unexpected access to 'exports'. Use 'module.exports' instead.",
- })
- }
- }
-
- function enforceExports() {
- const globalScope = context.getScope()
- const exportsNodes = getExportsNodes(globalScope)
- const moduleExportsNodes = getModuleExportsNodes(globalScope)
- const assignList = batchAssignAllowed
- ? createAssignmentList(exportsNodes)
- : []
- const batchAssignList = []
- for (const node of moduleExportsNodes) {
-
- if (assignList.length > 0) {
- const found = assignList.indexOf(getTopAssignment(node))
- if (found !== -1) {
- batchAssignList.push(assignList[found])
- assignList.splice(found, 1)
- continue
- }
- }
-
- context.report({
- node,
- loc: getLocation(node),
- message:
- "Unexpected access to 'module.exports'. Use 'exports' instead.",
- })
- }
-
- for (const node of exportsNodes) {
-
- if (!isAssignee(node)) {
- continue
- }
-
- if (batchAssignList.indexOf(getTopAssignment(node)) !== -1) {
- continue
- }
-
- context.report({
- node,
- loc: getLocation(node),
- message:
- "Unexpected assignment to 'exports'. Don't modify 'exports' itself.",
- })
- }
- }
- return {
- "Program:exit"() {
- switch (mode) {
- case "module.exports":
- enforceModuleExports()
- break
- case "exports":
- enforceExports()
- break
-
- }
- },
- }
- },
- }
|