Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 288092a

Browse files
authored
feat(eslint-plugin): [prefer-literal-enum-member] add allowBitwiseExpressions option (typescript-eslint#3515)
1 parent 9e343fd commit 288092a

File tree

3 files changed

+184
-5
lines changed

3 files changed

+184
-5
lines changed

packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ The answer is that `Foo.c` will be `1` at runtime. The [playground](https://www.
2121

2222
This rule is meant to prevent unexpected results in code by requiring the use of literal values as enum members to prevent unexpected runtime behavior. Template literals, arrays, objects, constructors, and all other expression types can end up using a variable from its scope or the parent scope, which can result in the same unexpected behavior at runtime.
2323

24+
## Options
25+
26+
- `allowBitwiseExpressions` set to `true` will allow you to use bitwise expressions in enum initializer (Default: `false`).
27+
2428
Examples of **incorrect** code for this rule:
2529

2630
```ts
@@ -46,6 +50,37 @@ enum Valid {
4650
}
4751
```
4852

53+
### `allowBitwiseExpressions`
54+
55+
Examples of **incorrect** code for the `{ "allowBitwiseExpressions": true }` option:
56+
57+
```ts
58+
const x = 1;
59+
enum Foo {
60+
A = x << 0,
61+
B = x >> 0,
62+
C = x >>> 0,
63+
D = x | 0,
64+
E = x & 0,
65+
F = x ^ 0,
66+
G = ~x,
67+
}
68+
```
69+
70+
Examples of **correct** code for the `{ "allowBitwiseExpressions": true }` option:
71+
72+
```ts
73+
enum Foo {
74+
A = 1 << 0,
75+
B = 1 >> 0,
76+
C = 1 >>> 0,
77+
D = 1 | 0,
78+
E = 1 & 0,
79+
F = 1 ^ 0,
80+
G = ~1,
81+
}
82+
```
83+
4984
## When Not To Use It
5085

5186
If you want use anything other than simple literals as an enum value.

packages/eslint-plugin/src/rules/prefer-literal-enum-member.ts

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,24 @@ export default createRule({
1515
messages: {
1616
notLiteral: `Explicit enum value must only be a literal value (string, number, boolean, etc).`,
1717
},
18-
schema: [],
18+
schema: [
19+
{
20+
type: 'object',
21+
properties: {
22+
allowBitwiseExpressions: {
23+
type: 'boolean',
24+
},
25+
},
26+
additionalProperties: false,
27+
},
28+
],
1929
},
20-
defaultOptions: [],
21-
create(context) {
30+
defaultOptions: [
31+
{
32+
allowBitwiseExpressions: false,
33+
},
34+
],
35+
create(context, [{ allowBitwiseExpressions }]) {
2236
return {
2337
TSEnumMember(node): void {
2438
// If there is no initializer, then this node is just the name of the member, so ignore.
@@ -39,8 +53,21 @@ export default createRule({
3953
// -1 and +1
4054
if (
4155
node.initializer.type === AST_NODE_TYPES.UnaryExpression &&
42-
['+', '-'].includes(node.initializer.operator) &&
43-
node.initializer.argument.type === AST_NODE_TYPES.Literal
56+
node.initializer.argument.type === AST_NODE_TYPES.Literal &&
57+
(['+', '-'].includes(node.initializer.operator) ||
58+
(allowBitwiseExpressions && node.initializer.operator === '~'))
59+
) {
60+
return;
61+
}
62+
63+
if (
64+
allowBitwiseExpressions &&
65+
node.initializer.type === AST_NODE_TYPES.BinaryExpression &&
66+
['|', '&', '^', '<<', '>>', '>>>'].includes(
67+
node.initializer.operator,
68+
) &&
69+
node.initializer.left.type === AST_NODE_TYPES.Literal &&
70+
node.initializer.right.type === AST_NODE_TYPES.Literal
4471
) {
4572
return;
4673
}

packages/eslint-plugin/tests/rules/prefer-literal-enum-member.test.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ enum ValidKeyWithComputedSyntaxButNoComputedKey {
6262
['a'],
6363
}
6464
`,
65+
{
66+
code: `
67+
enum Foo {
68+
A = 1 << 0,
69+
B = 1 >> 0,
70+
C = 1 >>> 0,
71+
D = 1 | 0,
72+
E = 1 & 0,
73+
F = 1 ^ 0,
74+
G = ~1,
75+
}
76+
`,
77+
options: [{ allowBitwiseExpressions: true }],
78+
},
6579
],
6680
invalid: [
6781
{
@@ -255,5 +269,108 @@ enum InvalidSpread {
255269
},
256270
],
257271
},
272+
{
273+
code: `
274+
enum Foo {
275+
A = 1 << 0,
276+
B = 1 >> 0,
277+
C = 1 >>> 0,
278+
D = 1 | 0,
279+
E = 1 & 0,
280+
F = 1 ^ 0,
281+
G = ~1,
282+
}
283+
`,
284+
options: [{ allowBitwiseExpressions: false }],
285+
errors: [
286+
{
287+
messageId: 'notLiteral',
288+
line: 3,
289+
column: 3,
290+
},
291+
{
292+
messageId: 'notLiteral',
293+
line: 4,
294+
column: 3,
295+
},
296+
{
297+
messageId: 'notLiteral',
298+
line: 5,
299+
column: 3,
300+
},
301+
{
302+
messageId: 'notLiteral',
303+
line: 6,
304+
column: 3,
305+
},
306+
{
307+
messageId: 'notLiteral',
308+
line: 7,
309+
column: 3,
310+
},
311+
{
312+
messageId: 'notLiteral',
313+
line: 8,
314+
column: 3,
315+
},
316+
{
317+
messageId: 'notLiteral',
318+
line: 9,
319+
column: 3,
320+
},
321+
],
322+
},
323+
{
324+
code: `
325+
const x = 1;
326+
enum Foo {
327+
A = x << 0,
328+
B = x >> 0,
329+
C = x >>> 0,
330+
D = x | 0,
331+
E = x & 0,
332+
F = x ^ 0,
333+
G = ~x,
334+
}
335+
`,
336+
options: [{ allowBitwiseExpressions: true }],
337+
errors: [
338+
{
339+
messageId: 'notLiteral',
340+
line: 4,
341+
column: 3,
342+
},
343+
{
344+
messageId: 'notLiteral',
345+
line: 5,
346+
column: 3,
347+
},
348+
{
349+
messageId: 'notLiteral',
350+
line: 6,
351+
column: 3,
352+
},
353+
{
354+
messageId: 'notLiteral',
355+
line: 7,
356+
column: 3,
357+
},
358+
{
359+
messageId: 'notLiteral',
360+
line: 8,
361+
column: 3,
362+
},
363+
{
364+
messageId: 'notLiteral',
365+
line: 9,
366+
column: 3,
367+
},
368+
{
369+
messageId: 'notLiteral',
370+
line: 10,
371+
column: 3,
372+
},
373+
],
374+
},
258375
],
259376
});

0 commit comments

Comments
 (0)