@@ -587,6 +587,159 @@ test('mergeWithFileConfig: tsx files', async t => {
587587 } ) ;
588588} ) ;
589589
590+ test ( 'mergeWithFileConfigs: nested configs with prettier' , async t => {
591+ const cwd = path . resolve ( 'fixtures' , 'nested-configs' ) ;
592+ const paths = [
593+ 'no-semicolon.js' ,
594+ 'child/semicolon.js' ,
595+ 'child-override/two-spaces.js' ,
596+ 'child-override/child-prettier-override/semicolon.js' ,
597+ ] . map ( file => path . resolve ( cwd , file ) ) ;
598+ const result = await manager . mergeWithFileConfigs ( paths , { cwd} , [
599+ {
600+ filepath : path . resolve ( cwd , 'child-override' , 'child-prettier-override' , 'package.json' ) ,
601+ config : { overrides : [ { files : 'semicolon.js' , prettier : true } ] } ,
602+ } ,
603+ { filepath : path . resolve ( cwd , 'package.json' ) , config : { semicolon : true } } ,
604+ {
605+ filepath : path . resolve ( cwd , 'child-override' , 'package.json' ) ,
606+ config : { overrides : [ { files : 'two-spaces.js' , space : 4 } ] } ,
607+ } ,
608+ { filepath : path . resolve ( cwd , 'child' , 'package.json' ) , config : { semicolon : false } } ,
609+ ] ) ;
610+
611+ t . deepEqual ( result , [
612+ {
613+ files : [ path . resolve ( cwd , 'no-semicolon.js' ) ] ,
614+ options : {
615+ semicolon : true ,
616+ cwd,
617+ extensions : DEFAULT_EXTENSION ,
618+ ignores : DEFAULT_IGNORES ,
619+ } ,
620+ prettierOptions : { } ,
621+ } ,
622+ {
623+ files : [ path . resolve ( cwd , 'child/semicolon.js' ) ] ,
624+ options : {
625+ semicolon : false ,
626+ cwd : path . resolve ( cwd , 'child' ) ,
627+ extensions : DEFAULT_EXTENSION ,
628+ ignores : DEFAULT_IGNORES ,
629+ } ,
630+ prettierOptions : { } ,
631+ } ,
632+ {
633+ files : [ path . resolve ( cwd , 'child-override/two-spaces.js' ) ] ,
634+ options : {
635+ space : 4 ,
636+ rules : { } ,
637+ settings : { } ,
638+ globals : [ ] ,
639+ envs : [ ] ,
640+ plugins : [ ] ,
641+ extends : [ ] ,
642+ cwd : path . resolve ( cwd , 'child-override' ) ,
643+ extensions : DEFAULT_EXTENSION ,
644+ ignores : DEFAULT_IGNORES ,
645+ } ,
646+ prettierOptions : { } ,
647+ } ,
648+ {
649+ files : [ path . resolve ( cwd , 'child-override/child-prettier-override/semicolon.js' ) ] ,
650+ options : {
651+ prettier : true ,
652+ rules : { } ,
653+ settings : { } ,
654+ globals : [ ] ,
655+ envs : [ ] ,
656+ plugins : [ ] ,
657+ extends : [ ] ,
658+ cwd : path . resolve ( cwd , 'child-override' , 'child-prettier-override' ) ,
659+ extensions : DEFAULT_EXTENSION ,
660+ ignores : DEFAULT_IGNORES ,
661+ } ,
662+ prettierOptions : { endOfLine : 'lf' , semi : false , useTabs : true } ,
663+ } ,
664+ ] ) ;
665+ } ) ;
666+
667+ test ( 'mergeWithFileConfigs: typescript files' , async t => {
668+ const cwd = path . resolve ( 'fixtures' , 'typescript' ) ;
669+ const paths = [ 'two-spaces.tsx' , 'child/extra-semicolon.ts' , 'child/sub-child/four-spaces.ts' ] . map ( file => path . resolve ( cwd , file ) ) ;
670+ const configFiles = [
671+ { filepath : path . resolve ( cwd , 'child/sub-child/package.json' ) , config : { space : 2 } } ,
672+ { filepath : path . resolve ( cwd , 'package.json' ) , config : { space : 4 } } ,
673+ { filepath : path . resolve ( cwd , 'child/package.json' ) , config : { semicolon : false } } ,
674+ ] ;
675+ const result = await manager . mergeWithFileConfigs ( paths , { cwd} , configFiles ) ;
676+
677+ t . deepEqual ( omit ( result [ 0 ] , 'options.tsConfigPath' ) , {
678+ files : [ path . resolve ( cwd , 'two-spaces.tsx' ) ] ,
679+ options : {
680+ space : 4 ,
681+ cwd,
682+ extensions : DEFAULT_EXTENSION ,
683+ ignores : DEFAULT_IGNORES ,
684+ ts : true ,
685+ } ,
686+ prettierOptions : { } ,
687+ } ) ;
688+ t . deepEqual ( await readJson ( result [ 0 ] . options . tsConfigPath ) , {
689+ files : [ path . resolve ( cwd , 'two-spaces.tsx' ) ] ,
690+ compilerOptions : {
691+ newLine : 'lf' ,
692+ noFallthroughCasesInSwitch : true ,
693+ noImplicitReturns : true ,
694+ noUnusedLocals : true ,
695+ noUnusedParameters : true ,
696+ strict : true ,
697+ target : 'es2018' ,
698+ } ,
699+ } ) ;
700+
701+ t . deepEqual ( omit ( result [ 1 ] , 'options.tsConfigPath' ) , {
702+ files : [ path . resolve ( cwd , 'child/extra-semicolon.ts' ) ] ,
703+ options : {
704+ semicolon : false ,
705+ cwd : path . resolve ( cwd , 'child' ) ,
706+ extensions : DEFAULT_EXTENSION ,
707+ ignores : DEFAULT_IGNORES ,
708+ ts : true ,
709+ } ,
710+ prettierOptions : { } ,
711+ } ) ;
712+
713+ t . deepEqual ( omit ( result [ 2 ] , 'options.tsConfigPath' ) , {
714+ files : [ path . resolve ( cwd , 'child/sub-child/four-spaces.ts' ) ] ,
715+ options : {
716+ space : 2 ,
717+ cwd : path . resolve ( cwd , 'child/sub-child' ) ,
718+ extensions : DEFAULT_EXTENSION ,
719+ ignores : DEFAULT_IGNORES ,
720+ ts : true ,
721+ } ,
722+ prettierOptions : { } ,
723+ } ) ;
724+
725+ // Verify that we use the same temporary tsconfig.json for both files group sharing the same original tsconfig.json even if they have different xo config
726+ t . is ( result [ 1 ] . options . tsConfigPath , result [ 2 ] . options . tsConfigPath ) ;
727+ t . deepEqual ( await readJson ( result [ 1 ] . options . tsConfigPath ) , {
728+ extends : path . resolve ( cwd , 'child/tsconfig.json' ) ,
729+ files : [ path . resolve ( cwd , 'child/extra-semicolon.ts' ) , path . resolve ( cwd , 'child/sub-child/four-spaces.ts' ) ] ,
730+ include : [
731+ slash ( path . resolve ( cwd , 'child/**/*.ts' ) ) ,
732+ slash ( path . resolve ( cwd , 'child/**/*.tsx' ) ) ,
733+ ] ,
734+ } ) ;
735+
736+ const secondResult = await manager . mergeWithFileConfigs ( paths , { cwd} , configFiles ) ;
737+
738+ // Verify that on each run the options.tsConfigPath is consistent to preserve ESLint cache
739+ t . is ( result [ 0 ] . options . tsConfigPath , secondResult [ 0 ] . options . tsConfigPath ) ;
740+ t . is ( result [ 1 ] . options . tsConfigPath , secondResult [ 1 ] . options . tsConfigPath ) ;
741+ } ) ;
742+
590743test ( 'applyOverrides' , t => {
591744 t . deepEqual (
592745 manager . applyOverrides (
0 commit comments