Skip to content
Permalink
Browse files

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
  • Loading branch information...
bradzacher committed Nov 3, 2019
1 parent 17c956e commit 366518f75944dd387d2f55a33a31d2ac9c743f1d
@@ -80,6 +80,6 @@
"url": "https://opencollective.com/typescript-eslint"
},
"resolutions": {
"typescript": "^3.7.0-dev.20191018"
"typescript": "^3.7.0-dev.20191021"
}
}
@@ -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.

@@ -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,
/*
@@ -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;
@@ -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),
);
}

@@ -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,
};

0 comments on commit 366518f

Please sign in to comment.
You can’t perform that action at this time.