From 366518f75944dd387d2f55a33a31d2ac9c743f1d Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Sun, 3 Nov 2019 14:30:17 -0800 Subject: [PATCH] fix(typescript-estree): fix filename handling for vue JSX + markdown (#1127) * fix(typescript-estree): fix filename handling for vue JSX + markdown * fix: correct integration tests * fix: remove erroneous vue file * docs: add a readme for the integration tests * chore: respect known filenames, ignore unknown ones * fix: add explicit tests for filename/jsx handling * docs: explicitly state the expected behaviour for JSX * docs: correct wording * docs: correct wording * chore: new commit to force codecov --- package.json | 2 +- packages/parser/README.md | 13 +- packages/typescript-estree/README.md | 12 +- .../create-program/createIsolatedProgram.ts | 20 +- .../src/create-program/createSourceFile.ts | 10 +- .../src/create-program/shared.ts | 30 + .../tests/lib/__snapshots__/parse.ts.snap | 3813 +++++++++++++++++ packages/typescript-estree/tests/lib/parse.ts | 150 + tests/integration/README.md | 18 + tests/integration/docker-compose.yml | 40 +- .../fixtures/markdown/.eslintrc.yml | 23 + tests/integration/fixtures/markdown/Doc.md | 71 + .../integration/fixtures/markdown/Dockerfile | 17 + .../fixtures/markdown/test.js.snap | 197 + tests/integration/fixtures/markdown/test.sh | 22 + .../fixtures/markdown/tsconfig.json | 6 + .../fixtures/vue-jsx/.eslintrc.yml | 25 + tests/integration/fixtures/vue-jsx/Dockerfile | 17 + tests/integration/fixtures/vue-jsx/Jsx.vue | 36 + .../integration/fixtures/vue-jsx/test.js.snap | 63 + tests/integration/fixtures/vue-jsx/test.sh | 29 + .../fixtures/vue-jsx/tsconfig.json | 8 + tests/integration/fixtures/vue-sfc/test.sh | 4 + tests/integration/run-all-tests.sh | 6 + yarn.lock | 8 +- 25 files changed, 4623 insertions(+), 17 deletions(-) create mode 100644 tests/integration/README.md create mode 100644 tests/integration/fixtures/markdown/.eslintrc.yml create mode 100644 tests/integration/fixtures/markdown/Doc.md create mode 100644 tests/integration/fixtures/markdown/Dockerfile create mode 100644 tests/integration/fixtures/markdown/test.js.snap create mode 100755 tests/integration/fixtures/markdown/test.sh create mode 100644 tests/integration/fixtures/markdown/tsconfig.json create mode 100644 tests/integration/fixtures/vue-jsx/.eslintrc.yml create mode 100644 tests/integration/fixtures/vue-jsx/Dockerfile create mode 100644 tests/integration/fixtures/vue-jsx/Jsx.vue create mode 100644 tests/integration/fixtures/vue-jsx/test.js.snap create mode 100755 tests/integration/fixtures/vue-jsx/test.sh create mode 100644 tests/integration/fixtures/vue-jsx/tsconfig.json diff --git a/package.json b/package.json index 6390641fcae..559b4e79271 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,6 @@ "url": "https://opencollective.com/typescript-eslint" }, "resolutions": { - "typescript": "^3.7.0-dev.20191018" + "typescript": "^3.7.0-dev.20191021" } } diff --git a/packages/parser/README.md b/packages/parser/README.md index 9fcb9d04363..011fb69b13d 100644 --- a/packages/parser/README.md +++ b/packages/parser/README.md @@ -42,9 +42,16 @@ The following additional configuration options are available by specifying them - **`ecmaFeatures.jsx`** - default `false`. Enable parsing JSX when `true`. More details can be found [here](https://www.typescriptlang.org/docs/handbook/jsx.html). - - It's `false` on `*.ts` files regardless of this option. - - It's `true` on `*.tsx` files regardless of this option. - - Otherwise, it respects this option. + NOTE: this setting does not effect known file types (.js, .jsx, .ts, .tsx, .json) because the typescript compiler has its own internal handling for known file extensions. The exact behaviour is as follows: + + - if `parserOptions.project` is _not_ provided: + - `.js`, `.jsx`, `.tsx` files are parsed as if this is true. + - `.ts` files are parsed as if this is false. + - unknown extensions (`.md`, `.vue`) will respect this setting. + - if `parserOptions.project` is provided (i.e. you are using rules with type information): + - `.js`, `.jsx`, `.tsx` files are parsed as if this is true. + - `.ts` files are parsed as if this is false. + - "unknown" extensions (`.md`, `.vue`) **are parsed as if this is false**. - **`useJSXTextNode`** - default `true`. Please set `false` if you use this parser on ESLint v4. If this is `false`, the parser creates the AST of JSX texts as the legacy style. diff --git a/packages/typescript-estree/README.md b/packages/typescript-estree/README.md index fe1515c869e..aca6f215dcb 100644 --- a/packages/typescript-estree/README.md +++ b/packages/typescript-estree/README.md @@ -47,7 +47,17 @@ Parses the given string of code with the options provided and returns an ESTree- // create a top-level comments array containing all comments comment: false, - // enable parsing JSX. For more details, see https://www.typescriptlang.org/docs/handbook/jsx.html + /* + * enable parsing JSX. For more details, see https://www.typescriptlang.org/docs/handbook/jsx.html + * + * NOTE: this setting does not effect known file types (.js, .jsx, .ts, .tsx, .json) because the + * typescript compiler has its own internal handling for known file extensions. + * + * Exact behaviour: + * - .js, .jsx, .tsx files are parsed as if this is true + * - .ts files are parsed as if this is false + * - unknown extensions (.md, .vue) will respect this setting + */ jsx: false, /* diff --git a/packages/typescript-estree/src/create-program/createIsolatedProgram.ts b/packages/typescript-estree/src/create-program/createIsolatedProgram.ts index d2e8c22901e..296aee2e5ba 100644 --- a/packages/typescript-estree/src/create-program/createIsolatedProgram.ts +++ b/packages/typescript-estree/src/create-program/createIsolatedProgram.ts @@ -1,7 +1,11 @@ import debug from 'debug'; import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports import { Extra } from '../parser-options'; -import { ASTAndProgram, DEFAULT_COMPILER_OPTIONS } from './shared'; +import { + ASTAndProgram, + DEFAULT_COMPILER_OPTIONS, + getScriptKind, +} from './shared'; const log = debug('typescript-eslint:typescript-estree:createIsolatedProgram'); @@ -10,7 +14,11 @@ const log = debug('typescript-eslint:typescript-estree:createIsolatedProgram'); * @returns Returns a new source file and program corresponding to the linted code */ function createIsolatedProgram(code: string, extra: Extra): ASTAndProgram { - log('Getting isolated program for: %s', extra.filePath); + log( + 'Getting isolated program in %s mode for: %s', + extra.jsx ? 'TSX' : 'TS', + extra.filePath, + ); const compilerHost: ts.CompilerHost = { fileExists() { @@ -34,7 +42,13 @@ function createIsolatedProgram(code: string, extra: Extra): ASTAndProgram { return '\n'; }, getSourceFile(filename: string) { - return ts.createSourceFile(filename, code, ts.ScriptTarget.Latest, true); + return ts.createSourceFile( + filename, + code, + ts.ScriptTarget.Latest, + true, + getScriptKind(extra, filename), + ); }, readFile() { return undefined; diff --git a/packages/typescript-estree/src/create-program/createSourceFile.ts b/packages/typescript-estree/src/create-program/createSourceFile.ts index 04815b24648..d1ab5f98d21 100644 --- a/packages/typescript-estree/src/create-program/createSourceFile.ts +++ b/packages/typescript-estree/src/create-program/createSourceFile.ts @@ -1,17 +1,23 @@ import debug from 'debug'; import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports import { Extra } from '../parser-options'; +import { getScriptKind } from './shared'; -const log = debug('typescript-eslint:typescript-estree:createIsolatedProgram'); +const log = debug('typescript-eslint:typescript-estree:createSourceFile'); function createSourceFile(code: string, extra: Extra): ts.SourceFile { - log('Getting AST without type information for: %s', extra.filePath); + log( + 'Getting AST without type information in %s mode for: %s', + extra.jsx ? 'TSX' : 'TS', + extra.filePath, + ); return ts.createSourceFile( extra.filePath, code, ts.ScriptTarget.Latest, /* setParentNodes */ true, + getScriptKind(extra), ); } diff --git a/packages/typescript-estree/src/create-program/shared.ts b/packages/typescript-estree/src/create-program/shared.ts index 3e948841773..6509997094f 100644 --- a/packages/typescript-estree/src/create-program/shared.ts +++ b/packages/typescript-estree/src/create-program/shared.ts @@ -41,11 +41,41 @@ function canonicalDirname(p: CanonicalPath): CanonicalPath { return path.dirname(p) as CanonicalPath; } +function getScriptKind( + extra: Extra, + filePath: string = extra.filePath, +): ts.ScriptKind { + const extension = path.extname(filePath).toLowerCase(); + // note - we respect the user's extension when it is known we could override it and force it to match their + // jsx setting, but that could create weird situations where we throw parse errors when TSC doesn't + switch (extension) { + case '.ts': + return ts.ScriptKind.TS; + + case '.tsx': + return ts.ScriptKind.TSX; + + case '.js': + return ts.ScriptKind.JS; + + case '.jsx': + return ts.ScriptKind.JSX; + + case '.json': + return ts.ScriptKind.JSON; + + default: + // unknown extension, force typescript to ignore the file extension, and respect the user's setting + return extra.jsx ? ts.ScriptKind.TSX : ts.ScriptKind.TS; + } +} + export { ASTAndProgram, canonicalDirname, CanonicalPath, DEFAULT_COMPILER_OPTIONS, getCanonicalFileName, + getScriptKind, getTsconfigPath, }; diff --git a/packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap index bca89ec8d8c..e953f852a8e 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/parse.ts.snap @@ -225,6 +225,3819 @@ The file does not match your project config: tests/fixtures/invalidFileErrors/js The file must be included in at least one of the projects provided." `; +exports[`parse() isolated parsing should parse .js file - with JSX content - parserOptions.jsx = false 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "children": Array [], + "closingElement": null, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "openingElement": Object { + "attributes": Array [], + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "name": "div", + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + }, + "range": Array [ + 10, + 17, + ], + "selfClosing": true, + "type": "JSXOpeningElement", + "typeParameters": undefined, + }, + "range": Array [ + 10, + 17, + ], + "type": "JSXElement", + }, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 17, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + "value": "div", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": "/", + }, + Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 16, + "line": 1, + }, + }, + "range": Array [ + 16, + 17, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .js file - with JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "children": Array [], + "closingElement": null, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "openingElement": Object { + "attributes": Array [], + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "name": "div", + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + }, + "range": Array [ + 10, + 17, + ], + "selfClosing": true, + "type": "JSXOpeningElement", + "typeParameters": undefined, + }, + "range": Array [ + 10, + 17, + ], + "type": "JSXElement", + }, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 17, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + "value": "div", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": "/", + }, + Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 16, + "line": 1, + }, + }, + "range": Array [ + 16, + 17, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .js file - without JSX content - parserOptions.jsx = false 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .js file - without JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .jsx file - with JSX content - parserOptions.jsx = false 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "children": Array [], + "closingElement": null, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "openingElement": Object { + "attributes": Array [], + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "name": "div", + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + }, + "range": Array [ + 10, + 17, + ], + "selfClosing": true, + "type": "JSXOpeningElement", + "typeParameters": undefined, + }, + "range": Array [ + 10, + 17, + ], + "type": "JSXElement", + }, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 17, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + "value": "div", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": "/", + }, + Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 16, + "line": 1, + }, + }, + "range": Array [ + 16, + 17, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .jsx file - with JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "children": Array [], + "closingElement": null, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "openingElement": Object { + "attributes": Array [], + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "name": "div", + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + }, + "range": Array [ + 10, + 17, + ], + "selfClosing": true, + "type": "JSXOpeningElement", + "typeParameters": undefined, + }, + "range": Array [ + 10, + 17, + ], + "type": "JSXElement", + }, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 17, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + "value": "div", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": "/", + }, + Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 16, + "line": 1, + }, + }, + "range": Array [ + 16, + 17, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .jsx file - without JSX content - parserOptions.jsx = false 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .jsx file - without JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .ts file - without JSX content - parserOptions.jsx = false 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .ts file - without JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .tsx file - with JSX content - parserOptions.jsx = false 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "children": Array [], + "closingElement": null, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "openingElement": Object { + "attributes": Array [], + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "name": "div", + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + }, + "range": Array [ + 10, + 17, + ], + "selfClosing": true, + "type": "JSXOpeningElement", + "typeParameters": undefined, + }, + "range": Array [ + 10, + 17, + ], + "type": "JSXElement", + }, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 17, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + "value": "div", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": "/", + }, + Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 16, + "line": 1, + }, + }, + "range": Array [ + 16, + 17, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .tsx file - with JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "children": Array [], + "closingElement": null, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "openingElement": Object { + "attributes": Array [], + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "name": "div", + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + }, + "range": Array [ + 10, + 17, + ], + "selfClosing": true, + "type": "JSXOpeningElement", + "typeParameters": undefined, + }, + "range": Array [ + 10, + 17, + ], + "type": "JSXElement", + }, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 17, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + "value": "div", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": "/", + }, + Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 16, + "line": 1, + }, + }, + "range": Array [ + 16, + 17, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .tsx file - without JSX content - parserOptions.jsx = false 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .tsx file - without JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .vue file - with JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "children": Array [], + "closingElement": null, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "openingElement": Object { + "attributes": Array [], + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "name": "div", + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + }, + "range": Array [ + 10, + 17, + ], + "selfClosing": true, + "type": "JSXOpeningElement", + "typeParameters": undefined, + }, + "range": Array [ + 10, + 17, + ], + "type": "JSXElement", + }, + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 17, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 18, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 14, + ], + "type": "JSXIdentifier", + "value": "div", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": "/", + }, + Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 1, + }, + "start": Object { + "column": 16, + "line": 1, + }, + }, + "range": Array [ + 16, + 17, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 17, + "line": 1, + }, + }, + "range": Array [ + 17, + 18, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .vue file - without JSX content - parserOptions.jsx = false 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + +exports[`parse() isolated parsing should parse .vue file - without JSX content - parserOptions.jsx = true 1`] = ` +Object { + "ast": Object { + "body": Array [ + Object { + "declarations": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "x", + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + }, + "init": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "raw": "1", + "type": "Literal", + "value": 1, + }, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 11, + ], + "type": "VariableDeclarator", + }, + ], + "kind": "const", + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "type": "VariableDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 11, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "const", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 7, + ], + "type": "Identifier", + "value": "x", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 8, + "line": 1, + }, + }, + "range": Array [ + 8, + 9, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Numeric", + "value": "1", + }, + ], + "type": "Program", + }, + "services": Object { + "esTreeNodeToTSNodeMap": undefined, + "program": undefined, + "tsNodeToESTreeNodeMap": undefined, + }, +} +`; + exports[`parse() non string code should correctly convert code to a string for parse() 1`] = ` Object { "body": Array [ diff --git a/packages/typescript-estree/tests/lib/parse.ts b/packages/typescript-estree/tests/lib/parse.ts index 21664b7bd41..53197b7a73d 100644 --- a/packages/typescript-estree/tests/lib/parse.ts +++ b/packages/typescript-estree/tests/lib/parse.ts @@ -229,6 +229,156 @@ describe('parse()', () => { }); }); + describe('isolated parsing', () => { + const config: TSESTreeOptions = { + comment: true, + tokens: true, + range: true, + loc: true, + }; + const testParse = ({ + ext, + jsxContent, + jsxSetting, + shouldThrow = false, + }: { + ext: '.js' | '.jsx' | '.ts' | '.tsx' | '.vue'; + jsxContent: boolean; + jsxSetting: boolean; + shouldThrow?: boolean; + }): void => { + const code = jsxContent ? 'const x =
;' : 'const x = 1'; + it(`should parse ${ext} file - ${ + jsxContent ? 'with' : 'without' + } JSX content - parserOptions.jsx = ${jsxSetting}`, () => { + let result; + let exp = expect(() => { + result = parser.parseAndGenerateServices(code, { + ...config, + jsx: jsxSetting, + filePath: join(FIXTURES_DIR, `file${ext}`), + }); + }); + if (!shouldThrow) { + exp = exp.not; + } + exp.toThrow(); + + if (!shouldThrow) { + expect(result).toMatchSnapshot(); + } + }); + }; + + testParse({ + ext: '.js', + jsxContent: false, + jsxSetting: false, + }); + testParse({ + ext: '.js', + jsxContent: false, + jsxSetting: true, + }); + testParse({ + ext: '.js', + jsxContent: true, + jsxSetting: false, + }); + testParse({ + ext: '.js', + jsxContent: true, + jsxSetting: true, + }); + + testParse({ + ext: '.jsx', + jsxContent: false, + jsxSetting: false, + }); + testParse({ + ext: '.jsx', + jsxContent: false, + jsxSetting: true, + }); + testParse({ + ext: '.jsx', + jsxContent: true, + jsxSetting: false, + }); + testParse({ + ext: '.jsx', + jsxContent: true, + jsxSetting: true, + }); + + testParse({ + ext: '.ts', + jsxContent: false, + jsxSetting: false, + }); + testParse({ + ext: '.ts', + jsxContent: false, + jsxSetting: true, + }); + testParse({ + ext: '.ts', + jsxContent: true, + jsxSetting: false, + shouldThrow: true, // Typescript does not allow JSX in a .ts file + }); + testParse({ + ext: '.ts', + jsxContent: true, + jsxSetting: true, + shouldThrow: true, + }); + + testParse({ + ext: '.tsx', + jsxContent: false, + jsxSetting: false, + }); + testParse({ + ext: '.tsx', + jsxContent: false, + jsxSetting: true, + }); + testParse({ + ext: '.tsx', + jsxContent: true, + jsxSetting: false, + }); + testParse({ + ext: '.tsx', + jsxContent: true, + jsxSetting: true, + }); + + testParse({ + ext: '.vue', + jsxContent: false, + jsxSetting: false, + }); + testParse({ + ext: '.vue', + jsxContent: false, + jsxSetting: true, + }); + testParse({ + ext: '.vue', + jsxContent: true, + jsxSetting: false, + shouldThrow: true, // "Unknown" filetype means we respect the JSX setting + }); + testParse({ + ext: '.vue', + jsxContent: true, + jsxSetting: true, + }); + }); + describe('invalid file error messages', () => { const PROJECT_DIR = resolve(FIXTURES_DIR, '../invalidFileErrors'); const code = 'var a = true'; diff --git a/tests/integration/README.md b/tests/integration/README.md new file mode 100644 index 00000000000..eb33e8bd62d --- /dev/null +++ b/tests/integration/README.md @@ -0,0 +1,18 @@ +# Integration Tests + +We have a set of integration tests defined in this project to help ensure we don't inadvertently break downstream packages that depend on us. + +These tests are setup to run within docker containers to ensure that each test is completely isolated; we don't want them to affect our local environment, and similarly we don't want them to be effected by our local environment. + +## Adding a new integration test + +1. [Install docker for your platform](https://docs.docker.com/v17.09/engine/installation/#supported-platforms). +1. Add a new folder in `/tests/integration/fixtures` +1. Add a `.eslintrc.yml`, and a `tsconfig.json` to your folder, with the config required. +1. Create the necessary files to test the integration. +1. Copy+paste the `Dockerfile` from an existing fixture (they are all the same). +1. Copy+paste the `test.sh` from an existing fixture, and adjust the `eslint` command as required. +1. Add a new entry to `docker-compose.yml` by copy+pasting an existing section, and changing the name to match your new folder. +1. Add a new entry to `run-all-tests.sh` by copy+pasting an existing command, and changing the name to match your new folder. +1. Run your integration test by running the single command you copied in . + - If your test finishes successfully, a `test.js.snap` will be created. diff --git a/tests/integration/docker-compose.yml b/tests/integration/docker-compose.yml index 74bfb63dab2..c3a0b450d65 100644 --- a/tests/integration/docker-compose.yml +++ b/tests/integration/docker-compose.yml @@ -3,7 +3,7 @@ version: '3' services: typescript-and-tslint-plugins-together: build: ./fixtures/typescript-and-tslint-plugins-together - container_name: "typescript-and-tslint-plugins-together" + container_name: 'typescript-and-tslint-plugins-together' volumes: # Runtime link to the relevant built @typescript-eslint packages and integration test utils, # but apply an empty volume for the package tests, we don't need those. @@ -22,7 +22,7 @@ services: vue-sfc: build: ./fixtures/vue-sfc - container_name: "vue-sfc" + container_name: 'vue-sfc' volumes: # Runtime link to the relevant built @typescript-eslint packages and integration test utils, # but apply an empty volume for the package tests, we don't need those. @@ -37,9 +37,26 @@ services: # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. - ./fixtures/vue-sfc:/usr/linked + vue-jsx: + build: ./fixtures/vue-jsx + container_name: 'vue-jsx' + volumes: + # Runtime link to the relevant built @typescript-eslint packages and integration test utils, + # but apply an empty volume for the package tests, we don't need those. + - ../../package.json/:/usr/root-package.json + - ./utils/:/usr/utils + - ../../packages/parser/:/usr/parser + - /usr/parser/tests + - ../../packages/typescript-estree/:/usr/typescript-estree + - /usr/typescript-estree/tests + - ../../packages/eslint-plugin/:/usr/eslint-plugin + - /usr/eslint-plugin/tests + # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. + - ./fixtures/vue-jsx:/usr/linked + recommended-does-not-require-program: build: ./fixtures/recommended-does-not-require-program - container_name: "recommended-does-not-require-program" + container_name: 'recommended-does-not-require-program' volumes: # Runtime link to the relevant built @typescript-eslint packages and integration test utils, # but apply an empty volume for the package tests, we don't need those. @@ -53,3 +70,20 @@ services: - /usr/eslint-plugin/tests # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. - ./fixtures/recommended-does-not-require-program:/usr/linked + + markdown: + build: ./fixtures/markdown + container_name: 'markdown' + volumes: + # Runtime link to the relevant built @typescript-eslint packages and integration test utils, + # but apply an empty volume for the package tests, we don't need those. + - ../../package.json/:/usr/root-package.json + - ./utils/:/usr/utils + - ../../packages/parser/:/usr/parser + - /usr/parser/tests + - ../../packages/typescript-estree/:/usr/typescript-estree + - /usr/typescript-estree/tests + - ../../packages/eslint-plugin/:/usr/eslint-plugin + - /usr/eslint-plugin/tests + # Runtime link to all the specific integration test files, so that most updates don't require a rebuild. + - ./fixtures/markdown:/usr/linked diff --git a/tests/integration/fixtures/markdown/.eslintrc.yml b/tests/integration/fixtures/markdown/.eslintrc.yml new file mode 100644 index 00000000000..92575183cd9 --- /dev/null +++ b/tests/integration/fixtures/markdown/.eslintrc.yml @@ -0,0 +1,23 @@ +root: true + +# Local version of @typescript-eslint/parser +parser: '@typescript-eslint/parser' + +env: + es6: true + node: true + +parserOptions: + sourceType: module + extraFileExtensions: ['.vue'] + ecmaFeatures: + jsx: true + +plugins: +- 'markdown' +# Local version of @typescript-eslint/eslint-plugin +- '@typescript-eslint' + +rules: + '@typescript-eslint/no-explicit-any': 'error' + 'no-console': 'error' diff --git a/tests/integration/fixtures/markdown/Doc.md b/tests/integration/fixtures/markdown/Doc.md new file mode 100644 index 00000000000..0d6eabe455e --- /dev/null +++ b/tests/integration/fixtures/markdown/Doc.md @@ -0,0 +1,71 @@ +Some extra text to verify that the markdown plugin is ignoring anything that is not a code block. + +expected no-console error: +```jsx +import { Button } from 'antd'; + +function MyComp() { + console.log('test'); + return ( +
+ + + + + +
+ ); +} +``` + +expected no-explicit-any error: +expected no-console error: +```jsx +import { Button } from 'antd'; + +function MyComp(): any { + console.log('test'); + return ( +
+ + + + + +
+ ); +} +``` + +expected no-console error: +```js +function foo() { + console.log('test'); +} +``` + +expected no-explicit-any error: +expected no-console error: +```js +function foo(): any { + console.log('test'); +} +``` + + +expected no-explicit-any error: +expected no-console error: +```javascript +function foo(): any { + console.log('test'); +} +``` + + +expected no-explicit-any error: +expected no-console error: +```node +function foo(): any { + console.log('test'); +} +``` diff --git a/tests/integration/fixtures/markdown/Dockerfile b/tests/integration/fixtures/markdown/Dockerfile new file mode 100644 index 00000000000..3b281e624c8 --- /dev/null +++ b/tests/integration/fixtures/markdown/Dockerfile @@ -0,0 +1,17 @@ +FROM node:carbon + +# Copy the test.sh into the container. Every other file will be linked, rather +# than copied to allow for changes without rebuilds wherever possible +WORKDIR /usr +COPY ./test.sh /usr/ + +# Create file which will be executed by jest +# to assert that the lint output is what we expect +RUN echo "const actualLintOutput = require('./lint-output.json');\n" \ + "\n" \ + "test('it should produce the expected lint ouput', () => {\n" \ + " expect(actualLintOutput).toMatchSnapshot();\n" \ + "});\n" > test.js + +# Run the integration test +CMD [ "./test.sh" ] diff --git a/tests/integration/fixtures/markdown/test.js.snap b/tests/integration/fixtures/markdown/test.js.snap new file mode 100644 index 00000000000..4fc96f79abc --- /dev/null +++ b/tests/integration/fixtures/markdown/test.js.snap @@ -0,0 +1,197 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`it should produce the expected lint ouput 1`] = ` +Array [ + Object { + "errorCount": 10, + "filePath": "/usr/linked/Doc.md", + "fixableErrorCount": 0, + "fixableWarningCount": 0, + "messages": Array [ + Object { + "column": 3, + "endColumn": 14, + "endLine": 8, + "line": 8, + "message": "Unexpected console statement.", + "messageId": "unexpected", + "nodeType": "MemberExpression", + "ruleId": "no-console", + "severity": 2, + }, + Object { + "column": 20, + "endColumn": 23, + "endLine": 26, + "line": 26, + "message": "Unexpected any. Specify a different type.", + "messageId": "unexpectedAny", + "nodeType": "TSAnyKeyword", + "ruleId": "@typescript-eslint/no-explicit-any", + "severity": 2, + }, + Object { + "column": 3, + "endColumn": 14, + "endLine": 27, + "line": 27, + "message": "Unexpected console statement.", + "messageId": "unexpected", + "nodeType": "MemberExpression", + "ruleId": "no-console", + "severity": 2, + }, + Object { + "column": 3, + "endColumn": 14, + "endLine": 43, + "line": 43, + "message": "Unexpected console statement.", + "messageId": "unexpected", + "nodeType": "MemberExpression", + "ruleId": "no-console", + "severity": 2, + }, + Object { + "column": 17, + "endColumn": 20, + "endLine": 50, + "line": 50, + "message": "Unexpected any. Specify a different type.", + "messageId": "unexpectedAny", + "nodeType": "TSAnyKeyword", + "ruleId": "@typescript-eslint/no-explicit-any", + "severity": 2, + }, + Object { + "column": 3, + "endColumn": 14, + "endLine": 51, + "line": 51, + "message": "Unexpected console statement.", + "messageId": "unexpected", + "nodeType": "MemberExpression", + "ruleId": "no-console", + "severity": 2, + }, + Object { + "column": 17, + "endColumn": 20, + "endLine": 59, + "line": 59, + "message": "Unexpected any. Specify a different type.", + "messageId": "unexpectedAny", + "nodeType": "TSAnyKeyword", + "ruleId": "@typescript-eslint/no-explicit-any", + "severity": 2, + }, + Object { + "column": 3, + "endColumn": 14, + "endLine": 60, + "line": 60, + "message": "Unexpected console statement.", + "messageId": "unexpected", + "nodeType": "MemberExpression", + "ruleId": "no-console", + "severity": 2, + }, + Object { + "column": 17, + "endColumn": 20, + "endLine": 68, + "line": 68, + "message": "Unexpected any. Specify a different type.", + "messageId": "unexpectedAny", + "nodeType": "TSAnyKeyword", + "ruleId": "@typescript-eslint/no-explicit-any", + "severity": 2, + }, + Object { + "column": 3, + "endColumn": 14, + "endLine": 69, + "line": 69, + "message": "Unexpected console statement.", + "messageId": "unexpected", + "nodeType": "MemberExpression", + "ruleId": "no-console", + "severity": 2, + }, + ], + "source": "Some extra text to verify that the markdown plugin is ignoring anything that is not a code block. + +expected no-console error: +\`\`\`jsx +import { Button } from 'antd'; + +function MyComp() { + console.log('test'); + return ( +
+ + + + + +
+ ); +} +\`\`\` + +expected no-explicit-any error: +expected no-console error: +\`\`\`jsx +import { Button } from 'antd'; + +function MyComp(): any { + console.log('test'); + return ( +
+ + + + + +
+ ); +} +\`\`\` + +expected no-console error: +\`\`\`js +function foo() { + console.log('test'); +} +\`\`\` + +expected no-explicit-any error: +expected no-console error: +\`\`\`js +function foo(): any { + console.log('test'); +} +\`\`\` + + +expected no-explicit-any error: +expected no-console error: +\`\`\`javascript +function foo(): any { + console.log('test'); +} +\`\`\` + + +expected no-explicit-any error: +expected no-console error: +\`\`\`node +function foo(): any { + console.log('test'); +} +\`\`\` +", + "warningCount": 0, + }, +] +`; diff --git a/tests/integration/fixtures/markdown/test.sh b/tests/integration/fixtures/markdown/test.sh new file mode 100755 index 00000000000..4641a6b33f4 --- /dev/null +++ b/tests/integration/fixtures/markdown/test.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Generate the package.json to use +node /usr/utils/generate-package-json.js + +# Install dependencies +npm install + +# Use the local volumes for our own packages +npm install $(npm pack /usr/typescript-estree | tail -1) +npm install $(npm pack /usr/parser | tail -1) +npm install $(npm pack /usr/eslint-plugin | tail -1) + +# Install the latest vue-eslint-parser (this may break us occassionally, but it's probably good to get that feedback early) +npm install eslint-plugin-markdown@latest + +# Run the linting +# (the "|| true" helps make sure that we run our tests on failed linting runs as well) +npx eslint --format json --output-file /usr/lint-output.json --config /usr/linked/.eslintrc.yml /usr/linked/**/*.md || true + +# Run our assertions against the linting output +npx jest /usr/test.js --snapshotResolver=/usr/utils/jest-snapshot-resolver.js diff --git a/tests/integration/fixtures/markdown/tsconfig.json b/tests/integration/fixtures/markdown/tsconfig.json new file mode 100644 index 00000000000..45234bf35aa --- /dev/null +++ b/tests/integration/fixtures/markdown/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "strict": true + }, + "include": [] +} diff --git a/tests/integration/fixtures/vue-jsx/.eslintrc.yml b/tests/integration/fixtures/vue-jsx/.eslintrc.yml new file mode 100644 index 00000000000..ea4319ac718 --- /dev/null +++ b/tests/integration/fixtures/vue-jsx/.eslintrc.yml @@ -0,0 +1,25 @@ +root: true + +parser: 'vue-eslint-parser' + +env: + es6: true + node: true + +extends: + plugin:vue/essential + +parserOptions: + # Local version of @typescript-eslint/parser + parser: '@typescript-eslint/parser' + sourceType: module + extraFileExtensions: ['.vue'] + ecmaFeatures: + jsx: true + +plugins: +# Local version of @typescript-eslint/eslint-plugin +- '@typescript-eslint' + +rules: + '@typescript-eslint/no-explicit-any': 'error' diff --git a/tests/integration/fixtures/vue-jsx/Dockerfile b/tests/integration/fixtures/vue-jsx/Dockerfile new file mode 100644 index 00000000000..3b281e624c8 --- /dev/null +++ b/tests/integration/fixtures/vue-jsx/Dockerfile @@ -0,0 +1,17 @@ +FROM node:carbon + +# Copy the test.sh into the container. Every other file will be linked, rather +# than copied to allow for changes without rebuilds wherever possible +WORKDIR /usr +COPY ./test.sh /usr/ + +# Create file which will be executed by jest +# to assert that the lint output is what we expect +RUN echo "const actualLintOutput = require('./lint-output.json');\n" \ + "\n" \ + "test('it should produce the expected lint ouput', () => {\n" \ + " expect(actualLintOutput).toMatchSnapshot();\n" \ + "});\n" > test.js + +# Run the integration test +CMD [ "./test.sh" ] diff --git a/tests/integration/fixtures/vue-jsx/Jsx.vue b/tests/integration/fixtures/vue-jsx/Jsx.vue new file mode 100644 index 00000000000..c08599249c3 --- /dev/null +++ b/tests/integration/fixtures/vue-jsx/Jsx.vue @@ -0,0 +1,36 @@ + diff --git a/tests/integration/fixtures/vue-jsx/test.js.snap b/tests/integration/fixtures/vue-jsx/test.js.snap new file mode 100644 index 00000000000..d4432e47428 --- /dev/null +++ b/tests/integration/fixtures/vue-jsx/test.js.snap @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`it should produce the expected lint ouput 1`] = ` +Array [ + Object { + "errorCount": 1, + "filePath": "/usr/linked/Jsx.vue", + "fixableErrorCount": 0, + "fixableWarningCount": 0, + "messages": Array [ + Object { + "column": 17, + "endColumn": 20, + "endLine": 17, + "line": 17, + "message": "Unexpected any. Specify a different type.", + "messageId": "unexpectedAny", + "nodeType": "TSAnyKeyword", + "ruleId": "@typescript-eslint/no-explicit-any", + "severity": 2, + }, + ], + "source": " +", + "warningCount": 0, + }, +] +`; diff --git a/tests/integration/fixtures/vue-jsx/test.sh b/tests/integration/fixtures/vue-jsx/test.sh new file mode 100755 index 00000000000..f59b6348fd6 --- /dev/null +++ b/tests/integration/fixtures/vue-jsx/test.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Generate the package.json to use +node /usr/utils/generate-package-json.js + +# Install dependencies +npm install + +# Use the local volumes for our own packages +npm install $(npm pack /usr/typescript-estree | tail -1) +npm install $(npm pack /usr/parser | tail -1) +npm install $(npm pack /usr/eslint-plugin | tail -1) + +# Install the latest vue-eslint-parser (this may break us occassionally, but it's probably good to get that feedback early) +npm install vue-eslint-parser@latest + +# Install the latest eslint-plugin-vue (this may break us occassionally, but it's probably good to get that feedback early) +npm install eslint-plugin-vue@latest + +# Install the latest some other vue utilities +npm install vuex@latest +npm install vue-property-decorator@latest + +# Run the linting +# (the "|| true" helps make sure that we run our tests on failed linting runs as well) +npx eslint --format json --output-file /usr/lint-output.json --config /usr/linked/.eslintrc.yml /usr/linked/**/*.vue || true + +# Run our assertions against the linting output +npx jest /usr/test.js --snapshotResolver=/usr/utils/jest-snapshot-resolver.js diff --git a/tests/integration/fixtures/vue-jsx/tsconfig.json b/tests/integration/fixtures/vue-jsx/tsconfig.json new file mode 100644 index 00000000000..861b7d99bed --- /dev/null +++ b/tests/integration/fixtures/vue-jsx/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "strict": true + }, + "include": [ + "*.vue" + ] +} diff --git a/tests/integration/fixtures/vue-sfc/test.sh b/tests/integration/fixtures/vue-sfc/test.sh index b61a140ff5b..f59b6348fd6 100755 --- a/tests/integration/fixtures/vue-sfc/test.sh +++ b/tests/integration/fixtures/vue-sfc/test.sh @@ -17,6 +17,10 @@ npm install vue-eslint-parser@latest # Install the latest eslint-plugin-vue (this may break us occassionally, but it's probably good to get that feedback early) npm install eslint-plugin-vue@latest +# Install the latest some other vue utilities +npm install vuex@latest +npm install vue-property-decorator@latest + # Run the linting # (the "|| true" helps make sure that we run our tests on failed linting runs as well) npx eslint --format json --output-file /usr/lint-output.json --config /usr/linked/.eslintrc.yml /usr/linked/**/*.vue || true diff --git a/tests/integration/run-all-tests.sh b/tests/integration/run-all-tests.sh index 4506da77349..8964e319869 100755 --- a/tests/integration/run-all-tests.sh +++ b/tests/integration/run-all-tests.sh @@ -10,5 +10,11 @@ docker-compose -f tests/integration/docker-compose.yml up --build --abort-on-con # vue-sfc docker-compose -f tests/integration/docker-compose.yml up --build --abort-on-container-exit vue-sfc +# vue-jsx +docker-compose -f tests/integration/docker-compose.yml up --build --abort-on-container-exit vue-jsx + # recommended-does-not-require-program docker-compose -f tests/integration/docker-compose.yml up --build --abort-on-container-exit recommended-does-not-require-program + +# markdown +docker-compose -f tests/integration/docker-compose.yml up --build --abort-on-container-exit markdown diff --git a/yarn.lock b/yarn.lock index 88507646d6d..58e28ad5ec0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7715,10 +7715,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@*, "typescript@>=3.2.1 <3.8.0 || >3.7.0-dev.0", typescript@^3.7.0-dev.20191018: - version "3.7.0-dev.20191018" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.0-dev.20191018.tgz#6b98a655b124ca697364e2d7977c469a2bfede3d" - integrity sha512-Z8KpsytbY5lBMp5cc08VFoO8CgHC6IcbgyiA5vjh7fitkoG0qcem9C354YuiWV4O2+i2gdC7vF8tNUYqO/vUkQ== +typescript@*, "typescript@>=3.2.1 <3.8.0 || >3.7.0-dev.0", typescript@^3.7.0-dev.20191021: + version "3.7.0-dev.20191021" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.0-dev.20191021.tgz#e0238e0b3eed9fc265767a1b7f5346fea8ab5edb" + integrity sha512-SSx/+QkyW7PMcaGQXzVmVkrRmmaLFsdOYXhP9sY9eYMiHrfmtZE9EL2hjtbihfnpyWfCmPup69VgbB4dTTEQgg== uglify-js@^3.1.4: version "3.6.0"