ariadne 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c5b693660af05c17570b71a98e6ed6899932f9b2571fd6f8e4fd7d66d61e4fc
4
- data.tar.gz: 8a3697425b580d3f40568b8b5a33d80e6d149197b0ede9fa2d35042b5ad90c8a
3
+ metadata.gz: a71929c19a3e8fff0abc484843c1762edf12ecf6f45d90a6e0394cb4743aa243
4
+ data.tar.gz: e5959ac737aaf0392957164769dcb56e72ca73362da8431fcbb4a9d47fcc835b
5
5
  SHA512:
6
- metadata.gz: 9d41649519721ea428249d049823a82ecaf4530dc436b27b4bd643e815e12f70eec38895e752b46ca57154ed7e9b5c9133bc799903b69479876c6d9c3577732f
7
- data.tar.gz: 70555aa75a6656cf16e199abb1b3b29ce960f806b3b68846edbf378072d7a4129c3268cfd2d8e06d44dde667f2682b9cee8766d63f9e98138df6f190b8a1ea7f
6
+ metadata.gz: 1bec945c8243605fb555b88e817c9cfe84268e06b4ae110ef2c5b472f86360deb5c91d4cfa3a8e3cf9220f90259bddcfe902fcd829fbe53d2090722bb6f454d9
7
+ data.tar.gz: fbb773617d74362a76c461c0c01283239175fea01d8915e3b810299b13b7849863cdefb1f8875592c3421da5a19945236736c7ec2df296a0d4fc72f8d666082c
data/lib/ariadne/log.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "open3"
4
- require "ariadne/text"
4
+ require "ariadne/string/color"
5
5
 
6
6
  module Ariadne
7
7
  class Log
@@ -22,50 +22,68 @@ module Ariadne
22
22
 
23
23
  def text
24
24
  @text ||=
25
- Text.new(
26
- [rank, " ", offset, " ", offset_dashes, class_name, prefix, method_name]
27
- .tap { add_parameters(_1) }
28
- .join
29
- ).truncate(200)
25
+ [
26
+ rank,
27
+ " ",
28
+ depth_dashes,
29
+ class_name,
30
+ prefix,
31
+ method_name,
32
+ parameters,
33
+ return_value_type
34
+ ].join
30
35
  end
31
36
 
32
37
  def rank
33
- Text.new(@seam.rank.to_s.rjust(4)).gray
38
+ @seam.rank.to_s.rjust(4).gray
34
39
  end
35
40
 
36
- def offset
37
- Text.new("(#{@seam.offset})").gray
38
- end
39
-
40
- def offset_dashes
41
- Text.new("-" * @seam.offset).gray.tap { _1 << " " if @seam.offset.positive? }
41
+ def depth_dashes
42
+ ("-" * @seam.depth).gray.tap { _1 << " " if @seam.depth.positive? }
42
43
  end
43
44
 
44
45
  def class_name
45
- Text.new(@seam.class_name).green
46
+ @seam.klass.name.green
46
47
  end
47
48
 
48
49
  def prefix
49
- Text.new(@seam.prefix).gray
50
+ @seam.prefix.gray
50
51
  end
51
52
 
52
53
  def method_name
53
- Text.new(@seam.method_name).cyan
54
+ @seam.method_name.to_s.cyan
54
55
  end
55
56
 
56
- def add_parameters(str)
57
- return if parameters == ""
58
-
59
- str << Text.new("(#{parameters})").magenta
57
+ def return_value_type
58
+ value = type(@seam.return_value)
59
+ " -> #{value}".yellow
60
60
  end
61
61
 
62
62
  def parameters
