I'm currently converting my TSLint rule to ESLint. Here is the TSLint 
version.

    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)
      })
    }


What does it do?
It goes through all my files and looks for `i18n.transl('foo')`. We use 
language files which look like this:

    // en.js
    module.exports = {
      foo: 'foo in english'
    }
    
    // de.js
    module.exports = {
      foo: 'foo in german'
    }


The rule should find keys inside our language files that we never use in 
our app. Let's say our language files look like this

    // en.js
    module.exports = {
      foo: 'foo in english',
      bar: 'bar in english'
    }
    
    // de.js
    module.exports = {
      foo: 'foo in german',
      bar: 'bar in german'
    }


But `i18n.transl('bar')` is never used.

My problem is: How do I know when ESLint is done with all my files? This 
would be the chance to compare the real language files with all occurrences 
found in the app. In TSLint I used `program.getRootFileNames().length` to 
get the total number of files which are being processed. Then I simply 
counted down and at `0` I compared the language file `en` with my temporary 
Set `foundKeys`.

I know about the `Program` and `Program:exit` hooks but they are only per 
file. I need hooks for something `ESLint:start` and `ESLint:done`.

I also looked at all the existing rules but couldn't find any hints. They 
all work on single files and not with multiple files.

Any ideas? I'm stuck. Thank you! I also asked the question at Stack 
Overflow 
https://stackoverflow.com/questions/56461061/how-does-my-rule-know-when-eslint-is-done-with-all-files
 but 
no feedback so far. 

-- 
You received this message because you are subscribed to the Google Groups 
"ESLint" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/eslint/78fdc2a3-fa23-47bc-8390-5f286676be69%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to