diff options
author | Austin Ziegler <austin@zieglers.ca> | 2020-07-03 12:41:48 -0400 |
---|---|---|
committer | Austin Ziegler <austin@zieglers.ca> | 2020-07-03 12:41:48 -0400 |
commit | 476b27efa27d89831ecb9f33e070ce8efa4f5d5e (patch) | |
tree | d24be368ab9f4b9e84b851eb219d4bd353a08d9d /lib/diff/lcs/change.rb | |
parent | ba11b5923a0007a950bfedef6bd3596baf200f2b (diff) | |
download | diff-lcs-sorbet.tar.gz |
Attempt to sorbetize #1sorbet
Diffstat (limited to 'lib/diff/lcs/change.rb')
-rw-r--r-- | lib/diff/lcs/change.rb | 155 |
1 files changed, 114 insertions, 41 deletions
diff --git a/lib/diff/lcs/change.rb b/lib/diff/lcs/change.rb index 7977be5..520aeda 100644 --- a/lib/diff/lcs/change.rb +++ b/lib/diff/lcs/change.rb @@ -1,107 +1,133 @@ # frozen_string_literal: true +# typed: strict # Represents a simplistic (non-contextual) change. Represents the removal or # addition of an element from either the old or the new sequenced # enumerable. class Diff::LCS::Change - INTEGER = 1.class # Fixnum is deprecated in Ruby 2.4 + extend T::Sig + + ArrayT = T.type_alias{ + T.any( + [String, Integer, T.untyped], + [String, Integer, T.untyped, Integer, T.untyped], + [String, [Integer, T.untyped], [Integer, T.untyped]] + ) + } + + ChangeT = T.type_alias { T.any(Diff::LCS::Change, Diff::LCS::ContextChange) } # The only actions valid for changes are '+' (add), '-' (delete), '=' # (no change), '!' (changed), '<' (tail changes from first sequence), or # '>' (tail changes from second sequence). The last two ('<>') are only # found with Diff::LCS::diff and Diff::LCS::sdiff. - VALID_ACTIONS = %w(+ - = ! > <).freeze + VALID_ACTIONS = T.let(%w(+ - = ! > <).freeze, T::Array[String]) + sig { params(action: T.any(String, Diff::LCS::Change)).returns(T::Boolean) } def self.valid_action?(action) - VALID_ACTIONS.include? action + return false unless action.kind_of?(String) + + VALID_ACTIONS.include?(action) end # Returns the action this Change represents. + sig { returns(String) } attr_reader :action + # Returns the position of the Change. + sig { returns(Integer) } attr_reader :position + # Returns the sequence element of the Change. + sig { returns(T.untyped) } attr_reader :element - def initialize(*args) - @action, @position, @element = *args + sig { + params( + action: String, + position: Integer, + element: T.untyped, + _: T.untyped + ).void + } + def initialize(action, position, element, *_) + @action = action + @position = position + @element = element fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action) - fail 'Invalid Position Type' unless @position.kind_of? INTEGER + fail 'Invalid Position Type' unless @position.kind_of? Integer end + sig { params(_args: T.untyped).returns(String) } def inspect(*_args) "#<#{self.class}: #{to_a.inspect}>" end + sig { returns(ArrayT) } def to_a [@action, @position, @element] end alias to_ary to_a + sig { params(arr: ArrayT).returns(ChangeT) } def self.from_a(arr) arr = arr.flatten(1) case arr.size when 5 - Diff::LCS::ContextChange.new(*(arr[0...5])) + Diff::LCS::ContextChange.new(arr[0], arr[1], arr[2], arr[3], arr[4]) when 3 - Diff::LCS::Change.new(*(arr[0...3])) + Diff::LCS::Change.new(arr[0], arr[1], arr[2]) else fail 'Invalid change array format provided.' end end - def to_change(action) - args = - case action - when '-' - [action, old_position, old_element] - when '+' - [action, new_position, new_element] - else - fail 'Invalid action for creating a change' - end - - Diff::LCS::Change.new(*args) - end - include Comparable + sig { params(other: ChangeT).returns(T::Boolean) } def ==(other) - (self.class == other.class) and - (action == other.action) and - (position == other.position) and - (element == other.element) + self.class == other.class && + action == other.action && + position == other.position && + element == other.element end + sig { params(other: Diff::LCS::Change).returns(Integer) } def <=>(other) r = action <=> other.action - r = position <=> other.position if r.zero? - r = element <=> other.element if r.zero? + r = position <=> other.position if T.must(r).zero? + r = element <=> other.element if T.must(r).zero? r end + sig { returns(T::Boolean) } def adding? @action == '+' end + sig { returns(T::Boolean) } def deleting? @action == '-' end + sig { returns(T::Boolean) } def unchanged? @action == '=' end + sig { returns(T::Boolean) } def changed? @action == '!' end + sig { returns(T::Boolean) } def finished_a? @action == '>' end + sig { returns(T::Boolean) } def finished_b? @action == '<' end @@ -111,27 +137,51 @@ end # elements in the old and the new sequenced enumerables as well as the action # taken. class Diff::LCS::ContextChange < Diff::LCS::Change + extend T::Sig + # We don't need these two values. undef :position undef :element # Returns the old position being changed. + sig { returns(Integer) } attr_reader :old_position + # Returns the new position being changed. + sig { returns(Integer) } attr_reader :new_position + # Returns the old element being changed. + sig { returns(T.untyped) } attr_reader :old_element + # Returns the new element being changed. + sig { returns(T.untyped) } attr_reader :new_element - def initialize(*args) - @action, @old_position, @old_element, @new_position, @new_element = *args + sig { + params( + action: String, + old_position: Integer, + old_element: T.untyped, + new_position: Integer, + new_element: T.untyped, + _: T.untyped + ).void + } + def initialize(action, old_position, old_element, new_position, new_element, *_) + @action = action + @old_position = old_position + @old_element = old_element + @new_position = new_position + @new_element = new_element fail "Invalid Change Action '#{@action}'" unless Diff::LCS::Change.valid_action?(@action) - fail 'Invalid (Old) Position Type' unless @old_position.nil? or @old_position.kind_of? INTEGER - fail 'Invalid (New) Position Type' unless @new_position.nil? or @new_position.kind_of? INTEGER + fail 'Invalid (Old) Position Type' unless @old_position.nil? or @old_position.kind_of? Integer + fail 'Invalid (New) Position Type' unless @new_position.nil? or @new_position.kind_of? Integer end + sig { returns(ArrayT) } def to_a [ @action, @@ -142,12 +192,26 @@ class Diff::LCS::ContextChange < Diff::LCS::Change alias to_ary to_a + sig { params(action: String).returns(Diff::LCS::Change) } + def to_change(action) + case action + when '-' + Diff::LCS::Change.new(action, old_position, old_element) + when '+' + Diff::LCS::Change.new(action, new_position, new_element) + else + fail 'Invalid action for creating a change' + end + end + + sig { params(arr: ArrayT).returns(ChangeT) } def self.from_a(arr) Diff::LCS::Change.from_a(arr) end # Simplifies a context change for use in some diff callbacks. '<' actions # are converted to '-' and '>' actions are converted to '+'. + sig { returns(T.any(Diff::LCS::Change, Diff::LCS::ContextChange)) } def simplify args = case action @@ -164,24 +228,33 @@ class Diff::LCS::ContextChange < Diff::LCS::Change # Simplifies a context change for use in some diff callbacks. '<' actions # are converted to '-' and '>' actions are converted to '+'. + sig { + params(event: Diff::LCS::ContextChange).returns(T.any( + Diff::LCS::Change, + Diff::LCS::ContextChange + )) + } def self.simplify(event) event.simplify end + sig { params(other: ChangeT).returns(T::Boolean) } def ==(other) - (self.class == other.class) and - (@action == other.action) and - (@old_position == other.old_position) and - (@new_position == other.new_position) and - (@old_element == other.old_element) and - (@new_element == other.new_element) + return false unless other.kind_of?(Diff::LCS::ContextChange) + + @action == other.action && + @old_position == other.old_position && + @new_position == other.new_position && + @old_element == other.old_element && + @new_element == other.new_element end + sig { params(other: Diff::LCS::ContextChange).returns(Integer) } def <=>(other) r = @action <=> other.action - r = @old_position <=> other.old_position if r.zero? - r = @new_position <=> other.new_position if r.zero? - r = @old_element <=> other.old_element if r.zero? + r = @old_position <=> other.old_position if T.must(r).zero? + r = @new_position <=> other.new_position if T.must(r).zero? + r = @old_element <=> other.old_element if T.must(r).zero? r = @new_element <=> other.new_element if r.zero? r end |