diff --git a/.changeset/big-laws-attend.md b/.changeset/big-laws-attend.md new file mode 100644 index 00000000..9aa529d4 --- /dev/null +++ b/.changeset/big-laws-attend.md @@ -0,0 +1,8 @@ +--- +"@plutolang/graphviz-generator": patch +"@plutolang/base": patch +--- + +fix: resolve topo sort failure by adding missing resource edge + +The topological sort was wrong due to a missing edge related to the resource argument. This commit adds the required edge to ensure correct sorting order. diff --git a/components/generators/graphviz/src/generator.ts b/components/generators/graphviz/src/generator.ts index 44902731..aea1bf6e 100644 --- a/components/generators/graphviz/src/generator.ts +++ b/components/generators/graphviz/src/generator.ts @@ -33,6 +33,8 @@ function archToGraphviz(archRef: arch.Architecture): string { for (const arg of res.arguments) { if (arg.type === "closure") { dotSource += ` ${res.id} -> ${arg.closureId} [color="black"];\n`; + } else if (arg.type === "resource" || arg.type === "capturedProperty") { + dotSource += ` ${res.id} -> ${arg.resourceId} [color="black"];\n`; } } } diff --git a/packages/base/arch/topo-sorter.ts b/packages/base/arch/topo-sorter.ts index afb13597..ca18700b 100644 --- a/packages/base/arch/topo-sorter.ts +++ b/packages/base/arch/topo-sorter.ts @@ -1,6 +1,5 @@ import { createHash } from "crypto"; import { Resource } from "./resource"; -import { BundleArgument } from "./argument"; import { Architecture } from "./architecture"; import { BundleEntity, Entity, EntityType, RelationshipEntity, ResourceEntity } from "./types"; import { @@ -119,20 +118,40 @@ export class TopoSorter { // Constructor: A resource depends on its parameters. // Thus, the edge originates from the parameter nodes and points towards the resource node. private addEdgesOfConstructor() { - this.archRef.resources.forEach((resource) => { + const addEdgesForOneResource = (resource: Resource) => { const targetNode = resource; - resource.arguments - .filter((arg): arg is BundleArgument => arg.type === "closure") - .forEach((arg) => { - const sourceNode = this.archRef.findClosure(arg.closureId); - if (sourceNode == undefined) { - throw Error( - `The architecture is invalid, the closure '${arg.closureId}' cannot be found.` - ); + + for (const arg of resource.arguments) { + switch (arg.type) { + case "closure": { + const sourceNode = this.archRef.findClosure(arg.closureId); + if (sourceNode == undefined) { + throw Error( + `The architecture is invalid, the closure '${arg.closureId}' cannot be found.` + ); + } + this.addOneEdge(BundleEntity.create(sourceNode), ResourceEntity.create(targetNode)); + break; } - this.addOneEdge(BundleEntity.create(sourceNode), ResourceEntity.create(targetNode)); - }); - }); + case "resource": + case "capturedProperty": + { + const sourceNode = this.archRef.findResource(arg.resourceId); + if (sourceNode == undefined) { + throw Error( + `The architecture is invalid, the resource '${arg.resourceId}' cannot be found.` + ); + } + this.addOneEdge(ResourceEntity.create(sourceNode), ResourceEntity.create(targetNode)); + } + break; + case "text": + break; + } + } + }; + + this.archRef.resources.forEach(addEdgesForOneResource); } // Create: The 'Create' relationship node depends on both the 'from' and 'to' properties.