File matching to determine generated tsconfig does not take relative directories into account
Overview
xo attempts to check if a given file that it's linting matches a tsconfig.json passed into parserOptions.project. If the file being checked does not match the tsconfig (according to minimatch), a temporary tsconfig will be created.
https://github.com/xojs/xo/blob/352f20c0b0572c674f519cdf98a46fa0f35a96d9/lib/options-manager.js#L178-L181
However, options.filePath here is an absolute filepath, and the includes glob of a given tsconfig.json may be specified as a relative path from the config file itself. If the tsconfig in question is not in the current working directory, this check will erroneously fail.
I noticed this issue due to xojs/vscode-linter-xo#110. I thought I had given xo a good parserOptions.project path, but xo and the vscode-linter-xo started generating competing (and different!) temporary tsconfigs in the cache, eventually causing the editor extension to start choking on parser errors.
Reproduction
Project structure
- my-project/
- package.json
- config/
- tsconfig.lint.json
- src/
- some-file.ts
tsconfig.lint.json
{
...
"include": ["../src/**/*"]
}
Behavior
/path/to/my-project/src/some-file.ts does not match the glob ../src/**/*, so a temporary tsconfig is created in node_modules/.cache/xo-linter, even though tsc would recognize the config as matching that file.
{
"extends": "/path/to/my-project/config/tsconfig.lint.json",
"files": ["/path/to/my-project/src/some-file.ts"],
"include": [],
"exclude": []
}
Proposal
Before passing options.filePath to micromatch, I think it should be made relative to options.tsConfigPath if it exists. If this is an acceptable solution, I'm happy open a PR!
micromatch.contains("/path/to/my-project/src/some-file.ts", ["src/**/*"])
> true
micromatch.contains("/path/to/my-project/src/some-file.ts", ["../src/**/*"])
> false
micromatch.contains("../src/some-file.ts", ["../src/**/*"])
> true
Workaround
This issue is pretty straightforward to workaround by placing the tsconfig given to parserOptions.project in the project root rather than a subdirectory, so that a glob like src/**/* will match an absolute path.