Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/main/scala/temple/DSL/semantics/Tarjan.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ class Tarjan[T] private (graph: Map[T, Iterable[T]]) {
sccBuffer.toSet
}

private def neighbours(node: T): Iterable[T] = graph.getOrElse(node, Nil)

private def visit(node: T): Unit = {
// Set the depth index for v to the smallest unused index
index(node) = index.size
lowLink(node) = index(node)
stack.push(node)
for (neighbour <- graph.getOrElse(node, Nil)) {
for (neighbour <- neighbours(node)) {
if (!index.contains(neighbour)) { // neighbour has not yet been visited; recurse on it
visit(neighbour)
lowLink(node) = math.min(lowLink(node), lowLink(neighbour))
Expand All @@ -34,7 +36,8 @@ class Tarjan[T] private (graph: Map[T, Iterable[T]]) {
if (lowLink(node) == index(node)) {
// Pop all elements from the stack until and including this element itself
val scc = (stack.popWhile(_ != node) :+ stack.pop()).toSet
sccBuffer += scc
// Only add single elements if they have a self-loop
if (scc.sizeIs != 1 || neighbours(node).iterator.contains(node)) sccBuffer += scc
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/temple/DSL/semantics/Validator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,10 @@ private class Validator private (templefile: Templefile) {
private val referenceCycles: Set[Set[String]] = {
val graph = templefile.providedBlockNames.map { blockName =>
blockName -> templefile.getBlock(blockName).attributes.values.collect {
case Attribute(ForeignKey(references), _, annotations) => references
case Attribute(ForeignKey(references), _, _) => references
}
}.toMap
Tarjan(graph).filter(_.sizeIs > 1)
Tarjan(graph)
}

def validate(): Seq[String] = {
Expand Down
9 changes: 9 additions & 0 deletions src/test/scala/temple/DSL/semantics/ValidatorTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,15 @@ class ValidatorTest extends FlatSpec with Matchers {
}

it should "find cycles in dependencies" in {
validationErrors(
Templefile(
"MyProject",
services = Map(
"Box" -> ServiceBlock(Map("box" -> Attribute(ForeignKey("Box")))),
),
),
) shouldBe Set("Cycle(s) were detected in foreign keys, between elements: { Box }")

validationErrors(
Templefile(
"MyProject",
Expand Down