feat(format): add check and fix workflows

This commit is contained in:
2026-05-14 13:18:49 +00:00
parent 6f0928e7c7
commit 278df40ba7
11 changed files with 635 additions and 250 deletions
+66 -4
View File
@@ -1,7 +1,11 @@
import * as plugins from './mod.plugins.js';
import { FormatContext } from './classes.formatcontext.js';
import { BaseFormatter } from './classes.baseformatter.js';
import type { IFormatPlan, IPlannedChange } from './interfaces.format.js';
import type {
IFormatPlan,
IPlannedChange,
IFormatWarning,
} from './interfaces.format.js';
import { getModuleIcon } from './interfaces.format.js';
import { logger } from '../gitzone.logging.js';
import { DiffReporter } from './classes.diffreporter.js';
@@ -42,15 +46,21 @@ export class FormatPlanner {
break;
}
}
const warnings = await module.validate();
plan.warnings.push(...warnings);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
plan.warnings.push({
level: 'error',
message: `Failed to analyze module ${module.name}: ${error.message}`,
message: `Failed to analyze module ${module.name}: ${errorMessage}`,
module: module.name,
});
}
}
plan.warnings.push(...this.detectConflictingChanges(plan.changes));
plan.summary.totalFiles =
plan.summary.filesAdded +
plan.summary.filesModified +
@@ -65,11 +75,12 @@ export class FormatPlanner {
context: FormatContext,
): Promise<void> {
const startTime = Date.now();
const changesByModule = this.groupChangesByModule(plan.changes);
for (const module of modules) {
const changes = this.plannedChanges.get(module.name) || [];
const changes = changesByModule.get(module.name) || [];
if (changes.length > 0) {
if (changes.length > 0 || module.runsWithoutChanges) {
logger.log('info', `Executing ${module.name} formatter...`);
await module.execute(changes);
}
@@ -138,4 +149,55 @@ export class FormatPlanner {
return '❌';
}
}
private groupChangesByModule(
changes: IPlannedChange[],
): Map<string, IPlannedChange[]> {
const changesByModule = new Map<string, IPlannedChange[]>();
for (const change of changes) {
const moduleChanges = changesByModule.get(change.module) || [];
moduleChanges.push(change);
changesByModule.set(change.module, moduleChanges);
}
return changesByModule;
}
private detectConflictingChanges(
changes: IPlannedChange[],
): IFormatWarning[] {
const warnings: IFormatWarning[] = [];
const changesByPath = new Map<string, IPlannedChange[]>();
for (const change of changes) {
if (!change.path || change.path === '<various files>') {
continue;
}
const pathChanges = changesByPath.get(change.path) || [];
pathChanges.push(change);
changesByPath.set(change.path, pathChanges);
}
for (const [path, pathChanges] of changesByPath) {
const modules = [...new Set(pathChanges.map((change) => change.module))];
if (modules.length < 2) {
continue;
}
const hasDelete = pathChanges.some((change) => change.type === 'delete');
const plannedContents = pathChanges
.map((change) => change.content)
.filter((content): content is string => content !== undefined);
const uniqueContents = new Set(plannedContents);
const level = hasDelete || uniqueContents.size > 1 ? 'warning' : 'info';
warnings.push({
level,
module: 'planner',
message: `Multiple formatters plan changes for ${path}: ${modules.join(', ')}. They will run in formatter order.`,
});
}
return warnings;
}
}