Skip to content

Commit

Permalink
feat(api): remove support for options editors
Browse files Browse the repository at this point in the history
Remove support for `OptionEditor` plugin types. Plugins are now expected to read their own config, from whatever source they want, in their own respective lifecycle.

`OptionsEditor`s (and `ConfigEditor`s before that) provided a way to edit stryker configuration after it was read from disk, but before mutation testing starts. This sounded good at first, but the very nature if OptionsEditors meant that users cannot disable them. They are also limited, because the configuration that is read from disk also needs to be serializable if you want it to end up in your x.y.z. plugin. It was also not great for maintainability.

Stryker's core plugins (`@stryker-mutator/...`) quitely moved away from using the `OptionEditor` API and we are now finally ready to pull the plugin on it once and for all.
  • Loading branch information
nicojs committed Jul 10, 2020
1 parent 3ca89cf commit 5e56d0e
Show file tree
Hide file tree
Showing 14 changed files with 27 additions and 265 deletions.
9 changes: 0 additions & 9 deletions packages/api/src/config/Config.ts

This file was deleted.

25 changes: 0 additions & 25 deletions packages/api/src/config/ConfigEditor.ts

This file was deleted.

22 changes: 0 additions & 22 deletions packages/api/src/core/OptionsEditor.ts

This file was deleted.

32 changes: 16 additions & 16 deletions packages/api/test/unit/plugin/Plugins.spec.ts
Expand Up @@ -4,42 +4,42 @@ import { declareClassPlugin, declareFactoryPlugin } from '../../../src/plugin/Pl
import { PluginKind } from '../../../src/plugin/PluginKind';
import { tokens, commonTokens } from '../../../src/plugin/tokens';
import { Logger } from '../../../logging';
import { Mutant } from '../../../core';
import { MutantResult } from '../../../report';

