From 60ab7f8b9fe2bcf3891257c3dfc067c06c1e3896 Mon Sep 17 00:00:00 2001 From: James Henry Date: Thu, 13 Oct 2016 23:01:57 +0100 Subject: [PATCH 1/6] WIP --- lib/rules/restrict-plus-operands.js | 58 +++++++++++++++++++++++ tests/lib/rules/restrict-plus-operands.js | 53 +++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 lib/rules/restrict-plus-operands.js create mode 100644 tests/lib/rules/restrict-plus-operands.js diff --git a/lib/rules/restrict-plus-operands.js b/lib/rules/restrict-plus-operands.js new file mode 100644 index 0000000..46d32f3 --- /dev/null +++ b/lib/rules/restrict-plus-operands.js @@ -0,0 +1,58 @@ +/** + * @fileoverview When adding two variables, operands must both be of type number or of type string. + * @author James Henry + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "When adding two variables, operands must both be of type number or of type string.", + category: "TypeScript" + }, + schema: [] + }, + + create: function(context) { + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + return { + BinaryExpression(node) { + + var ts = context.parserServices.ts; + var tsNode = context.parserServices.getTSNode(node); + + if (tsNode.operatorToken.kind === ts.SyntaxKind.PlusToken) { + + var program = context.parserServices.getCurrentProgram(); + var tc = program.getTypeChecker(); + var leftType = tc.typeToString(tc.getTypeAtLocation(tsNode.left)); + var rightType = tc.typeToString(tc.getTypeAtLocation(tsNode.right)); + + if (leftType !== rightType) { + context.report({ + node: node, + message: "Cannot add a '" + leftType + "' to a '" + rightType + "'." + }); + return; + } + + if (leftType !== "number" && leftType !== "string") { + context.report({ + node: node, + message: "'" + leftType + "' is not a supported type for addition." + }); + return; + } + + } + } + }; + } +}; diff --git a/tests/lib/rules/restrict-plus-operands.js b/tests/lib/rules/restrict-plus-operands.js new file mode 100644 index 0000000..791fbb8 --- /dev/null +++ b/tests/lib/rules/restrict-plus-operands.js @@ -0,0 +1,53 @@ +/** + * @fileoverview When adding two variables, operands must both be of type number or of type string. + * @author James Henry + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +var rule = require("../../../lib/rules/restrict-plus-operands"), + RuleTester = require("eslint").RuleTester; + + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +var ruleTester = new RuleTester(); +ruleTester.run("restrict-plus-operands", rule, { + + valid: [ + { + code: "var foo = 1 + 1;", + parser: "typescript-eslint-parser" + }, + { + code: "var foo = '1' + '1';", + parser: "typescript-eslint-parser" + }, + ], + + invalid: [ + { + code: "var foo = '1' + 1;", + parser: "typescript-eslint-parser", + errors: [{ + message: "Cannot add a 'string' to a 'number'.", + line: 1, + column: 11 + }] + }, + { + code: "var foo = [] + {};", + parser: "typescript-eslint-parser", + errors: [{ + message: "'{}' is not a supported type for addition.", + line: 1, + column: 11 + }] + } + ] +}); From 3ede57303e83f28163869258a42912dcb575b1c6 Mon Sep 17 00:00:00 2001 From: Armano Date: Sat, 15 Dec 2018 22:23:04 +0100 Subject: [PATCH 2/6] restrict plus plus operands --- lib/rules/restrict-plus-operands.js | 106 ++++++-- package.json | 2 +- tests/lib/rules/restrict-plus-operands.js | 316 ++++++++++++++++++++-- tests/lib/rules/tsconfig.json | 13 + yarn.lock | 19 +- 5 files changed, 394 insertions(+), 62 deletions(-) create mode 100644 tests/lib/rules/tsconfig.json diff --git a/lib/rules/restrict-plus-operands.js b/lib/rules/restrict-plus-operands.js index 46d32f3..cb4f416 100644 --- a/lib/rules/restrict-plus-operands.js +++ b/lib/rules/restrict-plus-operands.js @@ -1,9 +1,12 @@ /** * @fileoverview When adding two variables, operands must both be of type number or of type string. * @author James Henry + * @author Armano */ "use strict"; +const util = require("../util"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -11,48 +14,91 @@ module.exports = { meta: { docs: { - description: "When adding two variables, operands must both be of type number or of type string.", - category: "TypeScript" + description: + "When adding two variables, operands must both be of type number or of type string.", + extraDescription: [util.tslintRule("restrict-plus-operands")], + category: "TypeScript", + url: util.metaDocsUrl("restrict-plus-operands"), + }, + schema: [], + messages: { + notNumbers: + "Operands of '+' operation must either be both strings or both numbers.", + notStrings: + "Operands of '+' operation must either be both strings or both numbers, consider using template literals." }, - schema: [] }, - create: function(context) { + create(context) { + function getTSNode(node) { + return ( + context.parserServices && + context.parserServices.esTreeNodeToTSNodeMap && + context.parserServices.esTreeNodeToTSNodeMap.get(node) + ); + } + + function getTypeChecker() { + return ( + context.parserServices && + context.parserServices.program && + context.parserServices.program.getTypeChecker() + ); + } + + function getNodeType(node) { + const tsNode = getTSNode(node); + const typeChecker = getTypeChecker(); + + if (tsNode && typeChecker) { + const type = typeChecker.getTypeAtLocation(tsNode); + + if (type) { + if (type.isNumberLiteral() || type.flags & 32 || type.flags & 2) { + return "number"; + } + if (type.isStringLiteral() || type.flags & 64 || type.flags & 4) { + return "string"; + } + } + const stringType = typeChecker.typeToString(type); + + if (stringType === "number" || stringType === "number") { + return stringType; + } + return "invalid"; + } + return null; + } //---------------------------------------------------------------------- // Public //---------------------------------------------------------------------- return { - BinaryExpression(node) { - - var ts = context.parserServices.ts; - var tsNode = context.parserServices.getTSNode(node); - - if (tsNode.operatorToken.kind === ts.SyntaxKind.PlusToken) { + "BinaryExpression[operator='+']"(node) { + if (node.right && node.left) { + const rightType = getNodeType(node.right); + const leftType = getNodeType(node.left); - var program = context.parserServices.getCurrentProgram(); - var tc = program.getTypeChecker(); - var leftType = tc.typeToString(tc.getTypeAtLocation(tsNode.left)); - var rightType = tc.typeToString(tc.getTypeAtLocation(tsNode.right)); - - if (leftType !== rightType) { - context.report({ - node: node, - message: "Cannot add a '" + leftType + "' to a '" + rightType + "'." - }); - return; + if (!rightType || !leftType) { + return; // when there is no parser service } - if (leftType !== "number" && leftType !== "string") { - context.report({ - node: node, - message: "'" + leftType + "' is not a supported type for addition." - }); - return; + if (leftType === "invalid" || rightType === "invalid" || leftType !== rightType) { + if (leftType === "string" || rightType === "string") { + context.report({ + node, + messageId: "notStrings", + }); + } else { + context.report({ + node, + messageId: "notNumbers", + }); + } } - } - } + }, }; - } + }, }; diff --git a/package.json b/package.json index 67635df..a90e6ae 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "requireindex": "^1.2.0", - "typescript-eslint-parser": "21.0.2" + "typescript-eslint-parser": "git+https://github.com/uniqueiniquity/typescript-eslint-parser.git#0625f29a9721c6f10a7522de6c9d236a671bd1ac" }, "devDependencies": { "eslint": "^5.9.0", diff --git a/tests/lib/rules/restrict-plus-operands.js b/tests/lib/rules/restrict-plus-operands.js index 791fbb8..269c2e2 100644 --- a/tests/lib/rules/restrict-plus-operands.js +++ b/tests/lib/rules/restrict-plus-operands.js @@ -1,53 +1,327 @@ /** * @fileoverview When adding two variables, operands must both be of type number or of type string. * @author James Henry + * @author Armano */ "use strict"; //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ +const path = require("path"); -var rule = require("../../../lib/rules/restrict-plus-operands"), +const rule = require("../../../lib/rules/restrict-plus-operands"), RuleTester = require("eslint").RuleTester; - //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ -var ruleTester = new RuleTester(); -ruleTester.run("restrict-plus-operands", rule, { +const ruleTester = new RuleTester({ + parser: "typescript-eslint-parser", + parserOptions: { + generateServices: true, + project: path.join(__dirname, "tsconfig.json"), + tsconfigRootDir: path.resolve(__dirname), + }, +}); +console.log(__dirname); + +ruleTester.run("restrict-plus-operands", rule, { valid: [ + { + code: `var x = 5;`, + }, + { + code: `var y = "10";`, + }, + { + code: `var z = 8.2;`, + }, + { + code: `var w = "6.5";`, + }, + { + code: `var foo = 5 + 10;`, + }, + { + code: `var foo = "5.5" + "10";`, + }, + { + code: ` +/// +var foo = parseFloat("5.5", 10) + 10; + `, + }, + { + code: ` + var x = 5; + var z = 8.2; + var foo = x + z; + `, + }, + { + code: ` + var w = "6.5"; + var y = "10"; + var foo = y + w; + `, + }, { code: "var foo = 1 + 1;", - parser: "typescript-eslint-parser" }, { code: "var foo = '1' + '1';", - parser: "typescript-eslint-parser" + }, + { + code: ` +var pair: { first: number, second: string } = { + first: 5, + second: "10" +}; +var foo = pair.first + 10; + `, + }, + { + code: ` +var pair: { first: number, second: string } = { + first: 5, + second: "10" +}; +var foo = pair.first + (10 as number); + `, + }, + { + code: ` +var pair: { first: number, second: string } = { + first: 5, + second: "10" +}; +var foo = "5.5" + pair.second; + `, + }, + { + code: ` +var pair: { first: number, second: string } = { + first: 5, + second: "10" +}; +var foo = ("5.5" as string) + pair.second; + `, + }, + { + code: `const foo = 'hello' + (someBoolean ? 'a' : 'b') + (() => someBoolean ? 'c' : 'd')() + 'e';`, + }, + { + code: `const balls = true;`, + }, + { + code: `balls === true;`, }, ], - invalid: [ { code: "var foo = '1' + 1;", - parser: "typescript-eslint-parser", - errors: [{ - message: "Cannot add a 'string' to a 'number'.", - line: 1, - column: 11 - }] + errors: [ + { + messageId: "notStrings", + line: 1, + column: 11, + }, + ], }, { code: "var foo = [] + {};", - parser: "typescript-eslint-parser", - errors: [{ - message: "'{}' is not a supported type for addition.", - line: 1, - column: 11 - }] - } - ] + errors: [ + { + messageId: "notNumbers", + line: 1, + column: 11, + }, + ], + }, + { + code: `var foo = 5 + "10";`, + errors: [ + { + messageId: "notStrings", + line: 1, + column: 11, + }, + ], + }, + { + code: `var foo = [] + 5;`, + errors: [ + { + messageId: "notNumbers", + line: 1, + column: 11, + }, + ], + }, + { + code: `var foo = [] + {};`, + errors: [ + { + messageId: "notNumbers", + line: 1, + column: 11, + }, + ], + }, + { + code: `var foo = [] + [];`, + errors: [ + { + messageId: "notNumbers", + line: 1, + column: 11, + }, + ], + }, + { + code: `var foo = 5 + [];`, + errors: [ + { + messageId: "notNumbers", + line: 1, + column: 11, + }, + ], + }, + { + code: `var foo = "5" + {};`, + errors: [ + { + messageId: "notStrings", + line: 1, + column: 11, + }, + ], + }, + { + code: `var foo = 5.5 + "5";`, + errors: [ + { + messageId: "notStrings", + line: 1, + column: 11, + }, + ], + }, + { + code: `var foo = "5.5" + 5;`, + errors: [ + { + messageId: "notStrings", + line: 1, + column: 11, + }, + ], + }, + { + code: ` +var x = 5; +var y = "10"; +var foo = x + y; + `, + errors: [ + { + messageId: "notStrings", + line: 4, + column: 11, + }, + ], + }, + { + code: ` +var x = 5; +var y = "10"; +var foo = y + x; + `, + errors: [ + { + messageId: "notStrings", + line: 4, + column: 11, + }, + ], + }, + { + code: ` +var x = 5; +var foo = x + {}; + `, + errors: [ + { + messageId: "notNumbers", + line: 3, + column: 11, + }, + ], + }, + { + code: ` +var y = "10"; +var foo = [] + y; + `, + errors: [ + { + messageId: "notStrings", + line: 3, + column: 11, + }, + ], + }, + { + code: ` +var pair: { first: number, second: string } = { + first: 5, + second: "10" +}; +var foo = pair.first + "10"; + `, + errors: [ + { + messageId: "notStrings", + line: 6, + column: 11, + }, + ], + }, + { + code: ` +var pair: { first: number, second: string } = { + first: 5, + second: "10" +}; +var foo = 5 + pair.second; + `, + errors: [ + { + messageId: "notStrings", + line: 6, + column: 11, + }, + ], + }, + { + code: ` +var pair: { first: number, second: string } = { + first: 5, + second: "10" +}; +var foo = pair + pair; + `, + errors: [ + { + messageId: "notNumbers", + line: 6, + column: 11, + }, + ], + }, + ], }); diff --git a/tests/lib/rules/tsconfig.json b/tests/lib/rules/tsconfig.json new file mode 100644 index 0000000..220c3aa --- /dev/null +++ b/tests/lib/rules/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "lib": [ + "es2015", + "dom", + "es2017" + ] + } +} diff --git a/yarn.lock b/yarn.lock index 6c516a3..1eb4f4d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2472,7 +2472,7 @@ require-uncached@^1.0.3: caller-path "^0.1.0" resolve-from "^1.0.0" -requireindex@~1.2.0: +requireindex@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== @@ -2976,15 +2976,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-eslint-parser@21.0.2: - version "21.0.2" - resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-21.0.2.tgz#270af10e4724528677fbcf34ea495284bec3a894" - integrity sha512-u+pj4RVJBr4eTzj0n5npoXD/oRthvfUCjSKndhNI714MG0mQq2DJw5WP7qmonRNIFgmZuvdDOH3BHm9iOjIAfg== - dependencies: - eslint-scope "^4.0.0" - eslint-visitor-keys "^1.0.0" - typescript-estree "5.3.0" - typescript-eslint-parser@^16.0.0: version "16.0.1" resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-16.0.1.tgz#b40681c7043b222b9772748b700a000b241c031b" @@ -2993,6 +2984,14 @@ typescript-eslint-parser@^16.0.0: lodash.unescape "4.0.1" semver "5.5.0" +"typescript-eslint-parser@git+https://github.com/uniqueiniquity/typescript-eslint-parser.git#0625f29a9721c6f10a7522de6c9d236a671bd1ac": + version "21.0.2" + resolved "git+https://github.com/uniqueiniquity/typescript-eslint-parser.git#0625f29a9721c6f10a7522de6c9d236a671bd1ac" + dependencies: + eslint-scope "^4.0.0" + eslint-visitor-keys "^1.0.0" + typescript-estree "5.3.0" + typescript-estree@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/typescript-estree/-/typescript-estree-5.3.0.tgz#fb6c977b5e21073eb16cbdc0338a7f752da99ff5" From 261d567eae22e339701be44eb3a26850f7d583c3 Mon Sep 17 00:00:00 2001 From: Armano Date: Sat, 15 Dec 2018 23:05:26 +0100 Subject: [PATCH 3/6] simlify code & fix most of test cases --- README.md | 1 + docs/rules/restrict-plus-operands.md | 1 + lib/rules/restrict-plus-operands.js | 92 ++++++++++++----------- tests/lib/rules/restrict-plus-operands.js | 62 ++++++--------- 4 files changed, 73 insertions(+), 83 deletions(-) create mode 100644 docs/rules/restrict-plus-operands.md diff --git a/README.md b/README.md index 552b781..9bd641a 100644 --- a/README.md +++ b/README.md @@ -76,5 +76,6 @@ This guarantees 100% compatibility between the plugin and the parser. * [`typescript/no-use-before-define`](./docs/rules/no-use-before-define.md) — Disallow the use of variables before they are defined * [`typescript/no-var-requires`](./docs/rules/no-var-requires.md) — Disallows the use of require statements except in import statements (`no-var-requires` from TSLint) * [`typescript/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) — Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules. (`no-internal-module` from TSLint) +* [`typescript/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) — When adding two variables, operands must both be of type number or of type string. (`restrict-plus-operands` from TSLint) * [`typescript/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) — Require consistent spacing around type annotations (`typedef-whitespace` from TSLint) diff --git a/docs/rules/restrict-plus-operands.md b/docs/rules/restrict-plus-operands.md new file mode 100644 index 0000000..00da725 --- /dev/null +++ b/docs/rules/restrict-plus-operands.md @@ -0,0 +1 @@ +# When adding two variables, operands must both be of type number or of type string. (restrict-plus-operands) diff --git a/lib/rules/restrict-plus-operands.js b/lib/rules/restrict-plus-operands.js index cb4f416..0848fb8 100644 --- a/lib/rules/restrict-plus-operands.js +++ b/lib/rules/restrict-plus-operands.js @@ -20,55 +20,63 @@ module.exports = { category: "TypeScript", url: util.metaDocsUrl("restrict-plus-operands"), }, - schema: [], messages: { notNumbers: "Operands of '+' operation must either be both strings or both numbers.", notStrings: - "Operands of '+' operation must either be both strings or both numbers, consider using template literals." + "Operands of '+' operation must either be both strings or both numbers, consider using template literals.", }, + schema: [], }, create(context) { - function getTSNode(node) { - return ( - context.parserServices && - context.parserServices.esTreeNodeToTSNodeMap && - context.parserServices.esTreeNodeToTSNodeMap.get(node) - ); - } + const typeChecker = + context.parserServices && + context.parserServices.program && + context.parserServices.program.getTypeChecker(); - function getTypeChecker() { - return ( - context.parserServices && - context.parserServices.program && - context.parserServices.program.getTypeChecker() - ); - } + const TSNodeMap = + context.parserServices && + context.parserServices.esTreeNodeToTSNodeMap; - function getNodeType(node) { - const tsNode = getTSNode(node); - const typeChecker = getTypeChecker(); + /** + * Helper function to get base type of node + * @param {ts.Type} type type to be evaluated + * @returns {*} string, number or invalid + */ + function getBaseTypeOfLiteralType(type) { + if (type.isNumberLiteral()) { + return "number"; + } + if (type.isStringLiteral()) { + return "string"; + } + if (type.isUnion()) { + const types = type.types.map(getBaseTypeOfLiteralType); - if (tsNode && typeChecker) { - const type = typeChecker.getTypeAtLocation(tsNode); + return types.every(value => value === types[0]) + ? types[0] + : "invalid"; + } - if (type) { - if (type.isNumberLiteral() || type.flags & 32 || type.flags & 2) { - return "number"; - } - if (type.isStringLiteral() || type.flags & 64 || type.flags & 4) { - return "string"; - } - } - const stringType = typeChecker.typeToString(type); + const stringType = typeChecker.typeToString(type); - if (stringType === "number" || stringType === "number") { - return stringType; - } - return "invalid"; + if (stringType === "number" || stringType === "string") { + return stringType; } - return null; + return "invalid"; + } + + /** + * Helper function to get base type of node + * @param {ASTNode} node the node to be evaluated. + * @returns {*} string, number or invalid + */ + function getNodeType(node) { + const tsNode = TSNodeMap.get(node); + const type = typeChecker.getTypeAtLocation(tsNode); + + return getBaseTypeOfLiteralType(type); } //---------------------------------------------------------------------- @@ -76,15 +84,15 @@ module.exports = { //---------------------------------------------------------------------- return { "BinaryExpression[operator='+']"(node) { - if (node.right && node.left) { - const rightType = getNodeType(node.right); + if (typeChecker && TSNodeMap) { const leftType = getNodeType(node.left); + const rightType = getNodeType(node.right); - if (!rightType || !leftType) { - return; // when there is no parser service - } - - if (leftType === "invalid" || rightType === "invalid" || leftType !== rightType) { + if ( + leftType === "invalid" || + rightType === "invalid" || + leftType !== rightType + ) { if (leftType === "string" || rightType === "string") { context.report({ node, diff --git a/tests/lib/rules/restrict-plus-operands.js b/tests/lib/rules/restrict-plus-operands.js index 269c2e2..627ee1a 100644 --- a/tests/lib/rules/restrict-plus-operands.js +++ b/tests/lib/rules/restrict-plus-operands.js @@ -26,8 +26,6 @@ const ruleTester = new RuleTester({ }, }); -console.log(__dirname); - ruleTester.run("restrict-plus-operands", rule, { valid: [ { @@ -48,24 +46,27 @@ ruleTester.run("restrict-plus-operands", rule, { { code: `var foo = "5.5" + "10";`, }, + { + code: `var foo = parseFloat("5.5", 10) + 10;`, + }, { code: ` -/// -var foo = parseFloat("5.5", 10) + 10; +function test () : number { return 2; } +var foo = test("5.5", 10) + 10; `, }, { code: ` - var x = 5; - var z = 8.2; - var foo = x + z; +var x = 5; +var z = 8.2; +var foo = x + z; `, }, { code: ` - var w = "6.5"; - var y = "10"; - var foo = y + w; +var w = "6.5"; +var y = "10"; +var foo = y + w; `, }, { @@ -76,37 +77,25 @@ var foo = parseFloat("5.5", 10) + 10; }, { code: ` -var pair: { first: number, second: string } = { - first: 5, - second: "10" -}; +var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = pair.first + 10; `, }, { code: ` -var pair: { first: number, second: string } = { - first: 5, - second: "10" -}; +var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = pair.first + (10 as number); `, }, { code: ` -var pair: { first: number, second: string } = { - first: 5, - second: "10" -}; +var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = "5.5" + pair.second; `, }, { code: ` -var pair: { first: number, second: string } = { - first: 5, - second: "10" -}; +var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = ("5.5" as string) + pair.second; `, }, @@ -277,48 +266,39 @@ var foo = [] + y; }, { code: ` -var pair: { first: number, second: string } = { - first: 5, - second: "10" -}; +var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = pair.first + "10"; `, errors: [ { messageId: "notStrings", - line: 6, + line: 3, column: 11, }, ], }, { code: ` -var pair: { first: number, second: string } = { - first: 5, - second: "10" -}; +var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = 5 + pair.second; `, errors: [ { messageId: "notStrings", - line: 6, + line: 3, column: 11, }, ], }, { code: ` -var pair: { first: number, second: string } = { - first: 5, - second: "10" -}; +var pair = { first: 5, second: "10" }; var foo = pair + pair; `, errors: [ { messageId: "notNumbers", - line: 6, + line: 3, column: 11, }, ], From 3fb7f064986fb45821f2b34cdaed0a6a04576a55 Mon Sep 17 00:00:00 2001 From: Armano Date: Sun, 16 Dec 2018 01:29:39 +0100 Subject: [PATCH 4/6] valid filePath is required to get access to lib --- tests/lib/fixtures/empty/empty.ts | 0 .../{rules => fixtures/empty}/tsconfig.json | 1 - tests/lib/rules/restrict-plus-operands.js | 25 +++++++++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 tests/lib/fixtures/empty/empty.ts rename tests/lib/{rules => fixtures/empty}/tsconfig.json (91%) diff --git a/tests/lib/fixtures/empty/empty.ts b/tests/lib/fixtures/empty/empty.ts new file mode 100644 index 0000000..e69de29 diff --git a/tests/lib/rules/tsconfig.json b/tests/lib/fixtures/empty/tsconfig.json similarity index 91% rename from tests/lib/rules/tsconfig.json rename to tests/lib/fixtures/empty/tsconfig.json index 220c3aa..412bf8e 100644 --- a/tests/lib/rules/tsconfig.json +++ b/tests/lib/fixtures/empty/tsconfig.json @@ -6,7 +6,6 @@ "esModuleInterop": true, "lib": [ "es2015", - "dom", "es2017" ] } diff --git a/tests/lib/rules/restrict-plus-operands.js b/tests/lib/rules/restrict-plus-operands.js index 627ee1a..c8c1e1a 100644 --- a/tests/lib/rules/restrict-plus-operands.js +++ b/tests/lib/rules/restrict-plus-operands.js @@ -17,12 +17,17 @@ const rule = require("../../../lib/rules/restrict-plus-operands"), // Tests //------------------------------------------------------------------------------ +const rootPath = path.join(process.cwd(), "tests/lib/fixtures/empty"); +// valid filePath is required to get access to lib +// @see https://github.com/JamesHenry/typescript-estree/issues/50 +const filePath = path.join(rootPath, "empty.ts"); + const ruleTester = new RuleTester({ parser: "typescript-eslint-parser", parserOptions: { generateServices: true, - project: path.join(__dirname, "tsconfig.json"), - tsconfigRootDir: path.resolve(__dirname), + tsconfigRootDir: rootPath, + project: "./tsconfig.json", }, }); @@ -47,6 +52,11 @@ ruleTester.run("restrict-plus-operands", rule, { code: `var foo = "5.5" + "10";`, }, { + filename: filePath, + code: `var foo = parseInt("5.5", 10) + 10;`, + }, + { + filename: filePath, code: `var foo = parseFloat("5.5", 10) + 10;`, }, { @@ -290,6 +300,17 @@ var foo = 5 + pair.second; }, ], }, + { + filename: filePath, + code: `var foo = parseInt("5.5", 10) + "10";`, + errors: [ + { + messageId: "notStrings", + line: 1, + column: 11, + }, + ], + }, { code: ` var pair = { first: 5, second: "10" }; From 735ec84bb44fc604f9d028974815b0e18ea7be34 Mon Sep 17 00:00:00 2001 From: Armano Date: Tue, 18 Dec 2018 00:00:55 +0100 Subject: [PATCH 5/6] Fix merge conflict --- tests/lib/rules/restrict-plus-operands.js | 72 ++++++----------------- 1 file changed, 18 insertions(+), 54 deletions(-) diff --git a/tests/lib/rules/restrict-plus-operands.js b/tests/lib/rules/restrict-plus-operands.js index c8c1e1a..e1e5052 100644 --- a/tests/lib/rules/restrict-plus-operands.js +++ b/tests/lib/rules/restrict-plus-operands.js @@ -33,24 +33,12 @@ const ruleTester = new RuleTester({ ruleTester.run("restrict-plus-operands", rule, { valid: [ - { - code: `var x = 5;`, - }, - { - code: `var y = "10";`, - }, - { - code: `var z = 8.2;`, - }, - { - code: `var w = "6.5";`, - }, - { - code: `var foo = 5 + 10;`, - }, - { - code: `var foo = "5.5" + "10";`, - }, + `var x = 5;`, + `var y = "10";`, + `var z = 8.2;`, + `var w = "6.5";`, + `var foo = 5 + 10;`, + `var foo = "5.5" + "10";`, { filename: filePath, code: `var foo = parseInt("5.5", 10) + 10;`, @@ -59,65 +47,41 @@ ruleTester.run("restrict-plus-operands", rule, { filename: filePath, code: `var foo = parseFloat("5.5", 10) + 10;`, }, - { - code: ` + ` function test () : number { return 2; } var foo = test("5.5", 10) + 10; `, - }, - { - code: ` + ` var x = 5; var z = 8.2; var foo = x + z; `, - }, - { - code: ` + ` var w = "6.5"; var y = "10"; var foo = y + w; `, - }, - { - code: "var foo = 1 + 1;", - }, - { - code: "var foo = '1' + '1';", - }, - { - code: ` + "var foo = 1 + 1;", + "var foo = '1' + '1';", + ` var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = pair.first + 10; `, - }, - { - code: ` + ` var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = pair.first + (10 as number); `, - }, - { - code: ` + ` var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = "5.5" + pair.second; `, - }, - { - code: ` + ` var pair: { first: number, second: string } = { first: 5, second: "10" }; var foo = ("5.5" as string) + pair.second; `, - }, - { - code: `const foo = 'hello' + (someBoolean ? 'a' : 'b') + (() => someBoolean ? 'c' : 'd')() + 'e';`, - }, - { - code: `const balls = true;`, - }, - { - code: `balls === true;`, - }, + `const foo = 'hello' + (someBoolean ? 'a' : 'b') + (() => someBoolean ? 'c' : 'd')() + 'e';`, + `const balls = true;`, + `balls === true;`, ], invalid: [ { From 7de6524348a6f27e44c35f0b703ea7ab4bc030e3 Mon Sep 17 00:00:00 2001 From: Armano Date: Tue, 18 Dec 2018 21:15:46 +0100 Subject: [PATCH 6/6] FIx issues after merge --- lib/rules/restrict-plus-operands.js | 1 + tests/lib/fixtures/empty/tsconfig.json | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/rules/restrict-plus-operands.js b/lib/rules/restrict-plus-operands.js index 0848fb8..7e71515 100644 --- a/lib/rules/restrict-plus-operands.js +++ b/lib/rules/restrict-plus-operands.js @@ -13,6 +13,7 @@ const util = require("../util"); module.exports = { meta: { + type: "problem", docs: { description: "When adding two variables, operands must both be of type number or of type string.", diff --git a/tests/lib/fixtures/empty/tsconfig.json b/tests/lib/fixtures/empty/tsconfig.json index 412bf8e..2dd72f8 100644 --- a/tests/lib/fixtures/empty/tsconfig.json +++ b/tests/lib/fixtures/empty/tsconfig.json @@ -4,9 +4,6 @@ "module": "commonjs", "strict": true, "esModuleInterop": true, - "lib": [ - "es2015", - "es2017" - ] + "lib": ["es2015", "es2017"] } }