Diagnostic filtering

Source: src/engine/filter-diagnostics.ts

Removes diagnostics that match the user's ignore configuration, after every rule has run. Silencing a known diagnostic or excluding a generated file therefore does not require turning the rule off: no-orm-in-services can run everywhere and still stay quiet inside a legacy module.

Input is the diagnostics, the config, and the project root:

diagnostics: Diagnostic[]          // all diagnostics from rule execution
config: NestjsDoctorConfig         // contains ignore.rules and ignore.files
targetPath: string                 // root directory, used to make paths relative for glob matching

The result is a subset of the input:

Diagnostic[]    // filtered array (subset of input)

How it works

The config ignores run first. A second pass then reads suppression comments in the source.

Rule ignoring

ignore.rules contains rule IDs to suppress:

{
  "ignore": {
    "rules": ["architecture/no-orm-in-services"]
  }
}

The match is exact against the diagnostic's rule field. Every diagnostic from that rule is removed.

File ignoring

ignore.files contains glob patterns for files whose diagnostics should be hidden:

{
  "ignore": {
    "files": ["src/generated/**", "src/legacy/**"]
  }
}

File paths are normalized to forward slashes before matching, so patterns work across platforms.

Inline suppression

Source: src/engine/inline-suppressions.ts

After config-based filtering, a second pass (filterSuppressedDiagnostics) removes diagnostics silenced by comments in the source itself. Directives use the ignore verb, or disable as an alias, inside a // or /* */ comment:

const config = eval(raw); // nestjs-doctor-ignore security/no-eval
 
// nestjs-doctor-ignore-next-line security/no-eval
const config = eval(raw);
 
// nestjs-doctor-ignore-file security/no-eval

Each directive covers a different scope:

DirectiveScope
nestjs-doctor-ignore[-line] <rules>The comment's own line
nestjs-doctor-ignore-next-line <rules>The line below the comment
nestjs-doctor-ignore-file <rules>Every line in the file

How a directive is parsed:

  • The rule list is space- or comma-separated. Omit it to suppress every rule for that scope.
  • Only tokens containing / count as rule ids, since every id is category/name. A -- reason trailer is therefore ignored wherever it sits.
  • Only real comments are honored. String, template and regex contents are blanked via the AST before parsing, so a directive inside a string cannot suppress anything.

What it reads, and what it can reach:

  • TypeScript comes from the in-memory AST project, with no extra disk reads. Prisma .prisma files are not in that project, so they are read on demand.
  • Each file is parsed at most once per pass.
  • Line-scoped directives key off the diagnostic's line, so they only apply to code diagnostics. Schema diagnostics have no line and can only be suppressed with nestjs-doctor-ignore-file, including one placed anywhere in schema.prisma.

Performance

If no ignore config is set, which is the default, the filter returns the original array immediately without iterating. The inline-suppression pass skips any file whose source contains no nestjs-doctor-ignore/-disable token.

Difference from rules config

  • config.rules: disables a rule entirely. It never runs.
  • config.ignore.rules: lets the rule run, then hides its output.

The distinction matters for project-scoped rules that cross-reference data. For example, no-missing-injectable checks providers against the module graph.

Disabling it with config.rules means the rule never runs. Ignoring it with config.ignore.rules means the rule runs and its diagnostics are hidden.

Debugging tips

  • If diagnostics are disappearing unexpectedly, check ignore.rules and ignore.files in your config.
  • File patterns use glob syntax via picomatch. Double-star ** matches any depth.