Class: ArchSpec::Rules::NoCyclesRule

Inherits:
Object
  • Object
show all
Defined in:
lib/archspec/rules/cycle_rule.rb

Overview

Backs ArchSpec::DSL::Context#no_cycles. Flags each group of components that depend on each other, reporting the group once with an example cycle.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(among: nil) ⇒ NoCyclesRule

Returns a new instance of NoCyclesRule.



10
11
12
# File 'lib/archspec/rules/cycle_rule.rb', line 10

def initialize(among: nil)
  @components = Array(among).compact.map(&:to_sym)
end

Instance Attribute Details

#componentsObject (readonly)

Returns the value of attribute components.



8
9
10
# File 'lib/archspec/rules/cycle_rule.rb', line 8

def components
  @components
end

Instance Method Details

#evaluate(graph) ⇒ Object

One diagnostic per strongly connected component. Every component in an SCC reaches every other one, so the group is the thing to break up; enumerating its elementary cycles instead reports the same tangle exponentially many times.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/archspec/rules/cycle_rule.rb', line 22

def evaluate(graph)
  locations = dependency_locations(graph)
  adjacency = adjacency_for(locations)

  StronglyConnectedComponents.of(adjacency).filter_map do |group|
    next if group.size < 2

    cycle = shortest_cycle(adjacency, group)
    next unless cycle

    Diagnostic.new(
      rule: id,
      message: message_for(group, cycle),
      location: locations[[cycle[0], cycle[1]]] || SourceLocation.point(graph.root, 1, 1),
      evidence: cycle.join(' -> ')
    )
  end
end

#idObject



14
15
16
# File 'lib/archspec/rules/cycle_rule.rb', line 14

def id
  'dependencies.no_cycles'
end