diff --git a/packages/@romejs/codec-source-map/base64.ts b/packages/@romejs/codec-source-map/base64.ts index 640f7bc9fad7..2ee618c14f1d 100644 --- a/packages/@romejs/codec-source-map/base64.ts +++ b/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) { diff --git a/packages/@romejs/js-compiler/__rtests__/__rsnapshots__/lint.ts.rsnap b/packages/@romejs/js-compiler/__rtests__/__rsnapshots__/lint.ts.rsnap index 0e82d2e7160f..acbd47615071 100644 --- a/packages/@romejs/js-compiler/__rtests__/__rsnapshots__/lint.ts.rsnap +++ b/packages/@romejs/js-compiler/__rtests__/__rsnapshots__/lint.ts.rsnap @@ -5,5 +5,6 @@ "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}", "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}" + "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}", + "disallow var": "Object {\n src: 'var foobar;'\n diagnostics: Array [\n Object {\n category: 'lint/unusedVariables'\n filename: 'unknown'\n language: 'js'\n message: 'Unused variable foobar'\n mtime: undefined\n sourceType: 'module'\n origins: Array [Object {category: 'lint'}]\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 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: 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 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 ]\n }\n}" } \ No newline at end of file diff --git a/packages/@romejs/js-compiler/__rtests__/lint.ts b/packages/@romejs/js-compiler/__rtests__/lint.ts index ecab01b024ec..40ee47b48b11 100644 --- a/packages/@romejs/js-compiler/__rtests__/lint.ts +++ b/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, + }, + }, + ]); +}); diff --git a/packages/@romejs/js-compiler/transforms/lint/disallowVar.ts b/packages/@romejs/js-compiler/transforms/lint/disallowVar.ts new file mode 100644 index 000000000000..0049634cc9ce --- /dev/null +++ b/packages/@romejs/js-compiler/transforms/lint/disallowVar.ts @@ -0,0 +1,29 @@ +/** + * 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; + }, +}; diff --git a/packages/@romejs/js-compiler/transforms/lint/index.ts b/packages/@romejs/js-compiler/transforms/lint/index.ts index 71b70ec226d9..9fab2a7e6822 100644 --- a/packages/@romejs/js-compiler/transforms/lint/index.ts +++ b/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, ];