describe('plugins', () => {
describe(declareClassPlugin.name, () => {
it('should declare a class plugin', () => {
class MyMutator {
class MyReporter {
constructor(private readonly log: Logger) {}
public static inject = tokens(commonTokens.logger);

public mutate(): readonly Mutant[] {
this.log.info('');
return [];
public onMutantTested(result: MutantResult) {
this.log.info(JSON.stringify(result));
}
}
expect(declareClassPlugin(PluginKind.Mutator, 'mut', MyMutator)).deep.eq({
injectableClass: MyMutator,
kind: PluginKind.Mutator,
name: 'mut',
expect(declareClassPlugin(PluginKind.Reporter, 'rep', MyReporter)).deep.eq({
injectableClass: MyReporter,
kind: PluginKind.Reporter,
name: 'rep',
});
});
});

describe(declareFactoryPlugin.name, () => {
it('should declare a factory plugin', () => {
function myMutator() {
function createReporter(log: Logger) {
return {
mutate(): readonly Mutant[] {
return [];
onMutantTested(result: MutantResult) {
log.info(JSON.stringify(result));
},
};
}
createReporter.inject = tokens(commonTokens.logger);

expect(declareFactoryPlugin(PluginKind.Mutator, 'mut', myMutator)).deep.eq({
factory: myMutator,
kind: PluginKind.Mutator,
name: 'mut',
expect(declareFactoryPlugin(PluginKind.Reporter, 'rep', createReporter)).deep.eq({
factory: createReporter,
kind: PluginKind.Reporter,
name: 'rep',
});
});
});
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/config/ConfigReader.ts
@@ -1,6 +1,5 @@
import * as path from 'path';

import { Config } from '@stryker-mutator/api/config';
import { PartialStrykerOptions } from '@stryker-mutator/api/core';
import { StrykerOptions } from '@stryker-mutator/api/core';
import { Logger } from '@stryker-mutator/api/logging';
Expand Down Expand Up @@ -45,8 +44,8 @@ export default class ConfigReader {
return options;
}

private loadConfigModule(): ((config: Config) => void) | PartialStrykerOptions {
let configModule: PartialStrykerOptions | ((config: Config) => void) = {};
private loadConfigModule(): ((options: StrykerOptions) => void) | PartialStrykerOptions {
let configModule: PartialStrykerOptions | ((config: StrykerOptions) => void) = {};

if (!this.cliOptions.configFile) {
try {
Expand Down
39 changes: 0 additions & 39 deletions packages/core/src/config/OptionsEditorApplier.ts

This file was deleted.

11 changes: 4 additions & 7 deletions packages/core/src/config/createConfig.ts
@@ -1,18 +1,15 @@
import { deepMerge } from '@stryker-mutator/util/src/deepMerge';
import { StrykerOptions, PartialStrykerOptions } from '@stryker-mutator/api/core';
import { Config } from '@stryker-mutator/api/config';

/**
* Creates a `Config` object for given options.
* `Config` is the same as `StrykerOptions`, but with a `set` function that can be used as a shorthand to
* override options using a deep merge algorithm. This is mostly deprecated.
* Adds a `set` method to the options object that can be used as a shorthand to
* override options using a deep merge algorithm. This is mostly for backward compatibility purposes.
* @param options The stryker options use
* @deprecated Please use `StrykerOptions` directly instead
*/
export function createConfig(options: StrykerOptions): Config {
const config = options as Config;
export function createConfig(options: StrykerOptions): StrykerOptions {
options.set = (newConfig: PartialStrykerOptions) => {
deepMerge(options, newConfig);
};
return config;
return options;
}
1 change: 0 additions & 1 deletion packages/core/src/config/index.ts
@@ -1,4 +1,3 @@
export { OptionsEditorApplier } from './OptionsEditorApplier';
export * from './readConfig';
export * from './OptionsValidator';
export * from './buildSchemaWithPluginContributions';
22 changes: 3 additions & 19 deletions packages/core/src/di/buildMainInjector.ts
Expand Up @@ -4,30 +4,20 @@ import { commonTokens, Injector, OptionsContext, PluginKind, Scope, tokens } fro
import { Reporter } from '@stryker-mutator/api/report';
import { getLogger } from 'log4js';

import {
OptionsEditorApplier,
readConfig,
buildSchemaWithPluginContributions,
OptionsValidator,
validateOptions,
markUnknownOptions,
} from '../config';
import { readConfig, buildSchemaWithPluginContributions, OptionsValidator, validateOptions, markUnknownOptions } from '../config';
import ConfigReader from '../config/ConfigReader';
import BroadcastReporter from '../reporters/BroadcastReporter';
import { TemporaryDirectory } from '../utils/TemporaryDirectory';
import Timer from '../utils/Timer';

import { loggerFactory, mutatorDescriptorFactory, applyOptionsEditors, pluginResolverFactory } from './factoryMethods';
import { loggerFactory, mutatorDescriptorFactory, pluginResolverFactory } from './factoryMethods';

import { coreTokens, PluginCreator } from '.';

export interface MainContext extends OptionsContext {
[coreTokens.reporter]: Required<Reporter>;
[coreTokens.pluginCreatorReporter]: PluginCreator<PluginKind.Reporter>;
[coreTokens.pluginCreatorChecker]: PluginCreator<PluginKind.Checker>;
[coreTokens.pluginCreatorConfigEditor]: PluginCreator<PluginKind.ConfigEditor>;
[coreTokens.pluginCreatorMutator]: PluginCreator<PluginKind.Mutator>;
[coreTokens.pluginCreatorTestFramework]: PluginCreator<PluginKind.TestFramework>;
[coreTokens.timer]: Timer;
[coreTokens.temporaryDirectory]: TemporaryDirectory;
[coreTokens.execa]: typeof execa;
Expand All @@ -46,8 +36,6 @@ export function buildMainInjector(injector: CliOptionsProvider): Injector<MainCo
.provideFactory(commonTokens.mutatorDescriptor, mutatorDescriptorFactory)
.provideFactory(coreTokens.pluginCreatorReporter, PluginCreator.createFactory(PluginKind.Reporter))
.provideFactory(coreTokens.pluginCreatorChecker, PluginCreator.createFactory(PluginKind.Checker))
.provideFactory(coreTokens.pluginCreatorTestFramework, PluginCreator.createFactory(PluginKind.TestFramework))
.provideFactory(coreTokens.pluginCreatorMutator, PluginCreator.createFactory(PluginKind.Mutator))
.provideClass(coreTokens.reporter, BroadcastReporter)
.provideClass(coreTokens.temporaryDirectory, TemporaryDirectory)
.provideClass(coreTokens.timer, Timer)
Expand All @@ -65,11 +53,7 @@ export function createPluginResolverProvider(parent: BasicInjector): PluginResol
.provideFactory(coreTokens.validationSchema, buildSchemaWithPluginContributions)
.provideClass(coreTokens.optionsValidator, OptionsValidator)
.provideFactory(commonTokens.options, validateOptions)
.provideFactory(commonTokens.options, markUnknownOptions)
.provideFactory(coreTokens.pluginCreatorConfigEditor, PluginCreator.createFactory(PluginKind.ConfigEditor))
.provideFactory(coreTokens.pluginCreatorOptionsEditor, PluginCreator.createFactory(PluginKind.OptionsEditor))
.provideClass(coreTokens.configOptionsApplier, OptionsEditorApplier)
.provideFactory(commonTokens.options, applyOptionsEditors);
.provideFactory(commonTokens.options, markUnknownOptions);
}

function pluginDescriptorsFactory(options: StrykerOptions): readonly string[] {
Expand Down
5 changes: 0 additions & 5 deletions packages/core/src/di/coreTokens.ts
Expand Up @@ -28,12 +28,7 @@ export const reporter = 'reporter';
export const pluginKind = 'pluginKind';
export const pluginDescriptors = 'pluginDescriptors';
export const pluginCreatorReporter = 'pluginCreatorReporter';
export const pluginCreatorConfigEditor = 'pluginCreatorConfigEditor';
export const pluginCreatorChecker = 'pluginCreatorChecker';
export const pluginCreatorOptionsEditor = 'pluginCreatorOptionsEditor';
export const pluginCreatorTranspiler = 'pluginCreatorTranspiler';
export const pluginCreatorTestRunner = 'pluginCreatorTestRunner';
export const pluginCreatorMutator = 'pluginCreatorMutator';
export const pluginCreatorTestFramework = 'pluginCreatorTestFramework';
export const validationSchema = 'validationSchema';
export const optionsValidator = 'optionsValidator';
9 changes: 0 additions & 9 deletions packages/core/src/di/factoryMethods.ts
@@ -1,9 +1,6 @@
import { MutatorDescriptor, StrykerOptions } from '@stryker-mutator/api/core';
import { Logger, LoggerFactoryMethod } from '@stryker-mutator/api/logging';
import { commonTokens, Injector, PluginResolver, tokens } from '@stryker-mutator/api/plugin';
import { deepFreeze } from '@stryker-mutator/util';

import { OptionsEditorApplier } from '../config';

import { coreTokens, PluginLoader } from '.';

Expand All @@ -22,12 +19,6 @@ export function loggerFactory(getLogger: LoggerFactoryMethod, target: Function |
}
loggerFactory.inject = tokens(commonTokens.getLogger, commonTokens.target);

export function applyOptionsEditors(options: StrykerOptions, optionsEditorApplier: OptionsEditorApplier): StrykerOptions {
optionsEditorApplier.edit(options);
return deepFreeze(options) as StrykerOptions;
}
applyOptionsEditors.inject = tokens(commonTokens.options, coreTokens.configOptionsApplier);

export function mutatorDescriptorFactory(options: StrykerOptions): MutatorDescriptor {
const defaults: MutatorDescriptor = {
plugins: null,
Expand Down
58 changes: 0 additions & 58 deletions packages/core/test/unit/config/OptionsEditorApplier.spec.ts

This file was deleted.

0 comments on commit 5e56d0e

Please sign in to comment.