63
- @parameters ||=
64
- @seam.parameters.map do |parameter|
65
- arg = Text.new(parameter.stringified_arg).truncate(50)
66
- arg = parameter.type ? "<#{parameter.type}> #{arg}" : arg
67
- "#{parameter.param}: #{arg}"
68
- end.join(", ")
63
+ return if @seam.parameters.empty?
64
+
65
+ [
66
+ "(",
67
+ @seam.parameters.flat_map { "#{_1.param}: #{arg(_1)}" }.join(", "),
68
+ ")"
69
+ ].join.magenta
70
+ end
71
+
72
+ def arg(parameter)
73
+ if parameter.type == :rest || %i[* ** &].include?(parameter.param)
74
+ parameter.arg.map { type(_1) }.join(", ")
75
+ else
76
+ type(parameter.arg)
77
+ end
78
+ end
79
+
80
+ def type(arg)
81
+ case arg
82
+ when "<?>" then "<?>"
83
+ when TrueClass, FalseClass then "Boolean"
84
+ when NilClass then "nil"
85
+ else arg.class.to_s
86
+ end
69
87
  end
70
88
  end
71
89
  end
data/lib/ariadne/seam.rb CHANGED
@@ -1,40 +1,79 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "open3"
4
- require "ariadne/parameter"
5
4
 
6
5
  module Ariadne
7
- class Seam < SimpleDelegator
8
- attr_reader :rank, :offset
6
+ class Seam
7
+ attr_reader :rank, :depth, :klass, :method_name, :prefix, :parameters, :return_value, :binding, :path
9
8
 
10
- def initialize(tracepoint, rank:, offset:)
11
- super(tracepoint)
12
- @rank = rank
13
- @offset = offset
14
- end
9
+ Parameter = Struct.new(:type, :param, :arg)
10
+
11
+ class << self
12
+ # We cannot make public methods because accessing the TracePoint
13
+ # after it has been disabled would raise a RunTimeError
14
+ # with message "access from outside".
15
+ # We need to set the values while the TracePoint is enabled.
16
+ def build(tracepoint, rank:, depth:)
17
+ raise "tracepoint is disabled" unless tracepoint.enabled?
15
18
 
16
- # Seam.new(@rank, class_name(tp), prefix(tp), tp.method_id, parameters, @seams.size)
17
- def class_name
18
- if __getobj__.self.is_a?(Module)
19
- __getobj__.self.name
20
- else
21
- __getobj__.self.class.name
19
+ new(rank: rank, depth: depth).tap do |seam|
20
+ seam.instance_variable_set(:@klass, klass(tracepoint))
21
+ seam.instance_variable_set(:@prefix, prefix(tracepoint))
22
+ seam.instance_variable_set(:@method_name, method_name(tracepoint))
23
+ seam.instance_variable_set(:@parameters, parameters(tracepoint))
24
+ seam.instance_variable_set(:@path, path(tracepoint))
25
+ end
22
26
  end
23
- end
24
27
 
25
- def method_name
26
- method_id
27
- end
28
+ private
28
29
 
29
- def prefix
30
- __getobj__.self.is_a?(Module) ? "." : "#"
31
- end
30
+ def klass(tracepoint)
31
+ if tracepoint.self.is_a?(Module)
32
+ tracepoint.self
33
+ else
34
+ tracepoint.self.class
35
+ end
36
+ end
32
37
 
33
- def parameters
34
- method = __getobj__.self.method(method_name)
35
- method.parameters.map do |parameter|
36
- Parameter.new(parameter, binding: binding)
38
+ def method_name(tracepoint)
39
+ tracepoint.method_id
37
40
  end
41
+
42
+ def prefix(tracepoint)
43
+ tracepoint.self.is_a?(Module) ? "." : "#"
44
+ end
45
+
46
+ def parameters(tracepoint)
47
+ method = tracepoint.self.method(tracepoint.method_id)
48
+ if forwarded_parameters?(method)
49
+ [Parameter.new(:rest, "...", ["<?>"])]
50
+ else
51
+ method.parameters.flat_map do |parameter|
52
+ type = parameter.first
53
+ param = parameter.last
54
+ arg = %i[* ** &].include?(param) ? ["<?>"] : tracepoint.binding.local_variable_get(param)
55
+ Parameter.new(type, param, arg)
56
+ rescue NameError
57
+ Parameter.new(type, param, type == :rest ? ["<?>"] : "<?>")
58
+ end
59
+ end
60
+ end
61
+
62
+ # return true if method's signature is like `def my_method(...)`
63
+ def forwarded_parameters?(method)
64
+ method.parameters == [%i[rest *], %i[block &]]
65
+ end
66
+
67
+ def path(tracepoint)
68
+ tracepoint.path
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def initialize(rank:, depth:)
75
+ @rank = rank
76
+ @depth = depth
38
77
  end
