Skip to content

Commit

Permalink
feat(typescript-estree): added allowInvalidAST option to not throw on…
Browse files Browse the repository at this point in the history
… invalid tokens (#6247)
  • Loading branch information
JoshuaKGoldberg committed Mar 5, 2023
1 parent f98afd2 commit a3b177d
Show file tree
Hide file tree
Showing 56 changed files with 307 additions and 1,287 deletions.
7 changes: 6 additions & 1 deletion docs/architecture/TypeScript-ESTree.mdx
Expand Up @@ -31,6 +31,12 @@ Parses the given string of code with the options provided and returns an ESTree-

```ts
interface ParseOptions {
/**
* Prevents the parser from throwing an error if it receives an invalid AST from TypeScript.
* This case only usually occurs when attempting to lint invalid code.
*/
allowInvalidAST?: boolean;

/**
* create a top-level comments array containing all comments
*/
Expand Down Expand Up @@ -99,7 +105,6 @@ interface ParseOptions {

const PARSE_DEFAULT_OPTIONS: ParseOptions = {
comment: false,
errorOnUnknownASTType: false,
filePath: 'estree.ts', // or 'estree.tsx', if you pass jsx: true
jsx: false,
loc: false,
Expand Down
@@ -0,0 +1 @@
export class { }
@@ -0,0 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration ClassDeclaration _error_ export-missing-name TSESTree - Error 1`] = `
"TSError
> 1 | export class { }
| ^ A class declaration without the 'default' modifier must have a name.
2 |"
`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration ClassDeclaration _error_ export-missing-name Babel - Error 1`] = `[SyntaxError: A class name is required. (1:13)]`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration ClassDeclaration _error_ export-missing-name Error Alignment 1`] = `"Both errored"`;
@@ -1,3 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration ExportNamedDeclaration _error_ anonymous-class TSESTree - Error 1`] = `"NO ERROR"`;
exports[`AST Fixtures declaration ExportNamedDeclaration _error_ anonymous-class TSESTree - Error 1`] = `
"TSError
> 1 | export class {}
| ^ A class declaration without the 'default' modifier must have a name.
2 |"
`;
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration ExportNamedDeclaration _error_ anonymous-class Error Alignment 1`] = `"Babel errored but TSESTree didn't"`;
exports[`AST Fixtures declaration ExportNamedDeclaration _error_ anonymous-class Error Alignment 1`] = `"Both errored"`;
@@ -0,0 +1 @@
@decl enum Test {}
@@ -0,0 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSEnumDeclaration _error_ decorator TSESTree - Error 1`] = `
"TSError
> 1 | @decl enum Test {}
| ^ Decorators are not valid here.
2 |"
`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSEnumDeclaration _error_ decorator Babel - Error 1`] = `[SyntaxError: Leading decorators must be attached to a class declaration. (1:6)]`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSEnumDeclaration _error_ decorator Error Alignment 1`] = `"Both errored"`;
@@ -0,0 +1 @@
@decl interface Test {}
@@ -0,0 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSInterfaceDeclaration _error_ decorator TSESTree - Error 1`] = `
"TSError
> 1 | @decl interface Test {}
| ^ Decorators are not valid here.
2 |"
`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSInterfaceDeclaration _error_ decorator Babel - Error 1`] = `[SyntaxError: Leading decorators must be attached to a class declaration. (1:6)]`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSInterfaceDeclaration _error_ decorator Error Alignment 1`] = `"Both errored"`;
@@ -0,0 +1 @@
@decl type Test = {};
@@ -0,0 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSTypeAliasDeclaration _error_ decorator TSESTree - Error 1`] = `
"TSError
> 1 | @decl type Test = {};
| ^ Decorators are not valid here.
2 |"
`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSTypeAliasDeclaration _error_ decorator Babel - Error 1`] = `[SyntaxError: Leading decorators must be attached to a class declaration. (1:6)]`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration TSTypeAliasDeclaration _error_ decorator Error Alignment 1`] = `"Both errored"`;
@@ -0,0 +1 @@
@decl type Test = {};
@@ -0,0 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration VariableDeclaration _error_ decorator TSESTree - Error 1`] = `
"TSError
> 1 | @decl type Test = {};
| ^ Decorators are not valid here.
2 |"
`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration VariableDeclaration _error_ decorator Babel - Error 1`] = `[SyntaxError: Leading decorators must be attached to a class declaration. (1:6)]`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration VariableDeclaration _error_ decorator Error Alignment 1`] = `"Both errored"`;
@@ -1,3 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration VariableDeclaration _error_ missing-id-without-value TSESTree - Error 1`] = `"NO ERROR"`;
exports[`AST Fixtures declaration VariableDeclaration _error_ missing-id-without-value TSESTree - Error 1`] = `
"TSError
> 1 | const;
| ^ A variable declaration list must have at least one variable declarator.
2 |"
`;
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration VariableDeclaration _error_ missing-id-without-value Error Alignment 1`] = `"Babel errored but TSESTree didn't"`;
exports[`AST Fixtures declaration VariableDeclaration _error_ missing-id-without-value Error Alignment 1`] = `"Both errored"`;
@@ -0,0 +1 @@
const;
@@ -0,0 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration VariableDeclaration _error_ no-variables TSESTree - Error 1`] = `
"TSError
> 1 | const;
| ^ A variable declaration list must have at least one variable declarator.
2 |"
`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration VariableDeclaration _error_ no-variables Babel - Error 1`] = `[SyntaxError: Unexpected token (1:5)]`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures declaration VariableDeclaration _error_ no-variables Error Alignment 1`] = `"Both errored"`;
@@ -1,3 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-enum-declaration TSESTree - Error 1`] = `"NO ERROR"`;
exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-enum-declaration TSESTree - Error 1`] = `
"TSError
> 1 | // TODO: This fixture might be too large, and if so should be split up.
| ^ Decorators are not valid here.
2 |
3 | @dec enum E {}"
`;
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-enum-declaration Error Alignment 1`] = `"Babel errored but TSESTree didn't"`;
exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-enum-declaration Error Alignment 1`] = `"Both errored"`;
@@ -1,3 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-interface-declaration TSESTree - Error 1`] = `"NO ERROR"`;
exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-interface-declaration TSESTree - Error 1`] = `
"TSError
> 1 | // TODO: This fixture might be too large, and if so should be split up.
| ^ Decorators are not valid here.
2 |
3 | @deco()
4 | interface M {}"
`;
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-interface-declaration Error Alignment 1`] = `"Babel errored but TSESTree didn't"`;
exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-interface-declaration Error Alignment 1`] = `"Both errored"`;
@@ -1,3 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-variable TSESTree - Error 1`] = `"NO ERROR"`;
exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-variable TSESTree - Error 1`] = `
"TSError
> 1 | // TODO: This fixture might be too large, and if so should be split up.
| ^ Decorators are not valid here.
2 |
3 | @deco()
4 | const a = 1"
`;
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-variable Error Alignment 1`] = `"Babel errored but TSESTree didn't"`;
exports[`AST Fixtures legacy-fixtures errorRecovery _error_ decorator-on-variable Error Alignment 1`] = `"Both errored"`;
@@ -1,3 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures legacy-fixtures errorRecovery _error_ solo-const TSESTree - Error 1`] = `"NO ERROR"`;
exports[`AST Fixtures legacy-fixtures errorRecovery _error_ solo-const TSESTree - Error 1`] = `
"TSError
> 1 | // TODO: This fixture might be too large, and if so should be split up.
| ^ A variable declaration list must have at least one variable declarator.
2 |
3 | const"
`;
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures legacy-fixtures errorRecovery _error_ solo-const Error Alignment 1`] = `"Babel errored but TSESTree didn't"`;
exports[`AST Fixtures legacy-fixtures errorRecovery _error_ solo-const Error Alignment 1`] = `"Both errored"`;
@@ -0,0 +1,3 @@
{
throw
}
@@ -0,0 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures statement ThrowStatement _error_ missing-argument TSESTree - Error 1`] = `
"TSError
> 1 | {
| ^ A throw statement must throw an expression.
2 | throw
3 | }
4 |"
`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures statement ThrowStatement _error_ missing-argument Babel - Error 1`] = `[SyntaxError: Illegal newline after throw. (2:9)]`;
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AST Fixtures statement ThrowStatement _error_ missing-argument Error Alignment 1`] = `"Both errored"`;
6 changes: 0 additions & 6 deletions packages/ast-spec/tests/fixtures-with-differences-errors.shot
Expand Up @@ -8,7 +8,6 @@ Object {
"declaration/ClassDeclaration/fixtures/_error_/missing-type-param/fixture.ts",
"declaration/ExportAllDeclaration/fixtures/_error_/kind-type/fixture.ts",
"declaration/ExportAllDeclaration/fixtures/_error_/type-kind/fixture.ts",
"declaration/ExportNamedDeclaration/fixtures/_error_/anonymous-class/fixture.ts",
"declaration/ExportNamedDeclaration/fixtures/_error_/assertion/fixture.ts",
"declaration/FunctionDeclaration/fixtures/_error_/missing-type-param/fixture.ts",
"declaration/TSDeclareFunction/fixtures/_error_/async/fixture.ts",
Expand All @@ -20,7 +19,6 @@ Object {
"declaration/TSInterfaceDeclaration/fixtures/_error_/missing-type-param/fixture.ts",
"declaration/TSInterfaceDeclaration/fixtures/_error_/non-identifier-extends/fixture.ts",
"declaration/TSTypeAliasDeclaration/fixtures/_error_/missing-type-parameter/fixture.ts",
"declaration/VariableDeclaration/fixtures/_error_/missing-id-without-value/fixture.ts",
"element/AccessorProperty/fixtures/_error_/modifier-override-with-no-extends/fixture.ts",
"legacy-fixtures/basics/fixtures/_error_/abstract-class-with-abstract-static-constructor/fixture.ts",
"legacy-fixtures/basics/fixtures/_error_/abstract-class-with-override-property/fixture.ts",
Expand All @@ -45,10 +43,7 @@ Object {
"legacy-fixtures/errorRecovery/fixtures/_error_/class-empty-extends/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/class-extends-empty-implements/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/class-multiple-implements/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-enum-declaration/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-function/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-interface-declaration/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/decorator-on-variable/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/empty-type-arguments-in-call-expression/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/empty-type-arguments-in-new-expression/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/empty-type-arguments/fixture.ts",
Expand Down Expand Up @@ -77,7 +72,6 @@ Object {
"legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-public/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/interface-property-static/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/interface-with-optional-index-signature/fixture.ts",
"legacy-fixtures/errorRecovery/fixtures/_error_/solo-const/fixture.ts",
"legacy-fixtures/parameter-decorators/fixtures/_error_/parameter-array-pattern-decorator/fixture.ts",
"legacy-fixtures/parameter-decorators/fixtures/_error_/parameter-rest-element-decorator/fixture.ts",
},
Expand Down
1 change: 1 addition & 0 deletions packages/ast-spec/tests/util/parsers/typescript-estree.ts
Expand Up @@ -8,6 +8,7 @@ export function parseTSESTree(
): ParserResponse {
try {
const result = parse(contents, {
allowInvalidAST: fixture.config.allowInvalidAST,
comment: false,
jsx: fixture.ext.endsWith('x'),
loc: true,
Expand Down
6 changes: 6 additions & 0 deletions packages/ast-spec/typings/global.d.ts
Expand Up @@ -4,6 +4,12 @@
* This is a convenient property because it saves us from a lot of `../`!
*/
interface ASTFixtureConfig {
/**
* Prevents the parser from throwing an error if it receives an invalid AST from TypeScript.
* This case only usually occurs when attempting to lint invalid code.
*/
readonly allowInvalidAST?: boolean;

/**
* Specifies that we expect that babel doesn't yet support the code in this fixture, so we expect that it will error.
* This should not be used if we expect babel to throw for this feature due to a valid parser error!
Expand Down
2 changes: 0 additions & 2 deletions packages/eslint-plugin/tests/rules/indent/indent.test.ts
Expand Up @@ -758,8 +758,6 @@ const div: JQuery<HTMLElement> = $('<div>')
`,
options: [2, { VariableDeclarator: { const: 3 } }],
},
// https://github.com/typescript-eslint/typescript-eslint/issues/441
'const;',

