blob: b3a469221defc5538b3c63da10bd5c5d80b49f88 [file] [log] [blame]
Tim van der Lippefdbd42e2020-04-07 15:14:36 +01001'use strict'
2exports.__esModule = true
3
4const moduleRequire = require('./module-require').default
5const extname = require('path').extname
6
7const log = require('debug')('eslint-plugin-import:parse')
8
9exports.default = function parse(path, content, context) {
10
11 if (context == null) throw new Error('need context to parse properly')
12
13 let parserOptions = context.parserOptions
14 const parserPath = getParserPath(path, context)
15
16 if (!parserPath) throw new Error('parserPath is required!')
17
18 // hack: espree blows up with frozen options
19 parserOptions = Object.assign({}, parserOptions)
20 parserOptions.ecmaFeatures = Object.assign({}, parserOptions.ecmaFeatures)
21
22 // always include comments and tokens (for doc parsing)
23 parserOptions.comment = true
24 parserOptions.attachComment = true // keeping this for backward-compat with older parsers
25 parserOptions.tokens = true
26
27 // attach node locations
28 parserOptions.loc = true
29 parserOptions.range = true
30
31 // provide the `filePath` like eslint itself does, in `parserOptions`
32 // https://github.com/eslint/eslint/blob/3ec436ee/lib/linter.js#L637
33 parserOptions.filePath = path
34
35 // @typescript-eslint/parser will parse the entire project with typechecking if you provide
36 // "project" or "projects" in parserOptions. Removing these options means the parser will
37 // only parse one file in isolate mode, which is much, much faster.
38 // https://github.com/benmosher/eslint-plugin-import/issues/1408#issuecomment-509298962
39 delete parserOptions.project
40 delete parserOptions.projects
41
42 // require the parser relative to the main module (i.e., ESLint)
43 const parser = moduleRequire(parserPath)
44
45 if (typeof parser.parseForESLint === 'function') {
46 let ast
47 try {
48 ast = parser.parseForESLint(content, parserOptions).ast
49 } catch (e) {
50 console.warn()
51 console.warn('Error while parsing ' + parserOptions.filePath)
52 console.warn('Line ' + e.lineNumber + ', column ' + e.column + ': ' + e.message)
53 }
54 if (!ast || typeof ast !== 'object') {
55 console.warn(
56 '`parseForESLint` from parser `' +
57 parserPath +
58 '` is invalid and will just be ignored'
59 )
60 } else {
61 return ast
62 }
63 }
64
65 return parser.parse(content, parserOptions)
66}
67
68function getParserPath(path, context) {
69 const parsers = context.settings['import/parsers']
70 if (parsers != null) {
71 const extension = extname(path)
72 for (let parserPath in parsers) {
73 if (parsers[parserPath].indexOf(extension) > -1) {
74 // use this alternate parser
75 log('using alt parser:', parserPath)
76 return parserPath
77 }
78 }
79 }
80 // default to use ESLint parser
81 return context.parserPath
82}