import { Linter } from "eslint";

//#region src/types.d.ts
type Awaitable<T> = Promise<T> | T;
interface ValidTestCaseBase<RuleOptions = any, MessageId extends string = string> extends CompatConfigOptions, RuleTesterBehaviorOptions {
  name?: string;
  description?: string;
  code: string;
  options?: RuleOptions;
  filename?: string;
  only?: boolean;
  skip?: boolean;
  before?: (this: NormalizedTestCase<RuleOptions, MessageId>, configs: Linter.Config[]) => Awaitable<void>;
  after?: (this: NormalizedTestCase<RuleOptions, MessageId>, result: Linter.FixReport) => Awaitable<void>;
  /**
   * @deprecated Use `after` instead
   */
  onResult?: (result: Linter.FixReport) => void;
}
type TestCaseError<MessageId extends string = string> = Partial<Linter.LintMessage> & {
  /**
   * Data for interpolate the error message
   */
  data?: Record<string, any>;
  /**
   * Alias to `nodeType`
   * @deprecated `nodeType` is deprecated and will be removed in the next major version.
   */
  type?: string;
  messageId?: MessageId;
};
interface InvalidTestCaseBase<RuleOptions = any, MessageId extends string = string> extends ValidTestCaseBase<RuleOptions, MessageId> {
  /**
   * Expected errors.
   * If a number is provided, it asserts that the number of errors is equal to the number provided.
   * If an array of strings is provided, it asserts that the error messageIds are equal to the array provided.
   * If an array of objects is provided, it asserts that the errors are partially equal to the objects provided.
   */
  errors?: number | (MessageId | TestCaseError<MessageId>)[] | ((errors: Linter.LintMessage[]) => Awaitable<void>);
  /**
   * Assert if output is expected.
   * Pass `null` to assert that the output is the same as the input.
   */
  output?: string | null | ((output: string, input: string) => Awaitable<void>);
}
interface NormalizedTestCase<RuleOptions = any, MessageId extends string = string> extends InvalidTestCaseBase<RuleOptions, MessageId> {
  type: 'valid' | 'invalid';
  code: string;
}
type InvalidTestCase<RuleOptions = any, MessageId extends string = string> = InvalidTestCaseBase<RuleOptions, MessageId> | string;
type ValidTestCase<RuleOptions = any> = ValidTestCaseBase<RuleOptions> | string;
type TestCase<RuleOptions = any, MessageId extends string = string> = ValidTestCase<RuleOptions> | InvalidTestCase<RuleOptions, MessageId>;
interface TestExecutionResult extends Linter.FixReport {
  /**
   * If the rule fixes in multiple steps, each step will be present here
   */
  steps: Linter.FixReport[];
}
interface CompatConfigOptions {
  parserOptions?: Linter.ParserOptions;
  parser?: Linter.Parser;
  languageOptions?: Linter.Config['languageOptions'];
  linterOptions?: Linter.Config['linterOptions'];
  settings?: Linter.Config['settings'];
  processor?: Linter.Config['processor'];
  files?: Linter.Config['files'];
}
type RuleModule = any;
interface RuleTester<RuleOptions = any, MessageId extends string = string> {
  /**
   * Run a single test case
   */
  each: (arg: TestCase<RuleOptions, MessageId>) => Promise<{
    testcase: NormalizedTestCase<RuleOptions, MessageId>;
    result: TestExecutionResult;
  }>;
  /**
   * Run a single valid test case
   */
  valid: (arg: ValidTestCase<RuleOptions>) => Promise<{
    testcase: NormalizedTestCase<RuleOptions, MessageId>;
    result: TestExecutionResult;
  }>;
  /**
   * Run a single invalid test case
   */
  invalid: (arg: InvalidTestCase<RuleOptions, MessageId>) => Promise<{
    testcase: NormalizedTestCase<RuleOptions, MessageId>;
    result: TestExecutionResult;
  }>;
  /**
   * ESLint's RuleTester style test runner, that runs multiple test cases
   */
  run: (options: TestCasesOptions<RuleOptions, MessageId>) => Promise<void>;
}
interface RuleTesterBehaviorOptions {
  /**
   * The number of times to recursively apply the rule
   * @default 10
   */
  recursive?: number | false;
  /**
   * Run verification after applying the fix
   * @default true
   */
  verifyAfterFix?: boolean;
  /**
   * Verify that fix allways changes the code
   * @default true
   */
  verifyFixChanges?: boolean;
}
interface DefaultFilenames {
  js: string;
  jsx: string;
  ts: string;
  tsx: string;
}
interface RuleTesterInitOptions extends CompatConfigOptions, RuleTesterBehaviorOptions {
  /**
   * The rule to test
   */
  rule?: RuleModule;
  /**
   * The name of the rule to test
   */
  name?: string;
  /**
   * Additional flat configs to be merged with the rule config
   */
  configs?: Linter.Config | Linter.Config[];
  /**
   * The default filenames to use for type-aware tests.
   * @default { js: 'file.js', jsx: 'file.jsx', ts: 'file.ts', tsx: 'file.tsx' }
   */
  defaultFilenames?: Partial<DefaultFilenames>;
}
interface TestCasesOptions<RuleOptions = any, MessageId extends string = string> {
  valid?: (ValidTestCase<RuleOptions> | string)[];
  invalid?: (InvalidTestCase<RuleOptions, MessageId> | string)[];
  /**
   * Callback to be called after each test case
   */
  onResult?: (_case: NormalizedTestCase<RuleOptions, MessageId>, result: Linter.FixReport) => void | Promise<void>;
}
//#endregion
//#region src/options.d.ts
declare function pickFlatConfigFromOptions(options: CompatConfigOptions): Linter.Config | undefined;
//#endregion
//#region src/rule-tester.d.ts
declare function createRuleTester<RuleOptions = any, MessageId extends string = string>(options: RuleTesterInitOptions): RuleTester<RuleOptions, MessageId>;
//#endregion
//#region src/run.d.ts
/**
 * Shortcut to run test cases for a rule
 */
