You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.7 KiB
122 lines
3.7 KiB
/** |
|
* @fileoverview Restrict usage of specified globals. |
|
* @author Benoît Zugmeyer |
|
*/ |
|
"use strict"; |
|
|
|
//------------------------------------------------------------------------------ |
|
// Rule Definition |
|
//------------------------------------------------------------------------------ |
|
|
|
/** @type {import('../shared/types').Rule} */ |
|
module.exports = { |
|
meta: { |
|
type: "suggestion", |
|
|
|
docs: { |
|
description: "Disallow specified global variables", |
|
recommended: false, |
|
url: "https://eslint.org/docs/rules/no-restricted-globals" |
|
}, |
|
|
|
schema: { |
|
type: "array", |
|
items: { |
|
oneOf: [ |
|
{ |
|
type: "string" |
|
}, |
|
{ |
|
type: "object", |
|
properties: { |
|
name: { type: "string" }, |
|
message: { type: "string" } |
|
}, |
|
required: ["name"], |
|
additionalProperties: false |
|
} |
|
] |
|
}, |
|
uniqueItems: true, |
|
minItems: 0 |
|
}, |
|
|
|
messages: { |
|
defaultMessage: "Unexpected use of '{{name}}'.", |
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period |
|
customMessage: "Unexpected use of '{{name}}'. {{customMessage}}" |
|
} |
|
}, |
|
|
|
create(context) { |
|
|
|
// If no globals are restricted, we don't need to do anything |
|
if (context.options.length === 0) { |
|
return {}; |
|
} |
|
|
|
const restrictedGlobalMessages = context.options.reduce((memo, option) => { |
|
if (typeof option === "string") { |
|
memo[option] = null; |
|
} else { |
|
memo[option.name] = option.message; |
|
} |
|
|
|
return memo; |
|
}, {}); |
|
|
|
/** |
|
* Report a variable to be used as a restricted global. |
|
* @param {Reference} reference the variable reference |
|
* @returns {void} |
|
* @private |
|
*/ |
|
function reportReference(reference) { |
|
const name = reference.identifier.name, |
|
customMessage = restrictedGlobalMessages[name], |
|
messageId = customMessage |
|
? "customMessage" |
|
: "defaultMessage"; |
|
|
|
context.report({ |
|
node: reference.identifier, |
|
messageId, |
|
data: { |
|
name, |
|
customMessage |
|
} |
|
}); |
|
} |
|
|
|
/** |
|
* Check if the given name is a restricted global name. |
|
* @param {string} name name of a variable |
|
* @returns {boolean} whether the variable is a restricted global or not |
|
* @private |
|
*/ |
|
function isRestricted(name) { |
|
return Object.prototype.hasOwnProperty.call(restrictedGlobalMessages, name); |
|
} |
|
|
|
return { |
|
Program() { |
|
const scope = context.getScope(); |
|
|
|
// Report variables declared elsewhere (ex: variables defined as "global" by eslint) |
|
scope.variables.forEach(variable => { |
|
if (!variable.defs.length && isRestricted(variable.name)) { |
|
variable.references.forEach(reportReference); |
|
} |
|
}); |
|
|
|
// Report variables not declared at all |
|
scope.through.forEach(reference => { |
|
if (isRestricted(reference.identifier.name)) { |
|
reportReference(reference); |
|
} |
|
}); |
|
|
|
} |
|
}; |
|
} |
|
};
|
|
|