* Validate dependencies. * @param {Callback<MultiStats>} callback signals when the validation is complete * @returns {boolean} true if the dependencies are valid
(callback)
| 286 | * @returns {boolean} true if the dependencies are valid |
| 287 | */ |
| 288 | validateDependencies(callback) { |
| 289 | /** @type {Set<{ source: Compiler, target: Compiler }>} */ |
| 290 | const edges = new Set(); |
| 291 | /** @type {string[]} */ |
| 292 | const missing = []; |
| 293 | /** |
| 294 | * Returns target was found. |
| 295 | * @param {Compiler} compiler compiler |
| 296 | * @returns {boolean} target was found |
| 297 | */ |
| 298 | const targetFound = (compiler) => { |
| 299 | for (const edge of edges) { |
| 300 | if (edge.target === compiler) { |
| 301 | return true; |
| 302 | } |
| 303 | } |
| 304 | return false; |
| 305 | }; |
| 306 | /** |
| 307 | * Returns result. |
| 308 | * @param {{ source: Compiler, target: Compiler }} e1 edge 1 |
| 309 | * @param {{ source: Compiler, target: Compiler }} e2 edge 2 |
| 310 | * @returns {number} result |
| 311 | */ |
| 312 | const sortEdges = (e1, e2) => |
| 313 | /** @type {string} */ |
| 314 | (e1.source.name).localeCompare(/** @type {string} */ (e2.source.name)) || |
| 315 | /** @type {string} */ |
| 316 | (e1.target.name).localeCompare(/** @type {string} */ (e2.target.name)); |
| 317 | for (const source of this.compilers) { |
| 318 | const dependencies = this.dependencies.get(source); |
| 319 | if (dependencies) { |
| 320 | for (const dep of dependencies) { |
| 321 | const target = this.compilers.find((c) => c.name === dep); |
| 322 | if (!target) { |
| 323 | missing.push(dep); |
| 324 | } else { |
| 325 | edges.add({ |
| 326 | source, |
| 327 | target |
| 328 | }); |
| 329 | } |
| 330 | } |
| 331 | } |
| 332 | } |
| 333 | /** @type {string[]} */ |
| 334 | const errors = missing.map( |
| 335 | (m) => `Compiler dependency \`${m}\` not found.` |
| 336 | ); |
| 337 | const stack = this.compilers.filter((c) => !targetFound(c)); |
| 338 | while (stack.length > 0) { |
| 339 | const current = stack.pop(); |
| 340 | for (const edge of edges) { |
| 341 | if (edge.source === current) { |
| 342 | edges.delete(edge); |
| 343 | const target = edge.target; |
| 344 | if (!targetFound(target)) { |
| 345 | stack.push(target); |