From e7823334a61d6c187b3b14627346cd8ee14b8cf5 Mon Sep 17 00:00:00 2001 From: Brian Ng Date: Thu, 6 Sep 2018 10:33:21 -0500 Subject: [PATCH] Add valid-typeof rule with support for BigInt --- README.md | 4 +- rules/valid-typeof.js | 12 +++ tests/rules/valid-typeof.js | 193 ++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 rules/valid-typeof.js create mode 100644 tests/rules/valid-typeof.js diff --git a/README.md b/README.md index da1dfe2..7d1aebc 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ original ones as well!). "babel/object-curly-spacing": 1, "babel/quotes": 1, "babel/semi": 1, - "babel/no-unused-expressions": 1 + "babel/no-unused-expressions": 1, + "babel/valid-typeof": 1 } } ``` @@ -49,6 +50,7 @@ Each rule corresponds to a core `eslint` rule, and has the same options. - `babel/quotes`: doesn't complain about JSX fragment shorthand syntax (`<>foo;`) - `babel/semi`: doesn't fail when using `for await (let something of {})`. Includes class properties (🛠) - `babel/no-unused-expressions`: doesn't fail when using `do` expressions or [optional chaining](https://github.com/tc39/proposal-optional-chaining) (`a?.b()`). +- `babel/valid-typeof`: doesn't complain when used with [BigInt](https://github.com/tc39/proposal-bigint) (`typeof BigInt(9007199254740991) === 'bigint'`). #### Deprecated diff --git a/rules/valid-typeof.js b/rules/valid-typeof.js new file mode 100644 index 0000000..df5110b --- /dev/null +++ b/rules/valid-typeof.js @@ -0,0 +1,12 @@ +"use strict"; + +const ruleComposer = require('eslint-rule-composer'); +const eslint = require('eslint'); +const validTypeOf = new eslint.Linter().getRules().get('valid-typeof'); + +module.exports = ruleComposer.filterReports( + validTypeOf, + (problem, metadata) => { + return problem.node.value !== 'bigint'; + } +) diff --git a/tests/rules/valid-typeof.js b/tests/rules/valid-typeof.js new file mode 100644 index 0000000..8e474f6 --- /dev/null +++ b/tests/rules/valid-typeof.js @@ -0,0 +1,193 @@ +/** + * @fileoverview Ensures that the results of typeof are compared against a valid string + * @author Ian Christian Myers + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../rules/valid-typeof"), + RuleTester = require("../RuleTester"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); + +ruleTester.run("valid-typeof", rule, { + valid: [ + // Original test cases. + "typeof foo === 'string'", + "typeof foo === 'object'", + "typeof foo === 'function'", + "typeof foo === 'undefined'", + "typeof foo === 'boolean'", + "typeof foo === 'number'", + "'string' === typeof foo", + "'object' === typeof foo", + "'function' === typeof foo", + "'undefined' === typeof foo", + "'boolean' === typeof foo", + "'number' === typeof foo", + "typeof foo === typeof bar", + "typeof foo === baz", + "typeof foo !== someType", + "typeof bar != someType", + "someType === typeof bar", + "someType == typeof bar", + "typeof foo == 'string'", + "typeof(foo) === 'string'", + "typeof(foo) !== 'string'", + "typeof(foo) == 'string'", + "typeof(foo) != 'string'", + "var oddUse = typeof foo + 'thing'", + { + code: "typeof foo === 'number'", + options: [{ requireStringLiterals: true }] + }, + { + code: "typeof foo === \"number\"", + options: [{ requireStringLiterals: true }] + }, + { + code: "var baz = typeof foo + 'thing'", + options: [{ requireStringLiterals: true }] + }, + { + code: "typeof foo === typeof bar", + options: [{ requireStringLiterals: true }] + }, + { + code: "typeof foo === `string`", + options: [{ requireStringLiterals: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "`object` === typeof foo", + options: [{ requireStringLiterals: true }], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "typeof foo === `str${somethingElse}`", + parserOptions: { ecmaVersion: 6 } + }, + + // Babel-specific test cases. + { + code: "typeof BigInt(Number.MAX_SAFE_INTEGER) === 'bigint'" + }, + { + code: "'bigint' === typeof BigInt(Number.MAX_SAFE_INTEGER)" + }, + { + code: "typeof BigInt(Number.MAX_SAFE_INTEGER) === 'bigint'", + options: [{ requireStringLiterals: true }] + }, + ], + invalid: [ + { + code: "typeof foo === 'strnig'", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "'strnig' === typeof foo", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "if (typeof bar === 'umdefined') {}", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "typeof foo !== 'strnig'", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "'strnig' !== typeof foo", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "if (typeof bar !== 'umdefined') {}", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "typeof foo != 'strnig'", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "'strnig' != typeof foo", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "if (typeof bar != 'umdefined') {}", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "typeof foo == 'strnig'", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "'strnig' == typeof foo", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "if (typeof bar == 'umdefined') {}", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "if (typeof bar === `umdefined`) {}", + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Invalid typeof comparison value.", type: "TemplateLiteral" }] + }, + { + code: "typeof foo == 'invalid string'", + options: [{ requireStringLiterals: true }], + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "typeof foo == Object", + options: [{ requireStringLiterals: true }], + errors: [{ message: "Typeof comparisons should be to string literals.", type: "Identifier" }] + }, + { + code: "typeof foo === undefined", + options: [{ requireStringLiterals: true }], + errors: [{ message: "Typeof comparisons should be to string literals.", type: "Identifier" }] + }, + { + code: "undefined === typeof foo", + options: [{ requireStringLiterals: true }], + errors: [{ message: "Typeof comparisons should be to string literals.", type: "Identifier" }] + }, + { + code: "undefined == typeof foo", + options: [{ requireStringLiterals: true }], + errors: [{ message: "Typeof comparisons should be to string literals.", type: "Identifier" }] + }, + { + code: "typeof foo === `undefined${foo}`", + options: [{ requireStringLiterals: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Typeof comparisons should be to string literals.", type: "TemplateLiteral" }] + }, + { + code: "typeof foo === `${string}`", + options: [{ requireStringLiterals: true }], + parserOptions: { ecmaVersion: 6 }, + errors: [{ message: "Typeof comparisons should be to string literals.", type: "TemplateLiteral" }] + }, + + // Babel-specific test cases. + { + code: "typeof foo === 'bgiint'", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + { + code: "'bignit' === typeof foo", + errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }] + }, + ] +});