2020-08-15 22:24:16 +00:00
|
|
|
import { FlagLabel, getValueName, prioritySort, StateLabel, BaseLabel } from './labels';
|
2020-08-12 00:14:42 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* How a label changed.
|
|
|
|
*/
|
2020-08-15 14:31:28 +00:00
|
|
|
export enum ChangeVerb {
|
2020-08-12 00:14:42 +00:00
|
|
|
EXISTING = 'existing',
|
|
|
|
CREATED = 'created',
|
|
|
|
REMOVED = 'removed',
|
2020-08-12 03:19:01 +00:00
|
|
|
REQUIRED = 'required',
|
2020-08-12 00:14:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Details of a label change.
|
|
|
|
*/
|
|
|
|
export interface ChangeRecord {
|
2020-08-15 14:31:28 +00:00
|
|
|
/**
|
|
|
|
* The label which caused this change.
|
|
|
|
*/
|
2020-08-12 00:14:42 +00:00
|
|
|
cause: string;
|
2020-08-15 14:31:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* How the label was changed.
|
|
|
|
*/
|
|
|
|
effect: ChangeVerb;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The label being changed.
|
|
|
|
*/
|
|
|
|
label: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface ErrorRecord {
|
|
|
|
error: Error;
|
2020-08-12 00:14:42 +00:00
|
|
|
label: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Collected inputs for a resolver run.
|
|
|
|
*/
|
|
|
|
export interface ResolveInput {
|
2020-08-12 01:39:53 +00:00
|
|
|
flags: Array<FlagLabel>;
|
2020-08-12 00:14:42 +00:00
|
|
|
labels: Array<string>;
|
2020-08-12 01:39:53 +00:00
|
|
|
states: Array<StateLabel>;
|
2020-08-12 00:14:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Collected results from a resolver run.
|
|
|
|
*/
|
|
|
|
export interface ResolveResult {
|
|
|
|
changes: Array<ChangeRecord>;
|
2020-08-15 14:31:28 +00:00
|
|
|
errors: Array<ErrorRecord>;
|
2020-08-12 00:14:42 +00:00
|
|
|
labels: Array<string>;
|
|
|
|
}
|
|
|
|
|
2020-08-15 14:31:28 +00:00
|
|
|
/**
|
|
|
|
* Resolve the desired set of labels, given a starting set and the flags/states to be
|
|
|
|
* applied.
|
|
|
|
*/
|
2020-08-15 21:06:26 +00:00
|
|
|
/* eslint-disable-next-line sonarjs/cognitive-complexity */
|
2020-08-12 00:14:42 +00:00
|
|
|
export function resolveLabels(options: ResolveInput): ResolveResult {
|
|
|
|
const activeLabels = new Set(options.labels);
|
2020-08-12 03:19:01 +00:00
|
|
|
const changes: Array<ChangeRecord> = [];
|
2020-08-15 14:31:28 +00:00
|
|
|
const errors: Array<ErrorRecord> = [];
|
2020-08-12 00:14:42 +00:00
|
|
|
|
2020-08-15 22:24:16 +00:00
|
|
|
function checkLabelRules(label: BaseLabel) {
|
|
|
|
let isRemoved = false;
|
|
|
|
if (activeLabels.has(label.name)) {
|
|
|
|
for (const requiredLabel of label.requires) {
|
2020-08-15 21:06:26 +00:00
|
|
|
if (!activeLabels.has(requiredLabel.name)) {
|
2020-08-15 22:24:16 +00:00
|
|
|
activeLabels.delete(label.name);
|
|
|
|
isRemoved = true;
|
2020-08-15 21:06:26 +00:00
|
|
|
}
|
|
|
|
}
|
2020-08-15 22:24:16 +00:00
|
|
|
}
|
|
|
|
if (isRemoved) {
|
|
|
|
return;
|
|
|
|
}
|
2020-08-15 21:06:26 +00:00
|
|
|
|
2020-08-15 22:24:16 +00:00
|
|
|
for (const addedLabel of label.adds) {
|
|
|
|
activeLabels.add(addedLabel.name);
|
|
|
|
}
|
2020-08-15 21:06:26 +00:00
|
|
|
|
2020-08-15 22:24:16 +00:00
|
|
|
for (const removedLabel of label.removes) {
|
|
|
|
activeLabels.delete(removedLabel.name);
|
2020-08-12 00:14:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-15 22:24:16 +00:00
|
|
|
const sortedFlags = prioritySort(options.flags);
|
|
|
|
for (const flag of sortedFlags) {
|
|
|
|
checkLabelRules(flag);
|
|
|
|
}
|
|
|
|
|
2020-08-15 17:38:33 +00:00
|
|
|
const sortedStates = prioritySort(options.states);
|
2020-08-12 00:14:42 +00:00
|
|
|
for (const state of sortedStates) {
|
2020-08-15 22:24:16 +00:00
|
|
|
let firstActive = true;
|
2020-08-15 17:38:33 +00:00
|
|
|
const sortedValues = prioritySort(state.values);
|
2020-08-15 14:31:28 +00:00
|
|
|
for (const value of sortedValues) {
|
2020-08-15 17:38:33 +00:00
|
|
|
const name = getValueName(state, value);
|
2020-08-12 00:14:42 +00:00
|
|
|
if (activeLabels.has(name)) {
|
2020-08-15 22:24:16 +00:00
|
|
|
if (firstActive) {
|
|
|
|
// TODO: check requires
|
|
|
|
// TODO: check adds
|
|
|
|
// TODO: check removes
|
|
|
|
// TODO: check becomes
|
|
|
|
firstActive = false;
|
|
|
|
} else {
|
|
|
|
// removes all other values for this state and breaks?
|
|
|
|
}
|
2020-08-12 00:14:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
2020-08-12 03:19:01 +00:00
|
|
|
changes,
|
|
|
|
errors,
|
2020-08-12 00:14:42 +00:00
|
|
|
labels: Array.from(activeLabels),
|
|
|
|
};
|
|
|
|
}
|