Skip to content

Commit b801d56

Browse files
committed
feat: try all known parsers at runtime if no parser specific
1 parent d054d93 commit b801d56

File tree

4 files changed

+54
-34
lines changed

4 files changed

+54
-34
lines changed

.eslintrc.js

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,13 @@ tsNode.register({
1010
module.exports = {
1111
root: true,
1212
extends: ['@1stg/eslint-config/recommended'],
13-
overrides: [
14-
{
15-
files: '*.ts',
16-
settings: {
17-
node: {
18-
allowModules: ['@babel/types', 'estree', 'unist'],
19-
},
20-
},
21-
rules: {
22-
'@typescript-eslint/no-unnecessary-condition': 0,
23-
'@typescript-eslint/unbound-method': 0, // See https://github.com/typescript-eslint/typescript-eslint/issues/636
24-
},
13+
settings: {
14+
node: {
15+
allowModules: ['@babel/types', 'estree', 'unist'],
2516
},
26-
],
17+
},
18+
rules: {
19+
'@typescript-eslint/no-unnecessary-condition': 0,
20+
'@typescript-eslint/unbound-method': 0, // See https://github.com/typescript-eslint/typescript-eslint/issues/636
21+
},
2722
}

packages/eslint-mdx/src/helper.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// <reference path="../typings.d.ts" />
22

3-
import { AST } from 'eslint'
3+
import { AST, Linter } from 'eslint'
44
import { parse as esParse } from 'espree'
55
import { SourceLocation } from 'estree'
66
import { Position } from 'unist'
@@ -40,24 +40,31 @@ export const normalizeParser = (parser?: ParserOptions['parser']) => {
4040
if (typeof parser !== 'function') {
4141
throw new TypeError(`Invalid custom parser for \`eslint-mdx\`: ${parser}`)
4242
}
43-
} else {
44-
// try to load FALLBACK_PARSERS automatically
45-
for (const fallback of FALLBACK_PARSERS) {
46-
try {
47-
// eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/no-var-requires
48-
const fallbackParser = require(fallback)
49-
/* istanbul ignore next */
50-
parser = fallbackParser.parseForESLint || fallbackParser.parse
51-
break
52-
} catch (e) {}
53-
}
5443

55-
if (typeof parser !== 'function') {
56-
parser = esParse as ParserFn
57-
}
44+
return [parser]
45+
}
46+
47+
const parsers = [esParse as ParserFn]
48+
49+
// try to load FALLBACK_PARSERS automatically
50+
for (const fallback of FALLBACK_PARSERS) {
51+
try {
52+
// eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/no-var-requires
53+
const fallbackParser: Linter.ParserModule = require(fallback)
54+
/* istanbul ignore next */
55+
const parserFn =
56+
'parseForESLint' in fallbackParser
57+
? fallbackParser.parseForESLint
58+
: fallbackParser.parse
59+
/* istanbul ignore else */
60+
if (parserFn) {
61+
parsers.unshift(parserFn)
62+
}
63+
break
64+
} catch (e) {}
5865
}
5966

60-
return parser
67+
return parsers
6168
}
6269

6370
export const normalizePosition = (

packages/eslint-mdx/src/parser.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const OFFSET = JSX_WRAPPER_START.length
4848

4949
export class Parser {
5050
// @internal
51-
private _parser: ParserFn
51+
private _parsers: ParserFn[]
5252

5353
// @internal
5454
private _ast: AST.Program
@@ -191,14 +191,32 @@ export class Parser {
191191

192192
// @internal
193193
private _eslintParse(code: string, options: ParserOptions) {
194-
if (!this._parser || options.parser !== this._options.parser) {
195-
this._parser = normalizeParser(options.parser)
194+
if (!this._parsers || options.parser !== this._options.parser) {
195+
this._parsers = normalizeParser(options.parser)
196196
}
197+
197198
/* istanbul ignore else */
198199
if (options.filePath && this._options !== options) {
199200
Object.assign(this._options, options)
200201
}
201-
const program = this._parser(code, this._options)
202+
203+
let program: ReturnType<ParserFn>
204+
let parseError: Error
205+
for (const parser of this._parsers) {
206+
try {
207+
program = parser(code, this._options)
208+
break
209+
} catch (e) {
210+
if (!parseError) {
211+
parseError = e
212+
}
213+
}
214+
}
215+
216+
if (!program && parseError) {
217+
throw parseError
218+
}
219+
202220
/* istanbul ignore next */
203221
return ('ast' in program && program.ast
204222
? program

test/parser.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ describe('parser', () => {
141141

142142
it('should fallback to espree if no preferred parsers found', () => {
143143
jest.mock('@typescript-eslint/parser', noop).mock('babel-eslint', noop)
144-
expect(normalizeParser()).toBe(parse)
144+
expect(normalizeParser()).toContain(parse)
145145
jest.unmock('@typescript-eslint/parser').unmock('babel-eslint')
146146
})
147147

0 commit comments

Comments
 (0)