// https://github.com/typescript-eslint/typescript-eslint/issues/1115
{
Expand Down
2 changes: 0 additions & 2 deletions packages/parser/tests/lib/parser.ts
Expand Up @@ -35,7 +35,6 @@ describe('parser', () => {
// ts-estree specific
filePath: 'isolated-file.src.ts',
project: 'tsconfig.json',
errorOnUnknownASTType: false,
errorOnTypeScriptSyntacticAndSemanticIssues: false,
tsconfigRootDir: 'tests/fixtures/services',
extraFileExtensions: ['.foo'],
Expand Down Expand Up @@ -89,7 +88,6 @@ describe('parser', () => {
// ts-estree specific
filePath: 'isolated-file.src.ts',
project: 'tsconfig.json',
errorOnUnknownASTType: false,
errorOnTypeScriptSyntacticAndSemanticIssues: false,
tsconfigRootDir: 'tests/fixtures/services',
extraFileExtensions: ['.foo'],
Expand Down
1 change: 1 addition & 0 deletions packages/typescript-estree/src/ast-converter.ts
Expand Up @@ -26,6 +26,7 @@ export function astConverter(
* Recursively convert the TypeScript AST into an ESTree-compatible AST
*/
const instance = new Converter(ast, {
allowInvalidAST: parseSettings.allowInvalidAST || false,
errorOnUnknownASTType: parseSettings.errorOnUnknownASTType || false,
shouldPreserveNodeMaps,
});
Expand Down

0 comments on commit a3b177d

Please sign in to comment.