11'use strict' ;
22const path = require ( 'path' ) ;
3- const eslint = require ( 'eslint' ) ;
3+ const { ESLint } = require ( 'eslint' ) ;
44const globby = require ( 'globby' ) ;
55const isEqual = require ( 'lodash/isEqual' ) ;
66const uniq = require ( 'lodash/uniq' ) ;
7+ const pick = require ( 'lodash/pick' ) ;
8+ const omit = require ( 'lodash/omit' ) ;
79const micromatch = require ( 'micromatch' ) ;
810const arrify = require ( 'arrify' ) ;
911const pReduce = require ( 'p-reduce' ) ;
12+ const pMap = require ( 'p-map' ) ;
1013const { cosmiconfig, defaultLoaders} = require ( 'cosmiconfig' ) ;
11- const { CONFIG_FILES , MODULE_NAME , DEFAULT_IGNORES } = require ( './lib/constants' ) ;
14+ const defineLazyProperty = require ( 'define-lazy-prop' ) ;
15+ const pFilter = require ( 'p-filter' ) ;
16+ const { CONFIG_FILES , MODULE_NAME , DEFAULT_IGNORES , LINT_METHOD_OPTIONS } = require ( './lib/constants' ) ;
1217const {
1318 normalizeOptions,
1419 getIgnores,
@@ -37,18 +42,68 @@ const mergeReports = reports => {
3742 } ;
3843} ;
3944
40- const processReport = ( report , options ) => {
41- report . results = options . quiet ? eslint . CLIEngine . getErrorResults ( report . results ) : report . results ;
42- return report ;
45+ const getReportStatistics = results => {
46+ let errorCount = 0 ;
47+ let warningCount = 0 ;
48+ let fixableErrorCount = 0 ;
49+ let fixableWarningCount = 0 ;
50+
51+ for ( const {
52+ errorCount : currentErrorCount ,
53+ warningCount : currentWarningCount ,
54+ fixableErrorCount : currentFixableErrorCount ,
55+ fixableWarningCount : currentFixableWarningCount
56+ } of results ) {
57+ errorCount += currentErrorCount ;
58+ warningCount += currentWarningCount ;
59+ fixableErrorCount += currentFixableErrorCount ;
60+ fixableWarningCount += currentFixableWarningCount ;
61+ }
62+
63+ return {
64+ errorCount,
65+ warningCount,
66+ fixableErrorCount,
67+ fixableWarningCount
68+ } ;
69+ } ;
70+
71+ const processReport = ( report , { isQuiet = false } = { } ) => {
72+ if ( isQuiet ) {
73+ report = ESLint . getErrorResults ( report ) ;
74+ }
75+
76+ const result = {
77+ results : report ,
78+ ...getReportStatistics ( report )
79+ } ;
80+
81+ defineLazyProperty ( result , 'usedDeprecatedRules' , ( ) => {
82+ const seenRules = new Set ( ) ;
83+ const rules = [ ] ;
84+
85+ for ( const { usedDeprecatedRules} of report ) {
86+ for ( const rule of usedDeprecatedRules ) {
87+ if ( seenRules . has ( rule . ruleId ) ) {
88+ continue ;
89+ }
90+
91+ seenRules . add ( rule . ruleId ) ;
92+ rules . push ( rule ) ;
93+ }
94+ }
95+
96+ return rules ;
97+ } ) ;
98+
99+ return result ;
43100} ;
44101
45- const runEslint = ( paths , options ) => {
46- const engine = new eslint . CLIEngine ( options ) ;
47- const report = engine . executeOnFiles (
48- paths . filter ( path => ! engine . isPathIgnored ( path ) ) ,
49- options
50- ) ;
51- return processReport ( report , options ) ;
102+ const runEslint = async ( paths , options , processorOptions ) => {
103+ const engine = new ESLint ( options ) ;
104+
105+ const report = await engine . lintFiles ( await pFilter ( paths , async path => ! ( await engine . isPathIgnored ( path ) ) ) ) ;
106+ return processReport ( report , processorOptions ) ;
52107} ;
53108
54109const globFiles = async ( patterns , { ignores, extensions, cwd} ) => (
@@ -57,30 +112,30 @@ const globFiles = async (patterns, {ignores, extensions, cwd}) => (
57112 { ignore : ignores , gitignore : true , cwd}
58113 ) ) . filter ( file => extensions . includes ( path . extname ( file ) . slice ( 1 ) ) ) . map ( file => path . resolve ( cwd , file ) ) ;
59114
60- const getConfig = options => {
115+ const getConfig = async options => {
61116 const { options : foundOptions , prettierOptions} = mergeWithFileConfig ( normalizeOptions ( options ) ) ;
62117 options = buildConfig ( foundOptions , prettierOptions ) ;
63- const engine = new eslint . CLIEngine ( options ) ;
64- return engine . getConfigForFile ( options . filename ) ;
118+ const engine = new ESLint ( omit ( options , LINT_METHOD_OPTIONS ) ) ;
119+ return engine . calculateConfigForFile ( options . filePath ) ;
65120} ;
66121
67- const lintText = ( string , options ) => {
68- const { options : foundOptions , prettierOptions} = mergeWithFileConfig ( normalizeOptions ( options ) ) ;
69- options = buildConfig ( foundOptions , prettierOptions ) ;
122+ const lintText = async ( string , inputOptions = { } ) => {
123+ const { options : foundOptions , prettierOptions} = mergeWithFileConfig ( normalizeOptions ( inputOptions ) ) ;
124+ const options = buildConfig ( foundOptions , prettierOptions ) ;
70125
71- if ( options . ignores && ! isEqual ( getIgnores ( { } ) , options . ignores ) && typeof options . filename !== 'string' ) {
72- throw new Error ( 'The `ignores` option requires the `filename ` option to be defined.' ) ;
126+ if ( options . baseConfig . ignorePatterns && ! isEqual ( getIgnores ( { } ) , options . baseConfig . ignorePatterns ) && typeof options . filePath !== 'string' ) {
127+ throw new Error ( 'The `ignores` option requires the `filePath ` option to be defined.' ) ;
73128 }
74129
75- const engine = new eslint . CLIEngine ( options ) ;
130+ const engine = new ESLint ( omit ( options , LINT_METHOD_OPTIONS ) ) ;
76131
77- if ( options . filename ) {
78- const filename = path . relative ( options . cwd , options . filename ) ;
132+ if ( options . filePath ) {
133+ const filename = path . relative ( options . cwd , options . filePath ) ;
79134
80135 if (
81- micromatch . isMatch ( filename , options . ignores ) ||
82- globby . gitignore . sync ( { cwd : options . cwd , ignore : options . ignores } ) ( options . filename ) ||
83- engine . isPathIgnored ( options . filename )
136+ micromatch . isMatch ( filename , options . baseConfig . ignorePatterns ) ||
137+ globby . gitignore . sync ( { cwd : options . cwd , ignore : options . baseConfig . ignorePatterns } ) ( options . filePath ) ||
138+ await engine . isPathIgnored ( options . filePath )
84139 ) {
85140 return {
86141 errorCount : 0 ,
@@ -95,39 +150,42 @@ const lintText = (string, options) => {
95150 }
96151 }
97152
98- const report = engine . executeOnText ( string , options . filename ) ;
153+ const report = await engine . lintText ( string , pick ( options , LINT_METHOD_OPTIONS ) ) ;
99154
100- return processReport ( report , options ) ;
155+ return processReport ( report , { isQuiet : inputOptions . quiet } ) ;
101156} ;
102157
103- const lintFiles = async ( patterns , options = { } ) => {
104- options . cwd = path . resolve ( options . cwd || process . cwd ( ) ) ;
105- const configExplorer = cosmiconfig ( MODULE_NAME , { searchPlaces : CONFIG_FILES , loaders : { noExt : defaultLoaders [ '.json' ] } , stopDir : options . cwd } ) ;
158+ const lintFiles = async ( patterns , inputOptions = { } ) => {
159+ inputOptions . cwd = path . resolve ( inputOptions . cwd || process . cwd ( ) ) ;
160+ const configExplorer = cosmiconfig ( MODULE_NAME , { searchPlaces : CONFIG_FILES , loaders : { noExt : defaultLoaders [ '.json' ] } , stopDir : inputOptions . cwd } ) ;
106161
107162 const configFiles = ( await Promise . all (
108163 ( await globby (
109164 CONFIG_FILES . map ( configFile => `**/${ configFile } ` ) ,
110- { ignore : DEFAULT_IGNORES , gitignore : true , cwd : options . cwd }
111- ) ) . map ( async configFile => configExplorer . load ( path . resolve ( options . cwd , configFile ) ) )
165+ { ignore : DEFAULT_IGNORES , gitignore : true , cwd : inputOptions . cwd }
166+ ) ) . map ( async configFile => configExplorer . load ( path . resolve ( inputOptions . cwd , configFile ) ) )
112167 ) ) . filter ( Boolean ) ;
113168
114169 const paths = configFiles . length > 0 ?
115170 await pReduce (
116171 configFiles ,
117172 async ( paths , { filepath, config} ) =>
118- [ ...paths , ...( await globFiles ( patterns , { ...mergeOptions ( options , config ) , cwd : path . dirname ( filepath ) } ) ) ] ,
173+ [ ...paths , ...( await globFiles ( patterns , { ...mergeOptions ( inputOptions , config ) , cwd : path . dirname ( filepath ) } ) ) ] ,
119174 [ ] ) :
120- await globFiles ( patterns , mergeOptions ( options ) ) ;
175+ await globFiles ( patterns , mergeOptions ( inputOptions ) ) ;
176+
177+ return mergeReports ( await pMap ( await mergeWithFileConfigs ( uniq ( paths ) , inputOptions , configFiles ) , async ( { files, options, prettierOptions} ) => runEslint ( files , buildConfig ( options , prettierOptions ) , { isQuiet : options . quiet } ) ) ) ;
178+ } ;
121179
122- return mergeReports ( ( await mergeWithFileConfigs ( uniq ( paths ) , options , configFiles ) ) . map (
123- ( { files , options , prettierOptions } ) => runEslint ( files , buildConfig ( options , prettierOptions ) ) )
124- ) ;
180+ const getFormatter = async name => {
181+ const { format } = await new ESLint ( ) . loadFormatter ( name ) ;
182+ return format ;
125183} ;
126184
127185module . exports = {
128- getFormatter : eslint . CLIEngine . getFormatter ,
129- getErrorResults : eslint . CLIEngine . getErrorResults ,
130- outputFixes : eslint . CLIEngine . outputFixes ,
186+ getFormatter,
187+ getErrorResults : ESLint . getErrorResults ,
188+ outputFixes : async ( { results } ) => ESLint . outputFixes ( results ) ,
131189 getConfig,
132190 lintText,
133191 lintFiles
0 commit comments