Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/short-bees-sell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-import-x": patch
---

add languageOptions to ChildContext
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"dependencies": {
"@typescript-eslint/utils": "^7.4.0",
"debug": "^4.3.4",
"dequal": "^2.0.3",
"doctrine": "^3.0.0",
"eslint-import-resolver-node": "^0.3.9",
"get-tsconfig": "^4.7.3",
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export type ChildContext = {
settings: PluginSettings
parserPath?: string | null
parserOptions?: TSESLint.ParserOptions
languageOptions?: TSESLint.FlatConfig.LanguageOptions
path: string
filename?: string
}
Expand Down
74 changes: 55 additions & 19 deletions src/utils/export-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'node:path'

import type { TSESLint, TSESTree } from '@typescript-eslint/utils'
import debug from 'debug'
import { dequal } from 'dequal'
import type { Annotation } from 'doctrine'
import doctrine from 'doctrine'
import type { AST } from 'eslint'
Expand All @@ -20,7 +21,7 @@ import type {
} from '../types'

import { getValue } from './get-value'
import { hashObject } from './hash'
import { hashObject, hashify } from './hash'
import { hasValidExtension, ignore } from './ignore'
import { parse } from './parse'
import { relative, resolve } from './resolve'
Expand Down Expand Up @@ -1078,11 +1079,6 @@ export function recursivePatternCapture(
}
}

let parserOptionsHash = ''
let prevParserOptions = ''
let settingsHash = ''
let prevSettings = ''

/**
* don't hold full context object in memory, just grab what we need.
* also calculate a cacheKey, where parts of the cacheKey hash are memoized
Expand All @@ -1091,24 +1087,14 @@ function childContext(
path: string,
context: RuleContext | ChildContext,
): ChildContext {
const { settings, parserOptions, parserPath } = context

if (JSON.stringify(settings) !== prevSettings) {
settingsHash = hashObject({ settings }).digest('hex')
prevSettings = JSON.stringify(settings)
}

if (JSON.stringify(parserOptions) !== prevParserOptions) {
parserOptionsHash = hashObject({ parserOptions }).digest('hex')
prevParserOptions = JSON.stringify(parserOptions)
}
const { settings, parserOptions, parserPath, languageOptions } = context

return {
cacheKey:
String(parserPath) + parserOptionsHash + settingsHash + String(path),
cacheKey: makeContextCacheKey(context) + String(path),
settings,
parserOptions,
parserPath,
languageOptions,
path,
filename:
'physicalFilename' in context
Expand All @@ -1117,6 +1103,56 @@ function childContext(
}
}

type OptionsHashesCache = Record<
'settings' | 'parserOptions' | 'parserMeta',
{ value: unknown; hash: string }
>

const optionsHashesCache: OptionsHashesCache = {
settings: { value: null, hash: '' },
parserOptions: { value: null, hash: '' },
parserMeta: { value: null, hash: '' },
}

function getOptionsHash(key: keyof OptionsHashesCache, value: unknown) {
const entry = optionsHashesCache[key]

if (dequal(value, entry.value)) {
return entry.hash
}

const hash = hashify(value).digest('hex')

optionsHashesCache[key].value = value
optionsHashesCache[key].hash = hash

return hash
}

function makeContextCacheKey(context: RuleContext | ChildContext) {
const { settings, parserPath, parserOptions, languageOptions } = context

let hash = getOptionsHash('settings', settings)

const usedParserOptions = languageOptions
? languageOptions.parserOptions
: parserOptions

hash += getOptionsHash('parserOptions', usedParserOptions)

if (languageOptions) {
const { parser: { meta } = {}, ecmaVersion, sourceType } = languageOptions
hash +=
getOptionsHash('parserMeta', meta) +
String(ecmaVersion) +
String(sourceType)
} else {
hash += String(parserPath)
}

return hash
}

/**
* sometimes legacy support isn't _that_ hard... right?
*/
Expand Down