Skip to content

Commit

Permalink
feat: add es-roikoren/no-private-in rule (#11)
Browse files Browse the repository at this point in the history
* feat: add `es-roikoren/no-private-in` rule

* test: fix
  • Loading branch information
roikoren755 authored Dec 1, 2021
1 parent 20f6399 commit ae75c1b
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/late-cups-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'eslint-plugin-es-roikoren': patch
---

feat: add `es-roikoren/no-private-in` rule
1 change: 1 addition & 0 deletions docs/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ There is a config that enables the rules in this category: `plugin:es-roikoren/n
| [es-roikoren/no-class-fields](./no-class-fields.md) | disallow class fields. | |
| [es-roikoren/no-class-static-block](./no-class-static-block.md) | disallow class static block. | |
| [es-roikoren/no-object-hasown](./no-object-hasown.md) | disallow the `Object.hasOwn` method. | |
| [es-roikoren/no-private-in](./no-private-in.md) | disallow `#x in obj`. | |
| [es-roikoren/no-regexp-d-flag](./no-regexp-d-flag.md) | disallow RegExp `d` flag. | |

## ES2021
Expand Down
25 changes: 25 additions & 0 deletions docs/rules/no-private-in.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# es-roikoren/no-private-in
> disallow `#x in obj`.
- ✅ The following configurations enable this rule: `plugin:es-roikoren/no-new-in-esnext`

This rule reports ES2022 private in (`#x in obj`) as errors.

## Examples

⛔ Examples of **incorrect** code for this rule:

```js
/*eslint es-roikoren/no-private-in: error */
class A {
#x;
fn() {
var hasX = #x in obj;
}
}
```

## 📚 References

- [Rule source](https://github.com/roikoren755/eslint-plugin-es/blob/v0.0.6/src/rules/no-private-in.ts)
- [Test source](https://github.com/roikoren755/eslint-plugin-es/blob/v0.0.6/tests/src/rules/no-private-in.ts)
1 change: 1 addition & 0 deletions src/configs/no-new-in-esnext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const config: TSESLint.Linter.Config = {
'es-roikoren/no-class-fields': 'error',
'es-roikoren/no-class-static-block': 'error',
'es-roikoren/no-object-hasown': 'error',
'es-roikoren/no-private-in': 'error',
'es-roikoren/no-regexp-d-flag': 'error',
},
};
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ import noObjectValues from './rules/no-object-values';
import noOctalNumericLiterals from './rules/no-octal-numeric-literals';
import noOptionalCatchBinding from './rules/no-optional-catch-binding';
import noOptionalChaining from './rules/no-optional-chaining';
import noPrivateIn from './rules/no-private-in';
import noPromise from './rules/no-promise';
import noPromiseAllSettled from './rules/no-promise-all-settled';
import noPromiseAny from './rules/no-promise-any';
Expand Down Expand Up @@ -304,6 +305,7 @@ export default {
'no-octal-numeric-literals': noOctalNumericLiterals,
'no-optional-catch-binding': noOptionalCatchBinding,
'no-optional-chaining': noOptionalChaining,
'no-private-in': noPrivateIn,
'no-promise': noPromise,
'no-promise-all-settled': noPromiseAllSettled,
'no-promise-any': noPromiseAny,
Expand Down
33 changes: 33 additions & 0 deletions src/rules/no-private-in.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { TSESTree } from '@typescript-eslint/typescript-estree';

import { createRule } from '../util/create-rule';

export const category = 'ES2022';
export default createRule<[], 'forbidden'>({
name: 'no-private-in',
meta: {
type: 'problem',
docs: { description: 'disallow `#x in obj`.', recommended: false },
schema: [],
messages: { forbidden: 'ES2022 private in (`#{{private}} in {{object}}`) is forbidden.' },
},
defaultOptions: [],
create(context) {
return {
"BinaryExpression[operator='in'] > PrivateIdentifier.left"(node: TSESTree.PrivateIdentifier) {
if (node.parent?.type !== 'BinaryExpression') {
return;
}

context.report({
node,
messageId: 'forbidden',
data: {
private: node.name,
object: node.parent.right.type === 'Identifier' ? node.parent.right.name : 'object',
},
});
},
};
},
});
30 changes: 30 additions & 0 deletions tests/src/rules/no-private-in.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { TSESLint } from '@typescript-eslint/experimental-utils';
import { AST_NODE_TYPES } from '@typescript-eslint/types';

import { RuleTester } from '../../tester';
import rule from '../../../src/rules/no-private-in';

const error = (object: string): TSESLint.TestCaseError<'forbidden'> => ({
messageId: 'forbidden' as const,
line: 1,
column: 31,
type: AST_NODE_TYPES.PrivateIdentifier,
data: { object, private: 'x' },
});

if (!RuleTester.isSupported(2022)) {
console.log('Skip the tests of no-private-in.');
} else {
new RuleTester().run('no-private-in', rule, {
valid: [
"class A { f(obj) { return '#x' in obj } }",
'class A { f(obj) { return x in obj } }',
'class A { #x; f(obj) { return foo in obj.#x } }',
],
invalid: [
{ code: 'class A { #x; f(obj) { return #x in obj } }', errors: [error('obj')] },
{ code: 'class A { #x; f(obj) { return #x in obj.foo } }', errors: [error('object')] },
{ code: 'class A { #x; f(obj) { return #x in obj.#x } }', errors: [error('object')] },
],
});
}

0 comments on commit ae75c1b

Please sign in to comment.