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 ( +