Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(typescript-estree): allow specifying project: true #6084

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
efec873
feat(typescript-estree): allow specifying project: true
JoshuaKGoldberg Nov 25, 2022
4927c39
Also fix unchanged file for lint I guess
JoshuaKGoldberg Nov 25, 2022
d01f2bf
Added docs
JoshuaKGoldberg Nov 25, 2022
4bf121e
More tsconfigRootDir: __dirname removal
JoshuaKGoldberg Nov 25, 2022
db656f5
Added some unit tests
JoshuaKGoldberg Nov 25, 2022
003d993
you don't say
JoshuaKGoldberg Nov 25, 2022
eb34a95
Undo createWatchProgram.ts
JoshuaKGoldberg Nov 25, 2022
3a428c1
Merge branch 'main' into parser-options-project-true
JoshuaKGoldberg Nov 28, 2022
9ae3ce6
Added parse tests
JoshuaKGoldberg Nov 30, 2022
7cf6b80
Merge branch 'main' into parser-options-project-true
JoshuaKGoldberg Nov 30, 2022
3682aaf
Merge branch 'main'
JoshuaKGoldberg Dec 3, 2022
b024ad2
Fixed monorepos link
JoshuaKGoldberg Dec 3, 2022
6b16b04
Cache under all directories
JoshuaKGoldberg Dec 8, 2022
264a279
Added another test, just to be sure
JoshuaKGoldberg Dec 8, 2022
725603e
Merge branch 'main' into parser-options-project-true
JoshuaKGoldberg Dec 8, 2022
3c4850b
lint fix
JoshuaKGoldberg Dec 10, 2022
16e52d5
Add back tsconfigRootDir
JoshuaKGoldberg Dec 13, 2022
2be55de
Apply suggestions from code review
JoshuaKGoldberg Jan 23, 2023
fb6465c
Back to string |
JoshuaKGoldberg Jan 25, 2023
e6df49a
Merge branch main and use ExpiringCache and idk what else git is hard
JoshuaKGoldberg Feb 4, 2023
edc11e5
Fix website build
JoshuaKGoldberg Feb 4, 2023
315bcde
Fix the build
JoshuaKGoldberg Feb 4, 2023
040a56a
A global tsconfigMatchCache, with a test
JoshuaKGoldberg Feb 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 4 additions & 9 deletions packages/eslint-plugin-tslint/src/rules/config.ts
Expand Up @@ -98,18 +98,13 @@ export default createRule<Options, MessageIds>({
],
},
defaultOptions: [{}],
create(context) {
create(
context,
[{ rules: tslintRules, rulesDirectory: tslintRulesDirectory, lintFile }],
) {
const fileName = context.getFilename();
const sourceCode = context.getSourceCode().text;
const parserServices = ESLintUtils.getParserServices(context);

/**
* The TSLint rules configuration passed in by the user
*/
const [
{ rules: tslintRules, rulesDirectory: tslintRulesDirectory, lintFile },
] = context.options;

JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
const program = parserServices.program;

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/parser/README.md
Expand Up @@ -59,7 +59,7 @@ interface ParserOptions {
jsxFragmentName?: string | null;
lib?: string[];

project?: string | string[];
project?: string | string[] | true;
projectFolderIgnoreList?: string[];
tsconfigRootDir?: string;
extraFileExtensions?: string[];
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/parser-options.ts
Expand Up @@ -51,7 +51,7 @@ interface ParserOptions {
filePath?: string;
loc?: boolean;
program?: Program;
project?: string | string[];
project?: string | string[] | true;
projectFolderIgnoreList?: (string | RegExp)[];
range?: boolean;
sourceType?: SourceType;
Expand Down
5 changes: 3 additions & 2 deletions packages/typescript-estree/README.md
Expand Up @@ -180,10 +180,11 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
preserveNodeMaps?: boolean;

/**
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s).
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s),
* or `true` to find the nearest tsconfig.json to the file.
* If this is provided, type information will be returned.
*/
project?: string | string[];
project?: string | string[] | true;

/**
* If you provide a glob (or globs) to the project option, you can use this option to ignore certain folders from
Expand Down
Expand Up @@ -548,4 +548,4 @@ function maybeInvalidateProgram(
return null;
}

export { clearWatchCaches, createWatchProgram, getProgramsForProjects };
export { clearWatchCaches, getProgramsForProjects };
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
Expand Up @@ -8,6 +8,7 @@ import {
getCanonicalFileName,
} from '../create-program/shared';
import type { TSESTreeOptions } from '../parser-options';
import { getProjectConfigFiles } from './getProjectConfigFiles';
import type { MutableParseSettings } from './index';
import { inferSingleRun } from './inferSingleRun';
import { warnAboutTSVersion } from './warnAboutTSVersion';
Expand Down Expand Up @@ -112,7 +113,7 @@ export function createParseSettings(

parseSettings.projects = prepareAndTransformProjects(
tsconfigRootDir,
options.project,
getProjectConfigFiles(parseSettings, options.project),
projectFolderIgnoreList,
);
}
Expand Down
@@ -0,0 +1,80 @@
import debug from 'debug';
import fs from 'fs';
import path from 'path';

import type { ParseSettings } from '.';

const log = debug('typescript-eslint:typescript-estree:getProjectConfigFiles');

interface TSConfigMatch {
exists: boolean;
timestamp: number;
}

/**
* How many milliseconds we will respect a cache for checking an fs.existsSync
* check for a file file on disk.
*/
const RECHECK_FILE_THRESHOLD_MS = 50;

const tsconfigMatchCache = new Map<string, TSConfigMatch>();

/**
* Checks for a file file on disk, respecting a limited-time cache.
* This keeps a caches checked paths with existence and `Date.now()` timestamp.
* After `RECHECK_FILE_THRESHOLD_MS`, cache entries are ignored.
*
* @param filePath File path to check for existence on disk.
* @returns Whether the file exists on disk.
* @remarks
* We don't (yet!) have a way to attach file watchers on disk, but still need to
* cache file checks for rapid subsequent calls to fs.existsSync. See discussion
* in https://github.com/typescript-eslint/typescript-eslint/issues/101.
*/
function existsSyncCached(filePath: string): boolean {
const cached = tsconfigMatchCache.get(filePath);
const now = Date.now();

if (cached && now - cached.timestamp < RECHECK_FILE_THRESHOLD_MS) {
return cached.exists;
}

const exists = fs.existsSync(filePath);

tsconfigMatchCache.set(filePath, {
exists,
timestamp: now,
});

return exists;
}

export function getProjectConfigFiles(
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
parseSettings: ParseSettings,
projects: string | string[] | true | undefined,
): string | string[] | undefined {
if (projects !== true) {
return projects;
}

log('Looking for tsconfig.json at or above file: %s', parseSettings.filePath);
let directory = path.dirname(parseSettings.filePath);

do {
const tsconfigPath = path.join(directory, 'tsconfig.json');
log('Checking tsconfig.json path: %s', tsconfigPath);

if (existsSyncCached(tsconfigPath)) {
return [tsconfigPath];
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
}

directory = path.basename(directory);
} while (
directory &&
directory.length < parseSettings.tsconfigRootDir.length
);

throw new Error(
`project was set to \`true\` but couldn't find any tsconfig.json relative to '${parseSettings.filePath}' within '${parseSettings.tsconfigRootDir}.`,
);
}
5 changes: 3 additions & 2 deletions packages/typescript-estree/src/parser-options.ts
Expand Up @@ -117,10 +117,11 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
preserveNodeMaps?: boolean;

/**
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s).
* Absolute (or relative to `tsconfigRootDir`) paths to the tsconfig(s),
* or `true` to find the nearest tsconfig.json to the file.
* If this is provided, type information will be returned.
*/
project?: string | string[];
project?: string | string[] | true;

/**
* If you provide a glob (or globs) to the project option, you can use this option to ignore certain folders from
Expand Down