Skip to content

Commit

Permalink
fix(typescript-estree): fix filename handling for vue JSX + markdown (#…
Browse files Browse the repository at this point in the history
…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 366518f
Show file tree
Hide file tree
Showing 25 changed files with 4,623 additions and 17 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -80,6 +80,6 @@
"url": "https://opencollective.com/typescript-eslint"
},
"resolutions": {
"typescript": "^3.7.0-dev.20191018"
"typescript": "^3.7.0-dev.20191021"
}
}
13 changes: 10 additions & 3 deletions packages/parser/README.md
Expand Up @@ -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.

Expand Down
12 changes: 11 additions & 1 deletion packages/typescript-estree/README.md
Expand Up @@ -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,

/*
Expand Down
@@ -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');

Expand All @@ -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() {
Expand All @@ -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;
Expand Down
@@ -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),
);
}

Expand Down
30 changes: 30 additions & 0 deletions packages/typescript-estree/src/create-program/shared.ts
Expand Up @@ -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.