From c221c33396baabb7d121d53c5c9356605ddeab5a Mon Sep 17 00:00:00 2001 From: Hibariya Date: Mon, 15 Jul 2024 08:36:45 +0000 Subject: [PATCH 1/2] Order the types and method/attribute definitions generated by Orthoses::Trace --- lib/orthoses/trace/attribute.rb | 4 +-- lib/orthoses/trace/attribute_test.rb | 38 +++++++++++++++++++++-- lib/orthoses/trace/method.rb | 4 +-- lib/orthoses/trace/method_test.rb | 45 ++++++++++++++++++++++++++-- 4 files changed, 83 insertions(+), 8 deletions(-) diff --git a/lib/orthoses/trace/attribute.rb b/lib/orthoses/trace/attribute.rb index 4f1280f..c5473d1 100644 --- a/lib/orthoses/trace/attribute.rb +++ b/lib/orthoses/trace/attribute.rb @@ -44,8 +44,8 @@ def call end @captured_dict.each do |mod_name, captures| - captures.each do |(kind, prefix, name), types| - injected = Utils::TypeList.new(types).inject + captures.sort.each do |(kind, prefix, name), types| + injected = Utils::TypeList.new(types.sort).inject store[mod_name] << "#{kind} #{prefix}#{name}: #{injected}" end end diff --git a/lib/orthoses/trace/attribute_test.rb b/lib/orthoses/trace/attribute_test.rb index 50af341..a219d0b 100644 --- a/lib/orthoses/trace/attribute_test.rb +++ b/lib/orthoses/trace/attribute_test.rb @@ -12,6 +12,11 @@ class Bar attr_accessor :attr_acce_publ end + class Baz + attr_accessor :multi_types + attr_accessor :other + end + attr_accessor :attr_acce_publ attr_reader :attr_read_publ attr_writer :attr_writ_publ @@ -20,6 +25,7 @@ class << self end attr_accessor :attr_acce_priv + private :attr_acce_priv def initialize @@ -52,10 +58,10 @@ def test_attribute(t) expect = <<~RBS class TraceAttributeTest::Foo attr_accessor attr_acce_priv: Integer - attr_accessor attr_acce_publ: Symbol | String + attr_accessor attr_acce_publ: String | Symbol + attr_accessor self.self_attr_acce_publ: Integer? attr_reader attr_read_publ: Symbol attr_writer attr_writ_publ: Integer - attr_accessor self.self_attr_acce_publ: Integer? end class TraceAttributeTest::Foo::Bar @@ -66,4 +72,32 @@ class TraceAttributeTest::Foo::Bar t.error("expect=\n```rbs\n#{expect}```\n, but got \n```rbs\n#{actual}```\n") end end + + def test_order(t) + store1 = Orthoses::Trace::Attribute.new(->{ + LOADER_ATTRIBUTE.call + baz = Foo::Baz.new + baz.other = :sym + baz.multi_types = 0 + baz.multi_types = '1' + + Orthoses::Utils.new_store + }, patterns: ['TraceAttributeTest::Foo::Baz']).call + + store2 = Orthoses::Trace::Attribute.new(->{ + LOADER_ATTRIBUTE.call + baz = Foo::Baz.new + baz.multi_types = '1' + baz.multi_types = 0 + baz.other = :sym + + Orthoses::Utils.new_store + }, patterns: ['TraceAttributeTest::Foo::Baz']).call + + expect = store1.map { _2.to_rbs }.join("\n") + actual = store2.map { _2.to_rbs }.join("\n") + unless expect == actual + t.error("expect=\n```rbs\n#{expect}```\n, but got \n```rbs\n#{actual}```\n") + end + end end diff --git a/lib/orthoses/trace/method.rb b/lib/orthoses/trace/method.rb index 68b39c4..d4d2b80 100644 --- a/lib/orthoses/trace/method.rb +++ b/lib/orthoses/trace/method.rb @@ -77,9 +77,9 @@ def build_members def build_method_definitions untyped = ::RBS::Types::Bases::Any.new(location: nil) - @args_return_map.map do |(mod_name, kind, visibility, method_id), type_samples| + @args_return_map.sort_by {|key, _| key.join }.map do |(mod_name, kind, visibility, method_id), type_samples| type_samples.uniq! - method_types = type_samples.map do |(op_name_types, return_type)| + method_types = type_samples.sort.map do |(op_name_types, return_type)| required_positionals = [] optional_positionals = [] rest = nil diff --git a/lib/orthoses/trace/method_test.rb b/lib/orthoses/trace/method_test.rb index e8e7466..7423fd9 100644 --- a/lib/orthoses/trace/method_test.rb +++ b/lib/orthoses/trace/method_test.rb @@ -44,6 +44,15 @@ def if_raise(a) end end + def multi_types(key) + { + 0 => 0, + 1 => '1', + '2' => '2', + '3' => 3, + }[key] + end + private def priv(bool) @@ -86,13 +95,13 @@ def test_method(t) actual = store.map { |n, c| c.to_rbs }.join("\n") expect = <<~RBS class TraceMethodTest::M - private def initialize: (Integer a) -> void def a_ten: () -> Integer def b_ten: (Integer b) -> Integer - private def priv: (bool bool) -> (Integer | Symbol) def call_priv: (bool c) -> (Integer | Symbol) def dele: (*Array[bool] a, **Hash[untyped, untyped]) -> Integer def if_raise: (bool a) -> String + private def initialize: (Integer a) -> void + private def priv: (bool bool) -> (Integer | Symbol) def self.singleton_method?: () -> bool alias c_ten a_ten alias self.alias_singleton_method? self.singleton_method? @@ -131,4 +140,36 @@ def test_raise_first(t) Orthoses::Utils.new_store }, patterns: ['TraceMethodTest']).call end + + def test_order(t) + store1 = Orthoses::Trace::Method.new(->{ + LOADER_METHOD.call + m = M.new(100) + m.a_ten + m.multi_types 0 + m.multi_types 1 + m.multi_types '2' + m.multi_types '3' + + Orthoses::Utils.new_store + }, patterns: ['TraceMethodTest::M']).call + + store2 = Orthoses::Trace::Method.new(->{ + LOADER_METHOD.call + m = M.new(100) + m.multi_types '3' + m.multi_types '2' + m.multi_types 1 + m.multi_types 0 + m.a_ten + + Orthoses::Utils.new_store + }, patterns: ['TraceMethodTest::M']).call + + expect = store1.map { _2.to_rbs }.join("\n") + actual = store2.map { _2.to_rbs }.join("\n") + unless expect == actual + t.error("expect=\n```rbs\n#{expect}```\n, but got \n```rbs\n#{actual}```\n") + end + end end From 3eeea55a0410fc1d4fb9b3e7b7f94815aed358e2 Mon Sep 17 00:00:00 2001 From: Hibariya Date: Fri, 19 Jul 2024 13:17:59 +0000 Subject: [PATCH 2/2] Make it an option, also, sorting methods should be done by Orthoses::Sort --- known_sig/orthoses/trace/attribute.rbs | 3 ++ known_sig/orthoses/trace/method.rbs | 3 ++ lib/orthoses/trace/attribute.rb | 8 ++++-- lib/orthoses/trace/attribute_test.rb | 29 ++++++++++++++++---- lib/orthoses/trace/method.rb | 8 ++++-- lib/orthoses/trace/method_test.rb | 38 +++++++++++++++++++++----- sig/orthoses/trace.rbs | 10 ++++--- 7 files changed, 77 insertions(+), 22 deletions(-) diff --git a/known_sig/orthoses/trace/attribute.rbs b/known_sig/orthoses/trace/attribute.rbs index e96b069..781f4bc 100644 --- a/known_sig/orthoses/trace/attribute.rbs +++ b/known_sig/orthoses/trace/attribute.rbs @@ -2,6 +2,9 @@ module Orthoses class Trace class Attribute include Orthoses::Trace::Targetable + + def initialize: (Orthoses::_Call loader, patterns: Array[String], ?sort_union_types: bool?) -> void + def call: () -> Orthoses::store end end end diff --git a/known_sig/orthoses/trace/method.rbs b/known_sig/orthoses/trace/method.rbs index 9016e6e..f8a168f 100644 --- a/known_sig/orthoses/trace/method.rbs +++ b/known_sig/orthoses/trace/method.rbs @@ -2,6 +2,9 @@ module Orthoses class Trace class Method include Orthoses::Trace::Targetable + + def initialize: (Orthoses::_Call loader, patterns: Array[String], ?sort_union_types: bool?) -> void + def call: () -> Orthoses::store end end end diff --git a/lib/orthoses/trace/attribute.rb b/lib/orthoses/trace/attribute.rb index c5473d1..56ab1b0 100644 --- a/lib/orthoses/trace/attribute.rb +++ b/lib/orthoses/trace/attribute.rb @@ -23,9 +23,10 @@ def attr_writer(*names) include Targetable - def initialize(loader, patterns:) + def initialize(loader, patterns:, sort_union_types: true) @loader = loader @patterns = patterns + @sort_union_types = sort_union_types @captured_dict = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = [] } } end @@ -44,8 +45,9 @@ def call end @captured_dict.each do |mod_name, captures| - captures.sort.each do |(kind, prefix, name), types| - injected = Utils::TypeList.new(types.sort).inject + captures.each do |(kind, prefix, name), types| + types.sort! if @sort_union_types + injected = Utils::TypeList.new(types).inject store[mod_name] << "#{kind} #{prefix}#{name}: #{injected}" end end diff --git a/lib/orthoses/trace/attribute_test.rb b/lib/orthoses/trace/attribute_test.rb index a219d0b..c36ef07 100644 --- a/lib/orthoses/trace/attribute_test.rb +++ b/lib/orthoses/trace/attribute_test.rb @@ -14,7 +14,6 @@ class Bar class Baz attr_accessor :multi_types - attr_accessor :other end attr_accessor :attr_acce_publ @@ -59,9 +58,9 @@ def test_attribute(t) class TraceAttributeTest::Foo attr_accessor attr_acce_priv: Integer attr_accessor attr_acce_publ: String | Symbol - attr_accessor self.self_attr_acce_publ: Integer? attr_reader attr_read_publ: Symbol attr_writer attr_writ_publ: Integer + attr_accessor self.self_attr_acce_publ: Integer? end class TraceAttributeTest::Foo::Bar @@ -73,11 +72,10 @@ class TraceAttributeTest::Foo::Bar end end - def test_order(t) + def test_union_sort(t) store1 = Orthoses::Trace::Attribute.new(->{ LOADER_ATTRIBUTE.call baz = Foo::Baz.new - baz.other = :sym baz.multi_types = 0 baz.multi_types = '1' @@ -89,7 +87,6 @@ def test_order(t) baz = Foo::Baz.new baz.multi_types = '1' baz.multi_types = 0 - baz.other = :sym Orthoses::Utils.new_store }, patterns: ['TraceAttributeTest::Foo::Baz']).call @@ -100,4 +97,26 @@ def test_order(t) t.error("expect=\n```rbs\n#{expect}```\n, but got \n```rbs\n#{actual}```\n") end end + + def test_without_union_sort(t) + store = Orthoses::Trace::Attribute.new(->{ + LOADER_ATTRIBUTE.call + baz = Foo::Baz.new + # The order of the union types will be the following + baz.multi_types = '1' # String + baz.multi_types = 0 # Integer + + Orthoses::Utils.new_store + }, patterns: ['TraceAttributeTest::Foo::Baz'], sort_union_types: false).call + + expect = store.map { _2.to_rbs }.join("\n") + actual = <<~RBS + class TraceAttributeTest::Foo::Baz + attr_accessor multi_types: String | Integer + end + RBS + unless expect == actual + t.error("expect=\n```rbs\n#{expect}```\n, but got \n```rbs\n#{actual}```\n") + end + end end diff --git a/lib/orthoses/trace/method.rb b/lib/orthoses/trace/method.rb index d4d2b80..7a1e8de 100644 --- a/lib/orthoses/trace/method.rb +++ b/lib/orthoses/trace/method.rb @@ -7,9 +7,10 @@ class Method Info = Struct.new(:key, :op_name_types, :raised, keyword_init: true) include Targetable - def initialize(loader, patterns:) + def initialize(loader, patterns:, sort_union_types: true) @loader = loader @patterns = patterns + @sort_union_types = sort_union_types @stack = [] @args_return_map = Hash.new { |h, k| h[k] = [] } @@ -77,9 +78,10 @@ def build_members def build_method_definitions untyped = ::RBS::Types::Bases::Any.new(location: nil) - @args_return_map.sort_by {|key, _| key.join }.map do |(mod_name, kind, visibility, method_id), type_samples| + @args_return_map.map do |(mod_name, kind, visibility, method_id), type_samples| type_samples.uniq! - method_types = type_samples.sort.map do |(op_name_types, return_type)| + type_samples.sort! if @sort_union_types + method_types = type_samples.map do |(op_name_types, return_type)| required_positionals = [] optional_positionals = [] rest = nil diff --git a/lib/orthoses/trace/method_test.rb b/lib/orthoses/trace/method_test.rb index 7423fd9..2be18c4 100644 --- a/lib/orthoses/trace/method_test.rb +++ b/lib/orthoses/trace/method_test.rb @@ -95,13 +95,13 @@ def test_method(t) actual = store.map { |n, c| c.to_rbs }.join("\n") expect = <<~RBS class TraceMethodTest::M + private def initialize: (Integer a) -> void def a_ten: () -> Integer def b_ten: (Integer b) -> Integer + private def priv: (bool bool) -> (Integer | Symbol) def call_priv: (bool c) -> (Integer | Symbol) def dele: (*Array[bool] a, **Hash[untyped, untyped]) -> Integer def if_raise: (bool a) -> String - private def initialize: (Integer a) -> void - private def priv: (bool bool) -> (Integer | Symbol) def self.singleton_method?: () -> bool alias c_ten a_ten alias self.alias_singleton_method? self.singleton_method? @@ -141,11 +141,10 @@ def test_raise_first(t) }, patterns: ['TraceMethodTest']).call end - def test_order(t) - store1 = Orthoses::Trace::Method.new(->{ + def test_union_sort(t) + store1 = Orthoses::Trace::Method.new(-> { LOADER_METHOD.call m = M.new(100) - m.a_ten m.multi_types 0 m.multi_types 1 m.multi_types '2' @@ -154,14 +153,13 @@ def test_order(t) Orthoses::Utils.new_store }, patterns: ['TraceMethodTest::M']).call - store2 = Orthoses::Trace::Method.new(->{ + store2 = Orthoses::Trace::Method.new(-> { LOADER_METHOD.call m = M.new(100) m.multi_types '3' m.multi_types '2' m.multi_types 1 m.multi_types 0 - m.a_ten Orthoses::Utils.new_store }, patterns: ['TraceMethodTest::M']).call @@ -172,4 +170,30 @@ def test_order(t) t.error("expect=\n```rbs\n#{expect}```\n, but got \n```rbs\n#{actual}```\n") end end + + def test_without_union_sort(t) + store = Orthoses::Trace::Method.new(-> { + LOADER_METHOD.call + m = M.new(100) + # The order of the union types will be the following + m.multi_types '3' # (String) -> Integer + m.multi_types '2' # (String) -> String + m.multi_types 1 # (Integer) -> String + m.multi_types 0 # (Integer) -> Integer + + Orthoses::Utils.new_store + }, patterns: ['TraceMethodTest::M'], sort_union_types: false).call + + actual = store.map { _2.to_rbs }.join("\n") + expect = <<~RBS + class TraceMethodTest::M + private def initialize: (Integer a) -> void + def multi_types: (String key) -> (Integer | String) + | (Integer key) -> (String | Integer) + end + RBS + unless expect == actual + t.error("expect=\n```rbs\n#{expect}```\n, but got \n```rbs\n#{actual}```\n") + end + end end diff --git a/sig/orthoses/trace.rbs b/sig/orthoses/trace.rbs index ede5608..dad4105 100644 --- a/sig/orthoses/trace.rbs +++ b/sig/orthoses/trace.rbs @@ -10,9 +10,10 @@ end class Orthoses::Trace::Attribute @loader: untyped @patterns: untyped + @sort_union_types: untyped @captured_dict: untyped - def initialize: (untyped loader, patterns: untyped) -> void - def call: () -> untyped + def initialize: (Orthoses::_Call loader, patterns: Array[String], ?sort_union_types: bool?) -> void + def call: () -> Orthoses::store private def build_trace_hook: () -> untyped include Orthoses::Trace::Targetable end @@ -30,11 +31,12 @@ end class Orthoses::Trace::Method @loader: untyped @patterns: untyped + @sort_union_types: untyped @stack: untyped @args_return_map: untyped @alias_map: untyped - def initialize: (untyped loader, patterns: untyped) -> void - def call: () -> untyped + def initialize: (Orthoses::_Call loader, patterns: Array[String], ?sort_union_types: bool?) -> void + def call: () -> Orthoses::store private def build_trace_point: () -> untyped private def build_members: () -> untyped private def build_method_definitions: () -> untyped