@@ -17,6 +17,20 @@ type ResolveFmtConfigOptions = {
1717type PathMatcher = ( filePath : string ) => boolean ;
1818type FmtOptionsResolver = ( filePath : string ) => ResolvedFmtOptions ;
1919
20+ /**
21+ * Each path from the root represents an ordered sequence of matching overrides.
22+ * A node stores the options merged along that path.
23+ */
24+ type OptionsCacheNode = {
25+ children : WeakMap < ResolvedFmtOptions , OptionsCacheNode > ;
26+ options : ResolvedFmtOptions ;
27+ } ;
28+
29+ const createOptionsCacheNode = ( options : ResolvedFmtOptions ) : OptionsCacheNode => ( {
30+ children : new WeakMap ( ) ,
31+ options,
32+ } ) ;
33+
2034const neverMatches : PathMatcher = ( ) => false ;
2135
2236const compileMatchers = (
@@ -96,22 +110,27 @@ const createOptionsResolver = (config: ResolvedFmtConfig): FmtOptionsResolver =>
96110 }
97111
98112 const resolveRelativePath = createRelativePathResolver ( config . rootPath ) ;
113+ const rootCacheNode = createOptionsCacheNode ( config . baseOptions ) ;
99114
100115 return ( filePath ) => {
101- let options = config . baseOptions ;
116+ let cacheNode = rootCacheNode ;
102117 const relativeFilePath = resolveRelativePath ( filePath ) ;
103118
104119 for ( const override of config . overrides ) {
105120 if ( ! override . options || ! override . matches ( relativeFilePath ) ) {
106121 continue ;
107122 }
108- if ( options === config . baseOptions ) {
109- options = { ...options } ;
123+
124+ // Reuse the merged result for this override after the current matched sequence.
125+ let nextCacheNode = cacheNode . children . get ( override . options ) ;
126+ if ( ! nextCacheNode ) {
127+ nextCacheNode = createOptionsCacheNode ( { ...cacheNode . options , ...override . options } ) ;
128+ cacheNode . children . set ( override . options , nextCacheNode ) ;
110129 }
111- Object . assign ( options , override . options ) ;
130+ cacheNode = nextCacheNode ;
112131 }
113132
114- return options ;
133+ return cacheNode . options ;
115134 } ;
116135} ;
117136
0 commit comments