resolve method

DependencyResolutionResult resolve({
  1. required Map<String, List<ModuleDependency>> modules,
  2. required Map<String, String> moduleVersions,
})

Resolve dependencies and return load order Uses topological sort to determine correct order

Implementation

DependencyResolutionResult resolve({
  required Map<String, List<ModuleDependency>> modules,
  required Map<String, String> moduleVersions,
}) {
  final errors = <String>[];
  final warnings = <String>[];
  final resolved = <String>[];
  final unresolved = <String>{};
  // Flag to stop resolution immediately when circular dependency is found
  bool hasCircularDependency = false;

  void resolveModule(String moduleId) {
    // Stop immediately if circular dependency was detected
    if (hasCircularDependency) return;
    if (resolved.contains(moduleId)) return;
    if (unresolved.contains(moduleId)) {
      errors.add('Circular dependency detected: $moduleId');
      hasCircularDependency = true;
      return;
    }

    unresolved.add(moduleId);

    final deps = modules[moduleId] ?? [];
    for (final dep in deps) {
      // Check before processing each dependency to exit early
      if (hasCircularDependency) return;

      // Check if dependency exists
      if (!modules.containsKey(dep.moduleId)) {
        if (dep.isOptional) {
          warnings.add('Optional dependency ${dep.moduleId} not found');
        } else {
          errors.add('Missing required dependency: ${dep.moduleId}');
        }
        continue;
      }

      // Check version compatibility
      final depVersion = moduleVersions[dep.moduleId];
      if (depVersion != null && !dep.isSatisfiedBy(depVersion)) {
        errors.add(
          'Version mismatch: ${dep.moduleId} requires ${dep.versionRequirement}, '
          'got $depVersion',
        );
        continue;
      }

      resolveModule(dep.moduleId);
    }

    unresolved.remove(moduleId);
    if (!hasCircularDependency) {
      resolved.add(moduleId);
    }
  }

  // Resolve all modules
  for (final moduleId in modules.keys) {
    if (hasCircularDependency) break;
    resolveModule(moduleId);
  }

  return DependencyResolutionResult(
    success: errors.isEmpty,
    resolvedOrder: resolved,
    errors: errors,
    warnings: warnings,
  );
}