From 9acdfef592c7205a7c9cf134a9439d42a5601934 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 1 Aug 2024 17:20:13 -0400 Subject: [PATCH 1/6] chore: enabled eslint-plugin-perfectionist on utils --- eslint.config.mjs | 25 ++ package.json | 1 + .../ast-utils/eslint-utils/PatternMatcher.ts | 30 +-- .../eslint-utils/ReferenceTracker.ts | 39 +-- .../ast-utils/eslint-utils/astUtilities.ts | 15 +- .../src/ast-utils/eslint-utils/predicates.ts | 5 +- .../ast-utils/eslint-utils/scopeAnalysis.ts | 4 +- packages/utils/src/ast-utils/helpers.ts | 16 +- packages/utils/src/ast-utils/predicates.ts | 7 +- .../src/eslint-utils/InferTypesFromRule.ts | 2 +- .../utils/src/eslint-utils/RuleCreator.ts | 9 +- .../utils/src/eslint-utils/applyDefault.ts | 2 +- .../src/eslint-utils/getParserServices.ts | 1 + packages/utils/src/eslint-utils/index.ts | 4 +- packages/utils/src/json-schema.ts | 255 +++++++++--------- packages/utils/src/ts-eslint/Config.ts | 28 +- packages/utils/src/ts-eslint/ESLint.ts | 4 +- packages/utils/src/ts-eslint/Linter.ts | 42 +-- packages/utils/src/ts-eslint/Parser.ts | 40 +-- packages/utils/src/ts-eslint/Processor.ts | 18 +- packages/utils/src/ts-eslint/Rule.ts | 106 ++++---- packages/utils/src/ts-eslint/RuleTester.ts | 32 +-- packages/utils/src/ts-eslint/SourceCode.ts | 50 ++-- .../src/ts-eslint/eslint/ESLintShared.ts | 48 ++-- .../utils/src/ts-eslint/eslint/FlatESLint.ts | 4 +- .../src/ts-eslint/eslint/LegacyESLint.ts | 6 +- packages/utils/src/ts-estree.ts | 2 +- yarn.lock | 104 +++++++ 28 files changed, 524 insertions(+), 375 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 0075efb9b536..f54699d168a9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -13,6 +13,7 @@ import importPlugin from 'eslint-plugin-import'; import jestPlugin from 'eslint-plugin-jest'; import jsdocPlugin from 'eslint-plugin-jsdoc'; import jsxA11yPlugin from 'eslint-plugin-jsx-a11y'; +import perfectionistPlugin from 'eslint-plugin-perfectionist'; import reactPlugin from 'eslint-plugin-react'; import reactHooksPlugin from 'eslint-plugin-react-hooks'; import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort'; @@ -568,4 +569,28 @@ export default tseslint.config( 'import/no-default-export': 'off', }, }, + { + ...perfectionistPlugin.configs['recommended-alphabetical'], + files: ['packages/utils/src/**/*.ts'], + rules: { + ...perfectionistPlugin.configs['recommended-alphabetical'].rules, + 'perfectionist/sort-classes': [ + 'error', + { + order: 'asc', + partitionByComment: true, + type: 'natural', + }, + ], + 'perfectionist/sort-objects': [ + 'error', + { + order: 'asc', + partitionByComment: true, + type: 'natural', + }, + ], + 'simple-import-sort/imports': 'off', + }, + }, ); diff --git a/package.json b/package.json index 226c4f7fa5c0..80b84c1ea0d1 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsdoc": "^47.0.2", "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint-plugin-perfectionist": "^3.0.0", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-simple-import-sort": "^10.0.0", diff --git a/packages/utils/src/ast-utils/eslint-utils/PatternMatcher.ts b/packages/utils/src/ast-utils/eslint-utils/PatternMatcher.ts index 639677087bf4..34431ded3158 100644 --- a/packages/utils/src/ast-utils/eslint-utils/PatternMatcher.ts +++ b/packages/utils/src/ast-utils/eslint-utils/PatternMatcher.ts @@ -1,20 +1,6 @@ import * as eslintUtils from '@eslint-community/eslint-utils'; interface PatternMatcher { - /** - * Iterate all matched parts in a given string. - * - * @see {@link https://eslint-community.github.io/eslint-utils/api/ast-utils.html#matcher-execall} - */ - execAll(str: string): IterableIterator; - - /** - * Check whether this pattern matches a given string or not. - * - * @see {@link https://eslint-community.github.io/eslint-utils/api/ast-utils.html#matcher-test} - */ - test(str: string): boolean; - /** * Replace all matched parts by a given replacer. * @@ -39,8 +25,22 @@ interface PatternMatcher { */ [Symbol.replace]( str: string, - replacer: string | ((...strs: string[]) => string), + replacer: ((...strs: string[]) => string) | string, ): string; + + /** + * Iterate all matched parts in a given string. + * + * @see {@link https://eslint-community.github.io/eslint-utils/api/ast-utils.html#matcher-execall} + */ + execAll(str: string): IterableIterator; + + /** + * Check whether this pattern matches a given string or not. + * + * @see {@link https://eslint-community.github.io/eslint-utils/api/ast-utils.html#matcher-test} + */ + test(str: string): boolean; } /** diff --git a/packages/utils/src/ast-utils/eslint-utils/ReferenceTracker.ts b/packages/utils/src/ast-utils/eslint-utils/ReferenceTracker.ts index e71c75d6d51a..e18a01e21f1a 100644 --- a/packages/utils/src/ast-utils/eslint-utils/ReferenceTracker.ts +++ b/packages/utils/src/ast-utils/eslint-utils/ReferenceTracker.ts @@ -13,55 +13,56 @@ const ReferenceTrackerESM: unique symbol = eslintUtils.ReferenceTracker.ESM; interface ReferenceTracker { /** * Iterate the references that the given `traceMap` determined. - * This method starts to search from global variables. + * This method starts to search from `require()` expression. * - * @see {@link https://eslint-community.github.io/eslint-utils/api/scope-utils.html#tracker-iterateglobalreferences} + * @see {@link https://eslint-community.github.io/eslint-utils/api/scope-utils.html#tracker-iteratecjsreferences} */ - iterateGlobalReferences( + iterateCjsReferences( traceMap: ReferenceTracker.TraceMap, ): IterableIterator>; /** * Iterate the references that the given `traceMap` determined. - * This method starts to search from `require()` expression. + * This method starts to search from `import`/`export` declarations. * - * @see {@link https://eslint-community.github.io/eslint-utils/api/scope-utils.html#tracker-iteratecjsreferences} + * @see {@link https://eslint-community.github.io/eslint-utils/api/scope-utils.html#tracker-iterateesmreferences} */ - iterateCjsReferences( + iterateEsmReferences( traceMap: ReferenceTracker.TraceMap, ): IterableIterator>; /** * Iterate the references that the given `traceMap` determined. - * This method starts to search from `import`/`export` declarations. + * This method starts to search from global variables. * - * @see {@link https://eslint-community.github.io/eslint-utils/api/scope-utils.html#tracker-iterateesmreferences} + * @see {@link https://eslint-community.github.io/eslint-utils/api/scope-utils.html#tracker-iterateglobalreferences} */ - iterateEsmReferences( + iterateGlobalReferences( traceMap: ReferenceTracker.TraceMap, ): IterableIterator>; } interface ReferenceTrackerStatic { + readonly CALL: typeof ReferenceTrackerCALL; + readonly CONSTRUCT: typeof ReferenceTrackerCONSTRUCT; + readonly ESM: typeof ReferenceTrackerESM; + new ( globalScope: TSESLint.Scope.Scope, options?: { + /** + * The name list of Global Object. Optional. Default is `["global", "globalThis", "self", "window"]`. + */ + globalObjectNames?: readonly string[]; /** * The mode which determines how the `tracker.iterateEsmReferences()` method scans CommonJS modules. * If this is `"strict"`, the method binds CommonJS modules to the default export. Otherwise, the method binds * CommonJS modules to both the default export and named exports. Optional. Default is `"strict"`. */ mode?: 'legacy' | 'strict'; - /** - * The name list of Global Object. Optional. Default is `["global", "globalThis", "self", "window"]`. - */ - globalObjectNames?: readonly string[]; }, ): ReferenceTracker; readonly READ: typeof ReferenceTrackerREAD; - readonly CALL: typeof ReferenceTrackerCALL; - readonly CONSTRUCT: typeof ReferenceTrackerCONSTRUCT; - readonly ESM: typeof ReferenceTrackerESM; } namespace ReferenceTracker { @@ -73,18 +74,18 @@ namespace ReferenceTracker { // eslint-disable-next-line @typescript-eslint/no-explicit-any export type TraceMap = Record>; export interface TraceMapElement { - [ReferenceTrackerREAD]?: T; + [key: string]: TraceMapElement; [ReferenceTrackerCALL]?: T; [ReferenceTrackerCONSTRUCT]?: T; [ReferenceTrackerESM]?: true; - [key: string]: TraceMapElement; + [ReferenceTrackerREAD]?: T; } // eslint-disable-next-line @typescript-eslint/no-explicit-any export interface FoundReference { + info: T; node: TSESTree.Node; path: readonly string[]; type: ReferenceType; - info: T; } } diff --git a/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts b/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts index 404697d0e1ce..81f1561646f5 100644 --- a/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts +++ b/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts @@ -43,7 +43,7 @@ const getPropertyName = eslintUtils.getPropertyName as ( | TSESTree.Property | TSESTree.PropertyDefinition, initialScope?: TSESLint.Scope.Scope, -) => string | null; +) => null | string; /** * Get the value of a given node if it can decide the value statically. @@ -70,7 +70,7 @@ const getStaticValue = eslintUtils.getStaticValue as ( const getStringIfConstant = eslintUtils.getStringIfConstant as ( node: TSESTree.Node, initialScope?: TSESLint.Scope.Scope, -) => string | null; +) => null | string; /** * Check whether a given node has any side effect or not. @@ -105,6 +105,12 @@ const hasSideEffect = eslintUtils.hasSideEffect as ( ) => boolean; const isParenthesized = eslintUtils.isParenthesized as { + ( + times: number, + node: TSESTree.Node, + sourceCode: TSESLint.SourceCode, + ): boolean; + /** * Check whether a given node is parenthesized or not. * This function detects it correctly even if it's parenthesized by specific syntax. @@ -115,11 +121,6 @@ const isParenthesized = eslintUtils.isParenthesized as { * For example, `isParenthesized(2, node, sourceCode)` returns true for `((foo))`, but not for `(foo)`. */ (node: TSESTree.Node, sourceCode: TSESLint.SourceCode): boolean; - ( - times: number, - node: TSESTree.Node, - sourceCode: TSESLint.SourceCode, - ): boolean; }; export { diff --git a/packages/utils/src/ast-utils/eslint-utils/predicates.ts b/packages/utils/src/ast-utils/eslint-utils/predicates.ts index 2a3d6d678d43..759def4375fc 100644 --- a/packages/utils/src/ast-utils/eslint-utils/predicates.ts +++ b/packages/utils/src/ast-utils/eslint-utils/predicates.ts @@ -10,8 +10,9 @@ type IsNotSpecificTokenFunction = ( token: TSESTree.Token, ) => token is Exclude; -type PunctuatorTokenWithValue = - TSESTree.PunctuatorToken & { value: Value }; +type PunctuatorTokenWithValue = { + value: Value; +} & TSESTree.PunctuatorToken; type IsPunctuatorTokenWithValueFunction = IsSpecificTokenFunction>; type IsNotPunctuatorTokenWithValueFunction = diff --git a/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts b/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts index 43199ce05533..5b9ca52c958f 100644 --- a/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts +++ b/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts @@ -10,8 +10,8 @@ import type { TSESTree } from '../../ts-estree'; */ const findVariable = eslintUtils.findVariable as ( initialScope: TSESLint.Scope.Scope, - nameOrNode: TSESTree.Identifier | string, -) => TSESLint.Scope.Variable | null; + nameOrNode: string | TSESTree.Identifier, +) => null | TSESLint.Scope.Variable; /** * Get the innermost scope which contains a given node. diff --git a/packages/utils/src/ast-utils/helpers.ts b/packages/utils/src/ast-utils/helpers.ts index c76d24f88246..cc77e33c48c8 100644 --- a/packages/utils/src/ast-utils/helpers.ts +++ b/packages/utils/src/ast-utils/helpers.ts @@ -8,14 +8,14 @@ type ObjectEntries = ObjectEntry[]; export const isNodeOfType = (nodeType: NodeType) => ( - node: TSESTree.Node | null | undefined, + node: null | TSESTree.Node | undefined, ): node is Extract => node?.type === nodeType; export const isNodeOfTypes = (nodeTypes: NodeTypes) => ( - node: TSESTree.Node | null | undefined, + node: null | TSESTree.Node | undefined, ): node is Extract => !!node && nodeTypes.includes(node.type); @@ -27,12 +27,12 @@ export const isNodeOfTypeWithConditions = < nodeType: NodeType, conditions: Conditions, ): (( - node: TSESTree.Node | null | undefined, + node: null | TSESTree.Node | undefined, ) => node is Conditions & ExtractedNode) => { const entries = Object.entries(conditions) as ObjectEntries; return ( - node: TSESTree.Node | null | undefined, + node: null | TSESTree.Node | undefined, ): node is Conditions & ExtractedNode => node?.type === nodeType && entries.every(([key, value]) => node[key as keyof TSESTree.Node] === value); @@ -43,17 +43,17 @@ export const isTokenOfTypeWithConditions = < // This is technically unsafe, but we find it useful to extract out the type // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters ExtractedToken extends Extract, - Conditions extends Partial, + Conditions extends Partial<{ type: TokenType } & TSESTree.Token>, >( tokenType: TokenType, conditions: Conditions, ): (( - token: TSESTree.Token | null | undefined, + token: null | TSESTree.Token | undefined, ) => token is Conditions & ExtractedToken) => { const entries = Object.entries(conditions) as ObjectEntries; return ( - token: TSESTree.Token | null | undefined, + token: null | TSESTree.Token | undefined, ): token is Conditions & ExtractedToken => token?.type === tokenType && entries.every( @@ -70,7 +70,7 @@ export const isNotTokenOfTypeWithConditions = tokenType: TokenType, conditions: Conditions, ): (( - token: TSESTree.Token | null | undefined, + token: null | TSESTree.Token | undefined, ) => token is Exclude) => (token): token is Exclude => !isTokenOfTypeWithConditions(tokenType, conditions)(token); diff --git a/packages/utils/src/ast-utils/predicates.ts b/packages/utils/src/ast-utils/predicates.ts index 2d0c3831a877..e6f5ad0fb313 100644 --- a/packages/utils/src/ast-utils/predicates.ts +++ b/packages/utils/src/ast-utils/predicates.ts @@ -1,4 +1,5 @@ import type { TSESTree } from '../ts-estree'; + import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '../ts-estree'; import { isNodeOfType, @@ -164,20 +165,20 @@ const isLoop = isNodeOfTypes([ export { isAwaitExpression, isAwaitKeyword, - isConstructor, isClassOrTypeElement, + isConstructor, isFunction, isFunctionOrFunctionType, isFunctionType, isIdentifier, isImportKeyword, - isLoop, isLogicalOrOperator, + isLoop, isNonNullAssertionPunctuator, isNotNonNullAssertionPunctuator, isNotOptionalChainPunctuator, - isOptionalChainPunctuator, isOptionalCallExpression, + isOptionalChainPunctuator, isSetter, isTSConstructorType, isTSFunctionType, diff --git a/packages/utils/src/eslint-utils/InferTypesFromRule.ts b/packages/utils/src/eslint-utils/InferTypesFromRule.ts index c716912cdf1f..76280db1d8e4 100644 --- a/packages/utils/src/eslint-utils/InferTypesFromRule.ts +++ b/packages/utils/src/eslint-utils/InferTypesFromRule.ts @@ -20,4 +20,4 @@ type InferMessageIdsTypeFromRule = ? MessageIds : unknown; -export { InferOptionsTypeFromRule, InferMessageIdsTypeFromRule }; +export { InferMessageIdsTypeFromRule, InferOptionsTypeFromRule }; diff --git a/packages/utils/src/eslint-utils/RuleCreator.ts b/packages/utils/src/eslint-utils/RuleCreator.ts index ff5aa998b840..6dd7ce13e96c 100644 --- a/packages/utils/src/eslint-utils/RuleCreator.ts +++ b/packages/utils/src/eslint-utils/RuleCreator.ts @@ -5,6 +5,7 @@ import type { RuleMetaDataDocs, RuleModule, } from '../ts-eslint/Rule'; + import { applyDefault } from './applyDefault'; export type { RuleListener, RuleModule }; @@ -15,9 +16,9 @@ export type NamedCreateRuleMetaDocs = Omit; export type NamedCreateRuleMeta< MessageIds extends string, PluginDocs = unknown, -> = Omit, 'docs'> & { - docs: RuleMetaDataDocs & PluginDocs; -}; +> = { + docs: PluginDocs & RuleMetaDataDocs; +} & Omit, 'docs'>; export interface RuleCreateAndOptions< Options extends readonly unknown[], @@ -62,8 +63,8 @@ export function RuleCreator( Options extends readonly unknown[], MessageIds extends string, >({ - name, meta, + name, ...rule }: Readonly< RuleWithMetaAndName diff --git a/packages/utils/src/eslint-utils/applyDefault.ts b/packages/utils/src/eslint-utils/applyDefault.ts index 231561bef11d..161a10a8b91e 100644 --- a/packages/utils/src/eslint-utils/applyDefault.ts +++ b/packages/utils/src/eslint-utils/applyDefault.ts @@ -9,7 +9,7 @@ import { deepMerge, isObjectNotArray } from './deepMerge'; */ function applyDefault( defaultOptions: Readonly, - userOptions: Readonly | null, + userOptions: null | Readonly, ): Default { // clone defaults const options = JSON.parse( diff --git a/packages/utils/src/eslint-utils/getParserServices.ts b/packages/utils/src/eslint-utils/getParserServices.ts index f105fbf9902a..9c8f3bb8db39 100644 --- a/packages/utils/src/eslint-utils/getParserServices.ts +++ b/packages/utils/src/eslint-utils/getParserServices.ts @@ -3,6 +3,7 @@ import type { ParserServices, ParserServicesWithTypeInformation, } from '../ts-estree'; + import { parserSeemsToBeTSESLint } from './parserSeemsToBeTSESLint'; const ERROR_MESSAGE_REQUIRES_PARSER_SERVICES = diff --git a/packages/utils/src/eslint-utils/index.ts b/packages/utils/src/eslint-utils/index.ts index baf3e82bc653..632b6e051981 100644 --- a/packages/utils/src/eslint-utils/index.ts +++ b/packages/utils/src/eslint-utils/index.ts @@ -1,6 +1,6 @@ export * from './applyDefault'; +export * from './deepMerge'; export * from './getParserServices'; export * from './InferTypesFromRule'; -export * from './RuleCreator'; -export * from './deepMerge'; export * from './nullThrows'; +export * from './RuleCreator'; diff --git a/packages/utils/src/json-schema.ts b/packages/utils/src/json-schema.ts index 4f822a322670..09bd82a6ac42 100644 --- a/packages/utils/src/json-schema.ts +++ b/packages/utils/src/json-schema.ts @@ -25,12 +25,12 @@ export type JSONSchema4TypeName = /** * @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5 */ -export type JSONSchema4Type = boolean | number | string | null; +export type JSONSchema4Type = boolean | null | number | string; export type JSONSchema4TypeExtended = - | JSONSchema4Type | JSONSchema4Array - | JSONSchema4Object; + | JSONSchema4Object + | JSONSchema4Type; // Workaround for infinite type recursion // Also, https://github.com/typescript-eslint/typescript-eslint/issues/7863 @@ -78,14 +78,10 @@ export type JSONSchema4 = | JSONSchema4StringSchema; interface JSONSchema4Base { - id?: string | undefined; - - $schema?: JSONSchema4Version | undefined; - /** - * A single type, or a union of simple types + * Reusable definitions that can be referenced via `$ref` */ - type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined; + $defs?: Record | undefined; /** * Path to a schema defined in `definitions`/`$defs` that will form the base @@ -104,30 +100,35 @@ interface JSONSchema4Base { */ $ref?: string | undefined; + $schema?: JSONSchema4Version | undefined; + /** - * This attribute is a string that provides a short description of the - * instance property. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21 + * (AND) Must be valid against all of the sub-schemas */ - title?: string | undefined; + allOf?: JSONSchema4[] | undefined; /** - * This attribute is a string that provides a full description of the of - * purpose the instance property. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22 + * (OR) Must be valid against any of the sub-schemas */ - description?: string | undefined; + anyOf?: JSONSchema4[] | undefined; + + /** + * The default value for the item if not present + */ + default?: JSONSchema4TypeExtended | undefined; /** * Reusable definitions that can be referenced via `$ref` */ definitions?: Record | undefined; + /** - * Reusable definitions that can be referenced via `$ref` + * This attribute is a string that provides a full description of the of + * purpose the instance property. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22 */ - $defs?: Record | undefined; + description?: string | undefined; /** * The value of this property MUST be another schema which will provide @@ -145,12 +146,19 @@ interface JSONSchema4Base { * * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.26 */ - extends?: string[] | string | undefined; + extends?: string | string[] | undefined; + + id?: string | undefined; /** - * The default value for the item if not present + * (NOT) Must not be valid against the given schema */ - default?: JSONSchema4TypeExtended | undefined; + not?: JSONSchema4 | undefined; + + /** + * (XOR) Must be valid against exactly one of the sub-schemas + */ + oneOf?: JSONSchema4[] | undefined; /** * This attribute indicates if the instance must have a value, and not @@ -159,44 +167,40 @@ interface JSONSchema4Base { * * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7 */ - required?: string[] | boolean | undefined; + required?: boolean | string[] | undefined; /** - * (NOT) Must not be valid against the given schema - */ - not?: JSONSchema4 | undefined; - /** - * (AND) Must be valid against all of the sub-schemas - */ - allOf?: JSONSchema4[] | undefined; - /** - * (OR) Must be valid against any of the sub-schemas + * This attribute is a string that provides a short description of the + * instance property. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21 */ - anyOf?: JSONSchema4[] | undefined; + title?: string | undefined; + /** - * (XOR) Must be valid against exactly one of the sub-schemas + * A single type, or a union of simple types */ - oneOf?: JSONSchema4[] | undefined; + type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined; } export interface JSONSchema4RefSchema extends JSONSchema4Base { - type?: undefined; $ref: string; + type?: undefined; } export interface JSONSchema4AllOfSchema extends JSONSchema4Base { - type?: undefined; allOf: JSONSchema4[]; + type?: undefined; } export interface JSONSchema4AnyOfSchema extends JSONSchema4Base { - type?: undefined; anyOf: JSONSchema4[]; + type?: undefined; } export interface JSONSchema4OneOfSchema extends JSONSchema4Base { - type?: undefined; oneOf: JSONSchema4[]; + type?: undefined; } export interface JSONSchema4MultiSchema @@ -207,7 +211,6 @@ export interface JSONSchema4MultiSchema Omit, Omit, Omit { - type: JSONSchema4TypeName[]; /** * This provides an enumeration of all possible values that are valid * for the instance property. This MUST be an array, and each item in @@ -218,14 +221,13 @@ export interface JSONSchema4MultiSchema * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 */ enum?: JSONSchema4Type[]; + type: JSONSchema4TypeName[]; } /** * @see https://json-schema.org/understanding-json-schema/reference/object.html */ export interface JSONSchema4ObjectSchema extends JSONSchema4Base { - type: 'object'; - /** * This attribute defines a schema for all properties that are not * explicitly defined in an object type definition. If specified, the @@ -236,22 +238,24 @@ export interface JSONSchema4ObjectSchema extends JSONSchema4Base { * * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4 */ - additionalProperties?: JSONSchema4 | boolean | undefined; + additionalProperties?: boolean | JSONSchema4 | undefined; /** - * This attribute is an object with property definitions that define the - * valid values of instance object property values. When the instance - * value is an object, the property values of the instance object MUST - * conform to the property definitions in this object. In this object, - * each property definition's value MUST be a schema, and the property's - * name MUST be the name of the instance property that it defines. The - * instance property value MUST be valid according to the schema from - * the property definition. Properties are considered unordered, the - * order of the instance properties MAY be in any order. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.2 + * The `dependencies` keyword conditionally applies a sub-schema when a given + * property is present. This schema is applied in the same way `allOf` applies + * schemas. Nothing is merged or extended. Both schemas apply independently. */ - properties?: Record | undefined; + dependencies?: Record | undefined; + + /** + * The maximum number of properties allowed for record-style schemas + */ + maxProperties?: number | undefined; + + /** + * The minimum number of properties required for record-style schemas + */ + minProperties?: number | undefined; /** * This attribute is an object that defines the schema for a set of @@ -267,28 +271,27 @@ export interface JSONSchema4ObjectSchema extends JSONSchema4Base { patternProperties?: Record | undefined; /** - * The `dependencies` keyword conditionally applies a sub-schema when a given - * property is present. This schema is applied in the same way `allOf` applies - * schemas. Nothing is merged or extended. Both schemas apply independently. + * This attribute is an object with property definitions that define the + * valid values of instance object property values. When the instance + * value is an object, the property values of the instance object MUST + * conform to the property definitions in this object. In this object, + * each property definition's value MUST be a schema, and the property's + * name MUST be the name of the instance property that it defines. The + * instance property value MUST be valid according to the schema from + * the property definition. Properties are considered unordered, the + * order of the instance properties MAY be in any order. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.2 */ - dependencies?: Record | undefined; + properties?: Record | undefined; - /** - * The maximum number of properties allowed for record-style schemas - */ - maxProperties?: number | undefined; - /** - * The minimum number of properties required for record-style schemas - */ - minProperties?: number | undefined; + type: 'object'; } /** * @see https://json-schema.org/understanding-json-schema/reference/array.html */ export interface JSONSchema4ArraySchema extends JSONSchema4Base { - type: 'array'; - /** * May only be defined when "items" is defined, and is a tuple of JSONSchemas. * @@ -299,7 +302,7 @@ export interface JSONSchema4ArraySchema extends JSONSchema4Base { * * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.6 */ - additionalItems?: JSONSchema4 | boolean | undefined; + additionalItems?: boolean | JSONSchema4 | undefined; /** * This attribute defines the allowed items in an instance array, and @@ -332,6 +335,8 @@ export interface JSONSchema4ArraySchema extends JSONSchema4Base { */ minItems?: number | undefined; + type: 'array'; + /** * Enforces that all items in the array are unique */ @@ -342,32 +347,7 @@ export interface JSONSchema4ArraySchema extends JSONSchema4Base { * @see https://json-schema.org/understanding-json-schema/reference/string.html */ export interface JSONSchema4StringSchema extends JSONSchema4Base { - type: 'string'; - - /** - * The maximum allowed length for the string - */ - maxLength?: number | undefined; - - /** - * The minimum allowed length for the string - */ - minLength?: number | undefined; - - /** - * The `pattern` keyword is used to restrict a string to a particular regular - * expression. The regular expression syntax is the one defined in JavaScript - * (ECMA 262 specifically) with Unicode support. - * - * When defining the regular expressions, it’s important to note that the - * string is considered valid if the expression matches anywhere within the - * string. For example, the regular expression "p" will match any string with - * a p in it, such as "apple" not just a string that is simply "p". Therefore, - * it is usually less confusing, as a matter of course, to surround the - * regular expression in ^...$, for example, "^p$", unless there is a good - * reason not to do so. - */ - pattern?: string | undefined; + enum?: string[] | undefined; /** * The `format` keyword allows for basic semantic identification of certain @@ -399,30 +379,48 @@ export interface JSONSchema4StringSchema extends JSONSchema4Base { | 'uuid' | undefined; - enum?: string[] | undefined; -} - -/** - * @see https://json-schema.org/understanding-json-schema/reference/numeric.html - */ -export interface JSONSchema4NumberSchema extends JSONSchema4Base { - type: 'integer' | 'number'; + /** + * The maximum allowed length for the string + */ + maxLength?: number | undefined; /** - * Numbers can be restricted to a multiple of a given number, using the - * `multipleOf` keyword. It may be set to any positive number. + * The minimum allowed length for the string */ - multipleOf?: number | undefined; + minLength?: number | undefined; /** - * The maximum allowed value for the number + * The `pattern` keyword is used to restrict a string to a particular regular + * expression. The regular expression syntax is the one defined in JavaScript + * (ECMA 262 specifically) with Unicode support. + * + * When defining the regular expressions, it’s important to note that the + * string is considered valid if the expression matches anywhere within the + * string. For example, the regular expression "p" will match any string with + * a p in it, such as "apple" not just a string that is simply "p". Therefore, + * it is usually less confusing, as a matter of course, to surround the + * regular expression in ^...$, for example, "^p$", unless there is a good + * reason not to do so. */ - maximum?: number | undefined; + pattern?: string | undefined; + + type: 'string'; +} +/** + * @see https://json-schema.org/understanding-json-schema/reference/numeric.html + */ +export interface JSONSchema4NumberSchema extends JSONSchema4Base { /** - * The minimum allowed value for the number + * This provides an enumeration of all possible values that are valid + * for the instance property. This MUST be an array, and each item in + * the array represents a possible value for the instance value. If + * this attribute is defined, the instance value MUST be one of the + * values in the array in order for the schema to be valid. + * + * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 */ - minimum?: number | undefined; + enum?: number[] | undefined; /** * The exclusive minimum allowed value for the number @@ -443,23 +441,28 @@ export interface JSONSchema4NumberSchema extends JSONSchema4Base { exclusiveMinimum?: boolean | undefined; /** - * This provides an enumeration of all possible values that are valid - * for the instance property. This MUST be an array, and each item in - * the array represents a possible value for the instance value. If - * this attribute is defined, the instance value MUST be one of the - * values in the array in order for the schema to be valid. - * - * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 + * The maximum allowed value for the number */ - enum?: number[] | undefined; + maximum?: number | undefined; + + /** + * The minimum allowed value for the number + */ + minimum?: number | undefined; + + /** + * Numbers can be restricted to a multiple of a given number, using the + * `multipleOf` keyword. It may be set to any positive number. + */ + multipleOf?: number | undefined; + + type: 'integer' | 'number'; } /** * @see https://json-schema.org/understanding-json-schema/reference/boolean.html */ export interface JSONSchema4BooleanSchema extends JSONSchema4Base { - type: 'boolean'; - /** * This provides an enumeration of all possible values that are valid * for the instance property. This MUST be an array, and each item in @@ -470,14 +473,14 @@ export interface JSONSchema4BooleanSchema extends JSONSchema4Base { * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 */ enum?: boolean[] | undefined; + + type: 'boolean'; } /** * @see https://json-schema.org/understanding-json-schema/reference/null.html */ export interface JSONSchema4NullSchema extends JSONSchema4Base { - type: 'null'; - /** * This provides an enumeration of all possible values that are valid * for the instance property. This MUST be an array, and each item in @@ -488,6 +491,8 @@ export interface JSONSchema4NullSchema extends JSONSchema4Base { * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19 */ enum?: null[] | undefined; + + type: 'null'; } export interface JSONSchema4AnySchema extends JSONSchema4Base { diff --git a/packages/utils/src/ts-eslint/Config.ts b/packages/utils/src/ts-eslint/Config.ts index 0db4e73b2781..ee5b2d44e4f3 100644 --- a/packages/utils/src/ts-eslint/Config.ts +++ b/packages/utils/src/ts-eslint/Config.ts @@ -17,7 +17,7 @@ export namespace SharedConfig { export type RulesRecord = Partial>; export type GlobalVariableOptionBase = 'off' | 'readonly' | 'writable'; - export type GlobalVariableOption = GlobalVariableOptionBase | boolean; + export type GlobalVariableOption = boolean | GlobalVariableOptionBase; export interface GlobalsConfig { [name: string]: GlobalVariableOption; @@ -63,7 +63,7 @@ export namespace ClassicConfig { /** * The path to other config files or the package name of shareable configs. */ - extends?: string[] | string; + extends?: string | string[]; /** * The global variable settings. */ @@ -79,7 +79,7 @@ export namespace ClassicConfig { /** * The path to a parser or the package name of a parser. */ - parser?: string | null; + parser?: null | string; /** * The parser options. */ @@ -107,15 +107,15 @@ export namespace ClassicConfig { } export interface ConfigOverride extends BaseConfig { - excludedFiles?: string[] | string; - files: string[] | string; + excludedFiles?: string | string[]; + files: string | string[]; } export interface Config extends BaseConfig { /** * The glob patterns that ignore to lint. */ - ignorePatterns?: string[] | string; + ignorePatterns?: string | string[]; /** * The root flag. */ @@ -137,7 +137,7 @@ export namespace FlatConfig { export type Settings = SharedConfigurationSettings; export type Severity = SharedConfig.Severity; export type SeverityString = SharedConfig.SeverityString; - export type SourceType = ParserOptionsTypes.SourceType | 'commonjs'; + export type SourceType = 'commonjs' | ParserOptionsTypes.SourceType; export interface SharedConfigs { [key: string]: Config; @@ -187,9 +187,9 @@ export namespace FlatConfig { * @default "off" */ reportUnusedDisableDirectives?: + | boolean | SharedConfig.Severity - | SharedConfig.SeverityString - | boolean; + | SharedConfig.SeverityString; } export interface LanguageOptions { @@ -235,10 +235,6 @@ export namespace FlatConfig { // 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 string to identify the configuration object. Used in error messages and inspection tools. - */ - name?: string; /** * 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. @@ -261,6 +257,10 @@ export namespace FlatConfig { * An object containing settings related to the linting process. */ linterOptions?: LinterOptions; + /** + * An string to identify the configuration object. Used in error messages and inspection tools. + */ + name?: string; /** * 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. @@ -271,7 +271,7 @@ export namespace FlatConfig { * a string indicating the name of a processor inside of a plugin * (i.e., `"pluginName/processorName"`). */ - processor?: string | Processor; + processor?: Processor | string; /** * An object containing the configured rules. * When `files` or `ignores` are specified, these rule configurations are only available to the matching files. diff --git a/packages/utils/src/ts-eslint/ESLint.ts b/packages/utils/src/ts-eslint/ESLint.ts index 36653630b7c1..73cf60efe233 100644 --- a/packages/utils/src/ts-eslint/ESLint.ts +++ b/packages/utils/src/ts-eslint/ESLint.ts @@ -1,5 +1,7 @@ /* eslint-disable @typescript-eslint/no-namespace */ +export { FlatESLint } from './eslint/FlatESLint'; +export { FlatESLint as ESLint } from './eslint/FlatESLint'; export { // TODO(eslint@v10) - remove this in the next major /** @@ -7,5 +9,3 @@ export { */ LegacyESLint, } from './eslint/LegacyESLint'; -export { FlatESLint } from './eslint/FlatESLint'; -export { FlatESLint as ESLint } from './eslint/FlatESLint'; diff --git a/packages/utils/src/ts-eslint/Linter.ts b/packages/utils/src/ts-eslint/Linter.ts index e759668ec393..7efea1834f01 100644 --- a/packages/utils/src/ts-eslint/Linter.ts +++ b/packages/utils/src/ts-eslint/Linter.ts @@ -22,6 +22,11 @@ export type MinimalRuleModule< // eslint-disable-next-line @typescript-eslint/no-unused-vars declare class LinterBase { + /** + * The version from package.json. + */ + readonly version: string; + /** * Initialize the Linter. * @param config the config object @@ -84,6 +89,15 @@ declare class LinterBase { filenameOrOptions?: Linter.VerifyOptions | string, ): Linter.LintMessage[]; + //////////////////// + // static members // + //////////////////// + + /** + * The version from package.json. + */ + static readonly version: string; + /** * Performs multiple autofix passes over the text until as many fixes as possible have been applied. * @param code The source text to apply fixes to. @@ -96,20 +110,6 @@ declare class LinterBase { config: Linter.ConfigType, options: Linter.FixOptions, ): Linter.FixReport; - - /** - * The version from package.json. - */ - readonly version: string; - - //////////////////// - // static members // - //////////////////// - - /** - * The version from package.json. - */ - static readonly version: string; } namespace Linter { @@ -183,7 +183,7 @@ namespace Linter { /** * Adds reported errors for unused `eslint-disable` directives. */ - reportUnusedDisableDirectives?: SeverityString | boolean; + reportUnusedDisableDirectives?: boolean | SeverityString; } export interface FixOptions extends VerifyOptions { @@ -233,12 +233,12 @@ namespace Linter { /** * The ID of the rule which makes this message. */ - ruleId: string | null; + ruleId: null | string; /** * The severity of this message. */ severity: Severity; - source: string | null; + source: null | string; /** * Information for suggestions */ @@ -250,14 +250,14 @@ namespace Linter { * True, if the code was fixed */ fixed: boolean; - /** - * Fixed code text (might be the same as input if no fixes were applied). - */ - output: string; /** * Collection of all messages for the given code */ messages: LintMessage[]; + /** + * Fixed code text (might be the same as input if no fixes were applied). + */ + output: string; } /** @deprecated use Parser.ParserModule */ diff --git a/packages/utils/src/ts-eslint/Parser.ts b/packages/utils/src/ts-eslint/Parser.ts index c42ac21d5cd7..ad9f5763054f 100644 --- a/packages/utils/src/ts-eslint/Parser.ts +++ b/packages/utils/src/ts-eslint/Parser.ts @@ -24,16 +24,6 @@ export namespace Parser { * @see {@link LooseRuleDefinition}, {@link LooseProcessorModule} */ export type LooseParserModule = - | { - /** - * Information about the parser to uniquely identify it when serializing. - */ - meta?: { [K in keyof ParserMeta]?: ParserMeta[K] | undefined }; - /** - * Parses the given text into an ESTree AST - */ - parse(text: string, options?: unknown): unknown; - } | { /** * Information about the parser to uniquely identify it when serializing. @@ -49,6 +39,16 @@ export namespace Parser { // intentionally not using a Record to preserve optionals [k in keyof ParseResult]: unknown; }; + } + | { + /** + * Information about the parser to uniquely identify it when serializing. + */ + meta?: { [K in keyof ParserMeta]?: ParserMeta[K] | undefined }; + /** + * Parses the given text into an ESTree AST + */ + parse(text: string, options?: unknown): unknown; }; export type ParserModule = @@ -58,9 +58,9 @@ export namespace Parser { */ meta?: ParserMeta; /** - * Parses the given text into an ESTree AST + * Parses the given text into an AST */ - parse(text: string, options?: ParserOptions): TSESTree.Program; + parseForESLint(text: string, options?: ParserOptions): ParseResult; } | { /** @@ -68,9 +68,9 @@ export namespace Parser { */ meta?: ParserMeta; /** - * Parses the given text into an AST + * Parses the given text into an ESTree AST */ - parseForESLint(text: string, options?: ParserOptions): ParseResult; + parse(text: string, options?: ParserOptions): TSESTree.Program; }; export interface ParseResult { @@ -78,18 +78,18 @@ export namespace Parser { * 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; + /** + * 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; /** * An object to customize AST traversal. * The keys of the object are the type of AST nodes. diff --git a/packages/utils/src/ts-eslint/Processor.ts b/packages/utils/src/ts-eslint/Processor.ts index 243668c49e2b..5af746af4003 100644 --- a/packages/utils/src/ts-eslint/Processor.ts +++ b/packages/utils/src/ts-eslint/Processor.ts @@ -17,7 +17,7 @@ export namespace Processor { export type PreProcess = ( text: string, filename: string, - ) => (string | { text: string; filename: string })[]; + ) => ({ filename: string; text: string } | string)[]; export type PostProcess = ( messagesList: Linter.LintMessage[][], @@ -31,14 +31,14 @@ export namespace Processor { meta?: ProcessorMeta; /** - * The function to extract code blocks. + * The function to merge messages. */ - preprocess?: PreProcess; + postprocess?: PostProcess; /** - * The function to merge messages. + * The function to extract code blocks. */ - postprocess?: PostProcess; + preprocess?: PreProcess; /** * If `true` then it means the processor supports autofix. @@ -60,24 +60,24 @@ export namespace Processor { meta?: { [K in keyof ProcessorMeta]?: ProcessorMeta[K] | undefined }; /** - * The function to extract code blocks. + * The function to merge messages. */ /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentionally using `any` to allow bi-directional assignment (unknown and never only allow unidirectional) */ - preprocess?: (text: string, filename: string) => any; + postprocess?: (messagesList: any, filename: string) => any; /** - * The function to merge messages. + * The function to extract code blocks. */ /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentionally using `any` to allow bi-directional assignment (unknown and never only allow unidirectional) */ - postprocess?: (messagesList: any, filename: string) => any; + preprocess?: (text: string, filename: string) => any; /** * If `true` then it means the processor supports autofix. diff --git a/packages/utils/src/ts-eslint/Rule.ts b/packages/utils/src/ts-eslint/Rule.ts index 62cf392d38b3..0fd8d5f5affc 100644 --- a/packages/utils/src/ts-eslint/Rule.ts +++ b/packages/utils/src/ts-eslint/Rule.ts @@ -50,13 +50,6 @@ export interface RuleMetaData { * See: https://eslint.org/docs/developer-guide/working-with-rules#messageids */ messages: Record; - /** - * The type of rule. - * - `"problem"` means the rule is identifying code that either will cause an error or may cause a confusing behavior. Developers should consider this a high priority to resolve. - * - `"suggestion"` means the rule is identifying something that could be done in a better way but no errors will occur if the code isn’t changed. - * - `"layout"` means the rule cares primarily about whitespace, semicolons, commas, and parentheses, all the parts of the program that determine how the code looks rather than how it executes. These rules work on parts of the code that aren’t specified in the AST. - */ - type: 'problem' | 'suggestion' | 'layout'; /** * The name of the rule this rule was replaced by, if it was deprecated. */ @@ -65,6 +58,13 @@ export interface RuleMetaData { * The options schema. Supply an empty array if there are no options. */ schema: JSONSchema4 | readonly JSONSchema4[]; + /** + * The type of rule. + * - `"problem"` means the rule is identifying code that either will cause an error or may cause a confusing behavior. Developers should consider this a high priority to resolve. + * - `"suggestion"` means the rule is identifying something that could be done in a better way but no errors will occur if the code isn’t changed. + * - `"layout"` means the rule cares primarily about whitespace, semicolons, commas, and parentheses, all the parts of the program that determine how the code looks rather than how it executes. These rules work on parts of the code that aren’t specified in the AST. + */ + type: 'layout' | 'problem' | 'suggestion'; } export interface RuleMetaDataWithDocs< @@ -116,7 +116,7 @@ export interface SuggestionReportDescriptor export type ReportFixFunction = ( fixer: RuleFixer, -) => IterableIterator | RuleFix | readonly RuleFix[] | null; +) => IterableIterator | null | readonly RuleFix[] | RuleFix; export type ReportSuggestionArray = SuggestionReportDescriptor[]; @@ -131,7 +131,7 @@ interface ReportDescriptorBase { /** * The fixer function. */ - readonly fix?: ReportFixFunction | null; + readonly fix?: null | ReportFixFunction; /** * The messageId which is being reported. */ @@ -145,20 +145,20 @@ interface ReportDescriptorWithSuggestion /** * 6.7's Suggestions API */ - readonly suggest?: Readonly> | null; + readonly suggest?: null | Readonly>; } interface ReportDescriptorNodeOptionalLoc { - /** - * The Node or AST Token which the report is being attached to - */ - readonly node: TSESTree.Node | TSESTree.Token; /** * An override of the location of the report */ readonly loc?: | Readonly | Readonly; + /** + * The Node or AST Token which the report is being attached to + */ + readonly node: TSESTree.Node | TSESTree.Token; } interface ReportDescriptorLocOnly { /** @@ -167,9 +167,11 @@ interface ReportDescriptorLocOnly { loc: Readonly | Readonly; } -export type ReportDescriptor = - ReportDescriptorWithSuggestion & - (ReportDescriptorLocOnly | ReportDescriptorNodeOptionalLoc); +export type ReportDescriptor = ( + | ReportDescriptorLocOnly + | ReportDescriptorNodeOptionalLoc +) & + ReportDescriptorWithSuggestion; /** * Plugins can add their settings using declaration @@ -180,6 +182,8 @@ export interface SharedConfigurationSettings { [name: string]: unknown; } +/* eslint-disable perfectionist/sort-interfaces */ + export interface RuleContext< MessageIds extends string, Options extends readonly unknown[], @@ -188,23 +192,23 @@ export interface RuleContext< * The rule ID. */ id: string; + /** + * The language options configured for this run + */ + languageOptions: FlatConfig.LanguageOptions; /** * An array of the configured options for this rule. * This array does not include the rule severity. */ options: Options; - /** - * The name of the parser from configuration, if in eslintrc (legacy) config. - */ - parserPath: string | undefined; - /** - * The language options configured for this run - */ - languageOptions: FlatConfig.LanguageOptions; /** * The parser options configured for this run */ parserOptions: Linter.ParserOptions; + /** + * The name of the parser from configuration, if in eslintrc (legacy) config. + */ + parserPath: string | undefined; /** * An object containing parser-provided services for rules * @@ -217,6 +221,8 @@ export interface RuleContext< */ settings: SharedConfigurationSettings; + // Deprecated members + /** * Returns an array of the ancestors of the currently-traversed node, starting at * the root of the AST and continuing through the direct parent of the current node. @@ -306,6 +312,8 @@ export interface RuleContext< report(descriptor: ReportDescriptor): void; } +/* eslint-enable perfectionist/sort-interfaces */ + /** * Part of the code path analysis feature of ESLint: * https://eslint.org/docs/latest/extend/code-path-analysis @@ -316,6 +324,19 @@ export interface RuleContext< * @see https://github.com/typescript-eslint/typescript-eslint/issues/6993 */ export interface CodePath { + /** Code paths of functions this code path contains. */ + childCodePaths: CodePath[]; + + /** + * Segments of the current traversal position. + * + * @deprecated + */ + currentSegments: CodePathSegment[]; + + /** The final segments which includes both returned and thrown. */ + finalSegments: CodePathSegment[]; + /** * A unique string. Respective rules can use `id` to save additional * information for each code path. @@ -324,27 +345,14 @@ export interface CodePath { initialSegment: CodePathSegment; - /** The final segments which includes both returned and thrown. */ - finalSegments: CodePathSegment[]; - /** The final segments which includes only returned. */ returnedSegments: CodePathSegment[]; /** The final segments which includes only thrown. */ thrownSegments: CodePathSegment[]; - /** - * Segments of the current traversal position. - * - * @deprecated - */ - currentSegments: CodePathSegment[]; - /** The code path of the upper function/global scope. */ upper: CodePath | null; - - /** Code paths of functions this code path contains. */ - childCodePaths: CodePath[]; } /** @@ -625,6 +633,14 @@ export interface RuleModule< // for extending base rules ExtendedRuleListener extends RuleListener = RuleListener, > { + /** + * Function which returns an object with methods that ESLint calls to “visit” + * nodes while traversing the abstract syntax tree. + */ + create( + context: Readonly>, + ): ExtendedRuleListener; + /** * Default options the rule will be run with */ @@ -634,14 +650,6 @@ export interface RuleModule< * Metadata about the rule */ meta: RuleMetaData; - - /** - * Function which returns an object with methods that ESLint calls to “visit” - * nodes while traversing the abstract syntax tree. - */ - create( - context: Readonly>, - ): ExtendedRuleListener; } export type AnyRuleModule = RuleModule; @@ -678,11 +686,11 @@ export type AnyRuleModuleWithMetaDocs = RuleModuleWithMetaDocs< */ export type LooseRuleDefinition = // TODO - remove RuleCreateFunction once we no longer support ESLint 8 - | LooseRuleCreateFunction | { - meta?: object | undefined; create: LooseRuleCreateFunction; - }; + meta?: object | undefined; + } + | LooseRuleCreateFunction; /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentionally using `any` to allow bi-directional assignment (unknown and diff --git a/packages/utils/src/ts-eslint/RuleTester.ts b/packages/utils/src/ts-eslint/RuleTester.ts index 7c8e325f317b..92fb27cb4f8d 100644 --- a/packages/utils/src/ts-eslint/RuleTester.ts +++ b/packages/utils/src/ts-eslint/RuleTester.ts @@ -16,10 +16,6 @@ import type { * @deprecated Use `@typescript-eslint/rule-tester` instead. */ interface ValidTestCase { - /** - * Name for the test case. - */ - readonly name?: string; /** * Code for the test case. */ @@ -36,6 +32,14 @@ interface ValidTestCase { * The additional global variables. */ readonly globals?: Readonly; + /** + * Name for the test case. + */ + readonly name?: string; + /** + * Run this case exclusively for debugging in supported test frameworks. + */ + readonly only?: boolean; /** * Options for the test case. */ @@ -52,24 +56,20 @@ interface ValidTestCase { * Settings for the test case. */ readonly settings?: Readonly; - /** - * Run this case exclusively for debugging in supported test frameworks. - */ - readonly only?: boolean; } /** * @deprecated Use `@typescript-eslint/rule-tester` instead. */ interface SuggestionOutput { - /** - * Reported message ID. - */ - readonly messageId: MessageIds; /** * The data used to fill the message template. */ readonly data?: ReportDescriptorMessageData; + /** + * Reported message ID. + */ + readonly messageId: MessageIds; /** * NOTE: Suggestions will be applied as a stand-alone change, without triggering multi-pass fixes. * Each individual error has its own suggestion, so you have to show the correct, _isolated_ output for each suggestion. @@ -94,7 +94,7 @@ interface InvalidTestCase< /** * The expected code after autofixes are applied. If set to `null`, the test runner will assert that no autofix is suggested. */ - readonly output?: string | string[] | null; + readonly output?: null | string | string[]; } /** @@ -128,7 +128,7 @@ interface TestCaseError { /** * Reported suggestions. */ - readonly suggestions?: readonly SuggestionOutput[] | null; + readonly suggestions?: null | readonly SuggestionOutput[]; /** * The type of the reported AST node. */ @@ -155,8 +155,8 @@ interface RunTests< Options extends readonly unknown[], > { // RuleTester.run also accepts strings for valid cases - readonly valid: readonly (ValidTestCase | string)[]; readonly invalid: readonly InvalidTestCase[]; + readonly valid: readonly (string | ValidTestCase)[]; } /** @@ -230,11 +230,11 @@ class RuleTester extends (ESLintRuleTester as typeof RuleTesterBase) {} export { InvalidTestCase, - SuggestionOutput, RuleTester, RuleTesterConfig, RuleTesterTestFrameworkFunction, RunTests, + SuggestionOutput, TestCaseError, ValidTestCase, }; diff --git a/packages/utils/src/ts-eslint/SourceCode.ts b/packages/utils/src/ts-eslint/SourceCode.ts index ca1d2b7cf700..c65752297e12 100644 --- a/packages/utils/src/ts-eslint/SourceCode.ts +++ b/packages/utils/src/ts-eslint/SourceCode.ts @@ -48,7 +48,7 @@ declare class TokenStore { getFirstToken( node: TSESTree.Node, options?: T, - ): SourceCode.ReturnTypeFromOptions | null; + ): null | SourceCode.ReturnTypeFromOptions; /** * Gets the first token between two non-overlapping nodes. * @param left Node before the desired token range. @@ -60,7 +60,7 @@ declare class TokenStore { left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: T, - ): SourceCode.ReturnTypeFromOptions | null; + ): null | SourceCode.ReturnTypeFromOptions; /** * Gets the first `count` tokens of the given node. * @param node The AST node. @@ -91,7 +91,7 @@ declare class TokenStore { getLastToken( node: TSESTree.Node, options?: T, - ): SourceCode.ReturnTypeFromOptions | null; + ): null | SourceCode.ReturnTypeFromOptions; /** * Gets the last token between two non-overlapping nodes. * @param left Node before the desired token range. @@ -103,7 +103,7 @@ declare class TokenStore { left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: T, - ): SourceCode.ReturnTypeFromOptions | null; + ): null | SourceCode.ReturnTypeFromOptions; /** * Gets the last `count` tokens of the given node. * @param node The AST node. @@ -134,7 +134,7 @@ declare class TokenStore { getTokenAfter( node: TSESTree.Node | TSESTree.Token, options?: T, - ): SourceCode.ReturnTypeFromOptions | null; + ): null | SourceCode.ReturnTypeFromOptions; /** * Gets the token that precedes a given node or token. * @param node The AST node or token. @@ -144,7 +144,7 @@ declare class TokenStore { getTokenBefore( node: TSESTree.Node | TSESTree.Token, options?: T, - ): SourceCode.ReturnTypeFromOptions | null; + ): null | SourceCode.ReturnTypeFromOptions; /** * Gets the token starting at the specified index. * @param offset Index of the start of the token's range. @@ -154,7 +154,7 @@ declare class TokenStore { getTokenByRangeStart( offset: number, options?: T, - ): SourceCode.ReturnTypeFromOptions | null; + ): null | SourceCode.ReturnTypeFromOptions; /** * Gets all tokens that are related to the given node. * @param node The AST node. @@ -184,7 +184,7 @@ declare class TokenStore { */ getTokensAfter( node: TSESTree.Node | TSESTree.Token, - options?: T | number, + options?: number | T, ): SourceCode.ReturnTypeFromOptions[]; /** * Gets the `count` tokens that precedes a given node or token. @@ -193,7 +193,7 @@ declare class TokenStore { */ getTokensBefore( node: TSESTree.Node | TSESTree.Token, - options?: T | number, + options?: number | T, ): SourceCode.ReturnTypeFromOptions[]; /** * Gets all of the tokens between two non-overlapping nodes. @@ -205,7 +205,7 @@ declare class TokenStore { getTokensBetween( left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, - options?: T | number, + options?: number | T, ): SourceCode.ReturnTypeFromOptions[]; } @@ -256,7 +256,7 @@ declare class SourceCodeBase extends TokenStore { * @param index Range index of the desired node. * @returns The node if found or `null` if not found. */ - getNodeByRangeIndex(index: number): TSESTree.Node | null; + getNodeByRangeIndex(index: number): null | TSESTree.Node; /** * Gets the source code for the given node. * @param node The AST node to get the text for. @@ -335,7 +335,7 @@ declare class SourceCodeBase extends TokenStore { /** * The scope of this source code. */ - scopeManager: Scope.ScopeManager | null; + scopeManager: null | Scope.ScopeManager; /** * The original text source code. BOM was stripped from this text. */ @@ -377,11 +377,11 @@ namespace SourceCode { /** * The parser services. */ - parserServices: ParserServices | null; + parserServices: null | ParserServices; /** * The scope of this source code. */ - scopeManager: Scope.ScopeManager | null; + scopeManager: null | Scope.ScopeManager; /** * The source code text. */ @@ -389,7 +389,7 @@ namespace SourceCode { /** * The visitor keys to traverse AST. */ - visitorKeys: VisitorKeys | null; + visitorKeys: null | VisitorKeys; } export type VisitorKeys = Parser.VisitorKeys; @@ -415,8 +415,6 @@ namespace SourceCode { >; export type CursorWithSkipOptions = - | FilterPredicate - | number | { /** * The predicate function to choose tokens. @@ -430,12 +428,16 @@ namespace SourceCode { * The count of tokens the cursor skips. */ skip?: number; - }; + } + | FilterPredicate + | number; export type CursorWithCountOptions = - | FilterPredicate - | number | { + /** + * The maximum count of tokens the cursor iterates. + */ + count?: number; /** * The predicate function to choose tokens. */ @@ -444,11 +446,9 @@ namespace SourceCode { * The flag to iterate comments as well. */ includeComments?: boolean; - /** - * The maximum count of tokens the cursor iterates. - */ - count?: number; - }; + } + | FilterPredicate + | number; } class SourceCode extends (ESLintSourceCode as typeof SourceCodeBase) {} diff --git a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts b/packages/utils/src/ts-eslint/eslint/ESLintShared.ts index 9846eff420fc..ad3e6481ed6d 100644 --- a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts +++ b/packages/utils/src/ts-eslint/eslint/ESLintShared.ts @@ -42,7 +42,7 @@ export declare class ESLintBase< * @param patterns The lint target files. This can contain any of file paths, directory paths, and glob patterns. * @returns The promise that will be fulfilled with an array of LintResult objects. */ - lintFiles(patterns: string[] | string): Promise; + lintFiles(patterns: string | string[]): Promise; /** * This method lints the given source code text and then returns the results. @@ -133,7 +133,7 @@ export interface ESLintOptions { * Strategy for the cache to use for detecting changed files. * @default 'metadata' */ - cacheStrategy?: 'metadata' | 'content'; + cacheStrategy?: 'content' | 'metadata'; /** * The working directory. This must be an absolute path. * @default process.cwd() @@ -150,7 +150,7 @@ export interface ESLintOptions { * lint messages for which the function returned true. * @default false */ - fix?: boolean | ((message: LintMessage) => boolean); + fix?: ((message: LintMessage) => boolean) | boolean; /** * The types of the rules that the `eslint.lintFiles()` and `eslint.lintText()` methods use for autofix. * @default null @@ -177,18 +177,18 @@ export interface ESLintOptions { * This is a map-like object. Those keys are plugin IDs and each value is implementation. * @default null */ - plugins?: Record | null; + plugins?: null | Record; } export interface DeprecatedRuleInfo { - /** - * The rule ID. - */ - ruleId: string; /** * The rule IDs that replace this deprecated rule. */ replacedBy: string[]; + /** + * The rule ID. + */ + ruleId: string; } /** @@ -229,6 +229,13 @@ export interface LintResult { * property exists. */ source?: string; + /** + * Timing information of the lint run. + * This exists if and only if the `--stats` CLI flag was added or the `stats: true` + * option was passed to the ESLint class + * @since 9.0.0 + */ + stats?: LintStats; /** * The array of SuppressedLintMessage objects. */ @@ -241,13 +248,6 @@ export interface LintResult { * The number of warnings. This includes fixable warnings. */ warningCount: number; - /** - * Timing information of the lint run. - * This exists if and only if the `--stats` CLI flag was added or the `stats: true` - * option was passed to the ESLint class - * @since 9.0.0 - */ - stats?: LintStats; } export interface LintStats { @@ -263,6 +263,10 @@ export interface LintStats { }; } export interface LintStatsTimePass { + /** + * The total time that is spent on applying fixes to the code. + */ + fix: LintStatsFixTime; /** * The total time that is spent when parsing a file. */ @@ -271,10 +275,6 @@ export interface LintStatsTimePass { * The total time that is spent on a rule. */ rules?: Record; - /** - * The total time that is spent on applying fixes to the code. - */ - fix: LintStatsFixTime; /** * The cumulative total */ @@ -340,7 +340,7 @@ export interface LintMessage { * The rule name that generates this lint message. If this message is generated by the ESLint core rather than * rules, this is null. */ - ruleId: string | null; + ruleId: null | string; /** * The severity of this message. 1 means warning and 2 means error. */ @@ -366,14 +366,14 @@ export interface SuppressedLintMessage extends LintMessage { * The list of suppressions. */ suppressions?: { - /** - * Right now, this is always `directive` - */ - kind: string; /** * The free text description added after the `--` in the comment */ justification: string; + /** + * Right now, this is always `directive` + */ + kind: string; }[]; } diff --git a/packages/utils/src/ts-eslint/eslint/FlatESLint.ts b/packages/utils/src/ts-eslint/eslint/FlatESLint.ts index 658f955f55bc..561c6216b9ad 100644 --- a/packages/utils/src/ts-eslint/eslint/FlatESLint.ts +++ b/packages/utils/src/ts-eslint/eslint/FlatESLint.ts @@ -47,14 +47,14 @@ export namespace FlatESLint { * Ignore file patterns to use in addition to config ignores. These patterns are relative to cwd. * @default null */ - ignorePatterns?: string[] | null; + ignorePatterns?: null | string[]; /** * The path to a configuration file, overrides all configurations used with this instance. * The options.overrideConfig option is applied after this option is applied. * Searches for default config file when falsy; doesn't do any config file lookup when `true`; considered to be a config filename when a string. * @default false */ - overrideConfigFile?: string | boolean; + overrideConfigFile?: boolean | string; /** * A predicate function that filters rules to be run. * This function is called with an object containing `ruleId` and `severity`, and returns `true` if the rule should be run. diff --git a/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts b/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts index 6dc316991688..c2ba3988fbbd 100644 --- a/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts +++ b/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts @@ -32,7 +32,7 @@ export namespace LegacyESLint { * Note: This option only applies when you pass directory paths to the eslint.lintFiles() method. * If you pass glob patterns, ESLint will lint all files matching the glob pattern regardless of extension. */ - extensions?: string[] | null; + extensions?: null | string[]; /** * If false is present, the eslint.lintFiles() method doesn't respect `.eslintignore` files in your configuration. * @default true @@ -47,7 +47,7 @@ export namespace LegacyESLint { * The path to a configuration file, overrides all configurations used with this instance. * The options.overrideConfig option is applied after this option is applied. */ - overrideConfigFile?: string | null; + overrideConfigFile?: null | string; /** * The severity to report unused eslint-disable directives. * If this option is a severity, it overrides the reportUnusedDisableDirectives setting in your configurations. @@ -59,7 +59,7 @@ export namespace LegacyESLint { * setting. * If a path is present, ESLint loads all plugins from there. */ - resolvePluginsRelativeTo?: string | null; + resolvePluginsRelativeTo?: null | string; /** * An array of paths to directories to load custom rules from. */ diff --git a/packages/utils/src/ts-estree.ts b/packages/utils/src/ts-estree.ts index 212d339c4ba3..6c61253a1f05 100644 --- a/packages/utils/src/ts-estree.ts +++ b/packages/utils/src/ts-estree.ts @@ -9,6 +9,6 @@ export { export type { ParserServices, - ParserServicesWithTypeInformation, ParserServicesWithoutTypeInformation, + ParserServicesWithTypeInformation, } from '@typescript-eslint/typescript-estree'; diff --git a/yarn.lock b/yarn.lock index 936876b48990..72ac9044d083 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5781,6 +5781,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/scope-manager@npm:7.18.0" + dependencies: + "@typescript-eslint/types": 7.18.0 + "@typescript-eslint/visitor-keys": 7.18.0 + checksum: b982c6ac13d8c86bb3b949c6b4e465f3f60557c2ccf4cc229799827d462df56b9e4d3eaed7711d79b875422fc3d71ec1ebcb5195db72134d07c619e3c5506b57 + languageName: node + linkType: hard + "@typescript-eslint/type-utils@8.0.0, @typescript-eslint/type-utils@workspace:packages/type-utils": version: 0.0.0-use.local resolution: "@typescript-eslint/type-utils@workspace:packages/type-utils" @@ -5830,6 +5840,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:7.18.0, @typescript-eslint/types@npm:^7.16.1": + version: 7.18.0 + resolution: "@typescript-eslint/types@npm:7.18.0" + checksum: 7df2750cd146a0acd2d843208d69f153b458e024bbe12aab9e441ad2c56f47de3ddfeb329c4d1ea0079e2577fea4b8c1c1ce15315a8d49044586b04fedfe7a4d + languageName: node + linkType: hard + "@typescript-eslint/typescript-eslint@workspace:.": version: 0.0.0-use.local resolution: "@typescript-eslint/typescript-eslint@workspace:." @@ -5881,6 +5898,7 @@ __metadata: eslint-plugin-jest: ^27.9.0 eslint-plugin-jsdoc: ^47.0.2 eslint-plugin-jsx-a11y: ^6.8.0 + eslint-plugin-perfectionist: ^3.0.0 eslint-plugin-react: ^7.34.1 eslint-plugin-react-hooks: ^4.6.0 eslint-plugin-simple-import-sort: ^10.0.0 @@ -5971,6 +5989,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.18.0" + dependencies: + "@typescript-eslint/types": 7.18.0 + "@typescript-eslint/visitor-keys": 7.18.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + minimatch: ^9.0.4 + semver: ^7.6.0 + ts-api-utils: ^1.3.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: c82d22ec9654973944f779eb4eb94c52f4a6eafaccce2f0231ff7757313f3a0d0256c3252f6dfe6d43f57171d09656478acb49a629a9d0c193fb959bc3f36116 + languageName: node + linkType: hard + "@typescript-eslint/utils@8.0.0, @typescript-eslint/utils@workspace:^, @typescript-eslint/utils@workspace:packages/utils": version: 0.0.0-use.local resolution: "@typescript-eslint/utils@workspace:packages/utils" @@ -6024,6 +6061,20 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:^7.16.1": + version: 7.18.0 + resolution: "@typescript-eslint/utils@npm:7.18.0" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@typescript-eslint/scope-manager": 7.18.0 + "@typescript-eslint/types": 7.18.0 + "@typescript-eslint/typescript-estree": 7.18.0 + peerDependencies: + eslint: ^8.56.0 + checksum: 751dbc816dab8454b7dc6b26a56671dbec08e3f4ef94c2661ce1c0fc48fa2d05a64e03efe24cba2c22d03ba943cd3c5c7a5e1b7b03bbb446728aec1c640bd767 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@8.0.0, @typescript-eslint/visitor-keys@workspace:packages/visitor-keys": version: 0.0.0-use.local resolution: "@typescript-eslint/visitor-keys@workspace:packages/visitor-keys" @@ -6060,6 +6111,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:7.18.0": + version: 7.18.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.18.0" + dependencies: + "@typescript-eslint/types": 7.18.0 + eslint-visitor-keys: ^3.4.3 + checksum: 6e806a7cdb424c5498ea187a5a11d0fef7e4602a631be413e7d521e5aec1ab46ba00c76cfb18020adaa0a8c9802354a163bfa0deb74baa7d555526c7517bb158 + languageName: node + linkType: hard + "@typescript-eslint/website-eslint@8.0.0, @typescript-eslint/website-eslint@workspace:packages/website-eslint": version: 0.0.0-use.local resolution: "@typescript-eslint/website-eslint@workspace:packages/website-eslint" @@ -9919,6 +9980,33 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-perfectionist@npm:^3.0.0": + version: 3.0.0 + resolution: "eslint-plugin-perfectionist@npm:3.0.0" + dependencies: + "@typescript-eslint/types": ^7.16.1 + "@typescript-eslint/utils": ^7.16.1 + minimatch: ^10.0.1 + natural-compare-lite: ^1.4.0 + peerDependencies: + astro-eslint-parser: ^1.0.2 + eslint: ">=8.0.0" + svelte: ">=3.0.0" + svelte-eslint-parser: ^0.40.0 + vue-eslint-parser: ">=9.0.0" + peerDependenciesMeta: + astro-eslint-parser: + optional: true + svelte: + optional: true + svelte-eslint-parser: + optional: true + vue-eslint-parser: + optional: true + checksum: 9d41360dfe98f387bda20bc33a65c5acd8df99a274e3ef288ea4ef6c27a44fefaa29f87d2ce3aa162f7d5148b2584610a1ac32d731814cec4573e1b3f1586fca + languageName: node + linkType: hard + "eslint-plugin-react-hooks@npm:^4.6.0": version: 4.6.2 resolution: "eslint-plugin-react-hooks@npm:4.6.2" @@ -14961,6 +15049,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^10.0.1": + version: 10.0.1 + resolution: "minimatch@npm:10.0.1" + dependencies: + brace-expansion: ^2.0.1 + checksum: f5b63c2f30606091a057c5f679b067f84a2cd0ffbd2dbc9143bda850afd353c7be81949ff11ae0c86988f07390eeca64efd7143ee05a0dab37f6c6b38a2ebb6c + languageName: node + linkType: hard + "minimatch@npm:^5.0.1, minimatch@npm:^5.1.6": version: 5.1.6 resolution: "minimatch@npm:5.1.6" @@ -15191,6 +15288,13 @@ __metadata: languageName: node linkType: hard +"natural-compare-lite@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare-lite@npm:1.4.0" + checksum: 5222ac3986a2b78dd6069ac62cbb52a7bf8ffc90d972ab76dfe7b01892485d229530ed20d0c62e79a6b363a663b273db3bde195a1358ce9e5f779d4453887225 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" From c450608ed2149a57d072463dde31ffa3e05759b0 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 12 Aug 2024 12:11:40 -0400 Subject: [PATCH 2/6] Set ignoreCase to false --- eslint.config.mjs | 8 +++++ .../ast-utils/eslint-utils/scopeAnalysis.ts | 4 +-- packages/utils/src/ast-utils/helpers.ts | 14 ++++----- .../utils/src/eslint-utils/applyDefault.ts | 2 +- packages/utils/src/json-schema.ts | 10 +++---- packages/utils/src/ts-eslint/Config.ts | 6 ++-- packages/utils/src/ts-eslint/Linter.ts | 2 +- packages/utils/src/ts-eslint/Rule.ts | 6 ++-- packages/utils/src/ts-eslint/RuleTester.ts | 2 +- packages/utils/src/ts-eslint/SourceCode.ts | 30 +++++++++---------- .../src/ts-eslint/eslint/ESLintShared.ts | 2 +- 11 files changed, 47 insertions(+), 39 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index f54699d168a9..cdd8900908ed 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -590,6 +590,14 @@ export default tseslint.config( type: 'natural', }, ], + 'perfectionist/sort-union-types': [ + 'error', + { + order: 'asc', + ignoreCase: false, + type: 'natural', + }, + ], 'simple-import-sort/imports': 'off', }, }, diff --git a/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts b/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts index 5b9ca52c958f..43199ce05533 100644 --- a/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts +++ b/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts @@ -10,8 +10,8 @@ import type { TSESTree } from '../../ts-estree'; */ const findVariable = eslintUtils.findVariable as ( initialScope: TSESLint.Scope.Scope, - nameOrNode: string | TSESTree.Identifier, -) => null | TSESLint.Scope.Variable; + nameOrNode: TSESTree.Identifier | string, +) => TSESLint.Scope.Variable | null; /** * Get the innermost scope which contains a given node. diff --git a/packages/utils/src/ast-utils/helpers.ts b/packages/utils/src/ast-utils/helpers.ts index cc77e33c48c8..ca4252a5dfeb 100644 --- a/packages/utils/src/ast-utils/helpers.ts +++ b/packages/utils/src/ast-utils/helpers.ts @@ -8,14 +8,14 @@ type ObjectEntries = ObjectEntry[]; export const isNodeOfType = (nodeType: NodeType) => ( - node: null | TSESTree.Node | undefined, + node: TSESTree.Node | null | undefined, ): node is Extract => node?.type === nodeType; export const isNodeOfTypes = (nodeTypes: NodeTypes) => ( - node: null | TSESTree.Node | undefined, + node: TSESTree.Node | null | undefined, ): node is Extract => !!node && nodeTypes.includes(node.type); @@ -27,12 +27,12 @@ export const isNodeOfTypeWithConditions = < nodeType: NodeType, conditions: Conditions, ): (( - node: null | TSESTree.Node | undefined, + node: TSESTree.Node | null | undefined, ) => node is Conditions & ExtractedNode) => { const entries = Object.entries(conditions) as ObjectEntries; return ( - node: null | TSESTree.Node | undefined, + node: TSESTree.Node | null | undefined, ): node is Conditions & ExtractedNode => node?.type === nodeType && entries.every(([key, value]) => node[key as keyof TSESTree.Node] === value); @@ -48,12 +48,12 @@ export const isTokenOfTypeWithConditions = < tokenType: TokenType, conditions: Conditions, ): (( - token: null | TSESTree.Token | undefined, + token: TSESTree.Token | null | undefined, ) => token is Conditions & ExtractedToken) => { const entries = Object.entries(conditions) as ObjectEntries; return ( - token: null | TSESTree.Token | undefined, + token: TSESTree.Token | null | undefined, ): token is Conditions & ExtractedToken => token?.type === tokenType && entries.every( @@ -70,7 +70,7 @@ export const isNotTokenOfTypeWithConditions = tokenType: TokenType, conditions: Conditions, ): (( - token: null | TSESTree.Token | undefined, + token: TSESTree.Token | null | undefined, ) => token is Exclude) => (token): token is Exclude => !isTokenOfTypeWithConditions(tokenType, conditions)(token); diff --git a/packages/utils/src/eslint-utils/applyDefault.ts b/packages/utils/src/eslint-utils/applyDefault.ts index 161a10a8b91e..231561bef11d 100644 --- a/packages/utils/src/eslint-utils/applyDefault.ts +++ b/packages/utils/src/eslint-utils/applyDefault.ts @@ -9,7 +9,7 @@ import { deepMerge, isObjectNotArray } from './deepMerge'; */ function applyDefault( defaultOptions: Readonly, - userOptions: null | Readonly, + userOptions: Readonly | null, ): Default { // clone defaults const options = JSON.parse( diff --git a/packages/utils/src/json-schema.ts b/packages/utils/src/json-schema.ts index 09bd82a6ac42..840858470b16 100644 --- a/packages/utils/src/json-schema.ts +++ b/packages/utils/src/json-schema.ts @@ -238,7 +238,7 @@ export interface JSONSchema4ObjectSchema extends JSONSchema4Base { * * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4 */ - additionalProperties?: boolean | JSONSchema4 | undefined; + additionalProperties?: JSONSchema4 | boolean | undefined; /** * The `dependencies` keyword conditionally applies a sub-schema when a given @@ -302,7 +302,7 @@ export interface JSONSchema4ArraySchema extends JSONSchema4Base { * * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.6 */ - additionalItems?: boolean | JSONSchema4 | undefined; + additionalItems?: JSONSchema4 | boolean | undefined; /** * This attribute defines the allowed items in an instance array, and @@ -361,20 +361,20 @@ export interface JSONSchema4StringSchema extends JSONSchema4Base { * to throw during schema compilation */ format?: - | 'date-time' | 'date' + | 'date-time' | 'email' | 'hostname' | 'ipv4' | 'ipv6' - | 'json-pointer-uri-fragment' | 'json-pointer' + | 'json-pointer-uri-fragment' | 'regex' | 'relative-json-pointer' | 'time' + | 'uri' | 'uri-reference' | 'uri-template' - | 'uri' | 'url' | 'uuid' | undefined; diff --git a/packages/utils/src/ts-eslint/Config.ts b/packages/utils/src/ts-eslint/Config.ts index ee5b2d44e4f3..a71ab212501c 100644 --- a/packages/utils/src/ts-eslint/Config.ts +++ b/packages/utils/src/ts-eslint/Config.ts @@ -17,7 +17,7 @@ export namespace SharedConfig { export type RulesRecord = Partial>; export type GlobalVariableOptionBase = 'off' | 'readonly' | 'writable'; - export type GlobalVariableOption = boolean | GlobalVariableOptionBase; + export type GlobalVariableOption = GlobalVariableOptionBase | boolean; export interface GlobalsConfig { [name: string]: GlobalVariableOption; @@ -187,9 +187,9 @@ export namespace FlatConfig { * @default "off" */ reportUnusedDisableDirectives?: - | boolean | SharedConfig.Severity - | SharedConfig.SeverityString; + | SharedConfig.SeverityString + | boolean; } export interface LanguageOptions { diff --git a/packages/utils/src/ts-eslint/Linter.ts b/packages/utils/src/ts-eslint/Linter.ts index 7efea1834f01..c95e9b9991ca 100644 --- a/packages/utils/src/ts-eslint/Linter.ts +++ b/packages/utils/src/ts-eslint/Linter.ts @@ -183,7 +183,7 @@ namespace Linter { /** * Adds reported errors for unused `eslint-disable` directives. */ - reportUnusedDisableDirectives?: boolean | SeverityString; + reportUnusedDisableDirectives?: SeverityString | boolean; } export interface FixOptions extends VerifyOptions { diff --git a/packages/utils/src/ts-eslint/Rule.ts b/packages/utils/src/ts-eslint/Rule.ts index 0fd8d5f5affc..834e18608a1b 100644 --- a/packages/utils/src/ts-eslint/Rule.ts +++ b/packages/utils/src/ts-eslint/Rule.ts @@ -116,7 +116,7 @@ export interface SuggestionReportDescriptor export type ReportFixFunction = ( fixer: RuleFixer, -) => IterableIterator | null | readonly RuleFix[] | RuleFix; +) => IterableIterator | RuleFix | null | readonly RuleFix[]; export type ReportSuggestionArray = SuggestionReportDescriptor[]; @@ -131,7 +131,7 @@ interface ReportDescriptorBase { /** * The fixer function. */ - readonly fix?: null | ReportFixFunction; + readonly fix?: ReportFixFunction | null; /** * The messageId which is being reported. */ @@ -145,7 +145,7 @@ interface ReportDescriptorWithSuggestion /** * 6.7's Suggestions API */ - readonly suggest?: null | Readonly>; + readonly suggest?: Readonly> | null; } interface ReportDescriptorNodeOptionalLoc { diff --git a/packages/utils/src/ts-eslint/RuleTester.ts b/packages/utils/src/ts-eslint/RuleTester.ts index 92fb27cb4f8d..47d8df3ce049 100644 --- a/packages/utils/src/ts-eslint/RuleTester.ts +++ b/packages/utils/src/ts-eslint/RuleTester.ts @@ -156,7 +156,7 @@ interface RunTests< > { // RuleTester.run also accepts strings for valid cases readonly invalid: readonly InvalidTestCase[]; - readonly valid: readonly (string | ValidTestCase)[]; + readonly valid: readonly (ValidTestCase | string)[]; } /** diff --git a/packages/utils/src/ts-eslint/SourceCode.ts b/packages/utils/src/ts-eslint/SourceCode.ts index c65752297e12..b5caea851b92 100644 --- a/packages/utils/src/ts-eslint/SourceCode.ts +++ b/packages/utils/src/ts-eslint/SourceCode.ts @@ -48,7 +48,7 @@ declare class TokenStore { getFirstToken( node: TSESTree.Node, options?: T, - ): null | SourceCode.ReturnTypeFromOptions; + ): SourceCode.ReturnTypeFromOptions | null; /** * Gets the first token between two non-overlapping nodes. * @param left Node before the desired token range. @@ -60,7 +60,7 @@ declare class TokenStore { left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: T, - ): null | SourceCode.ReturnTypeFromOptions; + ): SourceCode.ReturnTypeFromOptions | null; /** * Gets the first `count` tokens of the given node. * @param node The AST node. @@ -91,7 +91,7 @@ declare class TokenStore { getLastToken( node: TSESTree.Node, options?: T, - ): null | SourceCode.ReturnTypeFromOptions; + ): SourceCode.ReturnTypeFromOptions | null; /** * Gets the last token between two non-overlapping nodes. * @param left Node before the desired token range. @@ -103,7 +103,7 @@ declare class TokenStore { left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: T, - ): null | SourceCode.ReturnTypeFromOptions; + ): SourceCode.ReturnTypeFromOptions | null; /** * Gets the last `count` tokens of the given node. * @param node The AST node. @@ -134,7 +134,7 @@ declare class TokenStore { getTokenAfter( node: TSESTree.Node | TSESTree.Token, options?: T, - ): null | SourceCode.ReturnTypeFromOptions; + ): SourceCode.ReturnTypeFromOptions | null; /** * Gets the token that precedes a given node or token. * @param node The AST node or token. @@ -144,7 +144,7 @@ declare class TokenStore { getTokenBefore( node: TSESTree.Node | TSESTree.Token, options?: T, - ): null | SourceCode.ReturnTypeFromOptions; + ): SourceCode.ReturnTypeFromOptions | null; /** * Gets the token starting at the specified index. * @param offset Index of the start of the token's range. @@ -154,7 +154,7 @@ declare class TokenStore { getTokenByRangeStart( offset: number, options?: T, - ): null | SourceCode.ReturnTypeFromOptions; + ): SourceCode.ReturnTypeFromOptions | null; /** * Gets all tokens that are related to the given node. * @param node The AST node. @@ -184,7 +184,7 @@ declare class TokenStore { */ getTokensAfter( node: TSESTree.Node | TSESTree.Token, - options?: number | T, + options?: T | number, ): SourceCode.ReturnTypeFromOptions[]; /** * Gets the `count` tokens that precedes a given node or token. @@ -193,7 +193,7 @@ declare class TokenStore { */ getTokensBefore( node: TSESTree.Node | TSESTree.Token, - options?: number | T, + options?: T | number, ): SourceCode.ReturnTypeFromOptions[]; /** * Gets all of the tokens between two non-overlapping nodes. @@ -205,7 +205,7 @@ declare class TokenStore { getTokensBetween( left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, - options?: number | T, + options?: T | number, ): SourceCode.ReturnTypeFromOptions[]; } @@ -256,7 +256,7 @@ declare class SourceCodeBase extends TokenStore { * @param index Range index of the desired node. * @returns The node if found or `null` if not found. */ - getNodeByRangeIndex(index: number): null | TSESTree.Node; + getNodeByRangeIndex(index: number): TSESTree.Node | null; /** * Gets the source code for the given node. * @param node The AST node to get the text for. @@ -335,7 +335,7 @@ declare class SourceCodeBase extends TokenStore { /** * The scope of this source code. */ - scopeManager: null | Scope.ScopeManager; + scopeManager: Scope.ScopeManager | null; /** * The original text source code. BOM was stripped from this text. */ @@ -377,11 +377,11 @@ namespace SourceCode { /** * The parser services. */ - parserServices: null | ParserServices; + parserServices: ParserServices | null; /** * The scope of this source code. */ - scopeManager: null | Scope.ScopeManager; + scopeManager: Scope.ScopeManager | null; /** * The source code text. */ @@ -389,7 +389,7 @@ namespace SourceCode { /** * The visitor keys to traverse AST. */ - visitorKeys: null | VisitorKeys; + visitorKeys: VisitorKeys | null; } export type VisitorKeys = Parser.VisitorKeys; diff --git a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts b/packages/utils/src/ts-eslint/eslint/ESLintShared.ts index ad3e6481ed6d..e32f9b4201e1 100644 --- a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts +++ b/packages/utils/src/ts-eslint/eslint/ESLintShared.ts @@ -177,7 +177,7 @@ export interface ESLintOptions { * This is a map-like object. Those keys are plugin IDs and each value is implementation. * @default null */ - plugins?: null | Record; + plugins?: Record | null; } export interface DeprecatedRuleInfo { From 6f157e97e9b0e08fe0af45ac52f9ddc40615b19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?= Date: Tue, 13 Aug 2024 10:25:29 -0400 Subject: [PATCH 3/6] Apply suggestions from code review Co-authored-by: Brad Zacher --- eslint.config.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index cdd8900908ed..8eb1a308310a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -570,10 +570,9 @@ export default tseslint.config( }, }, { - ...perfectionistPlugin.configs['recommended-alphabetical'], + extends: [perfectionistPlugin.configs['recommended-alphabetical']], files: ['packages/utils/src/**/*.ts'], rules: { - ...perfectionistPlugin.configs['recommended-alphabetical'].rules, 'perfectionist/sort-classes': [ 'error', { From 81888f5ae27d2373a733758eb0a20972cc3ec03c Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 20 Aug 2024 02:29:10 -0400 Subject: [PATCH 4/6] Put nullish last --- .../utils/src/ast-utils/eslint-utils/astUtilities.ts | 4 ++-- packages/utils/src/json-schema.ts | 2 +- packages/utils/src/ts-eslint/Config.ts | 12 ++++++------ packages/utils/src/ts-eslint/ESLint.ts | 4 ++-- packages/utils/src/ts-eslint/Linter.ts | 4 ++-- packages/utils/src/ts-eslint/Rule.ts | 2 +- packages/utils/src/ts-eslint/RuleTester.ts | 4 ++-- packages/utils/src/ts-eslint/eslint/ESLintShared.ts | 2 +- packages/utils/src/ts-eslint/eslint/FlatESLint.ts | 2 +- packages/utils/src/ts-eslint/eslint/LegacyESLint.ts | 6 +++--- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts b/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts index 81f1561646f5..dfb9fe863e65 100644 --- a/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts +++ b/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts @@ -43,7 +43,7 @@ const getPropertyName = eslintUtils.getPropertyName as ( | TSESTree.Property | TSESTree.PropertyDefinition, initialScope?: TSESLint.Scope.Scope, -) => null | string; +) => string | null; /** * Get the value of a given node if it can decide the value statically. @@ -70,7 +70,7 @@ const getStaticValue = eslintUtils.getStaticValue as ( const getStringIfConstant = eslintUtils.getStringIfConstant as ( node: TSESTree.Node, initialScope?: TSESLint.Scope.Scope, -) => null | string; +) => string | null; /** * Check whether a given node has any side effect or not. diff --git a/packages/utils/src/json-schema.ts b/packages/utils/src/json-schema.ts index 840858470b16..5c8229ced5ac 100644 --- a/packages/utils/src/json-schema.ts +++ b/packages/utils/src/json-schema.ts @@ -25,7 +25,7 @@ export type JSONSchema4TypeName = /** * @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5 */ -export type JSONSchema4Type = boolean | null | number | string; +export type JSONSchema4Type = boolean | number | string | null; export type JSONSchema4TypeExtended = | JSONSchema4Array diff --git a/packages/utils/src/ts-eslint/Config.ts b/packages/utils/src/ts-eslint/Config.ts index 85fa5045c71a..08911b2aff53 100644 --- a/packages/utils/src/ts-eslint/Config.ts +++ b/packages/utils/src/ts-eslint/Config.ts @@ -18,13 +18,13 @@ export namespace SharedConfig { export type GlobalVariableOptionBase = | 'off' + | 'readable' | 'readonly' - | 'writable' - | /** @deprecated use `'writable'` */ 'writeable' - | /** @deprecated use `'readonly'` */ 'readable'; + | /** @deprecated use `'writable'` */ 'writable' + | /** @deprecated use `'readonly'` */ 'writeable'; export type GlobalVariableOptionBoolean = - | /** @deprecated use `'writable'` */ true - | /** @deprecated use `'readonly'` */ false; + | /** @deprecated use `'writable'` */ false + | /** @deprecated use `'readonly'` */ true; export type GlobalVariableOption = | GlobalVariableOptionBase | GlobalVariableOptionBoolean; @@ -89,7 +89,7 @@ export namespace ClassicConfig { /** * The path to a parser or the package name of a parser. */ - parser?: null | string; + parser?: string | null; /** * The parser options. */ diff --git a/packages/utils/src/ts-eslint/ESLint.ts b/packages/utils/src/ts-eslint/ESLint.ts index 9ca17db29ab9..4fe9ddb44ea1 100644 --- a/packages/utils/src/ts-eslint/ESLint.ts +++ b/packages/utils/src/ts-eslint/ESLint.ts @@ -1,3 +1,5 @@ +export { FlatESLint } from './eslint/FlatESLint'; +export { FlatESLint as ESLint } from './eslint/FlatESLint'; export { // TODO(eslint@v10) - remove this in the next major /** @@ -5,5 +7,3 @@ export { */ LegacyESLint, } from './eslint/LegacyESLint'; -export { FlatESLint } from './eslint/FlatESLint'; -export { FlatESLint as ESLint } from './eslint/FlatESLint'; diff --git a/packages/utils/src/ts-eslint/Linter.ts b/packages/utils/src/ts-eslint/Linter.ts index c95e9b9991ca..b9bee0ee5d94 100644 --- a/packages/utils/src/ts-eslint/Linter.ts +++ b/packages/utils/src/ts-eslint/Linter.ts @@ -233,12 +233,12 @@ namespace Linter { /** * The ID of the rule which makes this message. */ - ruleId: null | string; + ruleId: string | null; /** * The severity of this message. */ severity: Severity; - source: null | string; + source: string | null; /** * Information for suggestions */ diff --git a/packages/utils/src/ts-eslint/Rule.ts b/packages/utils/src/ts-eslint/Rule.ts index 9f40f7d20a3a..45ea2f5501ea 100644 --- a/packages/utils/src/ts-eslint/Rule.ts +++ b/packages/utils/src/ts-eslint/Rule.ts @@ -116,7 +116,7 @@ export interface SuggestionReportDescriptor export type ReportFixFunction = ( fixer: RuleFixer, -) => IterableIterator | RuleFix | null | readonly RuleFix[]; +) => IterableIterator | RuleFix | readonly RuleFix[] | null; export type ReportSuggestionArray = SuggestionReportDescriptor[]; diff --git a/packages/utils/src/ts-eslint/RuleTester.ts b/packages/utils/src/ts-eslint/RuleTester.ts index 47d8df3ce049..2274a0aa8db2 100644 --- a/packages/utils/src/ts-eslint/RuleTester.ts +++ b/packages/utils/src/ts-eslint/RuleTester.ts @@ -94,7 +94,7 @@ interface InvalidTestCase< /** * The expected code after autofixes are applied. If set to `null`, the test runner will assert that no autofix is suggested. */ - readonly output?: null | string | string[]; + readonly output?: string | string[] | null; } /** @@ -128,7 +128,7 @@ interface TestCaseError { /** * Reported suggestions. */ - readonly suggestions?: null | readonly SuggestionOutput[]; + readonly suggestions?: readonly SuggestionOutput[] | null; /** * The type of the reported AST node. */ diff --git a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts b/packages/utils/src/ts-eslint/eslint/ESLintShared.ts index e32f9b4201e1..23ec9cc8de25 100644 --- a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts +++ b/packages/utils/src/ts-eslint/eslint/ESLintShared.ts @@ -340,7 +340,7 @@ export interface LintMessage { * The rule name that generates this lint message. If this message is generated by the ESLint core rather than * rules, this is null. */ - ruleId: null | string; + ruleId: string | null; /** * The severity of this message. 1 means warning and 2 means error. */ diff --git a/packages/utils/src/ts-eslint/eslint/FlatESLint.ts b/packages/utils/src/ts-eslint/eslint/FlatESLint.ts index 561c6216b9ad..085a9e0fdfa9 100644 --- a/packages/utils/src/ts-eslint/eslint/FlatESLint.ts +++ b/packages/utils/src/ts-eslint/eslint/FlatESLint.ts @@ -47,7 +47,7 @@ export namespace FlatESLint { * Ignore file patterns to use in addition to config ignores. These patterns are relative to cwd. * @default null */ - ignorePatterns?: null | string[]; + ignorePatterns?: string[] | 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/eslint/LegacyESLint.ts b/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts index c2ba3988fbbd..6dc316991688 100644 --- a/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts +++ b/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts @@ -32,7 +32,7 @@ export namespace LegacyESLint { * Note: This option only applies when you pass directory paths to the eslint.lintFiles() method. * If you pass glob patterns, ESLint will lint all files matching the glob pattern regardless of extension. */ - extensions?: null | string[]; + extensions?: string[] | null; /** * If false is present, the eslint.lintFiles() method doesn't respect `.eslintignore` files in your configuration. * @default true @@ -47,7 +47,7 @@ export namespace LegacyESLint { * The path to a configuration file, overrides all configurations used with this instance. * The options.overrideConfig option is applied after this option is applied. */ - overrideConfigFile?: null | string; + overrideConfigFile?: string | null; /** * The severity to report unused eslint-disable directives. * If this option is a severity, it overrides the reportUnusedDisableDirectives setting in your configurations. @@ -59,7 +59,7 @@ export namespace LegacyESLint { * setting. * If a path is present, ESLint loads all plugins from there. */ - resolvePluginsRelativeTo?: null | string; + resolvePluginsRelativeTo?: string | null; /** * An array of paths to directories to load custom rules from. */ From 6032d9022e535565798c3314ba8883295998026f Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 20 Aug 2024 12:12:31 -0400 Subject: [PATCH 5/6] Remove ignoreCase --- eslint.config.mjs | 3 +-- packages/utils/src/json-schema.ts | 4 ++-- packages/utils/src/ts-eslint/Config.ts | 12 ++++++------ packages/utils/src/ts-eslint/Rule.ts | 2 +- packages/utils/src/ts-eslint/RuleTester.ts | 2 +- packages/utils/src/ts-eslint/eslint/ESLintShared.ts | 2 +- 6 files changed, 12 insertions(+), 13 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 13ba992407a0..60b302d8cb50 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -600,8 +600,7 @@ export default tseslint.config( 'error', { order: 'asc', - groups: ['unknown', 'nullish'], - ignoreCase: false, + groups: ['unknown', 'keyword', 'nullish'], type: 'natural', }, ], diff --git a/packages/utils/src/json-schema.ts b/packages/utils/src/json-schema.ts index 5c8229ced5ac..83ba0fd36793 100644 --- a/packages/utils/src/json-schema.ts +++ b/packages/utils/src/json-schema.ts @@ -146,7 +146,7 @@ interface JSONSchema4Base { * * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.26 */ - extends?: string | string[] | undefined; + extends?: string[] | string | undefined; id?: string | undefined; @@ -167,7 +167,7 @@ interface JSONSchema4Base { * * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7 */ - required?: boolean | string[] | undefined; + required?: string[] | boolean | undefined; /** * This attribute is a string that provides a short description of the diff --git a/packages/utils/src/ts-eslint/Config.ts b/packages/utils/src/ts-eslint/Config.ts index 08911b2aff53..d69fd14f3509 100644 --- a/packages/utils/src/ts-eslint/Config.ts +++ b/packages/utils/src/ts-eslint/Config.ts @@ -73,7 +73,7 @@ export namespace ClassicConfig { /** * The path to other config files or the package name of shareable configs. */ - extends?: string | string[]; + extends?: string[] | string; /** * The global variable settings. */ @@ -117,15 +117,15 @@ export namespace ClassicConfig { } export interface ConfigOverride extends BaseConfig { - excludedFiles?: string | string[]; - files: string | string[]; + excludedFiles?: string[] | string; + files: string[] | string; } export interface Config extends BaseConfig { /** * The glob patterns that ignore to lint. */ - ignorePatterns?: string | string[]; + ignorePatterns?: string[] | string; /** * The root flag. */ @@ -250,9 +250,9 @@ export namespace FlatConfig { * If not specified, the configuration object applies to all files matched by any other configuration object. */ files?: ( - | string - // yes, a single layer of array nesting is supported | string[] + // yes, a single layer of array nesting is supported + | string )[]; /** * An array of glob patterns indicating the files that the configuration object should not apply to. diff --git a/packages/utils/src/ts-eslint/Rule.ts b/packages/utils/src/ts-eslint/Rule.ts index 45ea2f5501ea..0d409a83e3f5 100644 --- a/packages/utils/src/ts-eslint/Rule.ts +++ b/packages/utils/src/ts-eslint/Rule.ts @@ -116,7 +116,7 @@ export interface SuggestionReportDescriptor export type ReportFixFunction = ( fixer: RuleFixer, -) => IterableIterator | RuleFix | readonly RuleFix[] | null; +) => IterableIterator | readonly RuleFix[] | RuleFix | null; export type ReportSuggestionArray = SuggestionReportDescriptor[]; diff --git a/packages/utils/src/ts-eslint/RuleTester.ts b/packages/utils/src/ts-eslint/RuleTester.ts index 2274a0aa8db2..564a661520d8 100644 --- a/packages/utils/src/ts-eslint/RuleTester.ts +++ b/packages/utils/src/ts-eslint/RuleTester.ts @@ -94,7 +94,7 @@ interface InvalidTestCase< /** * The expected code after autofixes are applied. If set to `null`, the test runner will assert that no autofix is suggested. */ - readonly output?: string | string[] | null; + readonly output?: string[] | string | null; } /** diff --git a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts b/packages/utils/src/ts-eslint/eslint/ESLintShared.ts index 23ec9cc8de25..aad9b71e558b 100644 --- a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts +++ b/packages/utils/src/ts-eslint/eslint/ESLintShared.ts @@ -42,7 +42,7 @@ export declare class ESLintBase< * @param patterns The lint target files. This can contain any of file paths, directory paths, and glob patterns. * @returns The promise that will be fulfilled with an array of LintResult objects. */ - lintFiles(patterns: string | string[]): Promise; + lintFiles(patterns: string[] | string): Promise; /** * This method lints the given source code text and then returns the results. From 59df291d315e228a89895486b5511a9559444414 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 20 Aug 2024 13:35:34 -0400 Subject: [PATCH 6/6] Bump to version with fixed types --- package.json | 2 +- yarn.lock | 80 +++++++--------------------------------------------- 2 files changed, 11 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index 285aa50d4f94..dbd45ba3ffa6 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsdoc": "^47.0.2", "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-perfectionist": "^3.0.0", + "eslint-plugin-perfectionist": "^3.2.0", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-simple-import-sort": "^10.0.0", diff --git a/yarn.lock b/yarn.lock index 42664d6adf16..57e500d5887f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5789,16 +5789,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/scope-manager@npm:7.18.0" - dependencies: - "@typescript-eslint/types": 7.18.0 - "@typescript-eslint/visitor-keys": 7.18.0 - checksum: b982c6ac13d8c86bb3b949c6b4e465f3f60557c2ccf4cc229799827d462df56b9e4d3eaed7711d79b875422fc3d71ec1ebcb5195db72134d07c619e3c5506b57 - languageName: node - linkType: hard - "@typescript-eslint/type-utils@8.2.0, @typescript-eslint/type-utils@workspace:*, @typescript-eslint/type-utils@workspace:packages/type-utils": version: 0.0.0-use.local resolution: "@typescript-eslint/type-utils@workspace:packages/type-utils" @@ -5821,7 +5811,7 @@ __metadata: languageName: unknown linkType: soft -"@typescript-eslint/types@8.2.0, @typescript-eslint/types@workspace:*, @typescript-eslint/types@workspace:^, @typescript-eslint/types@workspace:packages/types": +"@typescript-eslint/types@8.2.0, @typescript-eslint/types@^8.1.0, @typescript-eslint/types@workspace:*, @typescript-eslint/types@workspace:^, @typescript-eslint/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@typescript-eslint/types@workspace:packages/types" dependencies: @@ -5848,13 +5838,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:7.18.0, @typescript-eslint/types@npm:^7.16.1": - version: 7.18.0 - resolution: "@typescript-eslint/types@npm:7.18.0" - checksum: 7df2750cd146a0acd2d843208d69f153b458e024bbe12aab9e441ad2c56f47de3ddfeb329c4d1ea0079e2577fea4b8c1c1ce15315a8d49044586b04fedfe7a4d - languageName: node - linkType: hard - "@typescript-eslint/typescript-eslint@workspace:.": version: 0.0.0-use.local resolution: "@typescript-eslint/typescript-eslint@workspace:." @@ -5906,7 +5889,7 @@ __metadata: eslint-plugin-jest: ^27.9.0 eslint-plugin-jsdoc: ^47.0.2 eslint-plugin-jsx-a11y: ^6.8.0 - eslint-plugin-perfectionist: ^3.0.0 + eslint-plugin-perfectionist: ^3.2.0 eslint-plugin-react: ^7.34.1 eslint-plugin-react-hooks: ^4.6.0 eslint-plugin-simple-import-sort: ^10.0.0 @@ -5997,26 +5980,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.18.0" - dependencies: - "@typescript-eslint/types": 7.18.0 - "@typescript-eslint/visitor-keys": 7.18.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - minimatch: ^9.0.4 - semver: ^7.6.0 - ts-api-utils: ^1.3.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: c82d22ec9654973944f779eb4eb94c52f4a6eafaccce2f0231ff7757313f3a0d0256c3252f6dfe6d43f57171d09656478acb49a629a9d0c193fb959bc3f36116 - languageName: node - linkType: hard - -"@typescript-eslint/utils@8.2.0, @typescript-eslint/utils@workspace:*, @typescript-eslint/utils@workspace:^, @typescript-eslint/utils@workspace:packages/utils": +"@typescript-eslint/utils@8.2.0, @typescript-eslint/utils@^8.1.0, @typescript-eslint/utils@workspace:*, @typescript-eslint/utils@workspace:^, @typescript-eslint/utils@workspace:packages/utils": version: 0.0.0-use.local resolution: "@typescript-eslint/utils@workspace:packages/utils" dependencies: @@ -6069,20 +6033,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:^7.16.1": - version: 7.18.0 - resolution: "@typescript-eslint/utils@npm:7.18.0" - dependencies: - "@eslint-community/eslint-utils": ^4.4.0 - "@typescript-eslint/scope-manager": 7.18.0 - "@typescript-eslint/types": 7.18.0 - "@typescript-eslint/typescript-estree": 7.18.0 - peerDependencies: - eslint: ^8.56.0 - checksum: 751dbc816dab8454b7dc6b26a56671dbec08e3f4ef94c2661ce1c0fc48fa2d05a64e03efe24cba2c22d03ba943cd3c5c7a5e1b7b03bbb446728aec1c640bd767 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@8.2.0, @typescript-eslint/visitor-keys@workspace:*, @typescript-eslint/visitor-keys@workspace:packages/visitor-keys": version: 0.0.0-use.local resolution: "@typescript-eslint/visitor-keys@workspace:packages/visitor-keys" @@ -6119,16 +6069,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.18.0" - dependencies: - "@typescript-eslint/types": 7.18.0 - eslint-visitor-keys: ^3.4.3 - checksum: 6e806a7cdb424c5498ea187a5a11d0fef7e4602a631be413e7d521e5aec1ab46ba00c76cfb18020adaa0a8c9802354a163bfa0deb74baa7d555526c7517bb158 - languageName: node - linkType: hard - "@typescript-eslint/website-eslint@workspace:*, @typescript-eslint/website-eslint@workspace:packages/website-eslint": version: 0.0.0-use.local resolution: "@typescript-eslint/website-eslint@workspace:packages/website-eslint" @@ -9988,19 +9928,19 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-perfectionist@npm:^3.0.0": - version: 3.0.0 - resolution: "eslint-plugin-perfectionist@npm:3.0.0" +"eslint-plugin-perfectionist@npm:^3.2.0": + version: 3.2.0 + resolution: "eslint-plugin-perfectionist@npm:3.2.0" dependencies: - "@typescript-eslint/types": ^7.16.1 - "@typescript-eslint/utils": ^7.16.1 + "@typescript-eslint/types": ^8.1.0 + "@typescript-eslint/utils": ^8.1.0 minimatch: ^10.0.1 natural-compare-lite: ^1.4.0 peerDependencies: astro-eslint-parser: ^1.0.2 eslint: ">=8.0.0" svelte: ">=3.0.0" - svelte-eslint-parser: ^0.40.0 + svelte-eslint-parser: ^0.41.0 vue-eslint-parser: ">=9.0.0" peerDependenciesMeta: astro-eslint-parser: @@ -10011,7 +9951,7 @@ __metadata: optional: true vue-eslint-parser: optional: true - checksum: 9d41360dfe98f387bda20bc33a65c5acd8df99a274e3ef288ea4ef6c27a44fefaa29f87d2ce3aa162f7d5148b2584610a1ac32d731814cec4573e1b3f1586fca + checksum: 1bb310a1165e1dcb1fa89a5bf008dc20c958256621f43dcf5563e1c9d4f8bb5eb14649545ba28fda11e0602316f20b6483374b43dcbb41a475a1e27b9cb3a39a languageName: node linkType: hard