39
78
  end
40
79
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ module String
5
+ module Color
6
+ COLORS = %w[
7
+ black
8
+ red
9
+ green
10
+ yellow
11
+ blue
12
+ magenta
13
+ cyan
14
+ gray
15
+ ].freeze
16
+
17
+ COLORS.each.with_index do |color, index|
18
+ code = index + 30
19
+ define_method(color) do
20
+ "\e[#{code}m#{bleach}\e[0m"
21
+ end
22
+ bg_code = index + 40
23
+ define_method("bg_#{color}") do
24
+ "\e[#{bg_code}m#{bleach}\e[0m"
25
+ end
26
+ end
27
+
28
+ def bleach
29
+ gsub(/\e\[\d{1,2}m/, "")
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ String.include Ariadne::String::Color
@@ -6,44 +6,86 @@ require "ariadne/log"
6
6
 
7
7
  module Ariadne
8
8
  class Thread
9
+ attr_reader :seams
10
+
9
11
  LOG_FILE = "thread.log"
10
12
  DEFAULT_INCLUDE_PATHS = Open3.capture3("pwd").first.strip
11
13
  DEFAULT_EXCLUDE_PATHS = [].freeze
12
14
 
13
15
  def initialize(include_paths: nil, exclude_paths: nil)
14
- @include_paths = include_paths || DEFAULT_INCLUDE_PATHS
15
- @exclude_paths = exclude_paths || DEFAULT_EXCLUDE_PATHS
16
+ @include_paths = Array(include_paths) || DEFAULT_INCLUDE_PATHS
17
+ @exclude_paths = Array(exclude_paths) || DEFAULT_EXCLUDE_PATHS
18
+ @seams = []
16
19
  end
17
20
 
18
21
  def call
19
- @rank = 0
20
- @seams = []
21
- file = File.open(LOG_FILE, "w")
22
- trace = build_trace
22
+ prepare
23
+ open_file
23
24
  trace.enable
24
25
  yield
25
26
  ensure
26
27
  trace.disable
27
- file.close
28
+ log
29
+ close_file
28
30
  end
29
31
 
30
32
  private
31
33
 
32
- def build_trace
33
- TracePoint.new(:call, :return) do |tp|
34
- next if @include_paths.none? { tp.path.include?(_1) }
35
- next if @exclude_paths.any? { tp.path.include?(_1) }
36
-
37
- case tp.event
38
- when :call
39
- seam = Seam.new(tp, rank: @rank, offset: @seams.size)
40
- @seams << seam
41
- @rank += 1
42
- Log.new(seam).call
43
- when :return
44
- @seams.pop
34
+ def prepare
35
+ @rank = 0
36
+ @depth = 0
37
+ @seams = []
38
+ end
39
+
40
+ def open_file
41
+ @file = File.open(LOG_FILE, "w")
42
+ end
43
+
44
+ def close_file
45
+ @file.close
46
+ end
47
+
48
+ def trace
49
+ @trace ||=
50
+ TracePoint.new(:call, :return) do |tracepoint|
51
+ next if tracepoint.self.is_a?(TracePoint)
52
+
53
+ case tracepoint.event
54
+ when :call
55
+ on_call(tracepoint)
56
+ when :return
57
+ on_return(tracepoint)
58
+ end
45
59
  end
46
- end
60
+ end
61
+
62
+ def on_call(tracepoint)
63
+ return unless selected?(tracepoint)
64
+
65
+ seam = Seam.build(tracepoint, rank: @rank, depth: @depth)
66
+ @seams << seam
67
+
68
+ @rank += 1
69
+ @depth += 1
70
+ end
71
+
72
+ def on_return(tracepoint)
73
+ return unless selected?(tracepoint)
74
+
75
+ @depth -= 1
76
+
77
+ seam = @seams.reverse.find { _1.depth == @depth }
78
+ seam&.instance_variable_set(:@return_value, tracepoint.return_value)
79
+ seam&.instance_variable_set(:@binding, tracepoint.binding)
80
+ end
81
+
82
+ def selected?(tracepoint)
83
+ @include_paths.any? { tracepoint.path.include?(_1) } &&
84
+ @exclude_paths.none? { tracepoint.path.include?(_1) }
85
+ end
86
+
87
+ def log
88
+ @seams.each { Log.new(_1).call }
47
89
  end
48
90
  end
49
91
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ariadne
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.5"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ariadne
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edouard Piron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-23 00:00:00.000000000 Z
11
+ date: 2023-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: simplecov
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: yard
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -117,9 +103,8 @@ extra_rdoc_files: []
117
103
  files:
118
104
  - lib/ariadne.rb
119
105
  - lib/ariadne/log.rb
120
- - lib/ariadne/parameter.rb
121
106
  - lib/ariadne/seam.rb
122
- - lib/ariadne/text.rb
107
+ - lib/ariadne/string/color.rb
123
108
  - lib/ariadne/thread.rb
124
109
  - lib/ariadne/version.rb
125
110
  homepage: https://github.com/BigBigDoudou/ariadne
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "open3"
4
- require "ariadne/text"
5
-
6
- module Ariadne
7
- class Parameter < SimpleDelegator
8
- RUBY_LITERALS = [
9
- NilClass,
10
- String,
11
- Integer,
12
- Float,
13
- Proc,
14
- TrueClass,
15
- FalseClass,
16
- Symbol,
17
- Array,
18
- Range,
19
- Regexp,
20
- Hash
21
- ].freeze
22
-
23
- def initialize(parameter, binding:)
24
- super(parameter)
25
- @binding = binding
26
- end
27
-
28
- def param
29
- last
30
- end
31
-
32
- def arg
33
- @binding.local_variable_get(last)
34
- rescue NameError
35
- "?"
36
- end
37
-
38
- def type
39
- return if arg.is_a?(Class) || RUBY_LITERALS.include?(arg.class)
40
-
41
- arg.class.name
42
- end
43
-
44
- def stringified_arg
45
- case arg
46
- when NilClass
47
- "nil"
48
- when Proc
49
- "#<Proc>"
50
- when Class
51
- arg.name
52
- when String
53
- "\"#{arg}\""
54
- else
55
- arg.to_s
56
- end
57
- end
58
- end
59
- end
data/lib/ariadne/text.rb DELETED
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Ariadne
4
- class Text < String
5
- COLORS = %w[
6
- black
7
- red
8
- green
9
- yellow
10
- blue
11
- magenta
12
- cyan
13
- gray
14
- ].freeze
15
-
16
- COLORS.each.with_index do |color, index|
17
- code = index + 30
18
- define_method(color) do
19
- "\e[#{code}m#{bleach}\e[0m"
20
- end
21
- bg_code = index + 40
22
- define_method("bg_#{color}") do
23
- "\e[#{bg_code}m#{bleach}\e[0m"
24
- end
25
- end
26
-
27
- def initialize(str)
28
- super(str.to_s)
29
- end
30
-
31
- def truncate(size)
32
- if self.size > size
33
- Text.new("#{self[..size]}...")
34
- else
35
- self
36
- end
37
- end
38
-
39
- def bleach
40
- gsub(/\e\[\d{1,2}m/, "")
41
- end
42
- end
43
- end