Add noDuplicateKeys lint rule
MODIFY
packages/@romejs/js-compiler/__rtests__/lint.ts
packages/@romejs/js-compiler/__rtests__/lint.ts
@@ -93,3 +93,41 @@ test('format enabled in project config should result in regenerated file', async
);
t.is(res.src, "foobar('yes');\n");
});
+
+test('no duplicate keys', async t => {
+ const res = await testLint(
+ `
+ const foo = {
+ test: true,
+ test2: true,
+ test: false,
+ }
+
+ // mark const as used
+ console.log(foo);
+ `,
+ LINT_ENABLED_FORMAT_DISABLED_CONFIG,
+ );
+
+ t.looksLike(res.diagnostics, [
+ {
+ category: 'lint/noDuplicateKeys',
+ filename: 'unknown',
+ language: 'js',
+ message: 'Duplicate key <emphasis>test</emphasis>',
+ mtime: undefined,
+ sourceType: 'module',
+ origins: [{category: 'lint'}],
+ end: {
+ column: 17,
+ index: 73,
+ line: 5,
+ },
+ start: {
+ column: 6,
+ index: 62,
+ line: 5,
+ },
+ },
+ ]);
+});

MODIFY
packages/@romejs/js-compiler/transforms/lint/index.ts
packages/@romejs/js-compiler/transforms/lint/index.ts
@@ -9,10 +9,12 @@ import defaultExportSameBasename from './defaultExportSameBasename';
import undeclaredVariables from './undeclaredVariables';
import unusedVariables from './unusedVariables';
import emptyBlocks from './emptyBlocks';
+import noDuplicateKeys from './noDuplicateKeys';
export const lintTransforms = [
undeclaredVariables,
defaultExportSameBasename,
unusedVariables,
emptyBlocks,
+ noDuplicateKeys,
];

ADD
packages/@romejs/js-compiler/transforms/lint/noDuplicateKeys.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 {ObjectProperty, ObjectMethod, SpreadProperty} from '@romejs/js-ast';
+import {TransformExitResult} from '@romejs/js-compiler/types';
+import {markup} from '@romejs/string-markup';
+
+function extractPropertyKey(
+ node: ObjectProperty | ObjectMethod | SpreadProperty,
+) {
+ if (
+ (node.type === 'ObjectMethod' || node.type === 'ObjectProperty') &&
+ node.key.type === 'StaticPropertyKey'
+ ) {
+ const {value} = node.key;
+
+ if (value.type === 'PrivateName') {
+ return value.id.name;
+ }
+
+ if (value.type === 'Identifier') {
+ return value.name;
+ }
+
+ return value.value;
+ }
+
+ return null;
+}
+
+export default {
+ name: 'noDuplicateKeys',
+ enter(path: Path): TransformExitResult {
+ const {node} = path;
+
+ if (node.type === 'ObjectExpression') {
+ const previousKeys = new Set();
+
+ for (const prop of node.properties) {
+ const key = extractPropertyKey(prop);
+
+ if (key !== null) {
+ if (previousKeys.has(key)) {
+ path.context.addNodeDiagnostic(prop, {
+ category: 'lint/noDuplicateKeys',
+ message: markup`Duplicate key <emphasis>${key}</emphasis>`,
+ });
+ }
+
+ previousKeys.add(key);
+ }
+ }
+ }
+
+ return node;
+ },
+};

Add noDuplicateKeys lint rule