rbs-trace 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +11 -1
  3. data/CHANGELOG.md +30 -0
  4. data/README.md +47 -24
  5. data/Rakefile +8 -6
  6. data/exe/rbs-trace +8 -0
  7. data/lib/rbs/trace/builder.rb +124 -0
  8. data/lib/rbs/trace/cli/inline.rb +62 -0
  9. data/lib/rbs/trace/cli/merge.rb +102 -0
  10. data/lib/rbs/trace/cli.rb +40 -0
  11. data/lib/rbs/trace/file.rb +69 -20
  12. data/lib/rbs/trace/helpers.rb +75 -0
  13. data/lib/rbs/trace/inline_comment_visitor.rb +63 -0
  14. data/lib/rbs/trace/overload_compact.rb +85 -0
  15. data/lib/rbs/trace/return_value_visitor.rb +63 -0
  16. data/lib/rbs/trace/version.rb +2 -2
  17. data/lib/rbs/trace.rb +153 -4
  18. data/rbs_collection.lock.yaml +27 -3
  19. data/sig/generated/rbs/trace/builder.rbs +33 -0
  20. data/sig/generated/rbs/trace/cli/inline.rbs +19 -0
  21. data/sig/generated/rbs/trace/cli/merge.rbs +24 -0
  22. data/sig/generated/rbs/trace/cli.rbs +17 -0
  23. data/sig/generated/rbs/trace/file.rbs +20 -9
  24. data/sig/generated/rbs/trace/helpers.rbs +33 -0
  25. data/sig/generated/rbs/trace/inline_comment_visitor.rbs +27 -0
  26. data/sig/generated/rbs/trace/overload_compact.rbs +21 -0
  27. data/sig/generated/rbs/trace/return_value_visitor.rbs +27 -0
  28. data/sig/generated/rbs/trace/version.rbs +1 -1
  29. data/sig/generated/rbs/trace.rbs +63 -1
  30. data/tmp/.keep +0 -0
  31. metadata +39 -17
  32. data/gemfiles/3.1.gemfile +0 -12
  33. data/gemfiles/3.1.gemfile.lock +0 -68
  34. data/lib/rbs/trace/declaration.rb +0 -107
  35. data/lib/rbs/trace/definition.rb +0 -33
  36. data/lib/rbs/trace/method_tracing.rb +0 -178
  37. data/sig/generated/rbs/trace/declaration.rbs +0 -36
  38. data/sig/generated/rbs/trace/definition.rbs +0 -25
  39. data/sig/generated/rbs/trace/method_tracing.rbs +0 -63
