1import { JSONSchema4 } from '../json-schema'; 2import { ParserServices, TSESTree } from '../ts-estree'; 3import { AST } from './AST'; 4import { Linter } from './Linter'; 5import { Scope } from './Scope'; 6import { SourceCode } from './SourceCode'; 7 8interface RuleMetaDataDocs { 9 /** 10 * The general category the rule falls within 11 */ 12 category: 13 | 'Best Practices' 14 | 'Stylistic Issues' 15 | 'Variables' 16 | 'Possible Errors'; 17 /** 18 * Concise description of the rule 19 */ 20 description: string; 21 /** 22 * The recommendation level for the rule. 23 * Used by the build tools to generate the recommended config. 24 * Set to false to not include it as a recommendation 25 */ 26 recommended: 'error' | 'warn' | false; 27 /** 28 * The URL of the rule's docs 29 */ 30 url: string; 31 /** 32 * Specifies whether the rule can return suggestions. 33 */ 34 suggestion?: boolean; 35 /** 36 * Does the rule require us to create a full TypeScript Program in order for it 37 * to type-check code. This is only used for documentation purposes. 38 */ 39 requiresTypeChecking?: boolean; 40 /** 41 * Does the rule extend (or is it based off of) an ESLint code rule? 42 * Alternately accepts the name of the base rule, in case the rule has been renamed. 43 * This is only used for documentation purposes. 44 */ 45 extendsBaseRule?: boolean | string; 46} 47interface RuleMetaData<TMessageIds extends string> { 48 /** 49 * True if the rule is deprecated, false otherwise 50 */ 51 deprecated?: boolean; 52 /** 53 * Documentation for the rule, unnecessary for custom rules/plugins 54 */ 55 docs?: RuleMetaDataDocs; 56 /** 57 * The fixer category. Omit if there is no fixer 58 */ 59 fixable?: 'code' | 'whitespace'; 60 /** 61 * A map of messages which the rule can report. 62 * The key is the messageId, and the string is the parameterised error string. 63 * See: https://eslint.org/docs/developer-guide/working-with-rules#messageids 64 */ 65 messages: Record<TMessageIds, string>; 66 /** 67 * The type of rule. 68 * - `"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. 69 * - `"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. 70 * - `"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. 71 */ 72 type: 'suggestion' | 'problem' | 'layout'; 73 /** 74 * The name of the rule this rule was replaced by, if it was deprecated. 75 */ 76 replacedBy?: string[]; 77 /** 78 * The options schema. Supply an empty array if there are no options. 79 */ 80 schema: JSONSchema4 | JSONSchema4[]; 81} 82 83interface RuleFix { 84 range: AST.Range; 85 text: string; 86} 87 88interface RuleFixer { 89 insertTextAfter( 90 nodeOrToken: TSESTree.Node | TSESTree.Token, 91 text: string, 92 ): RuleFix; 93 94 insertTextAfterRange(range: AST.Range, text: string): RuleFix; 95 96 insertTextBefore( 97 nodeOrToken: TSESTree.Node | TSESTree.Token, 98 text: string, 99 ): RuleFix; 100 101 insertTextBeforeRange(range: AST.Range, text: string): RuleFix; 102 103 remove(nodeOrToken: TSESTree.Node | TSESTree.Token): RuleFix; 104 105 removeRange(range: AST.Range): RuleFix; 106 107 replaceText( 108 nodeOrToken: TSESTree.Node | TSESTree.Token, 109 text: string, 110 ): RuleFix; 111 112 replaceTextRange(range: AST.Range, text: string): RuleFix; 113} 114 115type ReportFixFunction = ( 116 fixer: RuleFixer, 117) => null | RuleFix | RuleFix[] | IterableIterator<RuleFix>; 118type ReportSuggestionArray<TMessageIds extends string> = ReportDescriptorBase< 119 TMessageIds 120>[]; 121 122interface ReportDescriptorBase<TMessageIds extends string> { 123 /** 124 * The parameters for the message string associated with `messageId`. 125 */ 126 readonly data?: Readonly<Record<string, unknown>>; 127 /** 128 * The fixer function. 129 */ 130 readonly fix?: ReportFixFunction | null; 131 /** 132 * The messageId which is being reported. 133 */ 134 readonly messageId: TMessageIds; 135 136 // we disallow this because it's much better to use messageIds for reusable errors that are easily testable 137 // readonly desc?: string; 138} 139interface ReportDescriptorWithSuggestion<TMessageIds extends string> 140 extends ReportDescriptorBase<TMessageIds> { 141 /** 142 * 6.7's Suggestions API 143 */ 144 readonly suggest?: Readonly<ReportSuggestionArray<TMessageIds>> | null; 145} 146 147interface ReportDescriptorNodeOptionalLoc { 148 /** 149 * The Node or AST Token which the report is being attached to 150 */ 151 readonly node: TSESTree.Node | TSESTree.Comment | TSESTree.Token; 152 /** 153 * An override of the location of the report 154 */ 155 readonly loc?: 156 | Readonly<TSESTree.SourceLocation> 157 | Readonly<TSESTree.LineAndColumnData>; 158} 159interface ReportDescriptorLocOnly { 160 /** 161 * An override of the location of the report 162 */ 163 loc: Readonly<TSESTree.SourceLocation> | Readonly<TSESTree.LineAndColumnData>; 164} 165type ReportDescriptor< 166 TMessageIds extends string 167> = ReportDescriptorWithSuggestion<TMessageIds> & 168 (ReportDescriptorNodeOptionalLoc | ReportDescriptorLocOnly); 169 170interface RuleContext< 171 TMessageIds extends string, 172 TOptions extends readonly unknown[] 173> { 174 /** 175 * The rule ID. 176 */ 177 id: string; 178 /** 179 * An array of the configured options for this rule. 180 * This array does not include the rule severity. 181 */ 182 options: TOptions; 183 /** 184 * The name of the parser from configuration. 185 */ 186 parserPath: string; 187 /** 188 * The parser options configured for this run 189 */ 190 parserOptions: Linter.ParserOptions; 191 /** 192 * An object containing parser-provided services for rules 193 */ 194 parserServices?: ParserServices; 195 /** 196 * The shared settings from configuration. 197 * We do not have any shared settings in this plugin. 198 */ 199 settings: Record<string, unknown>; 200 201 /** 202 * Returns an array of the ancestors of the currently-traversed node, starting at 203 * the root of the AST and continuing through the direct parent of the current node. 204 * This array does not include the currently-traversed node itself. 205 */ 206 getAncestors(): TSESTree.Node[]; 207 208 /** 209 * Returns a list of variables declared by the given node. 210 * This information can be used to track references to variables. 211 */ 212 getDeclaredVariables(node: TSESTree.Node): Scope.Variable[]; 213 214 /** 215 * Returns the filename associated with the source. 216 */ 217 getFilename(): string; 218 219 /** 220 * Returns the scope of the currently-traversed node. 221 * This information can be used track references to variables. 222 */ 223 getScope(): Scope.Scope; 224 225 /** 226 * Returns a SourceCode object that you can use to work with the source that 227 * was passed to ESLint. 228 */ 229 getSourceCode(): Readonly<SourceCode>; 230 231 /** 232 * Marks a variable with the given name in the current scope as used. 233 * This affects the no-unused-vars rule. 234 */ 235 markVariableAsUsed(name: string): boolean; 236 237 /** 238 * Reports a problem in the code. 239 */ 240 report(descriptor: ReportDescriptor<TMessageIds>): void; 241} 242 243// This isn't the correct signature, but it makes it easier to do custom unions within reusable listeners 244// never will break someone's code unless they specifically type the function argument 245type RuleFunction<T extends TSESTree.BaseNode = never> = (node: T) => void; 246 247interface RuleListener { 248 [nodeSelector: string]: RuleFunction | undefined; 249 ArrayExpression?: RuleFunction<TSESTree.ArrayExpression>; 250 ArrayPattern?: RuleFunction<TSESTree.ArrayPattern>; 251 ArrowFunctionExpression?: RuleFunction<TSESTree.ArrowFunctionExpression>; 252 AssignmentPattern?: RuleFunction<TSESTree.AssignmentPattern>; 253 AssignmentExpression?: RuleFunction<TSESTree.AssignmentExpression>; 254 AwaitExpression?: RuleFunction<TSESTree.AwaitExpression>; 255 BigIntLiteral?: RuleFunction<TSESTree.BigIntLiteral>; 256 BinaryExpression?: RuleFunction<TSESTree.BinaryExpression>; 257 BlockStatement?: RuleFunction<TSESTree.BlockStatement>; 258 BreakStatement?: RuleFunction<TSESTree.BreakStatement>; 259 CallExpression?: RuleFunction<TSESTree.CallExpression>; 260 CatchClause?: RuleFunction<TSESTree.CatchClause>; 261 ChainExpression?: RuleFunction<TSESTree.ChainExpression>; 262 ClassBody?: RuleFunction<TSESTree.ClassBody>; 263 ClassDeclaration?: RuleFunction<TSESTree.ClassDeclaration>; 264 ClassExpression?: RuleFunction<TSESTree.ClassExpression>; 265 ClassProperty?: RuleFunction<TSESTree.ClassProperty>; 266 Comment?: RuleFunction<TSESTree.Comment>; 267 ConditionalExpression?: RuleFunction<TSESTree.ConditionalExpression>; 268 ContinueStatement?: RuleFunction<TSESTree.ContinueStatement>; 269 DebuggerStatement?: RuleFunction<TSESTree.DebuggerStatement>; 270 Decorator?: RuleFunction<TSESTree.Decorator>; 271 DoWhileStatement?: RuleFunction<TSESTree.DoWhileStatement>; 272 EmptyStatement?: RuleFunction<TSESTree.EmptyStatement>; 273 ExportAllDeclaration?: RuleFunction<TSESTree.ExportAllDeclaration>; 274 ExportDefaultDeclaration?: RuleFunction<TSESTree.ExportDefaultDeclaration>; 275 ExportNamedDeclaration?: RuleFunction<TSESTree.ExportNamedDeclaration>; 276 ExportSpecifier?: RuleFunction<TSESTree.ExportSpecifier>; 277 ExpressionStatement?: RuleFunction<TSESTree.ExpressionStatement>; 278 ForInStatement?: RuleFunction<TSESTree.ForInStatement>; 279 ForOfStatement?: RuleFunction<TSESTree.ForOfStatement>; 280 ForStatement?: RuleFunction<TSESTree.ForStatement>; 281 FunctionDeclaration?: RuleFunction<TSESTree.FunctionDeclaration>; 282 FunctionExpression?: RuleFunction<TSESTree.FunctionExpression>; 283 Identifier?: RuleFunction<TSESTree.Identifier>; 284 IfStatement?: RuleFunction<TSESTree.IfStatement>; 285 ImportDeclaration?: RuleFunction<TSESTree.ImportDeclaration>; 286 ImportDefaultSpecifier?: RuleFunction<TSESTree.ImportDefaultSpecifier>; 287 ImportExpression?: RuleFunction<TSESTree.ImportExpression>; 288 ImportNamespaceSpecifier?: RuleFunction<TSESTree.ImportNamespaceSpecifier>; 289 ImportSpecifier?: RuleFunction<TSESTree.ImportSpecifier>; 290 JSXAttribute?: RuleFunction<TSESTree.JSXAttribute>; 291 JSXClosingElement?: RuleFunction<TSESTree.JSXClosingElement>; 292 JSXClosingFragment?: RuleFunction<TSESTree.JSXClosingFragment>; 293 JSXElement?: RuleFunction<TSESTree.JSXElement>; 294 JSXEmptyExpression?: RuleFunction<TSESTree.JSXEmptyExpression>; 295 JSXExpressionContainer?: RuleFunction<TSESTree.JSXExpressionContainer>; 296 JSXFragment?: RuleFunction<TSESTree.JSXFragment>; 297 JSXIdentifier?: RuleFunction<TSESTree.JSXIdentifier>; 298 JSXMemberExpression?: RuleFunction<TSESTree.JSXMemberExpression>; 299 JSXOpeningElement?: RuleFunction<TSESTree.JSXOpeningElement>; 300 JSXOpeningFragment?: RuleFunction<TSESTree.JSXOpeningFragment>; 301 JSXSpreadAttribute?: RuleFunction<TSESTree.JSXSpreadAttribute>; 302 JSXSpreadChild?: RuleFunction<TSESTree.JSXSpreadChild>; 303 JSXText?: RuleFunction<TSESTree.JSXText>; 304 LabeledStatement?: RuleFunction<TSESTree.LabeledStatement>; 305 Literal?: RuleFunction<TSESTree.Literal>; 306 LogicalExpression?: RuleFunction<TSESTree.LogicalExpression>; 307 MemberExpression?: RuleFunction<TSESTree.MemberExpression>; 308 MetaProperty?: RuleFunction<TSESTree.MetaProperty>; 309 MethodDefinition?: RuleFunction<TSESTree.MethodDefinition>; 310 NewExpression?: RuleFunction<TSESTree.NewExpression>; 311 ObjectExpression?: RuleFunction<TSESTree.ObjectExpression>; 312 ObjectPattern?: RuleFunction<TSESTree.ObjectPattern>; 313 Program?: RuleFunction<TSESTree.Program>; 314 Property?: RuleFunction<TSESTree.Property>; 315 RestElement?: RuleFunction<TSESTree.RestElement>; 316 ReturnStatement?: RuleFunction<TSESTree.ReturnStatement>; 317 SequenceExpression?: RuleFunction<TSESTree.SequenceExpression>; 318 SpreadElement?: RuleFunction<TSESTree.SpreadElement>; 319 Super?: RuleFunction<TSESTree.Super>; 320 SwitchCase?: RuleFunction<TSESTree.SwitchCase>; 321 SwitchStatement?: RuleFunction<TSESTree.SwitchStatement>; 322 TaggedTemplateExpression?: RuleFunction<TSESTree.TaggedTemplateExpression>; 323 TemplateElement?: RuleFunction<TSESTree.TemplateElement>; 324 TemplateLiteral?: RuleFunction<TSESTree.TemplateLiteral>; 325 ThisExpression?: RuleFunction<TSESTree.ThisExpression>; 326 ThrowStatement?: RuleFunction<TSESTree.ThrowStatement>; 327 Token?: RuleFunction<TSESTree.Token>; 328 TryStatement?: RuleFunction<TSESTree.TryStatement>; 329 TSAbstractClassProperty?: RuleFunction<TSESTree.TSAbstractClassProperty>; 330 TSAbstractKeyword?: RuleFunction<TSESTree.TSAbstractKeyword>; 331 TSAbstractMethodDefinition?: RuleFunction< 332 TSESTree.TSAbstractMethodDefinition 333 >; 334 TSAnyKeyword?: RuleFunction<TSESTree.TSAnyKeyword>; 335 TSArrayType?: RuleFunction<TSESTree.TSArrayType>; 336 TSAsExpression?: RuleFunction<TSESTree.TSAsExpression>; 337 TSAsyncKeyword?: RuleFunction<TSESTree.TSAsyncKeyword>; 338 TSBigIntKeyword?: RuleFunction<TSESTree.TSBigIntKeyword>; 339 TSBooleanKeyword?: RuleFunction<TSESTree.TSBooleanKeyword>; 340 TSCallSignatureDeclaration?: RuleFunction< 341 TSESTree.TSCallSignatureDeclaration 342 >; 343 TSClassImplements?: RuleFunction<TSESTree.TSClassImplements>; 344 TSConditionalType?: RuleFunction<TSESTree.TSConditionalType>; 345 TSConstructorType?: RuleFunction<TSESTree.TSConstructorType>; 346 TSConstructSignatureDeclaration?: RuleFunction< 347 TSESTree.TSConstructSignatureDeclaration 348 >; 349 TSDeclareKeyword?: RuleFunction<TSESTree.TSDeclareKeyword>; 350 TSDeclareFunction?: RuleFunction<TSESTree.TSDeclareFunction>; 351 TSEmptyBodyFunctionExpression?: RuleFunction< 352 TSESTree.TSEmptyBodyFunctionExpression 353 >; 354 TSEnumDeclaration?: RuleFunction<TSESTree.TSEnumDeclaration>; 355 TSEnumMember?: RuleFunction<TSESTree.TSEnumMember>; 356 TSExportAssignment?: RuleFunction<TSESTree.TSExportAssignment>; 357 TSExportKeyword?: RuleFunction<TSESTree.TSExportKeyword>; 358 TSExternalModuleReference?: RuleFunction<TSESTree.TSExternalModuleReference>; 359 TSFunctionType?: RuleFunction<TSESTree.TSFunctionType>; 360 TSImportEqualsDeclaration?: RuleFunction<TSESTree.TSImportEqualsDeclaration>; 361 TSImportType?: RuleFunction<TSESTree.TSImportType>; 362 TSIndexedAccessType?: RuleFunction<TSESTree.TSIndexedAccessType>; 363 TSIndexSignature?: RuleFunction<TSESTree.TSIndexSignature>; 364 TSInferType?: RuleFunction<TSESTree.TSInferType>; 365 TSInterfaceBody?: RuleFunction<TSESTree.TSInterfaceBody>; 366 TSInterfaceDeclaration?: RuleFunction<TSESTree.TSInterfaceDeclaration>; 367 TSInterfaceHeritage?: RuleFunction<TSESTree.TSInterfaceHeritage>; 368 TSIntersectionType?: RuleFunction<TSESTree.TSIntersectionType>; 369 TSLiteralType?: RuleFunction<TSESTree.TSLiteralType>; 370 TSMappedType?: RuleFunction<TSESTree.TSMappedType>; 371 TSMethodSignature?: RuleFunction<TSESTree.TSMethodSignature>; 372 TSModuleBlock?: RuleFunction<TSESTree.TSModuleBlock>; 373 TSModuleDeclaration?: RuleFunction<TSESTree.TSModuleDeclaration>; 374 TSNamespaceExportDeclaration?: RuleFunction< 375 TSESTree.TSNamespaceExportDeclaration 376 >; 377 TSNeverKeyword?: RuleFunction<TSESTree.TSNeverKeyword>; 378 TSNonNullExpression?: RuleFunction<TSESTree.TSNonNullExpression>; 379 TSNullKeyword?: RuleFunction<TSESTree.TSNullKeyword>; 380 TSNumberKeyword?: RuleFunction<TSESTree.TSNumberKeyword>; 381 TSObjectKeyword?: RuleFunction<TSESTree.TSObjectKeyword>; 382 TSOptionalType?: RuleFunction<TSESTree.TSOptionalType>; 383 TSParameterProperty?: RuleFunction<TSESTree.TSParameterProperty>; 384 TSParenthesizedType?: RuleFunction<TSESTree.TSParenthesizedType>; 385 TSPrivateKeyword?: RuleFunction<TSESTree.TSPrivateKeyword>; 386 TSPropertySignature?: RuleFunction<TSESTree.TSPropertySignature>; 387 TSProtectedKeyword?: RuleFunction<TSESTree.TSProtectedKeyword>; 388 TSPublicKeyword?: RuleFunction<TSESTree.TSPublicKeyword>; 389 TSQualifiedName?: RuleFunction<TSESTree.TSQualifiedName>; 390 TSReadonlyKeyword?: RuleFunction<TSESTree.TSReadonlyKeyword>; 391 TSRestType?: RuleFunction<TSESTree.TSRestType>; 392 TSStaticKeyword?: RuleFunction<TSESTree.TSStaticKeyword>; 393 TSStringKeyword?: RuleFunction<TSESTree.TSStringKeyword>; 394 TSSymbolKeyword?: RuleFunction<TSESTree.TSSymbolKeyword>; 395 TSThisType?: RuleFunction<TSESTree.TSThisType>; 396 TSTupleType?: RuleFunction<TSESTree.TSTupleType>; 397 TSTypeAliasDeclaration?: RuleFunction<TSESTree.TSTypeAliasDeclaration>; 398 TSTypeAnnotation?: RuleFunction<TSESTree.TSTypeAnnotation>; 399 TSTypeAssertion?: RuleFunction<TSESTree.TSTypeAssertion>; 400 TSTypeLiteral?: RuleFunction<TSESTree.TSTypeLiteral>; 401 TSTypeOperator?: RuleFunction<TSESTree.TSTypeOperator>; 402 TSTypeParameter?: RuleFunction<TSESTree.TSTypeParameter>; 403 TSTypeParameterDeclaration?: RuleFunction< 404 TSESTree.TSTypeParameterDeclaration 405 >; 406 TSTypeParameterInstantiation?: RuleFunction< 407 TSESTree.TSTypeParameterInstantiation 408 >; 409 TSTypePredicate?: RuleFunction<TSESTree.TSTypePredicate>; 410 TSTypeQuery?: RuleFunction<TSESTree.TSTypeQuery>; 411 TSTypeReference?: RuleFunction<TSESTree.TSTypeReference>; 412 TSUndefinedKeyword?: RuleFunction<TSESTree.TSUndefinedKeyword>; 413 TSUnionType?: RuleFunction<TSESTree.TSUnionType>; 414 TSUnknownKeyword?: RuleFunction<TSESTree.TSUnknownKeyword>; 415 TSVoidKeyword?: RuleFunction<TSESTree.TSVoidKeyword>; 416 UnaryExpression?: RuleFunction<TSESTree.UnaryExpression>; 417 UpdateExpression?: RuleFunction<TSESTree.UpdateExpression>; 418 VariableDeclaration?: RuleFunction<TSESTree.VariableDeclaration>; 419 VariableDeclarator?: RuleFunction<TSESTree.VariableDeclarator>; 420 WhileStatement?: RuleFunction<TSESTree.WhileStatement>; 421 WithStatement?: RuleFunction<TSESTree.WithStatement>; 422 YieldExpression?: RuleFunction<TSESTree.YieldExpression>; 423} 424 425interface RuleModule< 426 TMessageIds extends string, 427 TOptions extends readonly unknown[], 428 // for extending base rules 429 TRuleListener extends RuleListener = RuleListener 430> { 431 /** 432 * Metadata about the rule 433 */ 434 meta: RuleMetaData<TMessageIds>; 435 436 /** 437 * Function which returns an object with methods that ESLint calls to “visit” 438 * nodes while traversing the abstract syntax tree. 439 */ 440 create(context: Readonly<RuleContext<TMessageIds, TOptions>>): TRuleListener; 441} 442 443type RuleCreateFunction = ( 444 context: Readonly<RuleContext<never, unknown[]>>, 445) => RuleListener; 446 447export { 448 ReportDescriptor, 449 ReportFixFunction, 450 ReportSuggestionArray, 451 RuleContext, 452 RuleCreateFunction, 453 RuleFix, 454 RuleFixer, 455 RuleFunction, 456 RuleListener, 457 RuleMetaData, 458 RuleMetaDataDocs, 459 RuleModule, 460}; 461