linter: add no function reassignment lint rule
MODIFY
packages/@romejs/js-compiler/__rtests__/lint.ts
packages/@romejs/js-compiler/__rtests__/lint.ts
@@ -10,6 +10,7 @@ import lint from '../api/lint';
import {parseJS} from '@romejs/js-parser';
import {createUnknownFilePath} from '@romejs/path';
import {DEFAULT_PROJECT_CONFIG, ProjectConfig} from '@romejs/project';
+import {PartialDiagnostic} from '@romejs/diagnostics/types';
const LINT_ENABLED_FORMAT_DISABLED_CONFIG: ProjectConfig = {
...DEFAULT_PROJECT_CONFIG,
@@ -219,3 +220,45 @@ test('no duplicate keys', async t => {
},
]);
});
+
+test('no function reassignment', async t => {
+ function checkCategory(diagnostic: PartialDiagnostic): Boolean {
+ return diagnostic.category === 'lint/noFunctionAssign';
+ }
+
+ const validTestCases = [
+ 'function foo() { var foo = bar; }',
+ 'function foo(foo) { foo = bar; }',
+ 'function foo() { var foo; foo = bar; }',
+ 'var foo = () => {}; foo = bar;',
+ 'var foo = function() {}; foo = bar;',
+ 'var foo = function() { foo = bar; };',
+ `import bar from 'bar'; function foo() { var foo = bar; }`,
+ ];
+
+ const invalidTestCases = [
+ 'function foo() {}; foo = bar;',
+ 'function foo() { foo = bar; }',
+ 'foo = bar; function foo() { };',
+ '[foo] = bar; function foo() { };',
+ '({x: foo = 0} = bar); function foo() { };',
+ 'function foo() { [foo] = bar; }',
+ '(function() { ({x: foo = 0} = bar); function foo() { }; })();',
+ ];
+
+ validTestCases.forEach(async testCase => {
+ const {diagnostics} = await testLint(
+ testCase,
+ LINT_ENABLED_FORMAT_DISABLED_CONFIG,
+ );
+ t.falsy(diagnostics.find(checkCategory));
+ });
+
+ invalidTestCases.forEach(async testCase => {
+ const {diagnostics} = await testLint(
+ testCase,
+ LINT_ENABLED_FORMAT_DISABLED_CONFIG,
+ );
+ t.truthy(diagnostics.find(checkCategory));
+ });
+});

MODIFY
packages/@romejs/js-compiler/transforms/lint/index.ts
packages/@romejs/js-compiler/transforms/lint/index.ts
@@ -14,6 +14,7 @@ import unsafeNegation from './unsafeNegation';
import noAsyncPromiseExecutor from './noAsyncPromiseExecutor';
import noLabelVar from './noLabelVar';
import noDuplicateKeys from './noDuplicateKeys';
+import noFunctionAssign from './noFunctionAssign';
export const lintTransforms = [
undeclaredVariables,
@@ -25,4 +26,5 @@ export const lintTransforms = [
noAsyncPromiseExecutor,
noLabelVar,
noDuplicateKeys,
+ noFunctionAssign,
];

ADD
packages/@romejs/js-compiler/transforms/lint/noFunctionAssign.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 {FunctionBinding} from '@romejs/js-compiler/scope/bindings';
+
+export default {
+ name: 'noFunctionAssign',
+ enter(path: Path): AnyNode {
+ const {node, scope} = path;
+ if (
+ node.type === 'AssignmentIdentifier' &&
+ scope.getBinding(node.name) instanceof FunctionBinding
+ ) {
+ path.context.addNodeDiagnostic(node, {
+ category: 'lint/noFunctionAssign',
+ message: 'Reassignment of function declaration',
+ });
+ }
+ return node;
+ },
+};

linter: add no function reassignment lint rule