diff --git a/package.json b/package.json index 17e77cb7..666443cf 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@types/mocha": "^5.2.4", "@types/node": "^10.12.21", "@typescript-eslint/eslint-plugin": "^4.9.1", - "@typescript-eslint/parser": "^4.7.0", + "@typescript-eslint/parser": "^4.14.0", "babel-eslint": "^10.0.1", "chokidar": "^2.0.4", "codecov": "^3.1.0", @@ -47,6 +47,7 @@ "rollup": "^1.1.2", "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-sourcemaps": "^0.4.2", + "semver": "^7.3.4", "ts-node": "^8.1.0", "typescript": "~4.0.5", "wait-on": "^3.2.0", diff --git a/src/script/index.ts b/src/script/index.ts index 19f5bbf8..af250027 100644 --- a/src/script/index.ts +++ b/src/script/index.ts @@ -47,7 +47,7 @@ import { fixLocations } from "../common/fix-locations" // [1] = aliases. // [2] = delimiter. // [3] = iterator. -const ALIAS_ITERATOR = /^([\s\S]*?(?:\s|\)))(\bin|of\b)([\s\S]*)$/u +const ALIAS_ITERATOR = /^([\s\S]*?(?:\s|\)))(\bin\b|\bof\b)([\s\S]*)$/u const PARENS = /^(\s*\()([\s\S]*?)(\)\s*)$/u const DUMMY_PARENT: any = {} diff --git a/test/fixtures/ast/v-for-directives-index/ast.json b/test/fixtures/ast/v-for-directives-index/ast.json new file mode 100644 index 00000000..36768789 --- /dev/null +++ b/test/fixtures/ast/v-for-directives-index/ast.json @@ -0,0 +1,815 @@ +{ + "type": "Program", + "start": 0, + "end": 0, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 0 + } + }, + "range": [ + 0, + 0 + ], + "body": [], + "sourceType": "script", + "comments": [], + "tokens": [], + "templateBody": { + "type": "VElement", + "range": [ + 0, + 65 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "name": "template", + "rawName": "template", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 0, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "selfClosing": false, + "attributes": [] + }, + "children": [ + { + "type": "VText", + "range": [ + 10, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 2, + "column": 4 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 15, + 53 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 42 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 15, + 47 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 36 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 20, + 46 + ], + "loc": { + "start": { + "line": 2, + "column": 9 + }, + "end": { + "line": 2, + "column": 35 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 20, + 25 + ], + "loc": { + "start": { + "line": 2, + "column": 9 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 20, + 25 + ], + "loc": { + "start": { + "column": 9, + "line": 2 + }, + "end": { + "column": 14, + "line": 2 + } + }, + "name": "for", + "rawName": "for" + }, + "argument": null, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 26, + 46 + ], + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 2, + "column": 35 + } + }, + "expression": { + "type": "VForExpression", + "range": [ + 27, + 45 + ], + "loc": { + "start": { + "line": 2, + "column": 16 + }, + "end": { + "line": 2, + "column": 34 + } + }, + "left": [ + { + "type": "Identifier", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "range": [ + 28, + 29 + ], + "name": "a" + }, + { + "type": "Identifier", + "start": 31, + "end": 36, + "loc": { + "start": { + "line": 2, + "column": 20 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "range": [ + 31, + 36 + ], + "name": "index" + } + ], + "right": { + "type": "Identifier", + "start": 41, + "end": 45, + "loc": { + "start": { + "line": 2, + "column": 30 + }, + "end": { + "line": 2, + "column": 34 + } + }, + "range": [ + 41, + 45 + ], + "name": "list" + } + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 41, + "end": 45, + "loc": { + "start": { + "line": 2, + "column": 30 + }, + "end": { + "line": 2, + "column": 34 + } + }, + "range": [ + 41, + 45 + ], + "name": "list" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 47, + 53 + ], + "loc": { + "start": { + "line": 2, + "column": 36 + }, + "end": { + "line": 2, + "column": 42 + } + } + }, + "variables": [ + { + "id": { + "type": "Identifier", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "range": [ + 28, + 29 + ], + "name": "a" + }, + "kind": "v-for" + }, + { + "id": { + "type": "Identifier", + "start": 31, + "end": 36, + "loc": { + "start": { + "line": 2, + "column": 20 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "range": [ + 31, + 36 + ], + "name": "index" + }, + "kind": "v-for" + } + ] + }, + { + "type": "VText", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "line": 2, + "column": 42 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 54, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + } + }, + "variables": [], + "tokens": [ + { + "type": "HTMLTagOpen", + "range": [ + 0, + 9 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "value": "template" + }, + { + "type": "HTMLTagClose", + "range": [ + 9, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 10, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 2, + "column": 4 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 15, + 19 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLIdentifier", + "range": [ + 20, + 25 + ], + "loc": { + "start": { + "column": 9, + "line": 2 + }, + "end": { + "column": 14, + "line": 2 + } + }, + "value": "v-for" + }, + { + "type": "HTMLAssociation", + "range": [ + 25, + 26 + ], + "loc": { + "start": { + "line": 2, + "column": 14 + }, + "end": { + "line": 2, + "column": 15 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 26, + 27 + ], + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 2, + "column": 16 + } + }, + "value": "\"" + }, + { + "type": "Punctuator", + "value": "(", + "start": 27, + "end": 28, + "loc": { + "start": { + "line": 2, + "column": 16 + }, + "end": { + "line": 2, + "column": 17 + } + }, + "range": [ + 27, + 28 + ] + }, + { + "type": "Identifier", + "value": "a", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "range": [ + 28, + 29 + ] + }, + { + "type": "Punctuator", + "value": ",", + "start": 29, + "end": 30, + "loc": { + "start": { + "line": 2, + "column": 18 + }, + "end": { + "line": 2, + "column": 19 + } + }, + "range": [ + 29, + 30 + ] + }, + { + "type": "Identifier", + "value": "index", + "start": 31, + "end": 36, + "loc": { + "start": { + "line": 2, + "column": 20 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "range": [ + 31, + 36 + ] + }, + { + "type": "Punctuator", + "value": ")", + "start": 36, + "end": 37, + "loc": { + "start": { + "line": 2, + "column": 25 + }, + "end": { + "line": 2, + "column": 26 + } + }, + "range": [ + 36, + 37 + ] + }, + { + "type": "Keyword", + "value": "in", + "start": 38, + "end": 40, + "loc": { + "start": { + "line": 2, + "column": 27 + }, + "end": { + "line": 2, + "column": 29 + } + }, + "range": [ + 38, + 40 + ] + }, + { + "type": "Identifier", + "value": "list", + "start": 41, + "end": 45, + "loc": { + "start": { + "line": 2, + "column": 30 + }, + "end": { + "line": 2, + "column": 34 + } + }, + "range": [ + 41, + 45 + ] + }, + { + "type": "Punctuator", + "range": [ + 45, + 46 + ], + "loc": { + "start": { + "line": 2, + "column": 34 + }, + "end": { + "line": 2, + "column": 35 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 46, + 47 + ], + "loc": { + "start": { + "line": 2, + "column": 35 + }, + "end": { + "line": 2, + "column": 36 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 47, + 52 + ], + "loc": { + "start": { + "line": 2, + "column": 36 + }, + "end": { + "line": 2, + "column": 41 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 52, + 53 + ], + "loc": { + "start": { + "line": 2, + "column": 41 + }, + "end": { + "line": 2, + "column": 42 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "line": 2, + "column": 42 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 54, + 64 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 10 + } + }, + "value": "template" + }, + { + "type": "HTMLTagClose", + "range": [ + 64, + 65 + ], + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 65, + 66 + ], + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 4, + "column": 0 + } + }, + "value": "\n" + } + ], + "comments": [], + "errors": [] + } +} \ No newline at end of file diff --git a/test/fixtures/ast/v-for-directives-index/source.vue b/test/fixtures/ast/v-for-directives-index/source.vue new file mode 100644 index 00000000..946b61bf --- /dev/null +++ b/test/fixtures/ast/v-for-directives-index/source.vue @@ -0,0 +1,3 @@ + diff --git a/test/fixtures/ast/v-for-directives-index/token-ranges.json b/test/fixtures/ast/v-for-directives-index/token-ranges.json new file mode 100644 index 00000000..7bd55315 --- /dev/null +++ b/test/fixtures/ast/v-for-directives-index/token-ranges.json @@ -0,0 +1,24 @@ +[ + "", + "\n ", + "", + "", + "\n", + "", + "\n" +] \ No newline at end of file diff --git a/test/fixtures/ast/v-for-directives-index/tree.json b/test/fixtures/ast/v-for-directives-index/tree.json new file mode 100644 index 00000000..a58a5eba --- /dev/null +++ b/test/fixtures/ast/v-for-directives-index/tree.json @@ -0,0 +1,89 @@ +[ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + } +] \ No newline at end of file diff --git a/test/index.js b/test/index.js index 4c82264a..95a48edd 100644 --- a/test/index.js +++ b/test/index.js @@ -12,6 +12,7 @@ const assert = require("assert") const path = require("path") const fs = require("fs-extra") +const semver = require("semver") const parse = require("../src").parse const parseForESLint = require("../src").parseForESLint const eslint = require("./fixtures/eslint") @@ -232,22 +233,24 @@ describe("Basic tests", () => { assert(messages.length === 0) }) - it("should notify no error with '@typescript-eslint/parser'", () => { - const cli = new CLIEngine({ - cwd: FIXTURE_DIR, - envs: ["es6", "node"], - parser: PARSER_PATH, - parserOptions: { - parser: "@typescript-eslint/parser", - }, - rules: { semi: ["error", "never"] }, - useEslintrc: false, - }) - const report = cli.executeOnFiles(["typed.js"]) - const messages = report.results[0].messages + if (semver.gte(process.version, "10.0.0")) { + it("should notify no error with '@typescript-eslint/parser'", () => { + const cli = new CLIEngine({ + cwd: FIXTURE_DIR, + envs: ["es6", "node"], + parser: PARSER_PATH, + parserOptions: { + parser: "@typescript-eslint/parser", + }, + rules: { semi: ["error", "never"] }, + useEslintrc: false, + }) + const report = cli.executeOnFiles(["typed.js"]) + const messages = report.results[0].messages - assert(messages.length === 0) - }) + assert(messages.length === 0) + }) + } }) describe("About fixtures/typed.vue", () => { @@ -269,22 +272,24 @@ describe("Basic tests", () => { assert(messages.length === 0) }) - it("should notify no error with '@typescript-eslint/parser'", () => { - const cli = new CLIEngine({ - cwd: FIXTURE_DIR, - envs: ["es6", "node"], - parser: PARSER_PATH, - parserOptions: { - parser: "@typescript-eslint/parser", - }, - rules: { semi: ["error", "never"] }, - useEslintrc: false, - }) - const report = cli.executeOnFiles(["typed.vue"]) - const messages = report.results[0].messages + if (semver.gte(process.version, "10.0.0")) { + it("should notify no error with '@typescript-eslint/parser'", () => { + const cli = new CLIEngine({ + cwd: FIXTURE_DIR, + envs: ["es6", "node"], + parser: PARSER_PATH, + parserOptions: { + parser: "@typescript-eslint/parser", + }, + rules: { semi: ["error", "never"] }, + useEslintrc: false, + }) + const report = cli.executeOnFiles(["typed.vue"]) + const messages = report.results[0].messages - assert(messages.length === 0) - }) + assert(messages.length === 0) + }) + } it("should fix 'semi' errors with --fix option with 'babel-eslint'", () => { const cli = new CLIEngine({ @@ -313,55 +318,59 @@ describe("Basic tests", () => { assert(actual === expected) }) - it("should fix 'semi' errors with --fix option with '@typescript-eslint/parser'", () => { - const cli = new CLIEngine({ - cwd: FIXTURE_DIR, - envs: ["es6", "node"], - fix: true, - parser: PARSER_PATH, - parserOptions: { - parser: "@typescript-eslint/parser", - }, - rules: { semi: ["error", "always"] }, - useEslintrc: false, + if (semver.gte(process.version, "10.0.0")) { + it("should fix 'semi' errors with --fix option with '@typescript-eslint/parser'", () => { + const cli = new CLIEngine({ + cwd: FIXTURE_DIR, + envs: ["es6", "node"], + fix: true, + parser: PARSER_PATH, + parserOptions: { + parser: "@typescript-eslint/parser", + }, + rules: { semi: ["error", "always"] }, + useEslintrc: false, + }) + CLIEngine.outputFixes(cli.executeOnFiles(["typed.vue"])) + + const actual = fs.readFileSync( + path.join(FIXTURE_DIR, "typed.vue"), + "utf8" + ) + const expected = fs.readFileSync( + path.join(FIXTURE_DIR, "typed.vue.fixed"), + "utf8" + ) + + assert(actual === expected) }) - CLIEngine.outputFixes(cli.executeOnFiles(["typed.vue"])) - - const actual = fs.readFileSync( - path.join(FIXTURE_DIR, "typed.vue"), - "utf8" - ) - const expected = fs.readFileSync( - path.join(FIXTURE_DIR, "typed.vue.fixed"), - "utf8" - ) - - assert(actual === expected) - }) + } }) - describe("About fixtures/ts-scope-manager.vue", () => { - it("should calculate the correct location with '@typescript-eslint/parser'", () => { - const cli = new CLIEngine({ - cwd: FIXTURE_DIR, - envs: ["es6", "node"], - parser: PARSER_PATH, - parserOptions: { - parser: "@typescript-eslint/parser", - }, - rules: { "no-unused-vars": ["error"] }, - useEslintrc: false, + if (semver.gte(process.version, "10.0.0")) { + describe("About fixtures/ts-scope-manager.vue", () => { + it("should calculate the correct location with '@typescript-eslint/parser'", () => { + const cli = new CLIEngine({ + cwd: FIXTURE_DIR, + envs: ["es6", "node"], + parser: PARSER_PATH, + parserOptions: { + parser: "@typescript-eslint/parser", + }, + rules: { "no-unused-vars": ["error"] }, + useEslintrc: false, + }) + const report = cli.executeOnFiles(["ts-scope-manager.vue"]) + const messages = report.results[0].messages + + assert.strictEqual(messages.length, 1) + assert.deepStrictEqual(messages[0].line, 8) + assert.deepStrictEqual(messages[0].column, 8) + assert.deepStrictEqual(messages[0].endLine, 8) + assert.deepStrictEqual(messages[0].endColumn, 14) }) - const report = cli.executeOnFiles(["ts-scope-manager.vue"]) - const messages = report.results[0].messages - - assert.strictEqual(messages.length, 1) - assert.deepStrictEqual(messages[0].line, 8) - assert.deepStrictEqual(messages[0].column, 8) - assert.deepStrictEqual(messages[0].endLine, 8) - assert.deepStrictEqual(messages[0].endColumn, 14) }) - }) + } describe("About fixtures/svg-attrs.vue", () => { it("parses attributes with colons", () => {