From c50efb2eed8a68b94297797cad15618bea82566a Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 4 Sep 2021 11:02:55 +0900 Subject: [PATCH] Fix bug when script tags are missing and multiple parsers are used --- scripts/update-fixtures-ast.js | 7 + src/index.ts | 1 + test/ast.js | 13 + .../services.json | 11 + .../services.json | 7 + .../services.json | 11 + .../ast.json | 651 ++++++++++++++++++ .../parser-options.json | 11 + .../services.json | 11 + .../source.vue | 3 + .../token-ranges.json | 19 + .../tree.json | 50 ++ 12 files changed, 795 insertions(+) create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-1/services.json create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-2/services.json create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-3/services.json create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-without-script/ast.json create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-without-script/parser-options.json create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-without-script/services.json create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-without-script/source.vue create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-without-script/token-ranges.json create mode 100644 test/fixtures/ast/parser-option-multiple-parsers-without-script/tree.json diff --git a/scripts/update-fixtures-ast.js b/scripts/update-fixtures-ast.js index 2290ba28..4e67c62d 100644 --- a/scripts/update-fixtures-ast.js +++ b/scripts/update-fixtures-ast.js @@ -223,6 +223,7 @@ for (const name of TARGETS) { const tokenRangesPath = path.join(ROOT, `${name}/token-ranges.json`) const treePath = path.join(ROOT, `${name}/tree.json`) const scopePath = path.join(ROOT, `${name}/scope.json`) + const servicesPath = path.join(ROOT, `${name}/services.json`) const source = fs.readFileSync(sourcePath, "utf8") const options = Object.assign( { filePath: sourcePath }, @@ -249,4 +250,10 @@ for (const name of TARGETS) { scopeToJSON(actual.scopeManager || analyze(actual.ast, options)) ) } + if (fs.existsSync(servicesPath)) { + fs.writeFileSync( + servicesPath, + JSON.stringify(Object.keys(actual.services).sort(), null, 4) + ) + } } diff --git a/src/index.ts b/src/index.ts index 5c733379..6bf09da3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -115,6 +115,7 @@ export function parseForESLint( result = parseScript("", { ...options, ecmaVersion: options.ecmaVersion || DEFAULT_ECMA_VERSION, + parser: scriptParser, }) } else if ( scripts.length === 2 && diff --git a/test/ast.js b/test/ast.js index e5634442..f1ab77df 100644 --- a/test/ast.js +++ b/test/ast.js @@ -175,6 +175,7 @@ describe("Template AST", () => { const sourcePath = path.join(ROOT, `${name}/source.vue`) const optionsPath = path.join(ROOT, `${name}/parser-options.json`) const requirementsPath = path.join(ROOT, `${name}/requirements.json`) + const servicesPath = path.join(ROOT, `${name}/services.json`) const source = fs.readFileSync(sourcePath, "utf8") const parserOptions = fs.existsSync(optionsPath) ? JSON.parse(fs.readFileSync(optionsPath, "utf8")) @@ -182,6 +183,9 @@ describe("Template AST", () => { const requirements = fs.existsSync(requirementsPath) ? JSON.parse(fs.readFileSync(requirementsPath, "utf8")) : {} + const services = fs.existsSync(servicesPath) + ? JSON.parse(fs.readFileSync(servicesPath, "utf8")) + : null const options = Object.assign( { filePath: sourcePath }, PARSER_OPTIONS, @@ -293,6 +297,15 @@ describe("Template AST", () => { it("should have correct parent properties.", () => { validateParent(source, parserOptions) }) + + if (services) { + it("should have correct services.", () => { + assert.deepStrictEqual( + Object.keys(actual.services).sort(), + services + ) + }) + } }) } }) diff --git a/test/fixtures/ast/parser-option-multiple-parsers-1/services.json b/test/fixtures/ast/parser-option-multiple-parsers-1/services.json new file mode 100644 index 00000000..7159ba5a --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-1/services.json @@ -0,0 +1,11 @@ +[ + "defineCustomBlocksVisitor", + "defineDocumentVisitor", + "defineTemplateBodyVisitor", + "esTreeNodeToTSNodeMap", + "getDocumentFragment", + "getTemplateBodyTokenStore", + "hasFullTypeInformation", + "program", + "tsNodeToESTreeNodeMap" +] \ No newline at end of file diff --git a/test/fixtures/ast/parser-option-multiple-parsers-2/services.json b/test/fixtures/ast/parser-option-multiple-parsers-2/services.json new file mode 100644 index 00000000..1f6c7551 --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-2/services.json @@ -0,0 +1,7 @@ +[ + "defineCustomBlocksVisitor", + "defineDocumentVisitor", + "defineTemplateBodyVisitor", + "getDocumentFragment", + "getTemplateBodyTokenStore" +] \ No newline at end of file diff --git a/test/fixtures/ast/parser-option-multiple-parsers-3/services.json b/test/fixtures/ast/parser-option-multiple-parsers-3/services.json new file mode 100644 index 00000000..7159ba5a --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-3/services.json @@ -0,0 +1,11 @@ +[ + "defineCustomBlocksVisitor", + "defineDocumentVisitor", + "defineTemplateBodyVisitor", + "esTreeNodeToTSNodeMap", + "getDocumentFragment", + "getTemplateBodyTokenStore", + "hasFullTypeInformation", + "program", + "tsNodeToESTreeNodeMap" +] \ No newline at end of file diff --git a/test/fixtures/ast/parser-option-multiple-parsers-without-script/ast.json b/test/fixtures/ast/parser-option-multiple-parsers-without-script/ast.json new file mode 100644 index 00000000..b7deda38 --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-without-script/ast.json @@ -0,0 +1,651 @@ +{ + "type": "Program", + "body": [], + "sourceType": "module", + "range": [ + 0, + 0 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 0 + } + }, + "tokens": [], + "comments": [], + "templateBody": { + "type": "VElement", + "range": [ + 0, + 38 + ], + "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, + 13 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VExpressionContainer", + "range": [ + 13, + 26 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 15 + } + }, + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "a", + "range": [ + 15, + 16 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 5 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "d", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 12 + } + } + } + ], + "optional": false, + "range": [ + 15, + 24 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "typeParameters": { + "type": "TSTypeParameterInstantiation", + "range": [ + 16, + 21 + ], + "params": [ + { + "type": "TSUnionType", + "types": [ + { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "b", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + } + } + }, + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + } + } + }, + { + "type": "TSTypeReference", + "typeName": { + "type": "Identifier", + "name": "c", + "range": [ + 19, + 20 + ], + "loc": { + "start": { + "line": 2, + "column": 8 + }, + "end": { + "line": 2, + "column": 9 + } + } + }, + "range": [ + 19, + 20 + ], + "loc": { + "start": { + "line": 2, + "column": 8 + }, + "end": { + "line": 2, + "column": 9 + } + } + } + ], + "range": [ + 17, + 20 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 9 + } + } + } + ], + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 10 + } + } + } + }, + "references": [ + { + "id": { + "type": "Identifier", + "name": "a", + "range": [ + 15, + 16 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 5 + } + } + }, + "mode": "r" + }, + { + "id": { + "type": "Identifier", + "name": "d", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + "mode": "r" + } + ] + }, + { + "type": "VText", + "range": [ + 26, + 27 + ], + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 27, + 38 + ], + "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, + 13 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VExpressionStart", + "range": [ + 13, + 15 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 4 + } + }, + "value": "{{" + }, + { + "type": "Identifier", + "value": "a", + "range": [ + 15, + 16 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 5 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 16, + 17 + ], + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 6 + } + } + }, + { + "type": "Identifier", + "value": "b", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + } + } + }, + { + "type": "Punctuator", + "value": "|", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 8 + } + } + }, + { + "type": "Identifier", + "value": "c", + "range": [ + 19, + 20 + ], + "loc": { + "start": { + "line": 2, + "column": 8 + }, + "end": { + "line": 2, + "column": 9 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 2, + "column": 9 + }, + "end": { + "line": 2, + "column": 10 + } + } + }, + { + "type": "Punctuator", + "value": "(", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 11 + } + } + }, + { + "type": "Identifier", + "value": "d", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 12 + } + } + }, + { + "type": "Punctuator", + "value": ")", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 13 + } + } + }, + { + "type": "VExpressionEnd", + "range": [ + 24, + 26 + ], + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 15 + } + }, + "value": "}}" + }, + { + "type": "HTMLWhitespace", + "range": [ + 26, + 27 + ], + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 27, + 37 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 10 + } + }, + "value": "template" + }, + { + "type": "HTMLTagClose", + "range": [ + 37, + 38 + ], + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "value": "" + } + ], + "comments": [], + "errors": [] + } +} \ No newline at end of file diff --git a/test/fixtures/ast/parser-option-multiple-parsers-without-script/parser-options.json b/test/fixtures/ast/parser-option-multiple-parsers-without-script/parser-options.json new file mode 100644 index 00000000..92adbd5d --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-without-script/parser-options.json @@ -0,0 +1,11 @@ +{ + "sourceType": "module", + "parser": { + "js": "@typescript-eslint/parser", + "ts": "espree" + }, + "vueFeatures": { + "interpolationAsNonHTML": true, + "filter": false + } +} diff --git a/test/fixtures/ast/parser-option-multiple-parsers-without-script/services.json b/test/fixtures/ast/parser-option-multiple-parsers-without-script/services.json new file mode 100644 index 00000000..7159ba5a --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-without-script/services.json @@ -0,0 +1,11 @@ +[ + "defineCustomBlocksVisitor", + "defineDocumentVisitor", + "defineTemplateBodyVisitor", + "esTreeNodeToTSNodeMap", + "getDocumentFragment", + "getTemplateBodyTokenStore", + "hasFullTypeInformation", + "program", + "tsNodeToESTreeNodeMap" +] \ No newline at end of file diff --git a/test/fixtures/ast/parser-option-multiple-parsers-without-script/source.vue b/test/fixtures/ast/parser-option-multiple-parsers-without-script/source.vue new file mode 100644 index 00000000..bc537212 --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-without-script/source.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/test/fixtures/ast/parser-option-multiple-parsers-without-script/token-ranges.json b/test/fixtures/ast/parser-option-multiple-parsers-without-script/token-ranges.json new file mode 100644 index 00000000..fc96f781 --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-without-script/token-ranges.json @@ -0,0 +1,19 @@ +[ + "", + "\n ", + "{{", + "a", + "<", + "b", + "|", + "c", + ">", + "(", + "d", + ")", + "}}", + "\n", + "" +] \ No newline at end of file diff --git a/test/fixtures/ast/parser-option-multiple-parsers-without-script/tree.json b/test/fixtures/ast/parser-option-multiple-parsers-without-script/tree.json new file mode 100644 index 00000000..c456ad64 --- /dev/null +++ b/test/fixtures/ast/parser-option-multiple-parsers-without-script/tree.json @@ -0,0 +1,50 @@ +[ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + } +] \ No newline at end of file