Add disallowVar lint rule
MODIFY
packages/@romejs/codec-source-map/base64.ts
packages/@romejs/codec-source-map/base64.ts
@@ -129,20 +129,20 @@ export function encodeVLQ(value: number): string {
* failure.
*/
export function decode(charCode: number): number {
- var bigA = 65; // 'A'
- var bigZ = 90; // 'Z'
+ const bigA = 65; // 'A'
+ const bigZ = 90; // 'Z'
- var littleA = 97; // 'a'
- var littleZ = 122; // 'z'
+ const littleA = 97; // 'a'
+ const littleZ = 122; // 'z'
- var zero = 48; // '0'
- var nine = 57; // '9'
+ const zero = 48; // '0'
+ const nine = 57; // '9'
- var plus = 43; // '+'
- var slash = 47; // '/'
+ const plus = 43; // '+'
+ const slash = 47; // '/'
- var littleOffset = 26;
- var numberOffset = 52;
+ const littleOffset = 26;
+ const numberOffset = 52;
// 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ
if (bigA <= charCode && charCode <= bigZ) {

MODIFY
packages/@romejs/js-compiler/__rtests__/__rsnapshots__/lint.ts.rsnap
packages/@romejs/js-compiler/__rtests__/__rsnapshots__/lint.ts.rsnap
"empty file": "Object {\n diagnostics: Array []\n src: ''\n ast: Program {\n body: Array []\n comments: Array []\n diagnostics: Array []\n directives: Array []\n filename: 'unknown'\n hasHoistedVars: false\n interpreter: undefined\n mtime: undefined\n sourceType: 'module'\n syntax: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 0\n index: 0\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n }\n}",
"undeclared variable": "Object {\n src: 'foobar;'\n diagnostics: Array [\n Object {\n category: 'lint/undeclaredVariables'\n filename: 'unknown'\n language: 'js'\n message: 'Undeclared variable <emphasis>foobar</emphasis>'\n mtime: undefined\n sourceType: 'module'\n origins: Array [Object {category: 'lint'}]\n end: Object {\n column: 6\n index: 6\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n ]\n ast: Program {\n comments: Array []\n diagnostics: Array []\n directives: Array []\n filename: 'unknown'\n hasHoistedVars: false\n interpreter: undefined\n mtime: undefined\n sourceType: 'module'\n syntax: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 7\n index: 7\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n body: Array [\n ExpressionStatement {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 7\n index: 7\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n expression: ReferenceIdentifier {\n name: 'foobar'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 6\n index: 6\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n }\n }\n ]\n }\n}",
"unsafe negation": "Object {\n src: '!1 in [1,2]'\n diagnostics: Array [\n Object {\n category: 'lint/unsafeNegation'\n filename: 'unknown'\n language: 'js'\n message: 'Unsafe usage of negation operator in left side of binary expression'\n mtime: undefined\n sourceType: 'module'\n origins: Array [Object {category: 'lint'}]\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n ]\n ast: Program {\n comments: Array []\n diagnostics: Array []\n directives: Array []\n filename: 'unknown'\n hasHoistedVars: false\n interpreter: undefined\n mtime: undefined\n sourceType: 'module'\n syntax: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n body: Array [\n ExpressionStatement {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n expression: BinaryExpression {\n operator: 'in'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n left: UnaryExpression {\n operator: '!'\n prefix: true\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 2\n index: 2\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n argument: NumericLiteral {\n value: 1\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 2\n index: 2\n line: 1\n }\n start: Object {\n column: 1\n index: 1\n line: 1\n }\n }\n }\n }\n right: ArrayExpression {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 6\n index: 6\n line: 1\n }\n }\n elements: Array [\n NumericLiteral {\n value: 1\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 8\n index: 8\n line: 1\n }\n start: Object {\n column: 7\n index: 7\n line: 1\n }\n }\n }\n NumericLiteral {\n value: 2\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 10\n index: 10\n line: 1\n }\n start: Object {\n column: 9\n index: 9\n line: 1\n }\n }\n }\n ]\n }\n }\n }\n ]\n }\n}",
- "unsafe negation: 1": "Object {\n diagnostics: Array []\n src: '!(1 in [1,2])'\n ast: Program {\n comments: Array []\n diagnostics: Array []\n directives: Array []\n filename: 'unknown'\n hasHoistedVars: false\n interpreter: undefined\n mtime: undefined\n sourceType: 'module'\n syntax: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 13\n index: 13\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n body: Array [\n ExpressionStatement {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 13\n index: 13\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n expression: UnaryExpression {\n operator: '!'\n prefix: true\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 13\n index: 13\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n argument: BinaryExpression {\n operator: 'in'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 12\n index: 12\n line: 1\n }\n start: Object {\n column: 2\n index: 2\n line: 1\n }\n }\n left: NumericLiteral {\n value: 1\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 3\n index: 3\n line: 1\n }\n start: Object {\n column: 2\n index: 2\n line: 1\n }\n }\n }\n right: ArrayExpression {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 12\n index: 12\n line: 1\n }\n start: Object {\n column: 7\n index: 7\n line: 1\n }\n }\n elements: Array [\n NumericLiteral {\n value: 1\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 9\n index: 9\n line: 1\n }\n start: Object {\n column: 8\n index: 8\n line: 1\n }\n }\n }\n NumericLiteral {\n value: 2\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 10\n index: 10\n line: 1\n }\n }\n }\n ]\n }\n }\n }\n }\n ]\n }\n}",
+ "disallow var": "Object {\n src: 'var foobar;\\nfoobar'\n diagnostics: Array [\n Object {\n category: 'lint/disallowVar'\n filename: 'unknown'\n language: 'js'\n message: 'Variable declarations using `var` are disallowed, use `let` or `const` instead.'\n mtime: undefined\n sourceType: 'module'\n origins: Array [Object {category: 'lint'}]\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n ]\n ast: Program {\n comments: Array []\n diagnostics: Array []\n directives: Array []\n filename: 'unknown'\n hasHoistedVars: true\n interpreter: undefined\n mtime: undefined\n sourceType: 'module'\n syntax: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 6\n index: 18\n line: 2\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n body: Array [\n VariableDeclarationStatement {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n declaration: VariableDeclaration {\n kind: 'var'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n declarations: Array [\n VariableDeclarator {\n id: BindingIdentifier {\n name: 'foobar'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 10\n index: 10\n line: 1\n }\n start: Object {\n column: 4\n index: 4\n line: 1\n }\n }\n }\n init: undefined\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 10\n index: 10\n line: 1\n }\n start: Object {\n column: 4\n index: 4\n line: 1\n }\n }\n }\n ]\n }\n }\n ExpressionStatement {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 6\n index: 18\n line: 2\n }\n start: Object {\n column: 0\n index: 12\n line: 2\n }\n }\n expression: ReferenceIdentifier {\n name: 'foobar'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 6\n index: 18\n line: 2\n }\n start: Object {\n column: 0\n index: 12\n line: 2\n }\n }\n }\n }\n ]\n }\n}",
"no async promise executor": "Object {\n src: 'new Promise(async function foo() {})'\n diagnostics: Array [\n Object {\n category: 'lint/noAsyncPromiseExecutor'\n filename: 'unknown'\n language: 'js'\n message: 'Promise executor functions should not be async.'\n mtime: undefined\n sourceType: 'module'\n origins: Array [Object {category: 'lint'}]\n end: Object {\n column: 35\n index: 35\n line: 1\n }\n start: Object {\n column: 12\n index: 12\n line: 1\n }\n }\n ]\n ast: Program {\n comments: Array []\n diagnostics: Array []\n directives: Array []\n filename: 'unknown'\n hasHoistedVars: false\n interpreter: undefined\n mtime: undefined\n sourceType: 'module'\n syntax: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 36\n index: 36\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n body: Array [\n ExpressionStatement {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 36\n index: 36\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n expression: NewExpression {\n optional: undefined\n typeArguments: undefined\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 36\n index: 36\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n callee: ReferenceIdentifier {\n name: 'Promise'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 4\n index: 4\n line: 1\n }\n }\n }\n arguments: Array [\n FunctionExpression {\n id: BindingIdentifier {\n name: 'foo'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 30\n index: 30\n line: 1\n }\n start: Object {\n column: 27\n index: 27\n line: 1\n }\n }\n }\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 35\n index: 35\n line: 1\n }\n start: Object {\n column: 12\n index: 12\n line: 1\n }\n }\n body: BlockStatement {\n body: Array []\n directives: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 35\n index: 35\n line: 1\n }\n start: Object {\n column: 33\n index: 33\n line: 1\n }\n }\n }\n head: FunctionHead {\n async: true\n generator: false\n hasHoistedVars: false\n params: Array []\n predicate: undefined\n rest: undefined\n returnType: undefined\n thisType: undefined\n typeParameters: undefined\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 33\n index: 33\n line: 1\n }\n start: Object {\n column: 12\n index: 12\n line: 1\n }\n }\n }\n }\n ]\n }\n }\n ]\n }\n}",
"no async promise executor: 1": "Object {\n src: 'new Promise(async () => {})'\n diagnostics: Array [\n Object {\n category: 'lint/noAsyncPromiseExecutor'\n filename: 'unknown'\n language: 'js'\n message: 'Promise executor functions should not be async.'\n mtime: undefined\n sourceType: 'module'\n origins: Array [Object {category: 'lint'}]\n end: Object {\n column: 26\n index: 26\n line: 1\n }\n start: Object {\n column: 12\n index: 12\n line: 1\n }\n }\n ]\n ast: Program {\n comments: Array []\n diagnostics: Array []\n directives: Array []\n filename: 'unknown'\n hasHoistedVars: false\n interpreter: undefined\n mtime: undefined\n sourceType: 'module'\n syntax: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 27\n index: 27\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n body: Array [\n ExpressionStatement {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 27\n index: 27\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n expression: NewExpression {\n optional: undefined\n typeArguments: undefined\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 27\n index: 27\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n callee: ReferenceIdentifier {\n name: 'Promise'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 4\n index: 4\n line: 1\n }\n }\n }\n arguments: Array [\n ArrowFunctionExpression {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 26\n index: 26\n line: 1\n }\n start: Object {\n column: 12\n index: 12\n line: 1\n }\n }\n body: BlockStatement {\n body: Array []\n directives: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 26\n index: 26\n line: 1\n }\n start: Object {\n column: 24\n index: 24\n line: 1\n }\n }\n }\n head: FunctionHead {\n async: true\n hasHoistedVars: false\n params: Array []\n rest: undefined\n returnType: undefined\n thisType: undefined\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 24\n index: 24\n line: 1\n }\n start: Object {\n column: 12\n index: 12\n line: 1\n }\n }\n }\n }\n ]\n }\n }\n ]\n }\n}",
"no async promise executor: 2": "Object {\n src: 'new Promise(((((async () => {})))))'\n diagnostics: Array [\n Object {\n category: 'lint/noAsyncPromiseExecutor'\n filename: 'unknown'\n language: 'js'\n message: 'Promise executor functions should not be async.'\n mtime: undefined\n sourceType: 'module'\n origins: Array [Object {category: 'lint'}]\n end: Object {\n column: 30\n index: 30\n line: 1\n }\n start: Object {\n column: 16\n index: 16\n line: 1\n }\n }\n ]\n ast: Program {\n comments: Array []\n diagnostics: Array []\n directives: Array []\n filename: 'unknown'\n hasHoistedVars: false\n interpreter: undefined\n mtime: undefined\n sourceType: 'module'\n syntax: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 35\n index: 35\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n body: Array [\n ExpressionStatement {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 35\n index: 35\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n expression: NewExpression {\n optional: undefined\n typeArguments: undefined\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 35\n index: 35\n line: 1\n }\n start: Object {\n column: 0\n index: 0\n line: 1\n }\n }\n callee: ReferenceIdentifier {\n name: 'Promise'\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 11\n index: 11\n line: 1\n }\n start: Object {\n column: 4\n index: 4\n line: 1\n }\n }\n }\n arguments: Array [\n ArrowFunctionExpression {\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 30\n index: 30\n line: 1\n }\n start: Object {\n column: 16\n index: 16\n line: 1\n }\n }\n body: BlockStatement {\n body: Array []\n directives: Array []\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 30\n index: 30\n line: 1\n }\n start: Object {\n column: 28\n index: 28\n line: 1\n }\n }\n }\n head: FunctionHead {\n async: true\n hasHoistedVars: false\n params: Array []\n rest: undefined\n returnType: undefined\n thisType: undefined\n loc: Object {\n filename: 'unknown'\n end: Object {\n column: 28\n index: 28\n line: 1\n }\n start: Object {\n column: 16\n index: 16\n line: 1\n }\n }\n }\n }\n ]\n }\n }\n ]\n }\n}"

MODIFY
packages/@romejs/js-compiler/__rtests__/lint.ts
packages/@romejs/js-compiler/__rtests__/lint.ts
@@ -219,3 +219,35 @@ test('no duplicate keys', async t => {
},
]);
});
+
+test('disallow var', async t => {
+ const res = await testLint(
+ 'var foobar;\nfoobar',
+ LINT_ENABLED_FORMAT_DISABLED_CONFIG,
+ );
+ t.snapshot(res);
+
+ // Redundant because of the snapshot above, but this is what we actually care about
+ t.looksLike(res.diagnostics, [
+ {
+ category: 'lint/disallowVar',
+ filename: 'unknown',
+ language: 'js',
+ message:
+ 'Variable declarations using `var` are disallowed, use `let` or `const` instead.',
+ mtime: undefined,
+ sourceType: 'module',
+ origins: [{category: 'lint'}],
+ end: {
+ column: 11,
+ index: 11,
+ line: 1,
+ },
+ start: {
+ column: 0,
+ index: 0,
+ line: 1,
+ },
+ },
+ ]);
+});

ADD
packages/@romejs/js-compiler/transforms/lint/disallowVar.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 {AnyNode} from '@romejs/js-ast';
+import {Path} from '@romejs/js-compiler';
+
+export default {
+ name: 'disallowVar',
+ enter(path: Path): AnyNode {
+ const {context, node: declaration} = path;
+
+ if (
+ declaration.type === 'VariableDeclaration' &&
+ declaration.kind === 'var'
+ ) {
+ context.addNodeDiagnostic(declaration, {
+ category: 'lint/disallowVar',
+ message:
+ 'Variable declarations using `var` are disallowed, use `let` or `const` instead.',
+ });
+ }
+
+ return declaration;
+ },
+};

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 disallowVar from './disallowVar';
export const lintTransforms = [
undeclaredVariables,
@@ -25,4 +26,5 @@ export const lintTransforms = [
noAsyncPromiseExecutor,
noLabelVar,
noDuplicateKeys,
+ disallowVar,
];

Add disallowVar lint rule