Skip to content

oxlint: ignorePatterns in root config is resolved relative to CWD #24310

Description

@leaysgur

TL;DR: Same config file, different results depending on where you run oxlint from.

Overview

Given this file structure:

repo/
├── .oxlintrc.json
└── packages/
    └── foo/
        ├── src/index.js
        └── dist/bundle.js

and this config:

{
  "ignorePatterns": ["packages/foo/dist"]
}
  • 🆗 Running oxlint . from repo/ as CWD
    • ignores packages/foo/dist as expected
  • 🆖 Running oxlint . from repo/packages/foo/
    • finds the same repo/.oxlintrc.json via ancestor search, but dist/bundle.js is now linted

The pattern is anchored at CWD (repo/packages/foo/), so it looks for repo/packages/foo/packages/foo/dist, which does not exist.

Why

The implementation roots the root config's ignorePatterns at CWD:
LintIgnoreMatcher::new(&base_ignore_patterns, &self.cwd, ...) in apps/oxlint/src/lint.rs. (The LSP roots them at the workspace root instead.)

This is inconsistent in several ways:

  • The doc comment on Oxlintrc::ignore_patterns already says "These are resolved from the configuration file path"
  • Nested configs' ignorePatterns are already rooted at each config file's directory
  • Oxfmt roots ignorePatterns at the config file's directory
  • ESLint's ignorePatterns is also resolved relative to the config file's directory

Rooting at the config file's directory would make all of these consistent.

Note

This is technically a breaking change: users who run oxlint from a subdirectory with path-anchored patterns (containing /) would see different results.

The impact should be small though, most users write bare file/directory names (dist, *.min.js) or **/-prefixed patterns (which match at any depth) and are unaffected by the root. For that reason, I think it could be justified as a bug fix.

As a follow-up, we can also port #24286 (reject .. in ignorePatterns at config load time), which only makes sense once patterns are rooted at the config directory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions