-
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix:
no-unused-keys
rule not working when using flat config (#497)
* fix: `no-unused-keys` rule not working when using flat config * fix * Create wicked-carpets-sing.md * test * fix * fix * fix
- Loading branch information
Showing
18 changed files
with
1,369 additions
and
529 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@intlify/eslint-plugin-vue-i18n": minor | ||
--- | ||
|
||
fix: `no-unused-keys` rule not working when using flat config |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
lib/utils/parser-config-resolver/build-parser-using-flat-config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// @ts-expect-error -- ignore | ||
import { createSyncFn } from 'synckit' | ||
import type { ParseResult, Parser } from '.' | ||
|
||
const getSync = createSyncFn(require.resolve('./worker')) | ||
|
||
/** | ||
* Build synchronously parser using the flat config | ||
*/ | ||
export function buildParserUsingFlatConfig(cwd: string): Parser { | ||
return (filePath: string) => { | ||
return getSync(cwd, filePath) as ParseResult | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
lib/utils/parser-config-resolver/build-parser-using-legacy-config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import type { Parser } from '.' | ||
// @ts-expect-error -- ignore | ||
import { Legacy } from '@eslint/eslintrc' | ||
import path from 'path' | ||
import { parseByParser } from './parse-by-parser' | ||
const { CascadingConfigArrayFactory } = Legacy | ||
|
||
/** | ||
* Build parser using legacy config | ||
*/ | ||
export function buildParserUsingLegacyConfig(cwd: string): Parser { | ||
const configArrayFactory = new CascadingConfigArrayFactory({ | ||
additionalPluginPool: new Map([ | ||
['@intlify/vue-i18n', require('../../index')] | ||
]), | ||
cwd, | ||
getEslintRecommendedConfig() { | ||
return {} | ||
}, | ||
getEslintAllConfig() { | ||
return {} | ||
} | ||
}) | ||
|
||
function getConfigForFile(filePath: string) { | ||
const absolutePath = path.resolve(cwd, filePath) | ||
return configArrayFactory | ||
.getConfigArrayForFile(absolutePath) | ||
.extractConfig(absolutePath) | ||
.toCompatibleObjectAsConfigFileContent() | ||
} | ||
|
||
return (filePath: string) => { | ||
const config = getConfigForFile(filePath) | ||
|
||
const parserOptions = Object.assign({}, config.parserOptions, { | ||
loc: true, | ||
range: true, | ||
raw: true, | ||
tokens: true, | ||
comment: true, | ||
eslintVisitorKeys: true, | ||
eslintScopeManager: true, | ||
filePath | ||
}) | ||
return parseByParser(filePath, config.parser, parserOptions) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { shouldUseFlatConfig } from './should-use-flat-config' | ||
import type { AST as VAST } from 'vue-eslint-parser' | ||
import { buildParserUsingLegacyConfig } from './build-parser-using-legacy-config' | ||
import { buildParserUsingFlatConfig } from './build-parser-using-flat-config' | ||
|
||
export type ParseResult = Pick< | ||
VAST.ESLintExtendedProgram, | ||
'ast' | 'visitorKeys' | ||
> | null | ||
export type Parser = (filePath: string) => ParseResult | ||
|
||
const parsers: Record<string, undefined | Parser> = {} | ||
|
||
export function buildParserFromConfig(cwd: string): Parser { | ||
const parser = parsers[cwd] | ||
if (parser) { | ||
return parser | ||
} | ||
if (shouldUseFlatConfig(cwd)) { | ||
return (parsers[cwd] = buildParserUsingFlatConfig(cwd)) | ||
} | ||
|
||
return (parsers[cwd] = buildParserUsingLegacyConfig(cwd)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import type { Linter } from 'eslint' | ||
import { readFileSync } from 'fs' | ||
import path from 'path' | ||
import { parseForESLint } from 'vue-eslint-parser' | ||
import type { ParseResult } from '.' | ||
|
||
export function parseByParser( | ||
filePath: string, | ||
parserDefine: Linter.ParserModule | string | undefined, | ||
parserOptions: unknown | ||
): ParseResult { | ||
const parser = getParser(parserDefine, filePath) | ||
try { | ||
const text = readFileSync(path.resolve(filePath), 'utf8') | ||
const parseResult = | ||
'parseForESLint' in parser && typeof parser.parseForESLint === 'function' | ||
? parser.parseForESLint(text, parserOptions) | ||
: // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
{ ast: (parser as any).parse(text, parserOptions) } | ||
return parseResult as ParseResult | ||
} catch (_e) { | ||
return null | ||
} | ||
} | ||
|
||
function getParser( | ||
parser: Linter.ParserModule | string | undefined, | ||
filePath: string | ||
): Linter.ParserModule { | ||
if (parser) { | ||
if (typeof parser === 'string') { | ||
try { | ||
return require(parser) | ||
} catch (_e) { | ||
// ignore | ||
} | ||
} else { | ||
return parser | ||
} | ||
} | ||
if (filePath.endsWith('.vue')) { | ||
return { parseForESLint } as Linter.ParserModule | ||
} | ||
return require('espree') | ||
} |
66 changes: 66 additions & 0 deletions
66
lib/utils/parser-config-resolver/should-use-flat-config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/** copied from https://github.com/eslint/eslint/blob/v8.56.0/lib/eslint/flat-eslint.js#L1119 */ | ||
|
||
import path from 'path' | ||
import fs from 'fs' | ||
|
||
const FLAT_CONFIG_FILENAMES = [ | ||
'eslint.config.js', | ||
'eslint.config.mjs', | ||
'eslint.config.cjs' | ||
] | ||
/** | ||
* Returns whether flat config should be used. | ||
* @returns {Promise<boolean>} Whether flat config should be used. | ||
*/ | ||
export function shouldUseFlatConfig(cwd: string): boolean { | ||
// eslint-disable-next-line no-process-env -- ignore | ||
switch (process.env.ESLINT_USE_FLAT_CONFIG) { | ||
case 'true': | ||
return true | ||
case 'false': | ||
return false | ||
default: | ||
// If neither explicitly enabled nor disabled, then use the presence | ||
// of a flat config file to determine enablement. | ||
return Boolean(findFlatConfigFile(cwd)) | ||
} | ||
} | ||
|
||
/** | ||
* Searches from the current working directory up until finding the | ||
* given flat config filename. | ||
* @param {string} cwd The current working directory to search from. | ||
* @returns {string|undefined} The filename if found or `undefined` if not. | ||
*/ | ||
export function findFlatConfigFile(cwd: string) { | ||
return findUp(FLAT_CONFIG_FILENAMES, { cwd }) | ||
} | ||
|
||
/** We used https://github.com/sindresorhus/find-up/blob/b733bb70d3aa21b22fa011be8089110d467c317f/index.js#L94 as a reference */ | ||
function findUp(names: string[], options: { cwd: string }) { | ||
let directory = path.resolve(options.cwd) | ||
const { root } = path.parse(directory) | ||
const stopAt = path.resolve(directory, root) | ||
// eslint-disable-next-line no-constant-condition -- ignore | ||
while (true) { | ||
for (const name of names) { | ||
const target = path.resolve(directory, name) | ||
const stat = fs.existsSync(target) | ||
? fs.statSync(target, { | ||
throwIfNoEntry: false | ||
}) | ||
: null | ||
if (stat?.isFile()) { | ||
return target | ||
} | ||
} | ||
|
||
if (directory === stopAt) { | ||
break | ||
} | ||
|
||
directory = path.dirname(directory) | ||
} | ||
|
||
return null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// @ts-expect-error -- ignore | ||
import { runAsWorker } from 'synckit' | ||
import { getESLint } from 'eslint-compat-utils/eslint' | ||
import type { Linter } from 'eslint' | ||
import type { ParseResult } from '.' | ||
import { parseByParser } from './parse-by-parser' | ||
const ESLint = getESLint() | ||
|
||
runAsWorker(async (cwd: string, filePath: string): Promise<ParseResult> => { | ||
const eslint = new ESLint({ cwd }) | ||
const config: Linter.FlatConfig = await eslint.calculateConfigForFile( | ||
filePath | ||
) | ||
const languageOptions = config.languageOptions || {} | ||
const parserOptions = Object.assign( | ||
{ | ||
sourceType: languageOptions.sourceType || 'module', | ||
ecmaVersion: languageOptions.ecmaVersion || 'latest' | ||
}, | ||
languageOptions.parserOptions, | ||
{ | ||
loc: true, | ||
range: true, | ||
raw: true, | ||
tokens: true, | ||
comment: true, | ||
eslintVisitorKeys: true, | ||
eslintScopeManager: true, | ||
filePath | ||
} | ||
) | ||
|
||
const result = parseByParser(filePath, languageOptions.parser, parserOptions) | ||
if (!result) { | ||
return null | ||
} | ||
|
||
return { | ||
ast: result.ast, | ||
visitorKeys: result?.visitorKeys | ||
} | ||
}) |
Oops, something went wrong.