import { TestFramework } from '../../test_framework';
import { TestRunner } from '../../test_runner';
import { Reporter } from '../../report';
import { Mutator } from '../../mutant';
import { Transpiler } from '../../transpile';
import { ConfigEditor } from '../../config';
import { PluginContexts } from './Contexts';
import { InjectionToken, InjectableClass, InjectableFunction } from 'typed-inject';
import { PluginKind } from './PluginKind';
/**
 * Represents a StrykerPlugin
 */
export declare type Plugin<TPluginKind extends PluginKind, Tokens extends InjectionToken<PluginContexts[TPluginKind]>[]> = FactoryPlugin<TPluginKind, Tokens> | ClassPlugin<TPluginKind, Tokens>;
/**
 * Represents a plugin that is created with a factory method
 */
export interface FactoryPlugin<TPluginKind extends PluginKind, Tokens extends InjectionToken<PluginContexts[TPluginKind]>[]> {
    readonly kind: TPluginKind;
    readonly name: string;
    /**
     * The factory method used to create the plugin
     */
    readonly factory: InjectableFunction<PluginContexts[TPluginKind], PluginInterfaces[TPluginKind], Tokens>;
}
/**
 * Represents a plugin that is created by instantiating a class.
 */
export interface ClassPlugin<TPluginKind extends PluginKind, Tokens extends InjectionToken<PluginContexts[TPluginKind]>[]> {
    readonly kind: TPluginKind;
    readonly name: string;
    readonly injectableClass: InjectableClass<PluginContexts[TPluginKind], PluginInterfaces[TPluginKind], Tokens>;
}
/**
 * Declare a class plugin. Use this method in order to type check the dependency graph of your plugin
 * @param kind The plugin kind
 * @param name The name of the plugin
 * @param injectableClass The class to be instantiated for the plugin
 */
export declare function declareClassPlugin<TPluginKind extends PluginKind, Tokens extends InjectionToken<PluginContexts[TPluginKind]>[]>(kind: TPluginKind, name: string, injectableClass: InjectableClass<PluginContexts[TPluginKind], PluginInterfaces[TPluginKind], Tokens>): ClassPlugin<TPluginKind, Tokens>;
/**
 * Declare a factory plugin. Use this method in order to type check the dependency graph of your plugin,
 * @param kind The plugin kind
 * @param name The name of the plugin
 * @param factory The factory used to instantiate the plugin
 */
export declare function declareFactoryPlugin<TPluginKind extends PluginKind, Tokens extends InjectionToken<PluginContexts[TPluginKind]>[]>(kind: TPluginKind, name: string, factory: InjectableFunction<PluginContexts[TPluginKind], PluginInterfaces[TPluginKind], Tokens>): FactoryPlugin<TPluginKind, Tokens>;
/**
 * Lookup type for plugin interfaces by kind.
 */
export interface PluginInterfaces {
    [PluginKind.ConfigEditor]: ConfigEditor;
    [PluginKind.Mutator]: Mutator;
    [PluginKind.Reporter]: Reporter;
    [PluginKind.TestFramework]: TestFramework;
    [PluginKind.TestRunner]: TestRunner;
    [PluginKind.Transpiler]: Transpiler;
}
/**
 * Lookup type for plugins by kind.
 */
export declare type Plugins = {
    [TPluginKind in keyof PluginInterfaces]: Plugin<TPluginKind, InjectionToken<PluginContexts[TPluginKind]>[]>;
};
/**
 * Plugin resolver responsible to load plugins
 */
export interface PluginResolver {
    resolve<T extends keyof Plugins>(kind: T, name: string): Plugins[T];
    resolveAll<T extends keyof Plugins>(kind: T): Plugins[T][];
}
//# sourceMappingURL=Plugins.d.ts.map