Skip to content

Commit 82fd5f4

Browse files
committed
feat(plugins/local): add 'no-shadowing-underscore' rule to prevent shadowing of '_' identifier
1 parent 9055c48 commit 82fd5f4

File tree

11 files changed

+146
-12
lines changed

11 files changed

+146
-12
lines changed

eslint.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ export default tseslint.config(
256256
"eslint-plugin/require-meta-docs-url": "off",
257257
// Part: local rules
258258
"local/avoid-multiline-template-expression": "warn",
259+
"local/no-shadowing-underscore": "error",
259260
"local/prefer-eqeq-nullish-comparison": "warn",
260261
},
261262
settings: {

packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ function getOptions(node: TSESTree.CallExpressionArgument, initialScope: Scope):
8989
}
9090
function getPropValue<A>(
9191
prop: TSESTree.Property | TSESTree.RestElement | TSESTree.SpreadElement | _,
92-
filter: (value: unknown) => value is A = (_): _ is A => true,
92+
filter: (value: unknown) => value is A = (a): a is A => true,
9393
): A | _ {
9494
if (prop?.type !== T.Property) return _;
9595
const { value } = prop;

packages/types/src/rule-name.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,4 @@ type RuleName =
137137
type RuleNameWithAdditional = `${RuleName}-${Additional}`;
138138

139139
// Example rule names
140-
const _: RuleName = "no-constructed-context-value";
140+
const ruleName: RuleName = "no-constructed-context-value";

packages/utilities/eff/docs/functions/returnVoid.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
# Function: returnVoid()
88

9-
> **returnVoid**(): [`_`](../type-aliases.md)
9+
> **returnVoid**(): `undefined`
1010
1111
Do nothing and return undefined
1212

1313
## Returns
1414

15-
[`_`](../type-aliases.md)
15+
`undefined`

packages/utilities/eff/docs/type-aliases.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88

99
> **\_**: `undefined`
1010
11-
1-byte version undefined, produces fewer bytes than `undefined` or `void 0` in the minified output d.ts.
11+
1-byte version undefined, produces fewer bytes than `undefined` or `void 0` in the minified output dts.

packages/utilities/eff/src/lang.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
import type { NarrowedTo } from "./type";
55

66
/**
7-
* 1-byte version undefined, produces fewer bytes than `undefined` or `void 0` in the minified output d.ts.
7+
* 1-byte version undefined, produces fewer bytes than `undefined` or `void 0` in the minified output dts.
88
*/
9-
export type _ = undefined;
9+
export type _ = undefined; // eslint-disable-line local/no-shadowing-underscore
1010

1111
/**
1212
* 1-byte version undefined, produces fewer bytes than `undefined` or `void 0` in the minified output js.
1313
*/
14-
export const _ = undefined;
14+
export const _ = undefined; // eslint-disable-line local/no-shadowing-underscore
1515

1616
/**
1717
* Do nothing and return false
@@ -30,8 +30,8 @@ export function returnTrue(): true {
3030
/**
3131
* Do nothing and return undefined
3232
*/
33-
export function returnVoid(): _ {
34-
return _;
33+
export function returnVoid(): undefined {
34+
return undefined;
3535
}
3636

3737
/**

workspace/eslint-plugin-local/dist/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ declare const _default: {
66
readonly version: string;
77
};
88
readonly rules: {
9+
readonly "no-shadowing-underscore": _typescript_eslint_utils_ts_eslint.RuleModule<"noShadowingUnderscore", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
910
readonly "avoid-multiline-template-expression": _typescript_eslint_utils_ts_eslint.RuleModule<"avoidMultilineTemplateExpression", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
1011
readonly "prefer-eqeq-nullish-comparison": _typescript_eslint_utils_ts_eslint.RuleModule<"unexpectedComparison" | "useLooseComparisonSuggestion", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener>;
1112
};

workspace/eslint-plugin-local/dist/index.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as AST from '@eslint-react/ast';
22
import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
3+
import * as VAR from '@eslint-react/var';
34
import { nullThrows, NullThrowsReasons } from '@typescript-eslint/utils/eslint-utils';
45

56
// package.json
@@ -42,7 +43,40 @@ var avoid_multiline_template_expression_default = createRule({
4243
},
4344
defaultOptions: []
4445
});
45-
var RULE_NAME2 = "prefer-eqeq-nullish-comparison";
46+
var RULE_NAME2 = "no-shadowing-underscore";
47+
var RULE_FEATURES2 = [
48+
"CHK"
49+
];
50+
var no_shadowing_underscore_default = createRule({
51+
meta: {
52+
type: "problem",
53+
docs: {
54+
description: "disallow multiline template expressions",
55+
[Symbol.for("rule_features")]: RULE_FEATURES2
56+
},
57+
messages: {
58+
noShadowingUnderscore: "In this codebase, '_' is used to represent the undefined. Avoid shadowing it."
59+
},
60+
schema: []
61+
},
62+
name: RULE_NAME2,
63+
create(context) {
64+
return {
65+
"Identifier[name='_']"(node) {
66+
const initialScope = context.sourceCode.getScope(node);
67+
const isFromImport = VAR.isInitializedFromSource("_", "@eslint-react/eff", initialScope);
68+
if (!isFromImport) {
69+
context.report({
70+
messageId: "noShadowingUnderscore",
71+
node
72+
});
73+
}
74+
}
75+
};
76+
},
77+
defaultOptions: []
78+
});
79+
var RULE_NAME3 = "prefer-eqeq-nullish-comparison";
4680
var prefer_eqeq_nullish_comparison_default = createRule({
4781
meta: {
4882
type: "suggestion",
@@ -57,7 +91,7 @@ var prefer_eqeq_nullish_comparison_default = createRule({
5791
},
5892
schema: []
5993
},
60-
name: RULE_NAME2,
94+
name: RULE_NAME3,
6195
create(context) {
6296
return {
6397
BinaryExpression(node) {
@@ -119,6 +153,7 @@ var index_default = {
119153
version
120154
},
121155
rules: {
156+
"no-shadowing-underscore": no_shadowing_underscore_default,
122157
"avoid-multiline-template-expression": avoid_multiline_template_expression_default,
123158
"prefer-eqeq-nullish-comparison": prefer_eqeq_nullish_comparison_default
124159
}

workspace/eslint-plugin-local/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { name, version } from "../package.json";
22
import avoidMultilineTemplateExpression from "./rules/avoid-multiline-template-expression";
3+
import noShadowingUnderscore from "./rules/no-shadowing-underscore";
34
import preferEqeqNullishComparison from "./rules/prefer-eqeq-nullish-comparison";
45

56
export default {
@@ -9,6 +10,7 @@ export default {
910
},
1011
rules: {
1112
"avoid-multiline-template-expression": avoidMultilineTemplateExpression,
13+
"no-shadowing-underscore": noShadowingUnderscore,
1214
"prefer-eqeq-nullish-comparison": preferEqeqNullishComparison,
1315
},
1416
} as const;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { ruleTester } from "../../../../test";
2+
import rule, { RULE_NAME } from "./no-shadowing-underscore";
3+
4+
ruleTester.run(RULE_NAME, rule, {
5+
invalid: [
6+
{
7+
code: /* ts */ `
8+
const _ = 1;
9+
`,
10+
errors: [{ messageId: "noShadowingUnderscore" }],
11+
},
12+
{
13+
code: /* ts */ `
14+
const [_, foo] = [1, 2];
15+
`,
16+
errors: [{ messageId: "noShadowingUnderscore" }],
17+
},
18+
{
19+
code: /* ts */ `
20+
const { name: _, ...rest } = { name: "foo", age: 20 };
21+
`,
22+
errors: [{ messageId: "noShadowingUnderscore" }],
23+
},
24+
],
25+
valid: [
26+
/* ts */ `
27+
const __ = 1;
28+
`,
29+
/* ts */ `
30+
const [__, foo] = [1, 2];
31+
`,
32+
/* ts */ `
33+
const { name: __, ...rest } = { name: "foo", age: 20 };
34+
`,
35+
/* ts */ `
36+
import { _ } from "@eslint-react/eff";
37+
`,
38+
/* ts */ `
39+
import { _ } from "@eslint-react/eff";
40+
41+
const value = _;
42+
`,
43+
/* ts */ `
44+
import { _ } from "@eslint-react/eff";
45+
46+
function foo() {
47+
return _;
48+
}
49+
`,
50+
],
51+
});

0 commit comments

Comments
 (0)