Class: Taski::StaticAnalysis::DependencyGraph

Inherits:
Object
  • Object
show all
Includes:
TSort
Defined in:
lib/taski/static_analysis/dependency_graph.rb

Overview

Builds a complete dependency graph from a root task class and provides topological sorting with cycle detection.

Instance Method Summary collapse

Constructor Details

#initializeDependencyGraph

Returns a new instance of DependencyGraph.



12
13
14
# File 'lib/taski/static_analysis/dependency_graph.rb', line 12

def initialize
  @graph = {}
end

Instance Method Details

#all_tasksArray<Class>

Get all task classes in the graph

Returns:

  • (Array<Class>)

    All registered task classes



54
55
56
# File 'lib/taski/static_analysis/dependency_graph.rb', line 54

def all_tasks
  @graph.keys
end

#build_from(root_task_class) ⇒ DependencyGraph

Build dependency graph starting from root task class

Parameters:

  • root_task_class (Class)

    The root task class to analyze

Returns:



19
20
21
22
# File 'lib/taski/static_analysis/dependency_graph.rb', line 19

def build_from(root_task_class)
  collect_dependencies(root_task_class)
  self
end

#cyclic?Boolean

Check if the graph contains circular dependencies

Returns:

  • (Boolean)

    true if circular dependencies exist



33
34
35
36
37
38
# File 'lib/taski/static_analysis/dependency_graph.rb', line 33

def cyclic?
  tsort
  false
rescue TSort::Cyclic
  true
end

#cyclic_componentsArray<Array<Class>>

Get task classes involved in cycles

Returns:

  • (Array<Array<Class>>)

    Only components with size > 1 (cycles)



48
49
50
# File 'lib/taski/static_analysis/dependency_graph.rb', line 48

def cyclic_components
  strongly_connected_components.select { |component| component.size > 1 }
end

#dependencies_for(task_class) ⇒ Set<Class>

Get direct dependencies for a task class

Parameters:

  • task_class (Class)

    The task class

Returns:

  • (Set<Class>)

    Direct dependencies



61
62
63
# File 'lib/taski/static_analysis/dependency_graph.rb', line 61

def dependencies_for(task_class)
  @graph.fetch(task_class, Set.new)
end

#sortedArray<Class>

Get topologically sorted task classes (dependencies first)

Returns:

  • (Array<Class>)

    Sorted task classes

Raises:

  • (TSort::Cyclic)

    If circular dependency is detected



27
28
29
# File 'lib/taski/static_analysis/dependency_graph.rb', line 27

def sorted
  tsort
end

#strongly_connected_componentsArray<Array<Class>>

Get strongly connected components (useful for debugging cycles)

Returns:

  • (Array<Array<Class>>)

    Groups of mutually dependent classes



42
43
44
# File 'lib/taski/static_analysis/dependency_graph.rb', line 42

def strongly_connected_components
  each_strongly_connected_component.to_a
end

#tsort_each_child(node, &block) ⇒ Object

TSort interface: iterate over children (dependencies) of a node



71
72
73
# File 'lib/taski/static_analysis/dependency_graph.rb', line 71

def tsort_each_child(node, &block)
  @graph.fetch(node, Set.new).each(&block)
end

#tsort_each_node(&block) ⇒ Object

TSort interface: iterate over all nodes



66
67
68
# File 'lib/taski/static_analysis/dependency_graph.rb', line 66

def tsort_each_node(&block)
  @graph.each_key(&block)
end