@@ -179,12 +179,12 @@ function parseListConfig(string) {
179179 * scope.
180180 * @param {Scope } globalScope The global scope.
181181 * @param {Object } config The existing configuration data.
182+ * @param {{exportedVariables: Object, enabledGlobals: Object} } commentDirectives Directives from comment configuration
182183 * @param {Environments } envContext Env context
183184 * @returns {void }
184185 */
185- function addDeclaredGlobals ( globalScope , config , envContext ) {
186+ function addDeclaredGlobals ( globalScope , config , commentDirectives , envContext ) {
186187 const declaredGlobals = { } ,
187- exportedGlobals = { } ,
188188 explicitGlobals = { } ,
189189 builtin = envContext . get ( "builtin" ) ;
190190
@@ -199,9 +199,8 @@ function addDeclaredGlobals(globalScope, config, envContext) {
199199 }
200200 } ) ;
201201
202- Object . assign ( exportedGlobals , config . exported ) ;
203202 Object . assign ( declaredGlobals , config . globals ) ;
204- Object . assign ( explicitGlobals , config . astGlobals ) ;
203+ Object . assign ( explicitGlobals , commentDirectives . enabledGlobals ) ;
205204
206205 Object . keys ( declaredGlobals ) . forEach ( name => {
207206 let variable = globalScope . set . get ( name ) ;
@@ -229,7 +228,7 @@ function addDeclaredGlobals(globalScope, config, envContext) {
229228 } ) ;
230229
231230 // mark all exported variables as such
232- Object . keys ( exportedGlobals ) . forEach ( name => {
231+ Object . keys ( commentDirectives . exportedVariables ) . forEach ( name => {
233232 const variable = globalScope . set . get ( name ) ;
234233
235234 if ( variable ) {
@@ -283,108 +282,90 @@ function createDisableDirectives(type, loc, value) {
283282 * where reporting is disabled or enabled and merges them with reporting config.
284283 * @param {string } filename The file being checked.
285284 * @param {ASTNode } ast The top node of the AST.
286- * @param {Object } config The existing configuration data.
287285 * @param {function(string): {create: Function} } ruleMapper A map from rule IDs to defined rules
288- * @returns {{config : Object, problems: Problem[], disableDirectives: DisableDirective[]} }
289- * Modified config object , along with any problems encountered while parsing config comments
286+ * @returns {{configuredRules: Object, enabledGlobals: Object, exportedVariables : Object, problems: Problem[], disableDirectives: DisableDirective[]} }
287+ * A collection of the directive comments that were found , along with any problems that occurred when parsing
290288 */
291- function modifyConfigsFromComments ( filename , ast , config , ruleMapper ) {
292-
293- const commentConfig = {
294- exported : { } ,
295- astGlobals : { } ,
296- rules : { } ,
297- env : { }
298- } ;
299- const commentRules = { } ;
289+ function getDirectiveComments ( filename , ast , ruleMapper ) {
290+ const configuredRules = { } ;
291+ const enabledGlobals = { } ;
292+ const exportedVariables = { } ;
300293 const problems = [ ] ;
301294 const disableDirectives = [ ] ;
302295
303296 ast . comments . filter ( token => token . type !== "Shebang" ) . forEach ( comment => {
297+ const trimmedCommentText = comment . value . trim ( ) ;
298+ const match = / ^ ( e s l i n t ( - \w + ) { 0 , 3 } | e x p o r t e d | g l o b a l s ? ) ( \s | $ ) / . exec ( trimmedCommentText ) ;
304299
305- let value = comment . value . trim ( ) ;
306- const match = / ^ ( e s l i n t ( - \w + ) { 0 , 3 } | e x p o r t e d | g l o b a l s ? ) ( \s | $ ) / . exec ( value ) ;
307-
308- if ( match ) {
309- value = value . slice ( match . index + match [ 1 ] . length ) ;
310- if ( comment . type === "Block" ) {
311- switch ( match [ 1 ] ) {
312- case "exported" :
313- Object . assign ( commentConfig . exported , parseBooleanConfig ( value , comment ) ) ;
314- break ;
315-
316- case "globals" :
317- case "global" :
318- Object . assign ( commentConfig . astGlobals , parseBooleanConfig ( value , comment ) ) ;
319- break ;
320-
321- case "eslint-disable" :
322- [ ] . push . apply ( disableDirectives , createDisableDirectives ( "disable" , comment . loc . start , value ) ) ;
323- break ;
324-
325- case "eslint-disable-line" :
326- if ( comment . loc . start . line === comment . loc . end . line ) {
327- [ ] . push . apply ( disableDirectives , createDisableDirectives ( "disable-line" , comment . loc . start , value ) ) ;
328- }
329- break ;
330-
331- case "eslint-disable-next-line" :
332- if ( comment . loc . start . line === comment . loc . end . line ) {
333- [ ] . push . apply ( disableDirectives , createDisableDirectives ( "disable-next-line" , comment . loc . start , value ) ) ;
334- }
335- break ;
336-
337- case "eslint-enable" :
338- [ ] . push . apply ( disableDirectives , createDisableDirectives ( "enable" , comment . loc . start , value ) ) ;
339- break ;
340-
341- case "eslint" : {
342- const parseResult = parseJsonConfig ( value , comment . loc ) ;
343-
344- if ( parseResult . success ) {
345- Object . keys ( parseResult . config ) . forEach ( name => {
346- const ruleValue = parseResult . config [ name ] ;
347-
348- try {
349- validator . validateRuleOptions ( ruleMapper ( name ) , name , ruleValue ) ;
350- } catch ( err ) {
351- problems . push ( {
352- ruleId : name ,
353- severity : 2 ,
354- source : null ,
355- message : err . message ,
356- line : comment . loc . start . line ,
357- column : comment . loc . start . column + 1 ,
358- endLine : comment . loc . end . line ,
359- endColumn : comment . loc . end . column + 1 ,
360- nodeType : null
361- } ) ;
362- }
363- commentRules [ name ] = ruleValue ;
364- } ) ;
365- } else {
366- problems . push ( parseResult . error ) ;
367- }
300+ if ( ! match ) {
301+ return ;
302+ }
368303
369- break ;
304+ const directiveValue = trimmedCommentText . slice ( match . index + match [ 1 ] . length ) ;
305+
306+ if ( / ^ e s l i n t - d i s a b l e - ( n e x t - ) ? l i n e $ / . test ( match [ 1 ] ) && comment . loc . start . line === comment . loc . end . line ) {
307+ const directiveType = match [ 1 ] . slice ( "eslint-" . length ) ;
308+
309+ [ ] . push . apply ( disableDirectives , createDisableDirectives ( directiveType , comment . loc . start , directiveValue ) ) ;
310+ } else if ( comment . type === "Block" ) {
311+ switch ( match [ 1 ] ) {
312+ case "exported" :
313+ Object . assign ( exportedVariables , parseBooleanConfig ( directiveValue , comment ) ) ;
314+ break ;
315+
316+ case "globals" :
317+ case "global" :
318+ Object . assign ( enabledGlobals , parseBooleanConfig ( directiveValue , comment ) ) ;
319+ break ;
320+
321+ case "eslint-disable" :
322+ [ ] . push . apply ( disableDirectives , createDisableDirectives ( "disable" , comment . loc . start , directiveValue ) ) ;
323+ break ;
324+
325+ case "eslint-enable" :
326+ [ ] . push . apply ( disableDirectives , createDisableDirectives ( "enable" , comment . loc . start , directiveValue ) ) ;
327+ break ;
328+
329+ case "eslint" : {
330+ const parseResult = parseJsonConfig ( directiveValue , comment . loc ) ;
331+
332+ if ( parseResult . success ) {
333+ Object . keys ( parseResult . config ) . forEach ( name => {
334+ const ruleValue = parseResult . config [ name ] ;
335+
336+ try {
337+ validator . validateRuleOptions ( ruleMapper ( name ) , name , ruleValue ) ;
338+ } catch ( err ) {
339+ problems . push ( {
340+ ruleId : name ,
341+ severity : 2 ,
342+ source : null ,
343+ message : err . message ,
344+ line : comment . loc . start . line ,
345+ column : comment . loc . start . column + 1 ,
346+ endLine : comment . loc . end . line ,
347+ endColumn : comment . loc . end . column + 1 ,
348+ nodeType : null
349+ } ) ;
350+ }
351+ configuredRules [ name ] = ruleValue ;
352+ } ) ;
353+ } else {
354+ problems . push ( parseResult . error ) ;
370355 }
371356
372- // no default
373- }
374- } else { // comment.type === "Line"
375- if ( match [ 1 ] === "eslint-disable-line" ) {
376- [ ] . push . apply ( disableDirectives , createDisableDirectives ( "disable-line" , comment . loc . start , value ) ) ;
377- } else if ( match [ 1 ] === "eslint-disable-next-line" ) {
378- [ ] . push . apply ( disableDirectives , createDisableDirectives ( "disable-next-line" , comment . loc . start , value ) ) ;
357+ break ;
379358 }
359+
360+ // no default
380361 }
381362 }
382363 } ) ;
383364
384- Object . assign ( commentConfig . rules , commentRules ) ;
385-
386365 return {
387- config : ConfigOps . merge ( config , commentConfig ) ,
366+ configuredRules,
367+ enabledGlobals,
368+ exportedVariables,
388369 problems,
389370 disableDirectives
390371 } ;
@@ -775,10 +756,11 @@ module.exports = class Linter {
775756 // evaluate arguments
776757 if ( typeof filenameOrOptions === "object" ) {
777758 providedFilename = filenameOrOptions . filename ;
778- allowInlineConfig = filenameOrOptions . allowInlineConfig ;
759+ allowInlineConfig = filenameOrOptions . allowInlineConfig !== false ;
779760 reportUnusedDisableDirectives = filenameOrOptions . reportUnusedDisableDirectives ;
780761 } else {
781762 providedFilename = filenameOrOptions ;
763+ allowInlineConfig = true ;
782764 }
783765
784766 if ( typeof textOrSourceCode === "string" ) {
@@ -861,24 +843,23 @@ module.exports = class Linter {
861843 }
862844 }
863845
864- const problems = [ ] ;
865846 const sourceCode = lastSourceCodes . get ( this ) ;
866- let disableDirectives ;
847+ const commentDirectives = allowInlineConfig
848+ ? getDirectiveComments ( filename , sourceCode . ast , ruleId => this . rules . get ( ruleId ) )
849+ : { configuredRules : { } , enabledGlobals : { } , exportedVariables : { } , problems : [ ] , disableDirectives : [ ] } ;
867850
868- // parse global comments and modify config
869- if ( allowInlineConfig !== false ) {
870- const modifyConfigResult = modifyConfigsFromComments ( filename , sourceCode . ast , config , ruleId => this . rules . get ( ruleId ) ) ;
851+ const configuredRules = Object . assign ( { } , config . rules , commentDirectives . configuredRules ) ;
871852
872- config = modifyConfigResult . config ;
873- modifyConfigResult . problems . forEach ( problem => problems . push ( problem ) ) ;
874- disableDirectives = modifyConfigResult . disableDirectives ;
875- } else {
876- disableDirectives = [ ] ;
877- }
853+ // augment global scope with declared global variables
854+ addDeclaredGlobals (
855+ sourceCode . scopeManager . scopes [ 0 ] ,
856+ config ,
857+ { exportedVariables : commentDirectives . exportedVariables , enabledGlobals : commentDirectives . enabledGlobals } ,
858+ this . environments
859+ ) ;
878860
879861 const emitter = createEmitter ( ) ;
880862 const traverser = new Traverser ( ) ;
881- const scopeManager = sourceCode . scopeManager ;
882863
883864 /*
884865 * Create a frozen object with the ruleContext properties and methods that are shared by all rules.
@@ -890,11 +871,11 @@ module.exports = class Linter {
890871 Object . create ( BASE_TRAVERSAL_CONTEXT ) ,
891872 {
892873 getAncestors : ( ) => traverser . parents ( ) ,
893- getDeclaredVariables : scopeManager . getDeclaredVariables . bind ( scopeManager ) ,
874+ getDeclaredVariables : sourceCode . scopeManager . getDeclaredVariables . bind ( sourceCode . scopeManager ) ,
894875 getFilename : ( ) => filename ,
895- getScope : ( ) => getScope ( scopeManager , traverser . current ( ) , config . parserOptions . ecmaVersion ) ,
876+ getScope : ( ) => getScope ( sourceCode . scopeManager , traverser . current ( ) , config . parserOptions . ecmaVersion ) ,
896877 getSourceCode : ( ) => sourceCode ,
897- markVariableAsUsed : name => markVariableAsUsed ( scopeManager , traverser . current ( ) , config . parserOptions , name ) ,
878+ markVariableAsUsed : name => markVariableAsUsed ( sourceCode . scopeManager , traverser . current ( ) , config . parserOptions , name ) ,
898879 parserOptions : config . parserOptions ,
899880 parserPath : config . parser ,
900881 parserServices : sourceCode . parserServices ,
@@ -916,9 +897,11 @@ module.exports = class Linter {
916897 )
917898 ) ;
918899
900+ const lintingProblems = [ ] ;
901+
919902 // enable appropriate rules
920- Object . keys ( config . rules ) . forEach ( ruleId => {
921- const severity = ConfigOps . getRuleSeverity ( config . rules [ ruleId ] ) ;
903+ Object . keys ( configuredRules ) . forEach ( ruleId => {
904+ const severity = ConfigOps . getRuleSeverity ( configuredRules [ ruleId ] ) ;
922905
923906 if ( severity === 0 ) {
924907 return ;
@@ -932,7 +915,7 @@ module.exports = class Linter {
932915 Object . create ( sharedTraversalContext ) ,
933916 {
934917 id : ruleId ,
935- options : getRuleOptions ( config . rules [ ruleId ] ) ,
918+ options : getRuleOptions ( configuredRules [ ruleId ] ) ,
936919 report ( ) {
937920
938921 /*
@@ -953,7 +936,7 @@ module.exports = class Linter {
953936 if ( problem . fix && rule . meta && ! rule . meta . fixable ) {
954937 throw new Error ( "Fixable rules should export a `meta.fixable` property." ) ;
955938 }
956- problems . push ( problem ) ;
939+ lintingProblems . push ( problem ) ;
957940
958941 /*
959942 * This is used to avoid breaking rules that used monkeypatch Linter, and relied on
@@ -995,9 +978,6 @@ module.exports = class Linter {
995978 }
996979 } ) ;
997980
998- // augment global scope with declared global variables
999- addDeclaredGlobals ( scopeManager . scopes [ 0 ] , config , this . environments ) ;
1000-
1001981 const eventGenerator = new CodePathAnalyzer ( new NodeEventGenerator ( emitter ) ) ;
1002982
1003983 /*
@@ -1018,8 +998,10 @@ module.exports = class Linter {
1018998 } ) ;
1019999
10201000 return applyDisableDirectives ( {
1021- directives : disableDirectives ,
1022- problems : problems . sort ( ( problemA , problemB ) => problemA . line - problemB . line || problemA . column - problemB . column ) ,
1001+ directives : commentDirectives . disableDirectives ,
1002+ problems : lintingProblems
1003+ . concat ( commentDirectives . problems )
1004+ . sort ( ( problemA , problemB ) => problemA . line - problemB . line || problemA . column - problemB . column ) ,
10231005 reportUnusedDisableDirectives
10241006 } ) ;
10251007 }
0 commit comments