From 96b6e74b8b79796c4e675a63a2c3128b8a25abea Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Wed, 19 Jul 2023 23:22:15 +0930 Subject: [PATCH 1/2] feat: add types for flat config files --- packages/eslint-plugin/index.d.ts | 4 +- .../eslint-plugin/tools/generate-configs.ts | 18 +- packages/rule-tester/src/RuleTester.ts | 3 +- .../rule-tester/src/types/RuleTesterConfig.ts | 7 +- .../rule-tester/src/types/ValidTestCase.ts | 5 +- .../src/utils/validationHelpers.ts | 6 +- packages/scope-manager/src/ScopeManager.ts | 4 +- packages/scope-manager/src/analyze.ts | 4 +- packages/types/src/parser-options.ts | 10 +- packages/utils/src/ts-eslint/Config.ts | 244 ++++++++++++++++++ packages/utils/src/ts-eslint/ESLint.ts | 7 +- packages/utils/src/ts-eslint/Linter.ts | 177 +++---------- packages/utils/src/ts-eslint/Parser.ts | 70 +++++ packages/utils/src/ts-eslint/Processor.ts | 48 ++++ packages/utils/src/ts-eslint/RuleTester.ts | 7 +- packages/utils/src/ts-eslint/SourceCode.ts | 5 +- packages/utils/src/ts-eslint/index.ts | 3 + .../website/src/components/linter/config.ts | 4 +- .../src/components/linter/createLinter.ts | 25 +- .../src/components/linter/createParser.ts | 6 +- .../website/src/components/linter/types.ts | 15 +- 21 files changed, 478 insertions(+), 194 deletions(-) create mode 100644 packages/utils/src/ts-eslint/Config.ts create mode 100644 packages/utils/src/ts-eslint/Parser.ts create mode 100644 packages/utils/src/ts-eslint/Processor.ts diff --git a/packages/eslint-plugin/index.d.ts b/packages/eslint-plugin/index.d.ts index 7b4715f81f74..30f22e9b09ef 100644 --- a/packages/eslint-plugin/index.d.ts +++ b/packages/eslint-plugin/index.d.ts @@ -1,9 +1,9 @@ -import type { TSESLint } from '@typescript-eslint/utils'; +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; import type rules from './rules'; declare const cjsExport: { - configs: Record; + configs: Record; rules: typeof rules; }; export = cjsExport; diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index 5056bdb7de42..de9e7a9ac9b3 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -1,4 +1,10 @@ -import type { TSESLint } from '@typescript-eslint/utils'; +import type { + ClassicConfig, + Linter, + RuleListener, + RuleModule, + RuleRecommendation, +} from '@typescript-eslint/utils/ts-eslint'; import * as fs from 'fs'; import * as path from 'path'; import prettier from 'prettier'; @@ -48,10 +54,10 @@ async function main(): Promise { const prettierConfig = prettier.resolveConfig.sync(__dirname); interface LinterConfigRules { - [name: string]: TSESLint.Linter.RuleLevel; + [name: string]: ClassicConfig.RuleLevel; } - interface LinterConfig extends TSESLint.Linter.Config { + interface LinterConfig extends ClassicConfig.Config { extends?: string[] | string; plugins?: string[]; } @@ -78,7 +84,7 @@ async function main(): Promise { type RuleEntry = [ string, - TSESLint.RuleModule, + RuleModule, ]; const allRuleEntries: RuleEntry[] = Object.entries(rules).sort((a, b) => @@ -89,7 +95,7 @@ async function main(): Promise { deprecated?: 'exclude'; typeChecked?: 'exclude' | 'include-only'; baseRuleForExtensionRule?: 'exclude'; - forcedRuleLevel?: TSESLint.Linter.RuleLevel; + forcedRuleLevel?: Linter.RuleLevel; } /** @@ -190,7 +196,7 @@ async function main(): Promise { } function filterRuleEntriesTo( - ...recommendations: (TSESLint.RuleRecommendation | undefined)[] + ...recommendations: (RuleRecommendation | undefined)[] ): RuleEntry[] { return allRuleEntries.filter(([, rule]) => recommendations.includes(rule.meta.docs?.recommended), diff --git a/packages/rule-tester/src/RuleTester.ts b/packages/rule-tester/src/RuleTester.ts index cc6577611378..a61c5224e66c 100644 --- a/packages/rule-tester/src/RuleTester.ts +++ b/packages/rule-tester/src/RuleTester.ts @@ -10,6 +10,7 @@ import { deepMerge } from '@typescript-eslint/utils/eslint-utils'; import type { AnyRuleCreateFunction, AnyRuleModule, + Parser, ParserOptions, RuleContext, RuleModule, @@ -521,7 +522,7 @@ export class RuleTester extends TestFramework { this.#linter.defineParser( config.parser, - wrapParser(require(config.parser) as Linter.ParserModule), + wrapParser(require(config.parser) as Parser.ParserModule), ); if (schema) { diff --git a/packages/rule-tester/src/types/RuleTesterConfig.ts b/packages/rule-tester/src/types/RuleTesterConfig.ts index c722c5be074e..a51f1a4e0167 100644 --- a/packages/rule-tester/src/types/RuleTesterConfig.ts +++ b/packages/rule-tester/src/types/RuleTesterConfig.ts @@ -1,8 +1,11 @@ -import type { Linter, ParserOptions } from '@typescript-eslint/utils/ts-eslint'; +import type { + ClassicConfig, + ParserOptions, +} from '@typescript-eslint/utils/ts-eslint'; import type { DependencyConstraint } from './DependencyConstraint'; -export interface RuleTesterConfig extends Linter.Config { +export interface RuleTesterConfig extends ClassicConfig.Config { /** * The default parser to use for tests. * @default '@typescript-eslint/parser' diff --git a/packages/rule-tester/src/types/ValidTestCase.ts b/packages/rule-tester/src/types/ValidTestCase.ts index 74776b58f199..11b6c9e7e4b0 100644 --- a/packages/rule-tester/src/types/ValidTestCase.ts +++ b/packages/rule-tester/src/types/ValidTestCase.ts @@ -1,4 +1,5 @@ import type { + Linter, ParserOptions, SharedConfigurationSettings, } from '@typescript-eslint/utils/ts-eslint'; @@ -17,7 +18,7 @@ export interface ValidTestCase> { /** * Environments for the test case. */ - readonly env?: Readonly>; + readonly env?: Readonly; /** * The fake filename for the test case. Useful for rules that make assertion about filenames. */ @@ -25,7 +26,7 @@ export interface ValidTestCase> { /** * The additional global variables. */ - readonly globals?: Record; + readonly globals?: Readonly; /** * Options for the test case. */ diff --git a/packages/rule-tester/src/utils/validationHelpers.ts b/packages/rule-tester/src/utils/validationHelpers.ts index 33fd0c234de8..34e0ca3277de 100644 --- a/packages/rule-tester/src/utils/validationHelpers.ts +++ b/packages/rule-tester/src/utils/validationHelpers.ts @@ -1,6 +1,6 @@ import { simpleTraverse } from '@typescript-eslint/typescript-estree'; import type { TSESTree } from '@typescript-eslint/utils'; -import type { Linter, SourceCode } from '@typescript-eslint/utils/ts-eslint'; +import type { Parser, SourceCode } from '@typescript-eslint/utils/ts-eslint'; /* * List every parameters possible on a test case that are not related to eslint @@ -75,7 +75,7 @@ const parserSymbol = Symbol.for('eslint.RuleTester.parser'); * Wraps the given parser in order to intercept and modify return values from the `parse` and `parseForESLint` methods, for test purposes. * In particular, to modify ast nodes, tokens and comments to throw on access to their `start` and `end` properties. */ -export function wrapParser(parser: Linter.ParserModule): Linter.ParserModule { +export function wrapParser(parser: Parser.ParserModule): Parser.ParserModule { /** * Define `start`/`end` properties of all nodes of the given AST as throwing error. */ @@ -121,7 +121,7 @@ export function wrapParser(parser: Linter.ParserModule): Linter.ParserModule { return { // @ts-expect-error -- see above [parserSymbol]: parser, - parseForESLint(...args): Linter.ESLintParseResult { + parseForESLint(...args): Parser.ParseResult { const ret = parser.parseForESLint(...args); defineStartEndAsErrorInTree(ret.ast, ret.visitorKeys); diff --git a/packages/scope-manager/src/ScopeManager.ts b/packages/scope-manager/src/ScopeManager.ts index e6d3ee333c36..66f8bbe500f5 100644 --- a/packages/scope-manager/src/ScopeManager.ts +++ b/packages/scope-manager/src/ScopeManager.ts @@ -1,4 +1,4 @@ -import type { TSESTree } from '@typescript-eslint/types'; +import type { SourceType, TSESTree } from '@typescript-eslint/types'; import { assert } from './assert'; import type { Scope } from './scope'; @@ -27,7 +27,7 @@ import type { Variable } from './variable'; interface ScopeManagerOptions { globalReturn?: boolean; - sourceType?: 'module' | 'script'; + sourceType?: SourceType; impliedStrict?: boolean; } diff --git a/packages/scope-manager/src/analyze.ts b/packages/scope-manager/src/analyze.ts index 2ab613325c95..450283553b24 100644 --- a/packages/scope-manager/src/analyze.ts +++ b/packages/scope-manager/src/analyze.ts @@ -1,4 +1,4 @@ -import type { Lib, TSESTree } from '@typescript-eslint/types'; +import type { Lib, SourceType, TSESTree } from '@typescript-eslint/types'; import { visitorKeys } from '@typescript-eslint/visitor-keys'; import type { ReferencerOptions } from './referencer'; @@ -55,7 +55,7 @@ interface AnalyzeOptions { /** * The source type of the script. */ - sourceType?: 'module' | 'script'; + sourceType?: SourceType; /** * Emit design-type metadata for decorated declarations in source. diff --git a/packages/types/src/parser-options.ts b/packages/types/src/parser-options.ts index 5389efba75eb..bf1655125dc3 100644 --- a/packages/types/src/parser-options.ts +++ b/packages/types/src/parser-options.ts @@ -16,6 +16,8 @@ type EcmaVersion = | 11 | 12 | 13 + | 14 + | 15 | 2015 | 2016 | 2017 @@ -23,14 +25,18 @@ type EcmaVersion = | 2019 | 2020 | 2021 - | 2022; + | 2022 + | 2023 + | 2024; -type SourceType = 'module' | 'script'; +type SourceTypeClassic = 'module' | 'script'; +type SourceType = SourceTypeClassic | 'commonjs'; interface ParserOptions { ecmaFeatures?: { globalReturn?: boolean; jsx?: boolean; + [key: string]: unknown; }; ecmaVersion?: EcmaVersion | 'latest'; diff --git a/packages/utils/src/ts-eslint/Config.ts b/packages/utils/src/ts-eslint/Config.ts new file mode 100644 index 000000000000..61f943598d9a --- /dev/null +++ b/packages/utils/src/ts-eslint/Config.ts @@ -0,0 +1,244 @@ +/* eslint-disable @typescript-eslint/no-namespace */ + +import type { Parser as ParserType } from './Parser'; +import type * as ParserOptionsTypes from './ParserOptions'; +import type { Processor as ProcessorType } from './Processor'; +import type { + AnyRuleModule, + RuleCreateFunction, + SharedConfigurationSettings, +} from './Rule'; + +/** @internal */ +export namespace SharedConfig { + export type Severity = 0 | 1 | 2; + export type SeverityString = 'error' | 'off' | 'warn'; + export type RuleLevel = Severity | SeverityString; + + export type RuleLevelAndOptions = [RuleLevel, ...unknown[]]; + + export type RuleEntry = RuleLevel | RuleLevelAndOptions; + export type RulesRecord = Partial>; + + export type GlobalVariableOptionBase = 'off' | 'readonly' | 'writable'; + export type GlobalVariableOption = GlobalVariableOptionBase | boolean; + + export interface GlobalsConfig { + [name: string]: GlobalVariableOption; + } + export interface EnvironmentConfig { + [name: string]: boolean; + } + + export type ParserOptions = ParserOptionsTypes.ParserOptions; +} + +export namespace ClassicConfig { + export type EnvironmentConfig = SharedConfig.EnvironmentConfig; + export type GlobalsConfig = SharedConfig.GlobalsConfig; + export type GlobalVariableOption = SharedConfig.GlobalVariableOption; + export type GlobalVariableOptionBase = SharedConfig.GlobalVariableOptionBase; + export type ParserOptions = SharedConfig.ParserOptions; + export type RuleEntry = SharedConfig.RuleEntry; + export type RuleLevel = SharedConfig.RuleLevel; + export type RuleLevelAndOptions = SharedConfig.RuleLevelAndOptions; + export type RulesRecord = SharedConfig.RulesRecord; + export type Severity = SharedConfig.Severity; + export type SeverityString = SharedConfig.SeverityString; + + // https://github.com/eslint/eslintrc/blob/v2.1.0/conf/config-schema.js + interface BaseConfig { + $schema?: string; + /** + * The environment settings. + */ + env?: EnvironmentConfig; + /** + * The path to other config files or the package name of shareable configs. + */ + extends?: string[] | string; + /** + * The global variable settings. + */ + globals?: GlobalsConfig; + /** + * The flag that disables directive comments. + */ + noInlineConfig?: boolean; + /** + * The override settings per kind of files. + */ + overrides?: ConfigOverride[]; + /** + * The path to a parser or the package name of a parser. + */ + parser?: string | null; + /** + * The parser options. + */ + parserOptions?: ParserOptions; + /** + * The plugin specifiers. + */ + plugins?: string[]; + /** + * The processor specifier. + */ + processor?: string; + /** + * The flag to report unused `eslint-disable` comments. + */ + reportUnusedDisableDirectives?: boolean; + /** + * The rule settings. + */ + rules?: RulesRecord; + /** + * The shared settings. + */ + settings?: SharedConfigurationSettings; + } + + export interface ConfigOverride extends BaseConfig { + excludedFiles?: string[] | string; + files: string[] | string; + } + + export interface Config extends BaseConfig { + /** + * The glob patterns that ignore to lint. + */ + ignorePatterns?: string[] | string; + /** + * The root flag. + */ + root?: boolean; + } +} + +export namespace FlatConfig { + export type EcmaVersion = ParserOptionsTypes.EcmaVersion; + export type GlobalsConfig = SharedConfig.GlobalsConfig; + export type Parser = ParserType.ParserModule; + export type ParserOptions = SharedConfig.ParserOptions; + export type Processor = ProcessorType.ProcessorModule; + export type RuleEntry = SharedConfig.RuleEntry; + export type RuleLevel = SharedConfig.RuleLevel; + export type RuleLevelAndOptions = SharedConfig.RuleLevelAndOptions; + export type Rules = SharedConfig.RulesRecord; + export type Settings = SharedConfigurationSettings; + export type Severity = SharedConfig.Severity; + export type SeverityString = SharedConfig.SeverityString; + export type SourceType = ParserOptionsTypes.SourceType | 'commonjs'; + + export interface Plugin { + /** + * The definition of plugin processors. + * Can be referenced by string in the config (i.e., `"pluginName/processorName"`). + */ + processors?: Record; + /** + * The definition of plugin rules. + */ + rules?: Record; + } + export interface Plugins { + [pluginAlias: string]: Plugin; + } + + export interface LinterOptions { + /** + * A Boolean value indicating if inline configuration is allowed. + */ + noInlineConfig?: boolean; + /** + * A Boolean value indicating if unused disable directives should be tracked and reported. + */ + reportUnusedDisableDirectives?: boolean; + } + + export interface LanguageOptions { + /** + * The version of ECMAScript to support. + * May be any year (i.e., `2022`) or version (i.e., `5`). + * Set to `"latest"` for the most recent supported version. + * @default "latest" + */ + ecmaVersion?: EcmaVersion; + /** + * An object specifying additional objects that should be added to the global scope during linting. + */ + globals?: GlobalsConfig; + /** + * An object containing a `parse()` method or a `parseForESLint()` method. + * @default + * ``` + * // https://github.com/eslint/espree + * require('espree') + * ``` + */ + parser?: Parser; + /** + * An object specifying additional options that are passed directly to the parser. + * The available options are parser-dependent. + */ + parserOptions?: ParserOptions; + /** + * The type of JavaScript source code. + * Possible values are `"script"` for traditional script files, `"module"` for ECMAScript modules (ESM), and `"commonjs"` for CommonJS files. + * @default + * ``` + * // for `.js` and `.mjs` files + * "module" + * // for `.cjs` files + * "commonjs" + * ``` + */ + sourceType?: SourceType; + } + + // it's not a json schema so it's nowhere near as nice to read and convert... + // https://github.com/eslint/eslint/blob/v8.45.0/lib/config/flat-config-schema.js + export interface Config { + /** + * An array of glob patterns indicating the files that the configuration object should apply to. + * If not specified, the configuration object applies to all files matched by any other configuration object. + */ + files?: string[]; + /** + * An array of glob patterns indicating the files that the configuration object should not apply to. + * If not specified, the configuration object applies to all files matched by files. + */ + ignores?: string[]; + /** + * An object containing settings related to how JavaScript is configured for linting. + */ + languageOptions?: LanguageOptions; + /** + * An object containing settings related to the linting process. + */ + linterOptions?: LinterOptions; + /** + * An object containing a name-value mapping of plugin names to plugin objects. + * When `files` is specified, these plugins are only available to the matching files. + */ + plugins?: Plugins; + /** + * Either an object containing `preprocess()` and `postprocess()` methods or + * a string indicating the name of a processor inside of a plugin + * (i.e., `"pluginName/processorName"`). + */ + processor?: Processor; + /** + * An object containing the configured rules. + * When `files` or `ignores` are specified, these rule configurations are only available to the matching files. + */ + rules?: Rules; + /** + * An object containing name-value pairs of information that should be available to all rules. + */ + settings?: Settings; + } + export type ConfigArray = Config[]; + export type ConfigFile = ConfigArray | (() => Promise); +} diff --git a/packages/utils/src/ts-eslint/ESLint.ts b/packages/utils/src/ts-eslint/ESLint.ts index a7aa2daec98d..6e31deb13d07 100644 --- a/packages/utils/src/ts-eslint/ESLint.ts +++ b/packages/utils/src/ts-eslint/ESLint.ts @@ -2,6 +2,7 @@ import { ESLint as ESLintESLint } from 'eslint'; +import type { ClassicConfig } from './Config'; import type { Linter } from './Linter'; declare class ESLintBase { @@ -23,7 +24,7 @@ declare class ESLintBase { * because ESLint cannot handle the overrides setting. * @returns The promise that will be fulfilled with a configuration object. */ - calculateConfigForFile(filePath: string): Promise; + calculateConfigForFile(filePath: string): Promise; /** * This method checks if a given file is ignored by your configuration. * @param filePath The path to the file you want to check. @@ -107,7 +108,7 @@ namespace ESLint { * You can use this option to define the default settings that will be used if your configuration files don't * configure it. */ - baseConfig?: Linter.Config | null; + baseConfig?: Linter.ConfigType | null; /** * If true is present, the eslint.lintFiles() method caches lint results and uses it if each target file is not * changed. Please mind that ESLint doesn't clear the cache when you upgrade ESLint plugins. In that case, you have @@ -164,7 +165,7 @@ namespace ESLint { * Configuration object, overrides all configurations used with this instance. * You can use this option to define the settings that will be used even if your configuration files configure it. */ - overrideConfig?: Linter.ConfigOverride | null; + overrideConfig?: ClassicConfig.ConfigOverride | null; /** * The path to a configuration file, overrides all configurations used with this instance. * The options.overrideConfig option is applied after this option is applied. diff --git a/packages/utils/src/ts-eslint/Linter.ts b/packages/utils/src/ts-eslint/Linter.ts index 59274a7e6fc4..f1f645d82eb3 100644 --- a/packages/utils/src/ts-eslint/Linter.ts +++ b/packages/utils/src/ts-eslint/Linter.ts @@ -2,15 +2,10 @@ import { Linter as ESLintLinter } from 'eslint'; -import type { ParserServices, TSESTree } from '../ts-estree'; -import type { ParserOptions as TSParserOptions } from './ParserOptions'; -import type { - RuleCreateFunction, - RuleFix, - RuleModule, - SharedConfigurationSettings, -} from './Rule'; -import type { Scope } from './Scope'; +import type { ClassicConfig, FlatConfig, SharedConfig } from './Config'; +import type { Parser } from './Parser'; +import type { Processor as ProcessorType } from './Processor'; +import type { RuleCreateFunction, RuleFix, RuleModule } from './Rule'; import type { SourceCode } from './SourceCode'; export type MinimalRuleModule< @@ -31,7 +26,7 @@ declare class LinterBase { * @param parserId Name of the parser * @param parserModule The parser object */ - defineParser(parserId: string, parserModule: Linter.ParserModule): void; + defineParser(parserId: string, parserModule: Parser.ParserModule): void; /** * Defines a new linting rule. @@ -78,7 +73,7 @@ declare class LinterBase { */ verify( textOrSourceCode: SourceCode | string, - config: Linter.Config, + config: Linter.ConfigType, filenameOrOptions?: Linter.VerifyOptions | string, ): Linter.LintMessage[]; @@ -91,7 +86,7 @@ declare class LinterBase { */ verifyAndFix( code: string, - config: Linter.Config, + config: Linter.ConfigType, options: Linter.FixOptions, ): Linter.FixReport; @@ -118,95 +113,23 @@ namespace Linter { cwd?: string; } - export type Severity = 0 | 1 | 2; - export type SeverityString = 'error' | 'off' | 'warn'; - export type RuleLevel = Severity | SeverityString; - - export type RuleLevelAndOptions = [RuleLevel, ...unknown[]]; - - export type RuleEntry = RuleLevel | RuleLevelAndOptions; - export type RulesRecord = Partial>; - - export type GlobalVariableOptionBase = 'off' | 'readonly' | 'writable'; - export type GlobalVariableOption = GlobalVariableOptionBase | boolean; - - export interface GlobalsConfig { - [name: string]: GlobalVariableOption; - } - export interface EnvironmentConfig { - [name: string]: boolean; - } - - // https://github.com/eslint/eslint/blob/v6.8.0/conf/config-schema.js - interface BaseConfig { - $schema?: string; - /** - * The environment settings. - */ - env?: EnvironmentConfig; - /** - * The path to other config files or the package name of shareable configs. - */ - extends?: string[] | string; - /** - * The global variable settings. - */ - globals?: GlobalsConfig; - /** - * The flag that disables directive comments. - */ - noInlineConfig?: boolean; - /** - * The override settings per kind of files. - */ - overrides?: ConfigOverride[]; - /** - * The path to a parser or the package name of a parser. - */ - parser?: string; - /** - * The parser options. - */ - parserOptions?: ParserOptions; - /** - * The plugin specifiers. - */ - plugins?: string[]; - /** - * The processor specifier. - */ - processor?: string; - /** - * The flag to report unused `eslint-disable` comments. - */ - reportUnusedDisableDirectives?: boolean; - /** - * The rule settings. - */ - rules?: RulesRecord; - /** - * The shared settings. - */ - settings?: SharedConfigurationSettings; - } - - export interface ConfigOverride extends BaseConfig { - excludedFiles?: string[] | string; - files: string[] | string; - } - - export interface Config extends BaseConfig { - /** - * The glob patterns that ignore to lint. - */ - ignorePatterns?: string[] | string; - /** - * The root flag. - */ - root?: boolean; - } - - export type ParserOptions = TSParserOptions; + export type EnvironmentConfig = SharedConfig.EnvironmentConfig; + export type GlobalsConfig = SharedConfig.GlobalsConfig; + export type GlobalVariableOption = SharedConfig.GlobalVariableOption; + export type GlobalVariableOptionBase = SharedConfig.GlobalVariableOptionBase; + export type ParserOptions = SharedConfig.ParserOptions; + export type RuleEntry = SharedConfig.RuleEntry; + export type RuleLevel = SharedConfig.RuleLevel; + export type RuleLevelAndOptions = SharedConfig.RuleLevelAndOptions; + export type RulesRecord = SharedConfig.RulesRecord; + export type Severity = SharedConfig.Severity; + export type SeverityString = SharedConfig.SeverityString; + + /** @deprecated use ClassicConfig.ConfigType instead */ + export type Config = ClassicConfig.Config; + export type ConfigType = ClassicConfig.Config | FlatConfig.ConfigArray; + /** @deprecated use ClassicConfig.ConfigOverride instead */ + export type ConfigOverride = ClassicConfig.ConfigOverride; export interface VerifyOptions { /** @@ -233,12 +156,12 @@ namespace Linter { * the messages as appropriate, and return a one-dimensional array of * messages. */ - postprocess?: Processor['postprocess']; + postprocess?: ProcessorType.PostProcess; /** * preprocessor for source text. * If provided, this should accept a string of source text, and return an array of code blocks to lint. */ - preprocess?: Processor['preprocess']; + preprocess?: ProcessorType.PreProcess; /** * Adds reported errors for unused `eslint-disable` directives. */ @@ -319,50 +242,20 @@ namespace Linter { messages: LintMessage[]; } - export type ParserModule = - | { - parse(text: string, options?: ParserOptions): TSESTree.Program; - } - | { - parseForESLint( - text: string, - options?: ParserOptions, - ): ESLintParseResult; - }; + /** @deprecated use Parser.ParserModule */ + export type ParserModule = Parser.ParserModule; - export interface ESLintParseResult { - ast: TSESTree.Program; - services?: ParserServices; - scopeManager?: Scope.ScopeManager; - visitorKeys?: SourceCode.VisitorKeys; - } + /** @deprecated use Parser.ParseResult */ + export type ESLintParseResult = Parser.ParseResult; - export interface Processor { - /** - * The function to extract code blocks. - */ - preprocess?: ( - text: string, - filename: string, - ) => (string | { text: string; filename: string })[]; - /** - * The function to merge messages. - */ - postprocess?: ( - messagesList: Linter.LintMessage[][], - filename: string, - ) => Linter.LintMessage[]; - /** - * If `true` then it means the processor supports autofix. - */ - supportsAutofix?: boolean; - } + /** @deprecated use Processor.ProcessorModule */ + export type Processor = ProcessorType.ProcessorModule; export interface Environment { /** * The definition of global variables. */ - globals?: Record; + globals?: GlobalsConfig; /** * The parser options that will be enabled under this environment. */ @@ -373,7 +266,7 @@ namespace Linter { /** * The definition of plugin configs. */ - configs?: Record; + configs?: Record; /** * The definition of plugin environments. */ @@ -381,7 +274,7 @@ namespace Linter { /** * The definition of plugin processors. */ - processors?: Record; + processors?: Record; /** * The definition of plugin rules. */ diff --git a/packages/utils/src/ts-eslint/Parser.ts b/packages/utils/src/ts-eslint/Parser.ts new file mode 100644 index 000000000000..315ab789a823 --- /dev/null +++ b/packages/utils/src/ts-eslint/Parser.ts @@ -0,0 +1,70 @@ +/* eslint-disable @typescript-eslint/no-namespace */ + +import type { ParserServices, TSESTree } from '../ts-estree'; +import type { ParserOptions } from './ParserOptions'; +import type { Scope } from './Scope'; + +export namespace Parser { + export interface ParserMeta { + /** + * The unique name of the parser. + */ + name: string; + /** + * The a string identifying the version of the parser. + */ + version?: string; + } + + export type ParserModule = + | { + /** + * Information about the parser to uniquely identify it when serializing. + */ + meta?: ParserMeta; + /** + * Parses the given text into an ESTree AST + */ + parse(text: string, options?: ParserOptions): TSESTree.Program; + } + | { + /** + * Information about the parser to uniquely identify it when serializing. + */ + meta?: ParserMeta; + /** + * Parses the given text into an AST with optional + */ + parseForESLint(text: string, options?: ParserOptions): ParseResult; + }; + + export interface ParseResult { + /** + * The ESTree AST + */ + ast: TSESTree.Program; + /** + * Any parser-dependent services (such as type checkers for nodes). + * The value of the services property is available to rules as `context.sourceCode.parserServices`. + * The default is an empty object. + */ + services?: ParserServices; + /** + * A `ScopeManager` object. + * Custom parsers can use customized scope analysis for experimental/enhancement syntaxes. + * The default is the `ScopeManager` object which is created by `eslint-scope`. + */ + scopeManager?: Scope.ScopeManager; + /** + * An object to customize AST traversal. + * The keys of the object are the type of AST nodes. + * Each value is an array of the property names which should be traversed. + * The default is `KEYS` of `eslint-visitor-keys`. + */ + visitorKeys?: VisitorKeys; + } + + export interface VisitorKeys { + [nodeType: string]: string[]; + } +} diff --git a/packages/utils/src/ts-eslint/Processor.ts b/packages/utils/src/ts-eslint/Processor.ts new file mode 100644 index 000000000000..57f03ae5deff --- /dev/null +++ b/packages/utils/src/ts-eslint/Processor.ts @@ -0,0 +1,48 @@ +/* eslint-disable @typescript-eslint/no-namespace */ + +import type { Linter } from './Linter'; + +export namespace Processor { + export interface ProcessorMeta { + /** + * The unique name of the processor. + */ + name: string; + /** + * The a string identifying the version of the processor. + */ + version?: string; + } + + export type PreProcess = ( + text: string, + filename: string, + ) => (string | { text: string; filename: string })[]; + + export type PostProcess = ( + messagesList: Linter.LintMessage[][], + filename: string, + ) => Linter.LintMessage[]; + + export interface ProcessorModule { + /** + * Information about the processor to uniquely identify it when serializing. + */ + meta?: ProcessorMeta; + + /** + * The function to extract code blocks. + */ + preprocess?: PreProcess; + + /** + * The function to merge messages. + */ + postprocess?: PostProcess; + + /** + * If `true` then it means the processor supports autofix. + */ + supportsAutofix?: boolean; + } +} diff --git a/packages/utils/src/ts-eslint/RuleTester.ts b/packages/utils/src/ts-eslint/RuleTester.ts index 5e2af43d59b5..51b54fb7b5f3 100644 --- a/packages/utils/src/ts-eslint/RuleTester.ts +++ b/packages/utils/src/ts-eslint/RuleTester.ts @@ -1,6 +1,7 @@ import { RuleTester as ESLintRuleTester } from 'eslint'; import type { AST_NODE_TYPES, AST_TOKEN_TYPES } from '../ts-estree'; +import type { ClassicConfig } from './Config'; import type { Linter } from './Linter'; import type { ParserOptions } from './ParserOptions'; import type { @@ -23,7 +24,7 @@ interface ValidTestCase> { /** * Environments for the test case. */ - readonly env?: Readonly>; + readonly env?: Readonly; /** * The fake filename for the test case. Useful for rules that make assertion about filenames. */ @@ -31,7 +32,7 @@ interface ValidTestCase> { /** * The additional global variables. */ - readonly globals?: Record; + readonly globals?: Readonly; /** * Options for the test case. */ @@ -143,7 +144,7 @@ interface RunTests< readonly valid: readonly (ValidTestCase | string)[]; readonly invalid: readonly InvalidTestCase[]; } -interface RuleTesterConfig extends Linter.Config { +interface RuleTesterConfig extends ClassicConfig.Config { // should be require.resolve(parserPackageName) readonly parser: string; readonly parserOptions?: Readonly; diff --git a/packages/utils/src/ts-eslint/SourceCode.ts b/packages/utils/src/ts-eslint/SourceCode.ts index 3d7f33dd93c2..1654358d5e71 100644 --- a/packages/utils/src/ts-eslint/SourceCode.ts +++ b/packages/utils/src/ts-eslint/SourceCode.ts @@ -3,6 +3,7 @@ import { SourceCode as ESLintSourceCode } from 'eslint'; import type { ParserServices, TSESTree } from '../ts-estree'; +import type { Parser } from './Parser'; import type { Scope } from './Scope'; declare class TokenStore { @@ -384,9 +385,7 @@ namespace SourceCode { visitorKeys: VisitorKeys | null; } - export interface VisitorKeys { - [nodeType: string]: string[]; - } + export type VisitorKeys = Parser.VisitorKeys; export type FilterPredicate = (token: TSESTree.Token) => boolean; export type GetFilterPredicate = diff --git a/packages/utils/src/ts-eslint/index.ts b/packages/utils/src/ts-eslint/index.ts index 48af8aacb957..5f6a1e1b71d5 100644 --- a/packages/utils/src/ts-eslint/index.ts +++ b/packages/utils/src/ts-eslint/index.ts @@ -1,8 +1,11 @@ export * from './AST'; export * from './CLIEngine'; +export * from './Config'; export * from './ESLint'; export * from './Linter'; +export * from './Parser'; export * from './ParserOptions'; +export * from './Processor'; export * from './Rule'; export * from './RuleTester'; export * from './Scope'; diff --git a/packages/website/src/components/linter/config.ts b/packages/website/src/components/linter/config.ts index fc6389b4e1b2..d3c7319a8aa7 100644 --- a/packages/website/src/components/linter/config.ts +++ b/packages/website/src/components/linter/config.ts @@ -1,5 +1,5 @@ import type { ParseSettings } from '@typescript-eslint/typescript-estree/use-at-your-own-risk'; -import type { TSESLint } from '@typescript-eslint/utils'; +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; export const PARSER_NAME = '@typescript-eslint/parser'; @@ -31,7 +31,7 @@ export const defaultParseSettings: ParseSettings = { tsconfigRootDir: '/', }; -export const defaultEslintConfig: TSESLint.Linter.Config = { +export const defaultEslintConfig: ClassicConfig.Config = { parser: PARSER_NAME, parserOptions: { ecmaFeatures: { diff --git a/packages/website/src/components/linter/createLinter.ts b/packages/website/src/components/linter/createLinter.ts index 2f0c17253297..7f3f8541e787 100644 --- a/packages/website/src/components/linter/createLinter.ts +++ b/packages/website/src/components/linter/createLinter.ts @@ -1,5 +1,10 @@ import type * as tsvfs from '@site/src/vendor/typescript-vfs'; -import type { JSONSchema, TSESLint, TSESTree } from '@typescript-eslint/utils'; +import type { JSONSchema, TSESTree } from '@typescript-eslint/utils'; +import type { + ClassicConfig, + Linter, + SourceType, +} from '@typescript-eslint/utils/ts-eslint'; import type * as ts from 'typescript'; import { createCompilerOptions } from '../lib/createCompilerOptions'; @@ -25,11 +30,11 @@ export interface CreateLinter { } >; configs: string[]; - triggerFix(filename: string): TSESLint.Linter.FixReport | undefined; + triggerFix(filename: string): Linter.FixReport | undefined; triggerLint(filename: string): void; onLint(cb: LinterOnLint): () => void; onParse(cb: LinterOnParse): () => void; - updateParserOptions(sourceType?: TSESLint.SourceType): void; + updateParserOptions(sourceType?: SourceType): void; } export function createLinter( @@ -40,7 +45,7 @@ export function createLinter( const rules: CreateLinter['rules'] = new Map(); const configs = new Map(Object.entries(webLinterModule.configs)); let compilerOptions: ts.CompilerOptions = {}; - const eslintConfig: TSESLint.Linter.Config = { ...defaultEslintConfig }; + const eslintConfig: ClassicConfig.Config = { ...defaultEslintConfig }; const onLint = createEventsBinder(); const onParse = createEventsBinder(); @@ -76,7 +81,7 @@ export function createLinter( const messages = linter.verify(code, eslintConfig, filename); onLint.trigger(filename, messages); } catch (e) { - const lintMessage: TSESLint.Linter.LintMessage = { + const lintMessage: Linter.LintMessage = { source: 'eslint', ruleId: '', severity: 2, @@ -97,9 +102,7 @@ export function createLinter( } }; - const triggerFix = ( - filename: string, - ): TSESLint.Linter.FixReport | undefined => { + const triggerFix = (filename: string): Linter.FixReport | undefined => { const code = system.readFile(filename); if (code) { return linter.verifyAndFix(code, eslintConfig, { @@ -110,14 +113,14 @@ export function createLinter( return undefined; }; - const updateParserOptions = (sourceType?: TSESLint.SourceType): void => { + const updateParserOptions = (sourceType?: SourceType): void => { eslintConfig.parserOptions ??= {}; eslintConfig.parserOptions.sourceType = sourceType ?? 'module'; }; const resolveEslintConfig = ( - cfg: Partial, - ): TSESLint.Linter.Config => { + cfg: Partial, + ): ClassicConfig.Config => { const config = { rules: {} }; if (cfg.extends) { const cfgExtends = Array.isArray(cfg.extends) diff --git a/packages/website/src/components/linter/createParser.ts b/packages/website/src/components/linter/createParser.ts index 1c0d9258a8f2..ee509fed0acf 100644 --- a/packages/website/src/components/linter/createParser.ts +++ b/packages/website/src/components/linter/createParser.ts @@ -1,6 +1,6 @@ import type * as tsvfs from '@site/src/vendor/typescript-vfs'; import type { ParserOptions } from '@typescript-eslint/types'; -import type { TSESLint } from '@typescript-eslint/utils'; +import type { Parser } from '@typescript-eslint/utils/ts-eslint'; import type * as ts from 'typescript'; import { defaultParseSettings } from './config'; @@ -17,7 +17,7 @@ export function createParser( onUpdate: (filename: string, model: UpdateModel) => void, utils: WebLinterModule, vfs: typeof tsvfs, -): TSESLint.Linter.ParserModule & { +): Parser.ParserModule & { updateConfig: (compilerOptions: ts.CompilerOptions) => void; } { const registeredFiles = new Set(); @@ -42,7 +42,7 @@ export function createParser( parseForESLint: ( text: string, options: ParserOptions = {}, - ): TSESLint.Linter.ESLintParseResult => { + ): Parser.ParseResult => { const filePath = options.filePath ?? '/input.ts'; // if text is empty use empty line to avoid error diff --git a/packages/website/src/components/linter/types.ts b/packages/website/src/components/linter/types.ts index 540ad0e45218..b03a32ae4ce6 100644 --- a/packages/website/src/components/linter/types.ts +++ b/packages/website/src/components/linter/types.ts @@ -1,6 +1,11 @@ import type { analyze, ScopeManager } from '@typescript-eslint/scope-manager'; import type { astConverter } from '@typescript-eslint/typescript-estree/use-at-your-own-risk'; -import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; +import type { TSESTree } from '@typescript-eslint/utils'; +import type { + ClassicConfig, + Linter, + SourceCode, +} from '@typescript-eslint/utils/ts-eslint'; import type esquery from 'esquery'; import type * as ts from 'typescript'; @@ -14,12 +19,12 @@ export interface UpdateModel { } export interface WebLinterModule { - createLinter: () => TSESLint.Linter; + createLinter: () => Linter; analyze: typeof analyze; - visitorKeys: TSESLint.SourceCode.VisitorKeys; + visitorKeys: SourceCode.VisitorKeys; astConverter: typeof astConverter; esquery: typeof esquery; - configs: Record; + configs: Record; } export type PlaygroundSystem = Required< @@ -31,7 +36,7 @@ export type PlaygroundSystem = Required< export type LinterOnLint = ( fileName: string, - messages: TSESLint.Linter.LintMessage[], + messages: Linter.LintMessage[], ) => void; export type LinterOnParse = (fileName: string, model: UpdateModel) => void; From 91e943be1f90ef7fbddcf165a5d0915b1d0cc29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?= Date: Sat, 11 Nov 2023 16:16:12 -0500 Subject: [PATCH 2/2] Update packages/utils/src/ts-eslint/Parser.ts --- packages/utils/src/ts-eslint/Parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/src/ts-eslint/Parser.ts b/packages/utils/src/ts-eslint/Parser.ts index 315ab789a823..6b3c997c66b4 100644 --- a/packages/utils/src/ts-eslint/Parser.ts +++ b/packages/utils/src/ts-eslint/Parser.ts @@ -33,7 +33,7 @@ export namespace Parser { */ meta?: ParserMeta; /** - * Parses the given text into an AST with optional + * Parses the given text into an AST */ parseForESLint(text: string, options?: ParserOptions): ParseResult; }; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy