Rename and simplify noExAssign rule
MODIFY
packages/@romejs/codec-watchman/index.ts
packages/@romejs/codec-watchman/index.ts
@@ -210,7 +210,9 @@ export async function getWatchmanSocketLocation(): Promise<string> {
}
return data.sockname;
- } catch (err) {
+ } catch (_err) {
+ let err = _err;
+
// Better error message for syntatically invalid JSON
if (err instanceof SyntaxError) {
err = new Error(`Watchman returned malformed JSON payload`);

MODIFY
packages/@romejs/diagnostics/categories.ts
packages/@romejs/diagnostics/categories.ts
@@ -48,7 +48,7 @@ export type DiagnosticCategory =
| 'lint/noShorthandArrayType'
| 'lint/noTemplateCurlyInString'
| 'lint/noUnsafeFinally'
- | 'lint/noExAssign'
+ | 'lint/noCatchAssign'
| 'lint/noVar'
| 'lint/pendingFixes'
| 'lint/preferFunctionDeclarations'

MODIFY
packages/@romejs/diagnostics/descriptions.ts
packages/@romejs/diagnostics/descriptions.ts
@@ -258,6 +258,11 @@ export const descriptions = createMessages(
message: markup`Undeclared variable <emphasis>${name}</emphasis>`,
}),
+ NO_CATCH_ASSIGN: {
+ category: 'lint/noCatchAssign',
+ message: "Don't reassign catch parameters",
+ },
+
SPARSE_ARRAY: {
fixable: true,
category: 'lint/sparseArray',

MODIFY
packages/@romejs/js-compiler/scope/evaluators/CatchClause.ts
packages/@romejs/js-compiler/scope/evaluators/CatchClause.ts
@@ -16,12 +16,11 @@ export default {
const newScope = scope.fork('block', node);
if (node.param !== undefined) {
for (const id of getBindingIdentifiers(node.param)) {
- // TODO maybe add a `catch` binding type?
newScope.addBinding(new LetBinding({
node: id,
name: id.name,
scope: newScope,
- }));
+ }, 'catch'));
}
}
return newScope;

