Class: Canon::Diff::DiffNode

Inherits:
Object
  • Object
show all
Defined in:
lib/canon/diff/diff_node.rb

Overview

Represents a semantic difference between two nodes in a comparison tree This is created during the Comparison Layer and carries information about which dimension caused the difference and whether it’s normative or informative

DiffNode is library-agnostic - it works with data extracted from nodes, not the raw node references themselves. This allows Canon to work with any parsing library (Nokogiri, Moxml, etc.) without being tied to it.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node1:, node2:, dimension:, reason:, path: nil, serialized_before: nil, serialized_after: nil, attributes_before: nil, attributes_after: nil) ⇒ DiffNode

Returns a new instance of DiffNode.

Parameters:

  • node1 (Object)

    The first node being compared

  • node2 (Object)

    The second node being compared

  • dimension (Symbol)

    The match dimension that caused this diff (e.g., :text_content, :attribute_whitespace, :structural_whitespace, :comments, :key_order)

  • reason (String)

    Human-readable explanation of the difference

  • path (String, nil) (defaults to: nil)

    Optional canonical path with ordinal indices

  • serialized_before (String, nil) (defaults to: nil)

    Optional serialized content for display

  • serialized_after (String, nil) (defaults to: nil)

    Optional serialized content for display

  • attributes_before (Hash, nil) (defaults to: nil)

    Optional normalized attributes hash

  • attributes_after (Hash, nil) (defaults to: nil)

    Optional normalized attributes hash



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/canon/diff/diff_node.rb', line 33

def initialize(node1:, node2:, dimension:, reason:,
               path: nil, serialized_before: nil, serialized_after: nil,
               attributes_before: nil, attributes_after: nil)
  @node1 = node1
  @node2 = node2
  @dimension = dimension
  @reason = reason
  @normative = nil # Will be set by DiffClassifier
  @formatting = nil # Will be set by DiffClassifier
  # Enriched metadata (optional, populated by PathBuilder and NodeSerializer)
  @path = path
  @serialized_before = serialized_before
  @serialized_after = serialized_after
  @attributes_before = attributes_before
  @attributes_after = attributes_after
end

Instance Attribute Details

#attributes_afterObject

Returns the value of attribute attributes_after.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def attributes_after
  @attributes_after
end

#attributes_beforeObject

Returns the value of attribute attributes_before.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def attributes_before
  @attributes_before
end

#dimensionObject

Returns the value of attribute dimension.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def dimension
  @dimension
end

#formattingObject

Returns the value of attribute formatting.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def formatting
  @formatting
end

#node1Object (readonly)

Returns the value of attribute node1.



13
14
15
# File 'lib/canon/diff/diff_node.rb', line 13

def node1
  @node1
end

#node2Object (readonly)

Returns the value of attribute node2.



13
14
15
# File 'lib/canon/diff/diff_node.rb', line 13

def node2
  @node2
end

#normativeObject

Returns the value of attribute normative.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def normative
  @normative
end

#pathObject

Returns the value of attribute path.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def path
  @path
end

#reasonObject

Returns the value of attribute reason.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def reason
  @reason
end

#serialized_afterObject

Returns the value of attribute serialized_after.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def serialized_after
  @serialized_after
end

#serialized_beforeObject

Returns the value of attribute serialized_before.



14
15
16
# File 'lib/canon/diff/diff_node.rb', line 14

def serialized_before
  @serialized_before
end

Instance Method Details

#==(other) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/canon/diff/diff_node.rb', line 88

def ==(other)
  other.is_a?(DiffNode) &&
    node1 == other.node1 &&
    node2 == other.node2 &&
    dimension == other.dimension &&
    reason == other.reason &&
    normative == other.normative &&
    formatting == other.formatting
  # Note: path and serialized content are not part of equality
  # since they're derived from nodes, not independent properties
end

#formatting?Boolean

Formatting diffs are whitespace/line break differences with no semantic meaning

Returns:

  • (Boolean)

    true if this diff is formatting-only (purely cosmetic)



68
69
70
# File 'lib/canon/diff/diff_node.rb', line 68

def formatting?
  @formatting == true
end

#informative?Boolean

Formatting-only diffs are never informative

Returns:

  • (Boolean)

    true if this diff is informative only (doesn’t affect equivalence)



60
61
62
63
64
# File 'lib/canon/diff/diff_node.rb', line 60

def informative?
  return false if formatting?

  @normative == false
end

#normative?Boolean

Formatting-only diffs are never normative

Returns:

  • (Boolean)

    true if this diff is normative (affects equivalence)



52
53
54
55
56
# File 'lib/canon/diff/diff_node.rb', line 52

def normative?
  return false if formatting?

  @normative == true
end

#to_hObject



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/canon/diff/diff_node.rb', line 72

def to_h
  {
    node1: node1,
    node2: node2,
    dimension: dimension,
    reason: reason,
    normative: normative,
    formatting: formatting,
    path: path,
    serialized_before: serialized_before,
    serialized_after: serialized_after,
    attributes_before: attributes_before,
    attributes_after: attributes_after,
  }
end