@@ -3,6 +3,7 @@ import path from 'node:path'
3
3
4
4
import type { TSESLint , TSESTree } from '@typescript-eslint/utils'
5
5
import debug from 'debug'
6
+ import { dequal } from 'dequal'
6
7
import type { Annotation } from 'doctrine'
7
8
import doctrine from 'doctrine'
8
9
import type { AST } from 'eslint'
@@ -1078,11 +1079,6 @@ export function recursivePatternCapture(
1078
1079
}
1079
1080
}
1080
1081
1081
- let parserOptionsHash = ''
1082
- let prevParserOptions = ''
1083
- let settingsHash = ''
1084
- let prevSettings = ''
1085
-
1086
1082
/**
1087
1083
* don't hold full context object in memory, just grab what we need.
1088
1084
* also calculate a cacheKey, where parts of the cacheKey hash are memoized
@@ -1091,24 +1087,14 @@ function childContext(
1091
1087
path : string ,
1092
1088
context : RuleContext | ChildContext ,
1093
1089
) : ChildContext {
1094
- const { settings, parserOptions, parserPath } = context
1095
-
1096
- if ( JSON . stringify ( settings ) !== prevSettings ) {
1097
- settingsHash = hashObject ( { settings } ) . digest ( 'hex' )
1098
- prevSettings = JSON . stringify ( settings )
1099
- }
1100
-
1101
- if ( JSON . stringify ( parserOptions ) !== prevParserOptions ) {
1102
- parserOptionsHash = hashObject ( { parserOptions } ) . digest ( 'hex' )
1103
- prevParserOptions = JSON . stringify ( parserOptions )
1104
- }
1090
+ const { settings, parserOptions, parserPath, languageOptions } = context
1105
1091
1106
1092
return {
1107
- cacheKey :
1108
- String ( parserPath ) + parserOptionsHash + settingsHash + String ( path ) ,
1093
+ cacheKey : makeContextCacheKey ( context ) + String ( path ) ,
1109
1094
settings,
1110
1095
parserOptions,
1111
1096
parserPath,
1097
+ languageOptions,
1112
1098
path,
1113
1099
filename :
1114
1100
'physicalFilename' in context
@@ -1117,6 +1103,50 @@ function childContext(
1117
1103
}
1118
1104
}
1119
1105
1106
+ type OptionsVersionsCache = Record <
1107
+ 'settings' | 'parserOptions' | 'parser' ,
1108
+ { value : unknown ; version : number }
1109
+ >
1110
+
1111
+ const optionsVersionsCache : OptionsVersionsCache = {
1112
+ settings : { value : null , version : 0 } ,
1113
+ parserOptions : { value : null , version : 0 } ,
1114
+ parser : { value : null , version : 0 } ,
1115
+ }
1116
+
1117
+ function getOptionsVersion ( key : keyof OptionsVersionsCache , value : unknown ) {
1118
+ const entry = optionsVersionsCache [ key ]
1119
+
1120
+ if ( ! dequal ( value , entry . value ) ) {
1121
+ entry . value = value
1122
+ entry . version += 1
1123
+ }
1124
+
1125
+ return String ( entry . version )
1126
+ }
1127
+
1128
+ function makeContextCacheKey ( context : RuleContext | ChildContext ) {
1129
+ const { settings, parserPath, parserOptions, languageOptions } = context
1130
+
1131
+ let hash = getOptionsVersion ( 'settings' , settings )
1132
+
1133
+ const usedParserOptions = languageOptions ?. parserOptions ?? parserOptions
1134
+
1135
+ hash += getOptionsVersion ( 'parserOptions' , usedParserOptions )
1136
+
1137
+ if ( languageOptions ) {
1138
+ const { ecmaVersion, sourceType } = languageOptions
1139
+ hash += String ( ecmaVersion ) + String ( sourceType )
1140
+ }
1141
+
1142
+ hash += getOptionsVersion (
1143
+ 'parser' ,
1144
+ parserPath ?? languageOptions ?. parser ?. meta ?? languageOptions ?. parser ,
1145
+ )
1146
+
1147
+ return hash
1148
+ }
1149
+
1120
1150
/**
1121
1151
* sometimes legacy support isn't _that_ hard... right?
1122
1152
*/
0 commit comments