MODIFY
packages/@romejs/js-compiler/transforms/lint/index.ts
packages/@romejs/js-compiler/transforms/lint/index.ts
@@ -33,7 +33,7 @@ import noShadowRestrictedNames from './noShadowRestrictedNames';
import noShorthandArrayType from './noShorthandArrayType';
import noTemplateCurlyInString from './noTemplateCurlyInString';
import noUnsafeFinally from './noUnsafeFinally';
-import noExAssign from './noExAssign';
+import noCatchAssign from './noCatchAssign';
import noVar from './noVar';
import preferFunctionDeclarations from './preferFunctionDeclarations';
import preferTemplate from './preferTemplate';
@@ -72,7 +72,7 @@ export const lintTransforms = [
noShorthandArrayType,
noTemplateCurlyInString,
noUnsafeFinally,
- noExAssign,
+ noCatchAssign,
noVar,
preferFunctionDeclarations,
preferTemplate,

ADD
packages/@romejs/js-compiler/transforms/lint/noCatchAssign.test.md
+# `noCatchAssign.test.ts`
+
+**DO NOT MODIFY**. This file has been autogenerated. Run `rome test packages/@romejs/js-compiler/transforms/lint/noCatchAssign.test.ts --update-snapshots` to update.
+
+## `no exception assign`
+
+### `0`
+
+```javascript
+Object {
+ diagnostics: Array []
+ src: 'try { } catch (e) { three = 2 + 1; }'
+ suppressions: Array []
+}
+```
+
+### `1`
+
+```javascript
+Object {
+ src: 'try { } catch ({e}) { this.something = 2; }'
+ suppressions: Array []
+ diagnostics: Array [
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/unusedVariables'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused catch <emphasis>e</emphasis>'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 17
+ index: 17
+ line: 1
+ }
+ start: Object {
+ column: 16
+ index: 16
+ line: 1
+ }
+ }
+ }
+ ]
+}
+```
+
+### `2`
+
+```javascript
+Object {
+ src: 'function foo() { try { } catch (e) { return false; } }'
+ suppressions: Array []
+ diagnostics: Array [
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/unusedVariables'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused function <emphasis>foo</emphasis>'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 12
+ index: 12
+ line: 1
+ }
+ start: Object {
+ column: 9
+ index: 9
+ line: 1
+ }
+ }
+ }
+ ]
+}
+```
+
+### `3`
+
+```javascript
+Object {
+ src: 'try { } catch (e) { e; e = 10; }'
+ suppressions: Array []
+ diagnostics: Array [
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/noCatchAssign'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Don\'t reassign catch parameters'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 24
+ index: 24
+ line: 1
+ }
+ start: Object {
+ column: 23
+ index: 23
+ line: 1
+ }
+ }
+ }
+ ]
+}
+```
+
+### `4`
+
+```javascript
+Object {
+ src: 'try { } catch (ex) { console.log(\'test\'); ex = 10; }'
+ suppressions: Array []
+ diagnostics: Array [
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/noCatchAssign'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Don\'t reassign catch parameters'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 44
+ index: 44
+ line: 1
+ }
+ start: Object {
+ column: 42
+ index: 42
+ line: 1
+ }
+ }
+ }
+ ]
+}
+```
+
+### `5`
+
+```javascript
+Object {
+ src: 'try { } catch (ex) { [ex, test] = []; }'
+ suppressions: Array []
+ diagnostics: Array [
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/noCatchAssign'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Don\'t reassign catch parameters'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 24
+ index: 24
+ line: 1
+ }
+ start: Object {
+ column: 22
+ index: 22
+ line: 1
+ }
+ }
+ }
+ ]
+}
+```
+
+### `6`
+
+```javascript
+Object {
+ src: 'try { } catch ({message, name}) { message = \'test\'; name = 10; }'
+ suppressions: Array []
+ diagnostics: Array [
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/noCatchAssign'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Don\'t reassign catch parameters'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 41
+ index: 41
+ line: 1
+ }
+ start: Object {
+ column: 34
+ index: 34
+ line: 1
+ }
+ }
+ }
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/noCatchAssign'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Don\'t reassign catch parameters'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 56
+ index: 56
+ line: 1
+ }
+ start: Object {
+ column: 52
+ index: 52
+ line: 1
+ }
+ }
+ }
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/unusedVariables'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused catch <emphasis>name</emphasis>'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 29
+ index: 29
+ line: 1
+ }
+ start: Object {
+ column: 25
+ index: 25
+ line: 1
+ }
+ }
+ }
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/unusedVariables'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused catch <emphasis>message</emphasis>'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 23
+ index: 23
+ line: 1
+ }
+ start: Object {
+ column: 16
+ index: 16
+ line: 1
+ }
+ }
+ }
+ ]
+}
+```
+
+### `7`
+
+```javascript
+Object {
+ src: 'try { } catch (ex) { ({x: ex = 0} = {}); }'
+ suppressions: Array []
+ diagnostics: Array [
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/noCatchAssign'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Don\'t reassign catch parameters'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 28
+ index: 28
+ line: 1
+ }
+ start: Object {
+ column: 26
+ index: 26
+ line: 1
+ }
+ }
+ }
+ ]
+}
+```
+
+### `8`
+
+```javascript
+Object {
+ src: 'try { } catch (ex) { let a; ({x: a = ex = 0} = {}); }'
+ suppressions: Array []
+ diagnostics: Array [
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/noCatchAssign'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Don\'t reassign catch parameters'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 39
+ index: 39
+ line: 1
+ }
+ start: Object {
+ column: 37
+ index: 37
+ line: 1
+ }
+ }
+ }
+ Object {
+ origins: Array [Object {category: 'lint'}]
+ description: Object {
+ category: 'lint/unusedVariables'
+ message: PARTIAL_BLESSED_DIAGNOSTIC_MESSAGE {value: 'Unused variable <emphasis>a</emphasis>'}
+ }
+ location: Object {
+ filename: 'unknown'
+ language: 'js'
+ mtime: undefined
+ sourceType: 'module'
+ end: Object {
+ column: 26
+ index: 26
+ line: 1
+ }
+ start: Object {
+ column: 25
+ index: 25
+ line: 1
+ }
+ }
+ }
+ ]
+}
+```

RENAME
packages/@romejs/js-compiler/transforms/lint/noExAssign.test.ts
packages/@romejs/js-compiler/transforms/lint/noCatchAssign.test.ts
@@ -9,32 +9,22 @@ import test from '@romejs/test';
import {testLint} from '../../api/lint.test';
test('no exception assign', async (t) => {
- const validTestCases = [
+ const testCases = [
+ // VALID
`try { } catch (e) { three = 2 + 1; }`,
'try { } catch ({e}) { this.something = 2; }',
'function foo() { try { } catch (e) { return false; } }',
- ];
- const invalidTestCases = [
+ // INVALID
'try { } catch (e) { e; e = 10; }',
"try { } catch (ex) { console.log('test'); ex = 10; }",
'try { } catch (ex) { [ex, test] = []; }',
- "try { } catch ({message, name}) { message = 'test'; name = 10; }"
- // "try { } catch (ex) { ({x: ex = 0} = {}); }",
-
- // "try { } catch (ex) { let a; ({x: a = ex = 0} = {}); }"
- ,
+ "try { } catch ({message, name}) { message = 'test'; name = 10; }",
+ 'try { } catch (ex) { ({x: ex = 0} = {}); }',
+ 'try { } catch (ex) { let a; ({x: a = ex = 0} = {}); }',
];
- for (const validTestCase of validTestCases) {
- const {diagnostics} = await testLint(validTestCase);
-
- t.falsy(diagnostics.find((d) => d.category === 'lint/noExAssign'));
- }
-
- for (const invalidTestCase of invalidTestCases) {
- let {diagnostics} = await testLint(invalidTestCase);
-
- t.truthy(diagnostics.find((d) => d.category === 'lint/noExAssign'));
+ for (const test of testCases) {
+ t.snapshot(await testLint(test));
}
});

ADD
packages/@romejs/js-compiler/transforms/lint/noCatchAssign.ts
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import {Path} from '@romejs/js-compiler';
+import {AnyNode} from '@romejs/js-ast';
+import {descriptions} from '@romejs/diagnostics';
+
+export default {
+ name: 'noCatchAssign',
+ enter(path: Path): AnyNode {
+ const {node, context, scope} = path;
+
+ if (node.type === 'AssignmentIdentifier') {
+ const binding = scope.getBinding(node.name);
+
+ if (binding !== undefined && binding.kind === 'catch') {
+ context.addNodeDiagnostic(node, descriptions.LINT.NO_CATCH_ASSIGN);
+ }
+ }
+
+ return node;
+ },
+};

DELETE
packages/@romejs/js-compiler/transforms/lint/noExAssign.ts
-/**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import {
- getBindingIdentifiers,
- isVariableIdentifier,
-} from '@romejs/js-ast-utils';
-import {Path, Context} from '@romejs/js-compiler';
-import {AnyNode} from '@romejs/js-ast';
-
-function addDiagnostic(name: string, node: AnyNode, context: Context) {
- const identifiers = getBindingIdentifiers(node).map(
- (identifier) => identifier.name,
- );
-
- if (!identifiers.includes(name)) {
- return;
- }
-
- context.addNodeDiagnostic(node, {
- category: 'lint/noExAssign',
- message: 'Do not assign to the exception parameter.',
- });
-}
-
-export default {
- name: 'noExAssign',
- enter(path: Path): AnyNode {
- const {node, context} = path;
-
- if (node.type === 'CatchClause' && node.body.type === 'BlockStatement') {
- node.body.body.forEach((item) => {
- if (item.type === 'ExpressionStatement' && item.expression.type ===
- 'AssignmentExpression') {
- if (isVariableIdentifier(item.expression.left)) {
- const {name} = item.expression.left;
-
- addDiagnostic(name, node, context);
- }
-
- if (item.expression.left.type === 'AssignmentArrayPattern') {
- const {elements} = item.expression.left;
-
- elements.forEach((element) => {
- if (!element || element && !isVariableIdentifier(element)) {
- return;
- }
-
- const {name} = element;
-
- addDiagnostic(name, node, context);
- });
- }
- }
- });
- }
-
- return node;
- },
-};

Rename and simplify noExAssign rule