From 3f1203503ce1aff9a0374d185188f836420b32b0 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 10:12:41 -0400 Subject: [PATCH 1/4] feat(typescript-estree): add maximumDefaultProjectFileMatchCount --- docs/packages/TypeScript_ESTree.mdx | 9 ++ docs/troubleshooting/FAQ.mdx | 36 +++++++- .../typescript-estree/src/clear-caches.ts | 6 +- .../create-program/createProjectService.ts | 16 +++- .../validateDefaultProjectForFilesGlob.ts | 27 ++++++ .../typescript-estree/src/parser-options.ts | 9 ++ packages/typescript-estree/src/parser.ts | 7 ++ .../src/useProgramFromProjectService.ts | 22 ++++- .../lib/useProgramFromProjectService.test.ts | 91 +++++++++++++++++-- ...validateDefaultProjectForFilesGlob.test.ts | 31 +++++++ .../MDXComponents/HiddenHeading.module.css | 6 ++ .../src/theme/MDXComponents/HiddenHeading.tsx | 11 +++ .../website/src/theme/MDXComponents/index.tsx | 4 +- 13 files changed, 257 insertions(+), 18 deletions(-) create mode 100644 packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts create mode 100644 packages/typescript-estree/tests/lib/validateDefaultProjectForFilesGlob.test.ts create mode 100644 packages/website/src/theme/MDXComponents/HiddenHeading.module.css create mode 100644 packages/website/src/theme/MDXComponents/HiddenHeading.tsx diff --git a/docs/packages/TypeScript_ESTree.mdx b/docs/packages/TypeScript_ESTree.mdx index 7269942e84d3..3093c46d366d 100644 --- a/docs/packages/TypeScript_ESTree.mdx +++ b/docs/packages/TypeScript_ESTree.mdx @@ -283,6 +283,15 @@ interface ProjectServiceOptions { * Globs of files to allow running with the default inferred project settings. */ allowDefaultProjectForFiles?: string[]; + + /** + * The maximum number of files {@link allowDefaultProjectForFiles} may match. + * Each file match slows down linting, so if you do need to use this, please + * file an informative issue on typescript-eslint explaining why - so we can + * help you avoid using it! + * @default 8 + */ + maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING?: number; } interface ParserServices { diff --git a/docs/troubleshooting/FAQ.mdx b/docs/troubleshooting/FAQ.mdx index dd96a721bcc0..1ccc0d5a0210 100644 --- a/docs/troubleshooting/FAQ.mdx +++ b/docs/troubleshooting/FAQ.mdx @@ -32,6 +32,40 @@ If you don't find an existing extension rule, or the extension rule doesn't work > We release a new version our tooling every week. > _Please_ ensure that you [check our the latest list of "extension" rules](/rules/#extension-rules) **_before_** filing an issue. + + +## I get errors telling me "Having many files run with the default project is known to cause performance issues and slow down linting." + +These errors are caused by using the [`EXPERIMENTAL_useProjectService`](../packages/Parser.mdx#experimental_useprojectservice) `allowDefaultProjectForFiles` with an excessively wide glob. +`allowDefaultProjectForFiles` causes a new TypeScript "program" to be built for each "out of project" file it includes, which incurs a performance overhead for each file. + +To resolve this error, narrow the glob(s) used for `allowDefaultProjectForFiles` to include fewer files. +For example: + +```diff title="eslint.config.js" +parserOptions: { + EXPERIMENTAL_useProjectService: { + allowDefaultProjectForFiles: [ +- "**/*.js", ++ "./*.js" + ] + } +} +``` + +You may also need to include more files in your `tsconfig.json`. +For example: + +```diff title="tsconfig.json" +"include": [ + "src", ++ "*.js" +] +``` + +If you cannot do this, please [file an issue on typescript-eslint's typescript-estree package](https://github.com/typescript-eslint/typescript-eslint/issues/new?assignees=&labels=enhancement%2Ctriage&projects=&template=07-enhancement-other.yaml&title=Enhancement%3A+%3Ca+short+description+of+my+proposal%3E) telling us your use case and why you need more out-of-project files linted. +Be sure to include a minimal reproduction we can work with to understand your use case! + ## I get errors telling me "ESLint was configured to run ... However, that TSConfig does not / none of those TSConfigs include this file" These errors are caused by an ESLint config requesting type information be generated for a file that isn't included in the TypeScript configuration. @@ -499,6 +533,6 @@ If you think you're having issues with performance, see our [Performance Trouble ## Are TypeScript project references supported? -No, TypeScript project references are not yet supported. +Yes, but only with [`EXPERIMENTAL_useProjectService`](../packages/Parser.mdx#experimental_useprojectservice). See [issue #2094 discussing project references](https://github.com/typescript-eslint/typescript-eslint/issues/2094) for more details. diff --git a/packages/typescript-estree/src/clear-caches.ts b/packages/typescript-estree/src/clear-caches.ts index 015fd18e29c8..5e9867d3beab 100644 --- a/packages/typescript-estree/src/clear-caches.ts +++ b/packages/typescript-estree/src/clear-caches.ts @@ -1,5 +1,8 @@ import { clearWatchCaches } from './create-program/getWatchProgramsForProjects'; -import { clearProgramCache as clearProgramCacheOriginal } from './parser'; +import { + clearDefaultProjectMatchedFiles, + clearProgramCache as clearProgramCacheOriginal, +} from './parser'; import { clearTSConfigMatchCache, clearTSServerProjectService, @@ -14,6 +17,7 @@ import { clearGlobCache } from './parseSettings/resolveProjectList'; * - In custom lint tooling that iteratively lints one project at a time to prevent OOMs. */ export function clearCaches(): void { + clearDefaultProjectMatchedFiles(); clearProgramCacheOriginal(); clearWatchCaches(); clearTSConfigMatchCache(); diff --git a/packages/typescript-estree/src/create-program/createProjectService.ts b/packages/typescript-estree/src/create-program/createProjectService.ts index 1cf7f9d82992..034785b15185 100644 --- a/packages/typescript-estree/src/create-program/createProjectService.ts +++ b/packages/typescript-estree/src/create-program/createProjectService.ts @@ -2,6 +2,9 @@ import type * as ts from 'typescript/lib/tsserverlibrary'; import type { ProjectServiceOptions } from '../parser-options'; +import { validateDefaultProjectForFilesGlob } from './validateDefaultProjectForFilesGlob'; + +const DEFAULT_PROJECT_MATCHED_FILES_THRESHOLD = 8; const doNothing = (): void => {}; @@ -13,6 +16,7 @@ export type TypeScriptProjectService = ts.server.ProjectService; export interface ProjectServiceSettings { allowDefaultProjectForFiles: string[] | undefined; + maximumDefaultProjectFileMatchCount: number; service: TypeScriptProjectService; } @@ -20,6 +24,8 @@ export function createProjectService( options: boolean | ProjectServiceOptions | undefined, jsDocParsingMode: ts.JSDocParsingMode | undefined, ): ProjectServiceSettings { + validateDefaultProjectForFilesGlob(options); + // We import this lazily to avoid its cost for users who don't use the service // TODO: Once we drop support for TS<5.3 we can import from "typescript" directly const tsserver = require('typescript/lib/tsserverlibrary') as typeof ts; @@ -58,11 +64,13 @@ export function createProjectService( jsDocParsingMode, }); + const optionsOrDefaults = typeof options === 'object' ? options : {}; + return { - allowDefaultProjectForFiles: - typeof options === 'object' - ? options.allowDefaultProjectForFiles - : undefined, + allowDefaultProjectForFiles: optionsOrDefaults.allowDefaultProjectForFiles, + maximumDefaultProjectFileMatchCount: + optionsOrDefaults.maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING ?? + DEFAULT_PROJECT_MATCHED_FILES_THRESHOLD, service, }; } diff --git a/packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts b/packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts new file mode 100644 index 000000000000..9d1016fe5d93 --- /dev/null +++ b/packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts @@ -0,0 +1,27 @@ +import type { ProjectServiceOptions } from '../parser-options'; + +export const DEFAULT_PROJECT_FILES_ERROR_EXPLANATION = ` + +Having many files run with the default project is known to cause performance issues and slow down linting. + +See https://typescript-eslint.io/troubleshooting/#allowdefaultprojectforfiles-glob-too-wide +`; + +export function validateDefaultProjectForFilesGlob( + options: boolean | ProjectServiceOptions | undefined, +): void { + if ( + typeof options !== 'object' || + !options.allowDefaultProjectForFiles?.length + ) { + return; + } + + for (const glob of options.allowDefaultProjectForFiles) { + if (glob.includes('**')) { + throw new Error( + `allowDefaultProjectForFiles glob '${glob}' contains a disallowed '**'.${DEFAULT_PROJECT_FILES_ERROR_EXPLANATION}`, + ); + } + } +} diff --git a/packages/typescript-estree/src/parser-options.ts b/packages/typescript-estree/src/parser-options.ts index 4347ee29e47e..5346560c856b 100644 --- a/packages/typescript-estree/src/parser-options.ts +++ b/packages/typescript-estree/src/parser-options.ts @@ -109,6 +109,15 @@ export interface ProjectServiceOptions { * Globs of files to allow running with the default inferred project settings. */ allowDefaultProjectForFiles?: string[]; + + /** + * The maximum number of files {@link allowDefaultProjectForFiles} may match. + * Each file match slows down linting, so if you do need to use this, please + * file an informative issue on typescript-eslint explaining why - so we can + * help you avoid using it! + * @default 8 + */ + maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING?: number; } interface ParseAndGenerateServicesOptions extends ParseOptions { diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index ffa0c4212295..b4931a6da36e 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -40,6 +40,11 @@ function clearProgramCache(): void { existingPrograms.clear(); } +const defaultProjectMatchedFiles = new Set(); +function clearDefaultProjectMatchedFiles(): void { + defaultProjectMatchedFiles.clear(); +} + /** * @param parseSettings Internal settings for parsing the file * @param hasFullTypeInformation True if the program should be attempted to be calculated from provided tsconfig files @@ -54,6 +59,7 @@ function getProgramAndAST( parseSettings.EXPERIMENTAL_projectService, parseSettings, hasFullTypeInformation, + defaultProjectMatchedFiles, ); if (fromProjectService) { return fromProjectService; @@ -286,6 +292,7 @@ export { parse, parseAndGenerateServices, ParseAndGenerateServicesResult, + clearDefaultProjectMatchedFiles, clearProgramCache, clearParseAndGenerateServicesCalls, }; diff --git a/packages/typescript-estree/src/useProgramFromProjectService.ts b/packages/typescript-estree/src/useProgramFromProjectService.ts index ba80e5599024..8f18b08ed788 100644 --- a/packages/typescript-estree/src/useProgramFromProjectService.ts +++ b/packages/typescript-estree/src/useProgramFromProjectService.ts @@ -5,6 +5,7 @@ import path from 'path'; import { createProjectProgram } from './create-program/createProjectProgram'; import type { ProjectServiceSettings } from './create-program/createProjectService'; import type { ASTAndDefiniteProgram } from './create-program/shared'; +import { DEFAULT_PROJECT_FILES_ERROR_EXPLANATION } from './create-program/validateDefaultProjectForFilesGlob'; import type { MutableParseSettings } from './parseSettings'; const log = debug( @@ -12,9 +13,14 @@ const log = debug( ); export function useProgramFromProjectService( - { allowDefaultProjectForFiles, service }: ProjectServiceSettings, + { + allowDefaultProjectForFiles, + maximumDefaultProjectFileMatchCount, + service, + }: ProjectServiceSettings, parseSettings: Readonly, hasFullTypeInformation: boolean, + defaultProjectMatchedFiles: Set, ): ASTAndDefiniteProgram | undefined { // We don't canonicalize the filename because it caused a performance regression. // See https://github.com/typescript-eslint/typescript-eslint/issues/8519 @@ -77,6 +83,20 @@ export function useProgramFromProjectService( return undefined; } + defaultProjectMatchedFiles.add(filePathAbsolute); + if (defaultProjectMatchedFiles.size > maximumDefaultProjectFileMatchCount) { + throw new Error( + `Too many files (>${maximumDefaultProjectFileMatchCount}) have matched the default project.${DEFAULT_PROJECT_FILES_ERROR_EXPLANATION} +Matching files: +${Array.from(defaultProjectMatchedFiles) + .map(file => `- ${file}`) + .join('\n')} + +If you absolutely need more files included, set parserOptions.EXPERIMENTAL_useProjectService.maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING to a larger value. +`, + ); + } + log('Found project service program for: %s', filePathAbsolute); return createProjectProgram(parseSettings, [program]); diff --git a/packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts b/packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts index cec730d1cf74..cfb6fe0bf863 100644 --- a/packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts +++ b/packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts @@ -1,7 +1,10 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type -- Fancy mocks */ import path from 'path'; -import type { TypeScriptProjectService } from '../../src/create-program/createProjectService'; +import type { + ProjectServiceSettings, + TypeScriptProjectService, +} from '../../src/create-program/createProjectService'; import type { ParseSettings } from '../../src/parseSettings'; import { useProgramFromProjectService } from '../../src/useProgramFromProjectService'; @@ -42,14 +45,27 @@ const mockParseSettings = { filePath: 'path/PascalCaseDirectory/camelCaseFile.ts', } as ParseSettings; +const createProjectServiceSettings = < + T extends Partial, +>( + settings: T, +) => ({ + maximumDefaultProjectFileMatchCount: 8, + ...settings, +}); + describe('useProgramFromProjectService', () => { it('passes an absolute, case-matching file path to service.openClientFile', () => { const { service } = createMockProjectService(); useProgramFromProjectService( - { allowDefaultProjectForFiles: undefined, service }, + createProjectServiceSettings({ + allowDefaultProjectForFiles: undefined, + service, + }), mockParseSettings, false, + new Set(), ); expect(service.openClientFile).toHaveBeenCalledWith( @@ -69,9 +85,14 @@ describe('useProgramFromProjectService', () => { expect(() => useProgramFromProjectService( - { allowDefaultProjectForFiles: [mockParseSettings.filePath], service }, + { + allowDefaultProjectForFiles: [mockParseSettings.filePath], + maximumDefaultProjectFileMatchCount: 8, + service, + }, mockParseSettings, true, + new Set(), ), ).toThrow( `${mockParseSettings.filePath} was included by allowDefaultProjectForFiles but also was found in the project service. Consider removing it from allowDefaultProjectForFiles.`, @@ -85,28 +106,70 @@ describe('useProgramFromProjectService', () => { expect(() => useProgramFromProjectService( - { allowDefaultProjectForFiles: [], service }, + createProjectServiceSettings({ + allowDefaultProjectForFiles: [], + service, + }), mockParseSettings, true, + new Set(), ), ).toThrow( `${mockParseSettings.filePath} was not found by the project service. Consider either including it in the tsconfig.json or including it in allowDefaultProjectForFiles.`, ); }); + it('throws an error when called more than the maximum allowed file count', () => { + const { service } = createMockProjectService(); + const program = { getSourceFile: jest.fn() }; + + mockGetProgram.mockReturnValueOnce(program); + + service.openClientFile.mockReturnValueOnce({}); + + expect(() => + useProgramFromProjectService( + createProjectServiceSettings({ + allowDefaultProjectForFiles: [mockParseSettings.filePath], + maximumDefaultProjectFileMatchCount: 2, + service, + }), + mockParseSettings, + true, + new Set(['a', 'b']), + ), + ).toThrow(`Too many files (>2) have matched the default project. + +Having many files run with the default project is known to cause performance issues and slow down linting. + +See https://typescript-eslint.io/troubleshooting/#allowdefaultprojectforfiles-glob-too-wide + +Matching files: +- a +- b +- /repos/repo/path/PascalCaseDirectory/camelCaseFile.ts + +If you absolutely need more files included, set parserOptions.EXPERIMENTAL_useProjectService.maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING to a larger value. +`); + }); + it('returns undefined when hasFullTypeInformation is disabled, the file is both in the project service and allowDefaultProjectForFiles, and the service does not have a matching program', () => { const { service } = createMockProjectService(); - mockGetProgram.mockReturnValue(undefined); + mockGetProgram.mockReturnValueOnce(undefined); service.openClientFile.mockReturnValueOnce({ configFileName: 'tsconfig.json', }); const actual = useProgramFromProjectService( - { allowDefaultProjectForFiles: [mockParseSettings.filePath], service }, + createProjectServiceSettings({ + allowDefaultProjectForFiles: [mockParseSettings.filePath], + service, + }), mockParseSettings, false, + new Set(), ); expect(actual).toBeUndefined(); @@ -116,7 +179,7 @@ describe('useProgramFromProjectService', () => { const { service } = createMockProjectService(); const program = { getSourceFile: jest.fn() }; - mockGetProgram.mockReturnValue(program); + mockGetProgram.mockReturnValueOnce(program); service.openClientFile.mockReturnValueOnce({ configFileName: 'tsconfig.json', @@ -124,9 +187,13 @@ describe('useProgramFromProjectService', () => { mockCreateProjectProgram.mockReturnValueOnce(program); const actual = useProgramFromProjectService( - { allowDefaultProjectForFiles: [mockParseSettings.filePath], service }, + createProjectServiceSettings({ + allowDefaultProjectForFiles: [mockParseSettings.filePath], + service, + }), mockParseSettings, false, + new Set(), ); expect(actual).toBe(program); @@ -136,15 +203,19 @@ describe('useProgramFromProjectService', () => { const { service } = createMockProjectService(); const program = { getSourceFile: jest.fn() }; - mockGetProgram.mockReturnValue(program); + mockGetProgram.mockReturnValueOnce(program); service.openClientFile.mockReturnValueOnce({}); mockCreateProjectProgram.mockReturnValueOnce(program); const actual = useProgramFromProjectService( - { allowDefaultProjectForFiles: [], service }, + createProjectServiceSettings({ + allowDefaultProjectForFiles: [], + service, + }), mockParseSettings, false, + new Set(), ); expect(actual).toBe(program); diff --git a/packages/typescript-estree/tests/lib/validateDefaultProjectForFilesGlob.test.ts b/packages/typescript-estree/tests/lib/validateDefaultProjectForFilesGlob.test.ts new file mode 100644 index 000000000000..1a1afc0a05e1 --- /dev/null +++ b/packages/typescript-estree/tests/lib/validateDefaultProjectForFilesGlob.test.ts @@ -0,0 +1,31 @@ +import { validateDefaultProjectForFilesGlob } from '../../src/create-program/validateDefaultProjectForFilesGlob'; + +describe('validateDefaultProjectForFilesGlob', () => { + it('does not throw when options is falsy', () => { + expect(() => validateDefaultProjectForFilesGlob(false)).not.toThrow(); + }); + + it('does not throw when options.allowDefaultProjectForFiles is an empty array', () => { + expect(() => + validateDefaultProjectForFilesGlob({ allowDefaultProjectForFiles: [] }), + ).not.toThrow(); + }); + + it('does not throw when options.allowDefaultProjectForFiles contains a non-** glob', () => { + expect(() => + validateDefaultProjectForFilesGlob({ + allowDefaultProjectForFiles: ['./*.js'], + }), + ).not.toThrow(); + }); + + it('throws when options.allowDefaultProjectForFiles contains a ** glob', () => { + expect(() => + validateDefaultProjectForFilesGlob({ + allowDefaultProjectForFiles: ['**/*.js'], + }), + ).toThrow( + /allowDefaultProjectForFiles glob '\*\*\/\*\.js' contains a disallowed '\*\*'\./, + ); + }); +}); diff --git a/packages/website/src/theme/MDXComponents/HiddenHeading.module.css b/packages/website/src/theme/MDXComponents/HiddenHeading.module.css new file mode 100644 index 000000000000..79c1e7a6e7d3 --- /dev/null +++ b/packages/website/src/theme/MDXComponents/HiddenHeading.module.css @@ -0,0 +1,6 @@ +.hiddenHeading { + display: block; + position: relative; + top: calc(-1 * var(--ifm-navbar-height)); + visibility: hidden; +} diff --git a/packages/website/src/theme/MDXComponents/HiddenHeading.tsx b/packages/website/src/theme/MDXComponents/HiddenHeading.tsx new file mode 100644 index 000000000000..24ff9052f01d --- /dev/null +++ b/packages/website/src/theme/MDXComponents/HiddenHeading.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +import styles from './HiddenHeading.module.css'; + +export interface HiddenHeadingProps { + id: string; +} + +export function HiddenHeading({ id }: HiddenHeadingProps): React.JSX.Element { + return ; +} diff --git a/packages/website/src/theme/MDXComponents/index.tsx b/packages/website/src/theme/MDXComponents/index.tsx index f84c301edc35..787837995963 100644 --- a/packages/website/src/theme/MDXComponents/index.tsx +++ b/packages/website/src/theme/MDXComponents/index.tsx @@ -2,13 +2,15 @@ import Admonition from '@theme/Admonition'; import MDXComponents from '@theme-original/MDXComponents'; import { BaseRuleReference } from './BaseRuleReference'; +import { HiddenHeading } from './HiddenHeading'; import { RuleAttributes } from './RuleAttributes'; import { TryInPlayground } from './TryInPlayground'; export default { ...MDXComponents, + Admonition, BaseRuleReference, + HiddenHeading, RuleAttributes, TryInPlayground, - Admonition, }; From 1615505acc27773fd86abf0391ca16222f07c8a7 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 10:24:51 -0400 Subject: [PATCH 2/4] lil touchup for the asterisk --- .../src/create-program/validateDefaultProjectForFilesGlob.ts | 2 +- .../tests/lib/validateDefaultProjectForFilesGlob.test.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts b/packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts index 010b44b05861..598982bdc8e3 100644 --- a/packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts +++ b/packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts @@ -17,7 +17,7 @@ export function validateDefaultProjectForFilesGlob( for (const glob of options.allowDefaultProjectForFiles) { if (glob === '*') { throw new Error( - `allowDefaultProjectForFiles glob '${glob}' is the overly wide '*'.${DEFAULT_PROJECT_FILES_ERROR_EXPLANATION}`, + `allowDefaultProjectForFiles contains the overly wide '*'.${DEFAULT_PROJECT_FILES_ERROR_EXPLANATION}`, ); } if (glob.includes('**')) { diff --git a/packages/typescript-estree/tests/lib/validateDefaultProjectForFilesGlob.test.ts b/packages/typescript-estree/tests/lib/validateDefaultProjectForFilesGlob.test.ts index 6ff26780bcf2..6510182fefd9 100644 --- a/packages/typescript-estree/tests/lib/validateDefaultProjectForFilesGlob.test.ts +++ b/packages/typescript-estree/tests/lib/validateDefaultProjectForFilesGlob.test.ts @@ -20,9 +20,7 @@ describe('validateDefaultProjectForFilesGlob', () => { validateDefaultProjectForFilesGlob({ allowDefaultProjectForFiles: ['*'], }), - ).toThrow( - /allowDefaultProjectForFiles glob '\*\*\/\*\.js' is the overly wide '\*'\./, - ); + ).toThrow(/allowDefaultProjectForFiles contains the overly wide '\*'\./); }); it('throws when options.allowDefaultProjectForFiles contains a ** glob', () => { From ebf15a452f1f4ba621aa8aecb7accb7a695eb813 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 10:42:43 -0400 Subject: [PATCH 3/4] Spelling and Windows normalization --- .cspell.json | 2 ++ .../tests/lib/useProgramFromProjectService.test.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.cspell.json b/.cspell.json index 279727a77428..dc41dd9403fb 100644 --- a/.cspell.json +++ b/.cspell.json @@ -50,6 +50,7 @@ "Airbnb", "Airbnb's", "ambiently", + "allowdefaultprojectforfiles", "Armano", "astexplorer", "Astro", @@ -150,6 +151,7 @@ "unoptimized", "unprefixed", "upsert", + "useprojectservice", "Waiblinger", "warnonunsupportedtypescriptversion", "Zacher" diff --git a/packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts b/packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts index cfb6fe0bf863..5b4a9b8cabba 100644 --- a/packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts +++ b/packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts @@ -147,7 +147,7 @@ See https://typescript-eslint.io/troubleshooting/#allowdefaultprojectforfiles-gl Matching files: - a - b -- /repos/repo/path/PascalCaseDirectory/camelCaseFile.ts +- ${path.normalize('/repos/repo/path/PascalCaseDirectory/camelCaseFile.ts')} If you absolutely need more files included, set parserOptions.EXPERIMENTAL_useProjectService.maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING to a larger value. `); From d00856e3a2b9ccc021c556c3a8d52fa5be32ede9 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 11:26:48 -0400 Subject: [PATCH 4/4] Also reset new cache in persistentParse.test.ts --- .../typescript-estree/tests/lib/persistentParse.test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/typescript-estree/tests/lib/persistentParse.test.ts b/packages/typescript-estree/tests/lib/persistentParse.test.ts index dbfd2831dea5..2a55b63f09a0 100644 --- a/packages/typescript-estree/tests/lib/persistentParse.test.ts +++ b/packages/typescript-estree/tests/lib/persistentParse.test.ts @@ -4,7 +4,10 @@ import tmp from 'tmp'; import { clearCaches } from '../../src/clear-caches'; import { clearWatchCaches } from '../../src/create-program/getWatchProgramsForProjects'; -import { parseAndGenerateServices } from '../../src/parser'; +import { + clearDefaultProjectMatchedFiles, + parseAndGenerateServices, +} from '../../src/parser'; const CONTENTS = { foo: 'console.log("foo")', @@ -19,6 +22,9 @@ const CONTENTS = { const cwdCopy = process.cwd(); const tmpDirs = new Set(); afterEach(() => { + // reset project tracking + clearDefaultProjectMatchedFiles(); + // stop watching the files and folders clearWatchCaches();