feat(format): add check and fix workflows
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user