declare function run<RuleOptions = any, MessageId extends string = string>(options: TestCasesOptions<RuleOptions, MessageId> & RuleTesterInitOptions): Promise<void>;
/**
 * Shortcut to run test cases for a rule in classic style
 */
declare function runClassic<RuleOptions = any, MessageId extends string = string>(ruleName: string, rule: RuleModule, cases: TestCasesOptions<RuleOptions, MessageId>, options?: RuleTesterInitOptions): Promise<void>;
//#endregion
//#region node_modules/.pnpm/@antfu+utils@9.3.0/node_modules/@antfu/utils/dist/index.d.mts

/**
 * Remove common leading whitespace from a template string.
 * Will also remove empty lines at the beginning and end.
 * @category string
 * @example
 * ```ts
 * const str = unindent`
 *   if (a) {
 *     b()
 *   }
 * `
 */
declare function unindent(str: TemplateStringsArray | string): string;
//#endregion
//#region src/utils.d.ts
declare function normalizeTestCase<RuleOptions = any, MessageId extends string = string>(c: TestCase<RuleOptions, MessageId>, languageOptions: Linter.Config['languageOptions'], defaultFilenames: DefaultFilenames, type?: 'valid' | 'invalid'): NormalizedTestCase<RuleOptions, MessageId>;
declare function normalizeCaseError<MessageId extends string = string>(error: TestCaseError<MessageId> | MessageId, rule?: RuleModule): Partial<Linter.LintMessage>;
declare function isUsingTypeScriptParser(languageOptions: Linter.LanguageOptions): boolean;
declare function isUsingTypeScriptTypings(languageOptions: Linter.LanguageOptions): boolean;
//#endregion
export { unindent as $, unindent, type Awaitable, CompatConfigOptions, DefaultFilenames, InvalidTestCase, InvalidTestCaseBase, NormalizedTestCase, RuleModule, RuleTester, RuleTesterBehaviorOptions, RuleTesterInitOptions, TestCase, TestCaseError, TestCasesOptions, TestExecutionResult, ValidTestCase, ValidTestCaseBase, createRuleTester, isUsingTypeScriptParser, isUsingTypeScriptTypings, normalizeCaseError, normalizeTestCase, pickFlatConfigFromOptions, run, runClassic };