Skip to content

Commit

Permalink
chore: add some low hanging fruit types
Browse files Browse the repository at this point in the history
  • Loading branch information
scagood committed Jan 13, 2024
1 parent 4265094 commit 557778e
Show file tree
Hide file tree
Showing 48 changed files with 280 additions and 161 deletions.
35 changes: 17 additions & 18 deletions lib/configs/_commons.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
"use strict"

module.exports = {
commonRules: {
"n/no-deprecated-api": "error",
"n/no-extraneous-import": "error",
"n/no-extraneous-require": "error",
"n/no-exports-assign": "error",
"n/no-missing-import": "error",
"n/no-missing-require": "error",
"n/no-process-exit": "error",
"n/no-unpublished-bin": "error",
"n/no-unpublished-import": "error",
"n/no-unpublished-require": "error",
"n/no-unsupported-features/es-builtins": "error",
"n/no-unsupported-features/es-syntax": "error",
"n/no-unsupported-features/node-builtins": "error",
"n/process-exit-as-throw": "error",
"n/shebang": "error",
},
/** @type {Partial<import('eslint').Linter.RulesRecord>} */
module.exports.commonRules = {
"n/no-deprecated-api": "error",
"n/no-extraneous-import": "error",
"n/no-extraneous-require": "error",
"n/no-exports-assign": "error",
"n/no-missing-import": "error",
"n/no-missing-require": "error",
"n/no-process-exit": "error",
"n/no-unpublished-bin": "error",
"n/no-unpublished-import": "error",
"n/no-unpublished-require": "error",
"n/no-unsupported-features/es-builtins": "error",
"n/no-unsupported-features/es-syntax": "error",
"n/no-unsupported-features/node-builtins": "error",
"n/process-exit-as-throw": "error",
"n/shebang": "error",
}
14 changes: 11 additions & 3 deletions lib/configs/recommended-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
const globals = require("globals")
const { commonRules } = require("./_commons")

// eslintrc config: https://eslint.org/docs/latest/use/configure/configuration-files
/**
* https://eslint.org/docs/latest/use/configure/configuration-files
* @type {import('eslint').ESLint.ConfigData}
*/
module.exports.eslintrc = {
env: {
node: true,
Expand All @@ -30,7 +33,10 @@ module.exports.eslintrc = {
},
}

// flat config: https://eslint.org/docs/latest/use/configure/configuration-files-new
/**
* https://eslint.org/docs/latest/use/configure/configuration-files-new
* @type {import('eslint').Linter.FlatConfig}
*/
module.exports.flat = {
languageOptions: {
sourceType: "module",
Expand All @@ -39,5 +45,7 @@ module.exports.flat = {
...module.exports.eslintrc.globals,
},
},
rules: module.exports.eslintrc.rules,
rules:
/** @type {import('eslint').Linter.RulesRecord} */
(module.exports.eslintrc.rules),
}
14 changes: 11 additions & 3 deletions lib/configs/recommended-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
const globals = require("globals")
const { commonRules } = require("./_commons")

// eslintrc config: https://eslint.org/docs/latest/use/configure/configuration-files
/**
* https://eslint.org/docs/latest/use/configure/configuration-files
* @type {import('eslint').ESLint.ConfigData}
*/
module.exports.eslintrc = {
env: {
node: true,
Expand All @@ -27,7 +30,10 @@ module.exports.eslintrc = {
},
}

// https://eslint.org/docs/latest/use/configure/configuration-files-new
/**
* https://eslint.org/docs/latest/use/configure/configuration-files-new
* @type {import('eslint').Linter.FlatConfig}
*/
module.exports.flat = {
languageOptions: {
sourceType: "commonjs",
Expand All @@ -36,5 +42,7 @@ module.exports.flat = {
...module.exports.eslintrc.globals,
},
},
rules: module.exports.eslintrc.rules,
rules:
/** @type {import('eslint').Linter.RulesRecord} */
(module.exports.eslintrc.rules),
}
7 changes: 5 additions & 2 deletions lib/configs/recommended.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ const getPackageJson = require("../util/get-package-json")
const moduleConfig = require("./recommended-module")
const scriptConfig = require("./recommended-script")

const packageJson = getPackageJson()
const isModule = (packageJson && packageJson.type) === "module"
const isModule = getPackageJson()?.type === "module"
const recommendedConfig = isModule ? moduleConfig : scriptConfig

/**
* https://eslint.org/docs/latest/use/configure/configuration-files
* @type {import('eslint').ESLint.ConfigData}
*/
module.exports.eslintrc = {
...recommendedConfig.eslintrc,
overrides: [
Expand Down
136 changes: 76 additions & 60 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,88 @@ const esmConfig = require("./configs/recommended-module")
const cjsConfig = require("./configs/recommended-script")
const recommendedConfig = require("./configs/recommended")

const rules = {
"callback-return": require("./rules/callback-return"),
"exports-style": require("./rules/exports-style"),
"file-extension-in-import": require("./rules/file-extension-in-import"),
"global-require": require("./rules/global-require"),
"handle-callback-err": require("./rules/handle-callback-err"),
"no-callback-literal": require("./rules/no-callback-literal"),
"no-deprecated-api": require("./rules/no-deprecated-api"),
"no-exports-assign": require("./rules/no-exports-assign"),
"no-extraneous-import": require("./rules/no-extraneous-import"),
"no-extraneous-require": require("./rules/no-extraneous-require"),
"no-missing-import": require("./rules/no-missing-import"),
"no-missing-require": require("./rules/no-missing-require"),
"no-mixed-requires": require("./rules/no-mixed-requires"),
"no-new-require": require("./rules/no-new-require"),
"no-path-concat": require("./rules/no-path-concat"),
"no-process-env": require("./rules/no-process-env"),
"no-process-exit": require("./rules/no-process-exit"),
"no-restricted-import": require("./rules/no-restricted-import"),
"no-restricted-require": require("./rules/no-restricted-require"),
"no-sync": require("./rules/no-sync"),
"no-unpublished-bin": require("./rules/no-unpublished-bin"),
"no-unpublished-import": require("./rules/no-unpublished-import"),
"no-unpublished-require": require("./rules/no-unpublished-require"),
"no-unsupported-features/es-builtins": require("./rules/no-unsupported-features/es-builtins"),
"no-unsupported-features/es-syntax": require("./rules/no-unsupported-features/es-syntax"),
"no-unsupported-features/node-builtins": require("./rules/no-unsupported-features/node-builtins"),
"prefer-global/buffer": require("./rules/prefer-global/buffer"),
"prefer-global/console": require("./rules/prefer-global/console"),
"prefer-global/process": require("./rules/prefer-global/process"),
"prefer-global/text-decoder": require("./rules/prefer-global/text-decoder"),
"prefer-global/text-encoder": require("./rules/prefer-global/text-encoder"),
"prefer-global/url-search-params": require("./rules/prefer-global/url-search-params"),
"prefer-global/url": require("./rules/prefer-global/url"),
"prefer-promises/dns": require("./rules/prefer-promises/dns"),
"prefer-promises/fs": require("./rules/prefer-promises/fs"),
"process-exit-as-throw": require("./rules/process-exit-as-throw"),
shebang: require("./rules/shebang"),
/**
* @typedef {{
'recommended-module': import('eslint').ESLint.ConfigData;
'recommended-script': import('eslint').ESLint.ConfigData;
'recommended': import('eslint').ESLint.ConfigData;
'flat/recommended-module': import('eslint').Linter.FlatConfig;
'flat/recommended-script': import('eslint').Linter.FlatConfig;
'flat/recommended': import('eslint').Linter.FlatConfig;
'flat/mixed-esm-and-cjs': import('eslint').Linter.FlatConfig[];
}} Configs
*/

// Deprecated rules.
"no-hide-core-modules": require("./rules/no-hide-core-modules"),
"no-unsupported-features": require("./rules/no-unsupported-features"),
}

const mod = {
/** @type {import('eslint').ESLint.Plugin & { configs: Configs }} */
const plugin = {
meta: {
name: pkg.name,
version: pkg.version,
},
rules,
rules: /** @type {Record<string, import('eslint').Rule.RuleModule>} */ ({
"callback-return": require("./rules/callback-return"),
"exports-style": require("./rules/exports-style"),
"file-extension-in-import": require("./rules/file-extension-in-import"),
"global-require": require("./rules/global-require"),
"handle-callback-err": require("./rules/handle-callback-err"),
"no-callback-literal": require("./rules/no-callback-literal"),
"no-deprecated-api": require("./rules/no-deprecated-api"),
"no-exports-assign": require("./rules/no-exports-assign"),
"no-extraneous-import": require("./rules/no-extraneous-import"),
"no-extraneous-require": require("./rules/no-extraneous-require"),
"no-missing-import": require("./rules/no-missing-import"),
"no-missing-require": require("./rules/no-missing-require"),
"no-mixed-requires": require("./rules/no-mixed-requires"),
"no-new-require": require("./rules/no-new-require"),
"no-path-concat": require("./rules/no-path-concat"),
"no-process-env": require("./rules/no-process-env"),
"no-process-exit": require("./rules/no-process-exit"),
"no-restricted-import": require("./rules/no-restricted-import"),
"no-restricted-require": require("./rules/no-restricted-require"),
"no-sync": require("./rules/no-sync"),
"no-unpublished-bin": require("./rules/no-unpublished-bin"),
"no-unpublished-import": require("./rules/no-unpublished-import"),
"no-unpublished-require": require("./rules/no-unpublished-require"),
"no-unsupported-features/es-builtins": require("./rules/no-unsupported-features/es-builtins"),
"no-unsupported-features/es-syntax": require("./rules/no-unsupported-features/es-syntax"),
"no-unsupported-features/node-builtins": require("./rules/no-unsupported-features/node-builtins"),
"prefer-global/buffer": require("./rules/prefer-global/buffer"),
"prefer-global/console": require("./rules/prefer-global/console"),
"prefer-global/process": require("./rules/prefer-global/process"),
"prefer-global/text-decoder": require("./rules/prefer-global/text-decoder"),
"prefer-global/text-encoder": require("./rules/prefer-global/text-encoder"),
"prefer-global/url-search-params": require("./rules/prefer-global/url-search-params"),
"prefer-global/url": require("./rules/prefer-global/url"),
"prefer-promises/dns": require("./rules/prefer-promises/dns"),
"prefer-promises/fs": require("./rules/prefer-promises/fs"),
"process-exit-as-throw": require("./rules/process-exit-as-throw"),
shebang: require("./rules/shebang"),

// Deprecated rules.
"no-hide-core-modules": require("./rules/no-hide-core-modules"),
"no-unsupported-features": require("./rules/no-unsupported-features"),
}),
configs: {
"recommended-module": { plugins: ["n"], ...esmConfig.eslintrc },
"recommended-script": { plugins: ["n"], ...cjsConfig.eslintrc },
recommended: { plugins: ["n"], ...recommendedConfig.eslintrc },
"flat/recommended-module": { ...esmConfig.flat },
"flat/recommended-script": { ...cjsConfig.flat },
"flat/recommended": { ...recommendedConfig.flat },
"flat/mixed-esm-and-cjs": [
{ files: ["**/*.js"], ...recommendedConfig.flat },
{ files: ["**/*.mjs"], ...esmConfig.flat },
{ files: ["**/*.cjs"], ...cjsConfig.flat },
],
},
}

// set configs, e.g. mod.configs["recommended-module"]
// do not defined in the mod obj - to avoid circular dependency
mod.configs = {
"recommended-module": { plugins: ["n"], ...esmConfig.eslintrc },
"recommended-script": { plugins: ["n"], ...cjsConfig.eslintrc },
recommended: { plugins: ["n"], ...recommendedConfig.eslintrc },
"flat/recommended-module": { plugins: { n: mod }, ...esmConfig.flat },
"flat/recommended-script": { plugins: { n: mod }, ...cjsConfig.flat },
"flat/recommended": { plugins: { n: mod }, ...recommendedConfig.flat },
"flat/mixed-esm-and-cjs": [
{ plugins: { n: mod }, files: ["**/*.js"], ...recommendedConfig.flat },
{ plugins: { n: mod }, files: ["**/*.mjs"], ...esmConfig.flat },
{ plugins: { n: mod }, files: ["**/*.cjs"], ...cjsConfig.flat },
],
plugin.configs["flat/recommended-module"].plugins = { n: plugin }
plugin.configs["flat/recommended-script"].plugins = { n: plugin }
plugin.configs["flat/recommended"].plugins = { n: plugin }

for (const config of plugin.configs["flat/mixed-esm-and-cjs"]) {
config.plugins = { n: plugin }
}

module.exports = mod
module.exports = plugin
32 changes: 16 additions & 16 deletions lib/rules/callback-return.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
"use strict"

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
Expand All @@ -30,9 +31,9 @@ module.exports = {

/**
* Find the closest parent matching a list of types.
* @param {ASTNode} node The node whose parents we are searching
* @param {Array} types The node types to match
* @returns {ASTNode} The matched node or undefined.
* @param {import('eslint').Rule.Node} node The node whose parents we are searching
* @param {string[]} types The node types to match
* @returns {import('eslint').Rule.Node | null} The matched node or undefined.
*/
function findClosestParentOfType(node, types) {
if (!node.parent) {
Expand All @@ -46,7 +47,7 @@ module.exports = {

/**
* Check to see if a node contains only identifers
* @param {ASTNode} node The node to check
* @param {import('estree').Expression | import('estree').Super} node The node to check
* @returns {boolean} Whether or not the node contains only identifers
*/
function containsOnlyIdentifiers(node) {
Expand All @@ -68,7 +69,7 @@ module.exports = {

/**
* Check to see if a CallExpression is in our callback list.
* @param {ASTNode} node The node to check against our callback names list.
* @param {import('estree').CallExpression} node The node to check against our callback names list.
* @returns {boolean} Whether or not this function matches our callback name.
*/
function isCallback(node) {
Expand All @@ -80,8 +81,8 @@ module.exports = {

/**
* Determines whether or not the callback is part of a callback expression.
* @param {ASTNode} node The callback node
* @param {ASTNode} parentNode The expression node
* @param {import('eslint').Rule.Node} node The callback node
* @param {import('estree').Statement} parentNode The expression node
* @returns {boolean} Whether or not this is part of a callback expression
*/
function isCallbackExpression(node, parentNode) {
Expand Down Expand Up @@ -116,25 +117,24 @@ module.exports = {
}

// find the closest block, return or loop
const closestBlock =
findClosestParentOfType(node, [
"BlockStatement",
"ReturnStatement",
"ArrowFunctionExpression",
]) || {}
const closestBlock = findClosestParentOfType(node, [
"BlockStatement",
"ReturnStatement",
"ArrowFunctionExpression",
])

// if our parent is a return we know we're ok
if (closestBlock.type === "ReturnStatement") {
if (closestBlock?.type === "ReturnStatement") {
return
}

// arrow functions don't always have blocks and implicitly return
if (closestBlock.type === "ArrowFunctionExpression") {
if (closestBlock?.type === "ArrowFunctionExpression") {
return
}

// block statements are part of functions and most if statements
if (closestBlock.type === "BlockStatement") {
if (closestBlock?.type === "BlockStatement") {
// find the last item in the block
const lastItem =
closestBlock.body[closestBlock.body.length - 1]
Expand Down

0 comments on commit 557778e

Please sign in to comment.