我当前正在将TSLint规则转换为ESLint。这是TSLint版本。
import * as Lint from 'tslint'
import * as ts from 'typescript'
import en from '../app/src/i18n/en'
// counter to keep track of already process files
// we need this to know when we are done, e.g. at the last file
let rootFileCount = -1
// temporary storage for all keys that are used in our components
const foundKeys = new Set()
export class Rule extends Lint.Rules.TypedRule {
public static FAILURE_STRING =
'could not find i18n key in english language file'
public applyWithProgram(
sourceFile: ts.SourceFile,
program: ts.Program
): Lint.RuleFailure[] {
// at start set the counter to the number of files
if (rootFileCount === -1) {
rootFileCount = program.getRootFileNames().length - 1
} else {
// decrease counter for every file visited
rootFileCount -= 1
}
const failures = this.applyWithFunction(sourceFile, walk)
// when done with files check if we have unused keys inside our translation files
if (rootFileCount === 0) {
Object.keys(en).forEach(key => {
if (!foundKeys.has(key)) {
throw new Error(`i18n key "${key}" is not being used in any file`)
}
})
}
return failures
}
}
function walk(ctx: Lint.WalkContext<void>): void {
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.CallExpression) {
const callExpression = node as ts.CallExpression
if (callExpression.expression.getText() === 'i18n.transl') {
const arg = callExpression.arguments[0]
const argumentName = (arg as ts.Identifier).text
if (!en[argumentName]) {
ctx.addFailureAtNode(node, Rule.FAILURE_STRING)
}
foundKeys.add(argumentName)
}
}
return ts.forEachChild(node, cb)
})
}
它有什么作用?
它会遍历我所有的文件,并寻找i18n.transl('foo')
。我们使用如下语言文件:
// en.js
module.exports = {
foo: 'foo in english'
}
// de.js
module.exports = {
foo: 'foo in german'
}
规则应在我们的语言文件中找到我们从未在应用程序中使用过的键。假设我们的语言文件如下
// en.js
module.exports = {
foo: 'foo in english',
bar: 'bar in english'
}
// de.js
module.exports = {
foo: 'foo in german',
bar: 'bar in german'
}
但是从未使用过i18n.transl('bar')
。
我的问题是:我怎么知道所有文件都完成ESLint?这将是比较真实语言文件与在应用程序中找到的所有匹配项的机会。在TSLint中,我使用program.getRootFileNames().length
来获取正在处理的文件总数。然后我简单地倒数,然后在0
处将语言文件en
与我的临时Set foundKeys
进行比较。
我知道Program
和Program:exit
钩子,但它们仅针对每个文件。我需要挂钩ESLint:start
和ESLint:done
。
我也查看了所有现有规则,但找不到任何提示。它们都只能在单个文件上工作,而不能在多个文件上工作。
有什么想法吗?我被卡住了。谢谢!