UNPKG

eslint-plugin-svelte

Version:
250 lines (249 loc) 11.2 kB
import type { JSONSchema4 } from 'json-schema'; import type { Linter, Rule, SourceCode as ESLintSourceCode } from 'eslint'; import type { AST, StyleContext, SvelteConfig } from 'svelte-eslint-parser'; import type { TSESTree } from '@typescript-eslint/types'; import type { ScopeManager, Scope, Variable } from '@typescript-eslint/scope-manager'; import type { Rule as StyleRule, Node } from 'postcss'; import type { Root as SelectorRoot, Node as SelectorNode } from 'postcss-selector-parser'; import type { ASTNode, ASTNodeWithParent, ASTNodeListener } from './types-for-node.js'; import type * as TS from 'typescript'; import type { SourceLocation } from 'svelte-eslint-parser/lib/ast/common.js'; import type { SvelteContext } from './utils/svelte-context.js'; export type { ASTNode, ASTNodeWithParent, ASTNodeListener }; export interface RuleListener extends ASTNodeListener { onCodePathStart?(codePath: Rule.CodePath, node: never): void; onCodePathEnd?(codePath: Rule.CodePath, node: never): void; onCodePathSegmentStart?(segment: Rule.CodePathSegment, node: never): void; onCodePathSegmentEnd?(segment: Rule.CodePathSegment, node: never): void; onCodePathSegmentLoop?(fromSegment: Rule.CodePathSegment, toSegment: Rule.CodePathSegment, node: never): void; [key: string]: ((codePath: Rule.CodePath, node: never) => void) | ((segment: Rule.CodePathSegment, node: never) => void) | ((fromSegment: Rule.CodePathSegment, toSegment: Rule.CodePathSegment, node: never) => void) | ASTNodeListener[keyof ASTNodeListener] | ((node: never) => void) | undefined; } export interface RuleModule { meta: RuleMetaData; create: (context: RuleContext) => RuleListener; } export type RuleCategory = 'Possible Errors' | 'Security Vulnerability' | 'Best Practices' | 'Stylistic Issues' | 'Extension Rules' | 'SvelteKit' | 'Experimental' | 'System'; export interface RuleMetaData { docs: { description: string; category: RuleCategory; recommended: boolean | 'base'; extensionRule?: string | { plugin: string; url: string; }; url: string; ruleId: string; ruleName: string; default?: 'error' | 'warn'; conflictWithPrettier?: boolean; }; messages: { [messageId: string]: string; }; fixable?: 'code' | 'whitespace'; hasSuggestions?: boolean; schema: JSONSchema4 | JSONSchema4[]; deprecated?: boolean; replacedBy?: string[] | { note: string; }; type: 'problem' | 'suggestion' | 'layout'; } export interface PartialRuleModule { meta: PartialRuleMetaData; create: (context: RuleContext) => RuleListener; } export interface PartialRuleMetaData { docs: { description: string; recommended: boolean | 'base'; extensionRule?: string | { plugin: string; url: string; }; default?: 'error' | 'warn'; } & ({ category: Exclude<RuleCategory, 'Stylistic Issues'>; conflictWithPrettier?: boolean; } | { category: 'Stylistic Issues'; conflictWithPrettier: boolean; }); messages: { [messageId: string]: string; }; fixable?: 'code' | 'whitespace'; hasSuggestions?: boolean; schema: JSONSchema4 | JSONSchema4[]; deprecated?: boolean; replacedBy?: string[] | { note: string; }; type: 'problem' | 'suggestion' | 'layout'; /** * Conditions to determine whether this rule should be applied. * Multiple conditions can be specified as array, and the rule will be applied if any one of them matches (logical OR). * If not specified, the rule will be applied to all files. */ conditions?: { svelteVersions?: SvelteContext['svelteVersion'][]; svelteFileTypes?: SvelteContext['svelteFileType'][]; runes?: SvelteContext['runes'][]; svelteKitVersions?: SvelteContext['svelteKitVersion'][]; svelteKitFileTypes?: SvelteContext['svelteKitFileType'][]; }[]; } export type RuleContext = { id: string; options: any[]; settings?: { svelte?: { ignoreWarnings?: unknown; compileOptions?: { babel?: boolean; postcss?: false | { configFilePath?: unknown; }; }; kit?: { files?: { routes?: string; }; }; }; }; parserPath: string; parserOptions: Linter.ParserOptions; parserServices: ESLintSourceCode.ParserServices; getAncestors(): ASTNode[]; getDeclaredVariables(node: TSESTree.Node): Variable[]; filename: string; getScope(): Scope; sourceCode: SourceCode; markVariableAsUsed(name: string): boolean; report(descriptor: ReportDescriptor): void; cwd?: string; physicalFilename: string; }; export type NodeOrToken = { type: string; loc?: AST.SourceLocation | null; range?: [number, number]; }; interface ReportDescriptorOptionsBase { data?: { [key: string]: string; }; fix?: null | ((fixer: RuleFixer) => null | Rule.Fix | IterableIterator<Rule.Fix> | Rule.Fix[]); } type SuggestionDescriptorMessage = { desc: string; } | { messageId: string; }; export type SuggestionReportDescriptor = SuggestionDescriptorMessage & ReportDescriptorOptionsBase; interface ReportDescriptorOptions extends ReportDescriptorOptionsBase { suggest?: SuggestionReportDescriptor[] | null; } type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions; type ReportDescriptorMessage = { message: string; } | { messageId: string; }; type ReportDescriptorLocation = { node: NodeOrToken; } | { loc: AST.SourceLocation | { line: number; column: number; }; }; export interface RuleFixer { insertTextAfter(nodeOrToken: NodeOrToken, text: string): Rule.Fix; insertTextAfterRange(range: AST.Range, text: string): Rule.Fix; insertTextBefore(nodeOrToken: NodeOrToken, text: string): Rule.Fix; insertTextBeforeRange(range: AST.Range, text: string): Rule.Fix; remove(nodeOrToken: NodeOrToken): Rule.Fix; removeRange(range: AST.Range): Rule.Fix; replaceText(nodeOrToken: NodeOrToken, text: string): Rule.Fix; replaceTextRange(range: AST.Range, text: string): Rule.Fix; } export declare namespace SourceCode { function splitLines(text: string): string[]; } export interface SourceCode { text: string; ast: AST.SvelteProgram; lines: string[]; hasBOM: boolean; parserServices: { isSvelte?: boolean; isSvelteScript?: boolean; getSvelteHtmlAst?: () => unknown; getStyleContext?: () => StyleContext; getStyleSelectorAST?: (rule: StyleRule) => SelectorRoot; styleNodeLoc?: (node: Node) => Partial<SourceLocation>; styleNodeRange?: (node: Node) => [number | undefined, number | undefined]; styleSelectorNodeLoc?: (node: SelectorNode) => Partial<SourceLocation>; svelteParseContext?: { /** * Whether to use Runes mode. * May be `true` if the user is using Svelte v5. * Resolved from `svelte.config.js` or `parserOptions`, but may be overridden by `<svelte:options>`. */ runes?: boolean; /** The version of "svelte/compiler". */ compilerVersion?: string; /** The result of static analysis of `svelte.config.js`. */ svelteConfig?: SvelteConfig | null; }; program?: TS.Program; esTreeNodeToTSNodeMap?: ReadonlyMap<unknown, TS.Node>; tsNodeToESTreeNodeMap?: ReadonlyMap<TS.Node, ASTNode>; hasFullTypeInformation?: boolean; [key: string]: unknown; }; scopeManager: ScopeManager; visitorKeys: ESLintSourceCode.VisitorKeys; getText(node?: NodeOrToken, beforeCount?: number, afterCount?: number): string; getLines(): string[]; getDeclaredVariables(node: TSESTree.Node): Variable[]; getAllComments(): AST.Comment[]; getComments(node: NodeOrToken): { leading: AST.Comment[]; trailing: AST.Comment[]; }; getJSDocComment(node: NodeOrToken): AST.Comment | null; getNodeByRangeIndex(index: number): ASTNodeWithParent | null; isSpaceBetweenTokens(first: AST.Token, second: AST.Token): boolean; getLocFromIndex(index: number): AST.Position; getIndexFromLoc(location: AST.Position): number; getTokenByRangeStart(offset: number, options?: { includeComments?: boolean; }): AST.Token | AST.Comment | null; getFirstToken(node: NodeOrToken): AST.Token; getFirstToken(node: NodeOrToken, options?: Parameters<ESLintSourceCode['getFirstToken']>[1]): AST.Token | AST.Comment | null; getFirstTokens(node: NodeOrToken, options?: Parameters<ESLintSourceCode['getFirstTokens']>[1]): (AST.Token | AST.Comment)[]; getLastToken(node: NodeOrToken): AST.Token; getLastToken(node: NodeOrToken, options?: Parameters<ESLintSourceCode['getLastToken']>[1]): AST.Token | AST.Comment | null; getLastTokens(node: NodeOrToken, options?: Parameters<ESLintSourceCode['getLastTokens']>[1]): (AST.Token | AST.Comment)[]; getTokenBefore(node: NodeOrToken): AST.Token | null; getTokenBefore(node: NodeOrToken, options?: Parameters<ESLintSourceCode['getTokenBefore']>[1]): AST.Token | AST.Comment | null; getTokensBefore(node: NodeOrToken, options?: Parameters<ESLintSourceCode['getTokensBefore']>[1]): (AST.Token | AST.Comment)[]; getTokenAfter(node: NodeOrToken): AST.Token | null; getTokenAfter(node: NodeOrToken, options?: Parameters<ESLintSourceCode['getTokenAfter']>[1]): AST.Token | AST.Comment | null; getTokensAfter(node: NodeOrToken, options?: Parameters<ESLintSourceCode['getTokensAfter']>[1]): (AST.Token | AST.Comment)[]; getFirstTokenBetween(left: NodeOrToken, right: NodeOrToken, options?: Parameters<ESLintSourceCode['getFirstTokenBetween']>[2]): AST.Token | AST.Comment | null; getFirstTokensBetween(left: NodeOrToken, right: NodeOrToken, options?: Parameters<ESLintSourceCode['getFirstTokensBetween']>[2]): (AST.Token | AST.Comment)[]; getLastTokenBetween(left: NodeOrToken, right: NodeOrToken, options?: Parameters<ESLintSourceCode['getLastTokenBetween']>[2]): AST.Token | AST.Comment | null; getLastTokensBetween(left: NodeOrToken, right: NodeOrToken, options?: Parameters<ESLintSourceCode['getLastTokensBetween']>[2]): (AST.Token | AST.Comment)[]; getTokensBetween(left: NodeOrToken, right: NodeOrToken, padding?: Parameters<ESLintSourceCode['getTokensBetween']>[2]): (AST.Token | AST.Comment)[]; getTokens(node: NodeOrToken, beforeCount?: number, afterCount?: number): AST.Token[]; getTokens(node: NodeOrToken, options: Parameters<ESLintSourceCode['getTokens']>[1]): (AST.Token | AST.Comment)[]; commentsExistBetween(left: NodeOrToken, right: NodeOrToken): boolean; getCommentsBefore(nodeOrToken: NodeOrToken | AST.Token): AST.Comment[]; getCommentsAfter(nodeOrToken: NodeOrToken | AST.Token): AST.Comment[]; getCommentsInside(node: NodeOrToken): AST.Comment[]; }