Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
28 changes: 26 additions & 2 deletions lib/utils/parser-config-resolver/parse-by-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,43 @@ import path from 'path'
import { parseForESLint } from 'vue-eslint-parser'
import type { ParseResult } from '.'

function stripTypeAwareOptions(
parserOptions: unknown
): Record<string, unknown> {
if (
parserOptions == null ||
typeof parserOptions !== 'object' ||
Array.isArray(parserOptions)
) {
return (parserOptions ?? {}) as Record<string, unknown>
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { project, programs, projectService, ...rest } =
parserOptions as Record<string, unknown>
if (
rest.parserOptions != null &&
typeof rest.parserOptions === 'object' &&
!Array.isArray(rest.parserOptions)
) {
rest.parserOptions = stripTypeAwareOptions(rest.parserOptions)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this recursively?

}
return rest
}

export function parseByParser(
filePath: string,
parserDefine: Linter.Parser | string | undefined,
parserOptions: unknown
): ParseResult {
const parser = getParser(parserDefine, filePath)
const safeParserOptions = stripTypeAwareOptions(parserOptions)
try {
const text = readFileSync(path.resolve(filePath), 'utf8')
const parseResult =
'parseForESLint' in parser && typeof parser.parseForESLint === 'function'
? parser.parseForESLint(text, parserOptions)
? parser.parseForESLint(text, safeParserOptions)
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
{ ast: (parser as any).parse(text, parserOptions) }
{ ast: (parser as any).parse(text, safeParserOptions) }
return parseResult as ParseResult
} catch (_e) {
return null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const base = require("../../../../../lib/configs/flat/base");
module.exports = [
...base,
{
files: ['**/*.vue', '*.vue'],
languageOptions: {
parser: require('vue-eslint-parser'),
parserOptions: {
parser: "@typescript-eslint/parser",
project: true,
},
},
},
{
files: ['**/*.ts', '*.ts'],
languageOptions: {
parser: require('@typescript-eslint/parser'),
parserOptions: {
project: true,
},
},
},
{
rules: {
"@intlify/vue-i18n/no-unused-keys": [
"error",
{
src: "./src",
extensions: [".tsx", ".ts", ".vue"],
enableFix: true,
},
],
},
settings: {
"vue-i18n": {
localeDir: {
pattern: `./locales/*.{json,yaml,yml}`,
localeKey: "file",
},
},
},
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"hello": "hello world",
"messages": {
"hello": "hi DIO!",
"link": "@:message.hello",
"nested": {
"hello": "hi jojo!"
}
},
"hello_dio": "hello underscore DIO!",
"hello {name}": "hello {name}!",
"hello-dio": "hello hyphen DIO!"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
hello: "ハローワールド"
messages:
hello: "こんにちは、DIO!"
link: "@:message.hello"
nested:
hello: "こんにちは、ジョジョ!"
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
hello-dio: "こんにちは、ハイフン DIO!"
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<template>
<div id="app">
<p v-t="'hello_dio'">{{ $t('messages.hello') }}</p>
</div>
</template>

<script lang="ts">
export default {
name: 'App' as const,
created() {
this.$i18n.t('hello {name}', { name: 'DIO' })
}
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const $t = (a:any) => {}
$t('hello')
235 changes: 235 additions & 0 deletions tests/lib/rules/no-unused-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3324,6 +3324,241 @@ messages:
nested: {}
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
`
}
]
}
]
}
}
),
...getTestCasesFromFixtures(
{
eslint: '>=8',
cwd: join(cwdRoot, './invalid/typescript-with-project-true'),
localeDir: {
pattern: `./locales/*.{json,yaml,yml}`,
localeKey: 'file'
},
options: [
{
src: './src',
extensions: ['.tsx', '.ts', '.vue'],
enableFix: true
}
],
languageOptions: {
parser: tsParser
}
},
{
'src/App.vue': true,
'locales/en.json': {
output: `{
"hello": "hello world",
"messages": {
"hello": "hi DIO!",
"nested": {
}
},
"hello_dio": "hello underscore DIO!",
"hello {name}": "hello {name}!"
}
`,
errors: [
{
message: "unused 'messages.link' key",
suggestions: [
{
desc: "Remove the 'messages.link' key.",
output: `{
"hello": "hello world",
"messages": {
"hello": "hi DIO!",
"nested": {
"hello": "hi jojo!"
}
},
"hello_dio": "hello underscore DIO!",
"hello {name}": "hello {name}!",
"hello-dio": "hello hyphen DIO!"
}
`
},
{
desc: 'Remove all unused keys.',
output: `{
"hello": "hello world",
"messages": {
"hello": "hi DIO!",
"nested": {
}
},
"hello_dio": "hello underscore DIO!",
"hello {name}": "hello {name}!"
}
`
}
]
},
{
message: "unused 'messages.nested.hello' key",
suggestions: [
{
desc: "Remove the 'messages.nested.hello' key.",
output: `{
"hello": "hello world",
"messages": {
"hello": "hi DIO!",
"link": "@:message.hello",
"nested": {
}
},
"hello_dio": "hello underscore DIO!",
"hello {name}": "hello {name}!",
"hello-dio": "hello hyphen DIO!"
}
`
},
{
desc: 'Remove all unused keys.',
output: `{
"hello": "hello world",
"messages": {
"hello": "hi DIO!",
"nested": {
}
},
"hello_dio": "hello underscore DIO!",
"hello {name}": "hello {name}!"
}
`
}
]
},
{
message: "unused 'hello-dio' key",
suggestions: [
{
desc: "Remove the 'hello-dio' key.",
output: `{
"hello": "hello world",
"messages": {
"hello": "hi DIO!",
"link": "@:message.hello",
"nested": {
"hello": "hi jojo!"
}
},
"hello_dio": "hello underscore DIO!",
"hello {name}": "hello {name}!"
}
`
},
{
desc: 'Remove all unused keys.',
output: `{
"hello": "hello world",
"messages": {
"hello": "hi DIO!",
"nested": {
}
},
"hello_dio": "hello underscore DIO!",
"hello {name}": "hello {name}!"
}
`
}
]
}
]
},
'locales/ja.yaml': {
output: `hello: "ハローワールド"
messages:
hello: "こんにちは、DIO!"
nested: {}
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
`,
errors: [
{
message: "unused 'messages.link' key",
suggestions: [
{
desc: "Remove the 'messages.link' key.",
output: `hello: "ハローワールド"
messages:
hello: "こんにちは、DIO!"
nested:
hello: "こんにちは、ジョジョ!"
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
hello-dio: "こんにちは、ハイフン DIO!"
`
},
{
desc: 'Remove all unused keys.',
output: `hello: "ハローワールド"
messages:
hello: "こんにちは、DIO!"
nested: {}
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
`
}
]
},
{
message: "unused 'messages.nested.hello' key",
suggestions: [
{
desc: "Remove the 'messages.nested.hello' key.",
output: `hello: "ハローワールド"
messages:
hello: "こんにちは、DIO!"
link: "@:message.hello"
nested: {}
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
hello-dio: "こんにちは、ハイフン DIO!"
`
},
{
desc: 'Remove all unused keys.',
output: `hello: "ハローワールド"
messages:
hello: "こんにちは、DIO!"
nested: {}
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
`
}
]
},
{
message: "unused 'hello-dio' key",
suggestions: [
{
desc: "Remove the 'hello-dio' key.",
output: `hello: "ハローワールド"
messages:
hello: "こんにちは、DIO!"
link: "@:message.hello"
nested:
hello: "こんにちは、ジョジョ!"
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
`
},
{
desc: 'Remove all unused keys.',
output: `hello: "ハローワールド"
messages:
hello: "こんにちは、DIO!"
nested: {}
hello_dio: "こんにちは、アンダースコア DIO!"
"hello {name}": "こんにちは、{name}!"
`
}
]
Expand Down