@@ -1,178 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RBS
4
- module Trace
5
- class MethodTracing # rubocop:disable Metrics/ClassLength
6
- ASSIGNED_NODE_TYPES = %i[statements_node local_variable_write_node instance_variable_write_node
7
- class_variable_write_node constant_write_node call_node
8
- embedded_statements_node].freeze #: Array[Symbol]
9
- private_constant :ASSIGNED_NODE_TYPES
10
-
11
- # @rbs [T] () { () -> T } -> T
12
- def enable(&)
13
- trace.enable(&)
14
- end
15
-
16
- # @rbs () -> void
17
- def disable
18
- trace.disable
19
- end
20
-
21
- # @rbs () -> Hash[String, File]
22
- def files
23
- @files ||= {}
24
- end
25
-
26
- # @rbs () -> void
27
- def insert_rbs
28
- files.each_value(&:rewrite)
29
- end
30
-
31
- private
32
-
33
- # @rbs () -> TracePoint
34
- def trace
35
- @trace ||= TracePoint.new(:call, :return) { |tp| record(tp) }
36
- end
37
-
38
- # @rbs () -> Logger
39
- def logger
40
- return @logger if defined?(@logger)
41
-
42
- level = ENV["RBS_TRACE_DEBUG"] ? :debug : :info
43
- @logger = Logger.new($stdout, level:)
44
- end
45
-
46
- # @rbs () -> Array[Declaration]
47
- def stack_traces
48
- @stack_traces ||= []
49
- end
50
-
51
- # @rbs (String) -> File
52
- def find_or_new_file(path)
53
- files[path] ||= File.new(path)
54
- files[path]
55
- end
56
-
57
- # @rbs (File, TracePoint) -> Definition
58
- def find_or_new_definition(file, tp)
59
- name = tp.method_id
60
- is_singleton = tp.defined_class.singleton_class?
61
- klass = is_singleton ? tp.self : tp.defined_class
62
- mark = is_singleton ? "." : "#"
63
- signature = "#{klass}#{mark}#{name}"
64
-
65
- file.definitions[signature] ||= Definition.new(klass:, name:, lineno: tp.lineno)
66
- end
67
-
68
- # @rbs (TracePoint) -> void
69
- def record(tp) # rubocop:disable Metrics/MethodLength
70
- return if ignore_path?(tp.path)
71
-
72
- file = find_or_new_file(tp.path)
73
- definition = find_or_new_definition(file, tp)
74
-
75
- case tp.event
76
- when :call
77
- call_event(tp)
78
- when :return
79
- return_event(tp, definition)
80
- end
81
- rescue StandardError => e
82
- logger.debug(e)
83
- end
84
-
85
- # @rbs (TracePoint) -> void
86
- def call_event(tp) # rubocop:disable Metrics
87
- parameters = tp.parameters.filter_map do |kind, name|
88
- # steep:ignore:start
89
- value = tp.binding.local_variable_get(name) if name && !%i[* ** &].include?(name)
90
- # steep:ignore:end
91
- klass = case kind
92
- when :rest
93
- value ? value.map { |v| obj_to_class(v) }.uniq : [Object]
94
- when :keyrest
95
- value ? value.map { |_, v| obj_to_class(v) }.uniq : [Object]
96
- when :block
97
- # TODO: support block argument
98
- next
99
- else
100
- [obj_to_class(value)]
101
- end
102
- [kind, name, klass]
103
- end
104
- stack_traces << Declaration.new(parameters, void: !assign_return_value?(tp.path, tp.method_id))
105
- end
106
-
107
- # @rbs (TracePoint, Definition) -> void
108
- def return_event(tp, definition)
109
- decl = stack_traces.pop
110
- # TODO: check usecase where decl is nil
111
- return unless decl
112
-
113
- decl.return_type = [obj_to_class(tp.return_value)]
114
- definition.decls << decl
115
- end
116
-
117
- # @rbs (BasicObject) -> Class
118
- def obj_to_class(obj)
119
- Object.instance_method(:class).bind_call(obj)
120
- end
121
-
122
- # @rbs (String) -> bool
123
- def ignore_path?(path)
124
- bundle_path = Bundler.bundle_path.to_s # steep:ignore UnknownConstant
125
- ruby_lib_path = RbConfig::CONFIG["rubylibdir"]
126
-
127
- path.start_with?("<internal") ||
128
- path.start_with?("(eval") ||
129
- path.start_with?(bundle_path) ||
130
- path.start_with?(ruby_lib_path) ||
131
- path.start_with?(__FILE__)
132
- end
133
-
134
- # @rbs (String, Symbol) -> bool
135
- def assign_return_value?(path, method_id) # rubocop:disable Metrics
136
- is_initialize = method_id == :initialize
137
- return false if is_initialize
138
-
139
- locations = caller_locations || []
140
- i = locations.index { |loc| loc.path == path && loc.label == method_id.to_s }
141
- loc = locations[i + 1] if i
142
- # If the caller is not found, assume the return value is used.
143
- return true unless loc
144
-
145
- node = parsed_nodes(loc.path) # steep:ignore ArgumentTypeMismatch
146
- return false unless node
147
-
148
- method_name = is_initialize ? :new : method_id
149
- parents = find_parents(node, method_name:, lineno: loc.lineno)
150
- return false unless parents
151
-
152
- parent = parents[1]
153
- ASSIGNED_NODE_TYPES.include?(parent.type) # steep:ignore NoMethod
154
- end
155
-
156
- # @rbs (Prism::Node, method_name: Symbol, lineno: Integer, ?parents: Array[Prism::Node]) -> Array[Prism::Node]?
157
- def find_parents(node, method_name:, lineno:, parents: [])
158
- result = nil
159
- node.compact_child_nodes.each do |child| # steep:ignore NoMethod
160
- break if result
161
-
162
- found = child.type == :call_node && child.name == method_name && child.location.start_line == lineno
163
- result = found ? [child, *parents] : find_parents(child, method_name:, lineno:, parents: [node, *parents])
164
- end
165
- result
166
- end
167
-
168
- # @rbs (String) -> Prism::ProgramNode?
169
- def parsed_nodes(path)
170
- return unless ::File.exist?(path)
171
-
172
- @parsed_nodes ||= {}
173
- @parsed_nodes[path] ||= Prism.parse_file(path)
174
- @parsed_nodes[path].value
175
- end
176
- end
177
- end
178
- end
@@ -1,36 +0,0 @@
1
- # Generated from lib/rbs/trace/declaration.rb with RBS::Inline
2
-
3
- module RBS
4
- module Trace
5
- class Declaration
6
- METHOD_KINDS: Array[Symbol]
7
-
8
- attr_reader parameters: Array[untyped]
9
-
10
- attr_reader void: bool
11
-
12
- attr_accessor return_type: Array[Object]
13
-
14
- # @rbs (Array[untyped], ?void: bool) -> void
15
- def initialize: (Array[untyped], ?void: bool) -> void
16
-
17
- # @rbs () -> String
18
- def to_rbs: () -> String
19
-
20
- # @rbs (Declaration) -> Declaration
21
- def merge: (Declaration) -> Declaration
22
-
23
- private
24
-
25
- # TODO: support block argument
26
- # @rbs () -> String
27
- def parameters_rbs: () -> String
28
-
29
- # @rbs (Symbol, Symbol, Array[Object]) -> String?
30
- def convert: (Symbol, Symbol, Array[Object]) -> String?
31
-
32
- # @rbs (Array[Object]) -> String
33
- def convert_type: (Array[Object]) -> String
34
- end
35
- end
36
- end
@@ -1,25 +0,0 @@
1
- # Generated from lib/rbs/trace/definition.rb with RBS::Inline
2
-
3
- module RBS
4
- module Trace
5
- class Definition
6
- attr_reader klass: Class
7
-
8
- attr_reader name: Symbol
9
-
10
- attr_reader lineno: Integer
11
-
12
- # @rbs (klass: Object, name: Symbol, lineno: Integer) -> void
13
- def initialize: (klass: Object, name: Symbol, lineno: Integer) -> void
14
-
15
- # @rbs () -> Array[Declaration]
16
- def decls: () -> Array[Declaration]
17
-
18
- # @rbs (?Integer) -> String
19
- def rbs_comment: (?Integer) -> String
20
-
21
- # @rbs () -> String
22
- def rbs: () -> String
23
- end
24
- end
25
- end
@@ -1,63 +0,0 @@
1
- # Generated from lib/rbs/trace/method_tracing.rb with RBS::Inline
2
-
3
- module RBS
4
- module Trace
5
- class MethodTracing
6
- # rubocop:disable Metrics/ClassLength
7
- ASSIGNED_NODE_TYPES: Array[Symbol]
8
-
9
- # @rbs [T] () { () -> T } -> T
10
- def enable: [T] () { () -> T } -> T
11
-
12
- # @rbs () -> void
13
- def disable: () -> void
14
-
15
- # @rbs () -> Hash[String, File]
16
- def files: () -> Hash[String, File]
17
-
18
- # @rbs () -> void
19
- def insert_rbs: () -> void
20
-
21
- private
22
-
23
- # @rbs () -> TracePoint
24
- def trace: () -> TracePoint
25
-
26
- # @rbs () -> Logger
27
- def logger: () -> Logger
28
-
29
- # @rbs () -> Array[Declaration]
30
- def stack_traces: () -> Array[Declaration]
31
-
32
- # @rbs (String) -> File
33
- def find_or_new_file: (String) -> File
34
-
35
- # @rbs (File, TracePoint) -> Definition
36
- def find_or_new_definition: (File, TracePoint) -> Definition
37
-
38
- # @rbs (TracePoint) -> void
39
- def record: (TracePoint) -> void
40
-
41
- # @rbs (TracePoint) -> void
42
- def call_event: (TracePoint) -> void
43
-
44
- # @rbs (TracePoint, Definition) -> void
45
- def return_event: (TracePoint, Definition) -> void
46
-
47
- # @rbs (BasicObject) -> Class
48
- def obj_to_class: (BasicObject) -> Class
49
-
50
- # @rbs (String) -> bool
51
- def ignore_path?: (String) -> bool
52
-
53
- # @rbs (String, Symbol) -> bool
54
- def assign_return_value?: (String, Symbol) -> bool
55
-
56
- # @rbs (Prism::Node, method_name: Symbol, lineno: Integer, ?parents: Array[Prism::Node]) -> Array[Prism::Node]?
57
- def find_parents: (Prism::Node, method_name: Symbol, lineno: Integer, ?parents: Array[Prism::Node]) -> Array[Prism::Node]?
58
-
59
- # @rbs (String) -> Prism::ProgramNode?
60
- def parsed_nodes: (String) -> Prism::ProgramNode?
61
- end
62
- end
63
- end