Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(eslint): add unicorn/prefer-spread rule #2878

Merged
merged 10 commits into from
Sep 26, 2023
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ module.exports = {
'unicorn/no-useless-switch-case': 'error',
'unicorn/prefer-switch': 'error',
'unicorn/switch-case-braces': 'error',
'unicorn/prefer-spread': 'error',
'import/newline-after-import': ['error', { count: 1 }],
'import/first': 'error',
'import/order': [
Expand Down
2 changes: 1 addition & 1 deletion dev/ts/shared/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ function configureStyleFromParameters(parameters: URLSearchParams): void {
// Collect style properties to update them later with the bpmn-visualization API
logStartup(`Configuring the "Update Style" API from query parameters`);
// Only create the StyleUpdate object if some parameters are set
if (Array.from(parameters.keys()).some(key => key.startsWith('style.api.'))) {
if ([...parameters.keys()].some(key => key.startsWith('style.api.'))) {
style = { stroke: {}, font: {}, fill: {} };

parameters.get('style.api.stroke.color') && (style.stroke.color = parameters.get('style.api.stroke.color'));
Expand Down
3 changes: 3 additions & 0 deletions src/component/helpers/array-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,13 @@ export function ensureIsArray<T>(elements: (T | string)[] | T | string, acceptEm
export function filter<T extends string>(arrayToFilter: T[], suffix: string, options?: FilterParameter): T[] {
let pattern = '';
if (options?.startingWith) {
// eslint-disable-next-line unicorn/prefer-spread -- pattern is a string not an array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why the rule detects it as string.concat and not array.concat. If so, it is a bug in the rule
I am testing this locally

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pattern = pattern.concat(`^(${options.startingWith}).*`);
} else if (options?.notStartingWith) {
// eslint-disable-next-line unicorn/prefer-spread -- pattern is a string not an array
pattern = pattern.concat(`^(?!(${options.notStartingWith})).*`);
}
// eslint-disable-next-line unicorn/prefer-spread -- pattern is a string not an array
pattern = pattern.concat(`${suffix}$`);
csouchet marked this conversation as resolved.
Show resolved Hide resolved

return arrayToFilter.filter(element => (options?.ignoreCase ? new RegExp(pattern, 'i').test(element) : new RegExp(pattern).test(element)));
Expand Down
4 changes: 2 additions & 2 deletions src/component/mxgraph/config/ShapeConfigurator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ export default class ShapeConfigurator {
// 'this.state.cell.style' = the style applied to the cell: 1st element: style name = bpmn shape name
const cell = this.state.cell;
// dialect = strictHtml is set means that current node holds an HTML label
let allBpmnClassNames = computeAllBpmnClassNamesOfCell(cell, this.dialect === mxConstants.DIALECT_STRICTHTML);
const allBpmnClassNames = computeAllBpmnClassNamesOfCell(cell, this.dialect === mxConstants.DIALECT_STRICTHTML);
const extraCssClasses = this.state.style[BpmnStyleIdentifier.EXTRA_CSS_CLASSES];
if (typeof extraCssClasses == 'string') {
allBpmnClassNames = allBpmnClassNames.concat(extraCssClasses.split(','));
allBpmnClassNames.push(...extraCssClasses.split(','));
}

this.node.setAttribute('class', allBpmnClassNames.join(' '));
Expand Down
5 changes: 2 additions & 3 deletions src/component/mxgraph/renderer/StyleComputer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,8 @@ export default class StyleComputer {
const fontStyleValues = this.computeFontStyleValues(bpmnCell);
const labelStyleValues = StyleComputer.computeLabelStyleValues(bpmnCell, labelBounds);

return styles //
.concat(toArrayOfMxGraphStyleEntries([...mainStyleValues, ...fontStyleValues, ...labelStyleValues]))
.join(';');
styles.push(...toArrayOfMxGraphStyleEntries([...mainStyleValues, ...fontStyleValues, ...labelStyleValues]));
return styles.join(';');
}

private computeShapeStyleValues(shape: Shape): Map<string, string | number> {
Expand Down
3 changes: 2 additions & 1 deletion src/component/mxgraph/style/style-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export function createNewStyleUpdater(graph: BpmnGraph): StyleUpdater {
// The message flow icon is stored in a dedicated Cell, so it must be kept in sync
const withCellIdsOfMessageFlowIcons = (bpmnElementIds: string | string[]): string[] => {
const cellIds = ensureIsArray<string>(bpmnElementIds);
return cellIds.concat(cellIds.map(id => messageFlowIconId(id)));
cellIds.push(...cellIds.map(id => messageFlowIconId(id)));
return cellIds;
};

export class StyleUpdater {
Expand Down
16 changes: 9 additions & 7 deletions src/component/parser/json/converter/ProcessConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,14 @@ const computeSubProcessKind = (processedSemanticType: BpmnSemanticType, bpmnElem
}
};

const orderedFlowNodeBpmnTypes: BpmnSemanticType[] = (['adHocSubProcess', 'transaction'] as BpmnSemanticType[]) // specific management for adhoc and transaction sub-processes which are handled with a dedicated ShapeBpmnSubProcessKind
// process boundary events afterward as we need its parent activity to be available when building it
.concat(ShapeUtil.flowNodeKinds().filter(kind => kind != ShapeBpmnElementKind.EVENT_BOUNDARY) as BpmnSemanticType[])
.concat([ShapeBpmnElementKind.EVENT_BOUNDARY]);
// specific management for adhoc and transaction sub-processes which are handled with a dedicated ShapeBpmnSubProcessKind
// process boundary events afterward as we need its parent activity to be available when building it
csouchet marked this conversation as resolved.
Show resolved Hide resolved
const orderedFlowNodeBpmnTypes: BpmnSemanticType[] = [
'adHocSubProcess',
'transaction',
...(ShapeUtil.flowNodeKinds().filter(kind => kind !== ShapeBpmnElementKind.EVENT_BOUNDARY) as BpmnSemanticType[]),
ShapeBpmnElementKind.EVENT_BOUNDARY,
];

function getShapeBpmnElementKind(bpmnSemanticType: BpmnSemanticType): ShapeBpmnElementKind {
return ['adHocSubProcess', 'transaction'].includes(bpmnSemanticType as string) ? ShapeBpmnElementKind.SUB_PROCESS : (bpmnSemanticType as ShapeBpmnElementKind);
Expand Down Expand Up @@ -290,9 +294,7 @@ export default class ProcessConverter {
eventDefinitions.set(kind, eventDefinitions.get(kind) + 1);
}

return Array.from(eventDefinitions.keys())
.map(kind => ({ kind, counter: eventDefinitions.get(kind) }))
.filter(eventDefinition => eventDefinition.counter > 0);
return [...eventDefinitions.entries()].filter(([, counter]) => counter > 0).map(([kind, counter]) => ({ kind, counter }));
}

private buildShapeBpmnSubProcess(bpmnElement: TSubProcess, parentId: string, subProcessKind: ShapeBpmnSubProcessKind, markers: ShapeBpmnMarkerKind[]): ShapeBpmnSubProcess {
Expand Down
3 changes: 2 additions & 1 deletion src/component/registry/bpmn-model-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,9 @@ class SearchableModel {
private elements = new Map<string, Shape | Edge>();

constructor(bpmnModel: BpmnModel) {
for (const shapeOrEdge of ([] as (Edge | Shape)[]).concat(bpmnModel.pools, bpmnModel.lanes, bpmnModel.flowNodes, bpmnModel.edges))
for (const shapeOrEdge of [...bpmnModel.pools, ...bpmnModel.lanes, ...bpmnModel.flowNodes, ...bpmnModel.edges]) {
this.elements.set(shapeOrEdge.bpmnElement.id, shapeOrEdge);
}
}

elementById(id: string): Shape | Edge | undefined {
Expand Down
4 changes: 2 additions & 2 deletions src/component/registry/css-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class CssClassesCache {
* @return the registered CSS class names
*/
getClassNames(bpmnElementId: string): string[] {
return Array.from(this.classNamesByBpmnId.get(bpmnElementId) ?? []);
return this.classNamesByBpmnId.has(bpmnElementId) ? [...this.classNamesByBpmnId.get(bpmnElementId)] : [];
}

/**
Expand All @@ -101,7 +101,7 @@ export class CssClassesCache {
* @return an array representing the BPMN element IDs.
*/
getBpmnIds(): string[] {
return Array.from(this.classNamesByBpmnId.keys());
return [...this.classNamesByBpmnId.keys()];
}

/**
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/bpmn.theme.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('BPMN theme', () => {
);

const pageTester = new PageTester({ targetedPage: AvailableTestPages.BPMN_RENDERING, diagramSubfolder: 'theme' }, page);
const useCases = Array.from(styleOptionsPerUseCase.keys());
const useCases = [...styleOptionsPerUseCase.keys()];

it.each(useCases)(`Use case %s`, async (useCase: string) => {
await pageTester.gotoPageAndLoadBpmnDiagram('01.most.bpmn.types.without.label', {
Expand Down
4 changes: 2 additions & 2 deletions test/integration/helpers/html-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ export class HtmlElementLookup {
}
}

function computeClassValue(bpmnClasses: string[], additionalClasses?: string[]): string {
return bpmnClasses.concat(additionalClasses).filter(Boolean).join(' ');
function computeClassValue(bpmnClasses: string[], additionalClasses: string[] = []): string {
return [...bpmnClasses, ...additionalClasses].filter(Boolean).join(' ');
}

export function expectSvgEvent(svgGroupElement: HTMLElement): void {
Expand Down
2 changes: 1 addition & 1 deletion test/performance/bpmn.load.performance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ afterAll(async () => {
const oldData = JSON.parse(oldDataString.substring('const data = '.length, oldDataString.length)) as ChartData;
const data = {
zoom: oldData.zoom,
load: oldData.load.concat(metricsArray),
load: [...oldData.load, ...metricsArray],
};
fs.writeFileSync(performanceDataFilePath, 'const data = ' + JSON.stringify(data));
} catch (error) {
Expand Down
2 changes: 1 addition & 1 deletion test/performance/bpmn.navigation.performance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ afterAll(async () => {
const oldDataString = fs.readFileSync(performanceDataFilePath, 'utf8');
const oldData = JSON.parse(oldDataString.substring('const data = '.length, oldDataString.length)) as ChartData;
const data = {
zoom: oldData.zoom.concat(metricsArray),
zoom: [...oldData.zoom, ...metricsArray],
load: oldData.load,
};
fs.writeFileSync(performanceDataFilePath, 'const data = ' + JSON.stringify(data));
Expand Down
4 changes: 2 additions & 2 deletions test/unit/component/mxgraph/shape/render/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function computeAllPermutations(array: string[]): string[][][] {
const permutation = [...array];

const length = permutation.length,
result = [[permutation.slice()]],
result = [[[...permutation]]],
c = new Array(length).fill(0);
let index = 1,
k,
Expand All @@ -37,7 +37,7 @@ function computeAllPermutations(array: string[]): string[][][] {
permutation[k] = p;
++c[index];
index = 1;
result.push([permutation.slice()]);
result.push([[...permutation]]);
} else {
c[index] = 0;
++index;
Expand Down