rbs-trace 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +13 -0
- data/README.md +1 -3
- data/lib/rbs/trace/builder.rb +17 -5
- data/lib/rbs/trace/cli/inline.rb +0 -6
- data/lib/rbs/trace/helpers.rb +0 -8
- data/lib/rbs/trace/overload_compact.rb +9 -1
- data/lib/rbs/trace/return_value_visitor.rb +10 -7
- data/lib/rbs/trace/version.rb +1 -1
- data/lib/rbs/trace.rb +16 -20
- data/sig/generated/rbs/trace/builder.rbs +9 -2
- data/sig/generated/rbs/trace/helpers.rbs +0 -5
- data/sig/generated/rbs/trace/overload_compact.rbs +3 -0
- data/sig/generated/rbs/trace/return_value_visitor.rbs +1 -1
- data/sig/generated/rbs/trace.rbs +5 -11
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b10553866e335d8d7e7210d41cde3b905939b6ee26822994197c4bcfe8d324ce
|
4
|
+
data.tar.gz: ffa7d6f2f2bd57b7695b2e0622df519a0b0e830519aedb71185576038b514f3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f91f4b6facc4ce53917e0b574e85eb4d6f3e11646ce32407e39b79226e310f072ec564a993ef4e9ab68868bc83a261c1756b238f658ad66298d005806a4540f
|
7
|
+
data.tar.gz: c63bfaf42df1456961c16f9903df32f05dabab967d4a0305457aa2288e0b2d12d5e0a8be5ad1d62cf47e21b6bddacd8c82cc4eede8c5b4f1615bd715d4281b45
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5.0] - 2025-03-30
|
4
|
+
|
5
|
+
- feat: Add paths to control trace targets
|
6
|
+
- chore: Remove wrong examples
|
7
|
+
|
8
|
+
## [0.4.1] - 2025-02-24
|
9
|
+
|
10
|
+
- fix: Ensure class names are referenced
|
11
|
+
- fix: Prefer other types over void and untyped
|
12
|
+
- fix: Fix process to guess return value as void
|
13
|
+
- fix: Do not parse if the caller is not Ruby
|
14
|
+
- chore: Auto correct with rubocop-performance
|
15
|
+
|
3
16
|
## [0.4.0] - 2025-02-23
|
4
17
|
|
5
18
|
- feat: Implement the function to save as RBS files
|
data/README.md
CHANGED
@@ -111,9 +111,7 @@ end
|
|
111
111
|
### Insert RBS declarations for specific files only
|
112
112
|
|
113
113
|
```ruby
|
114
|
-
|
115
|
-
file.rewrite if path.include?("app/models/")
|
116
|
-
end
|
114
|
+
RBS::Trace.new(paths: Dir.glob("#{Dir.pwd}/app/models/**/*.rb"))
|
117
115
|
```
|
118
116
|
|
119
117
|
### Save RBS declarations as files
|
data/lib/rbs/trace/builder.rb
CHANGED
@@ -2,9 +2,13 @@
|
|
2
2
|
|
3
3
|
module RBS
|
4
4
|
class Trace
|
5
|
-
class Builder
|
5
|
+
class Builder # rubocop:disable Metrics/ClassLength
|
6
6
|
include Helpers
|
7
7
|
|
8
|
+
UNBOUND_CLASS_METHOD = Object.instance_method(:class)
|
9
|
+
UNBOUND_NAME_METHOD = Class.instance_method(:name)
|
10
|
+
private_constant :UNBOUND_CLASS_METHOD, :UNBOUND_NAME_METHOD
|
11
|
+
|
8
12
|
GENERICS_SIZE = {
|
9
13
|
Array => 1,
|
10
14
|
Range => 1,
|
@@ -12,12 +16,14 @@ module RBS
|
|
12
16
|
}.freeze
|
13
17
|
private_constant :GENERICS_SIZE
|
14
18
|
|
15
|
-
# @rbs (bind: Binding, parameters: Array[__todo__], void: bool) ->
|
19
|
+
# @rbs (bind: Binding, parameters: Array[__todo__], void: bool) -> Array[__todo__]
|
16
20
|
def method_call(bind:, parameters:, void:)
|
17
21
|
method_type = parse_parameters(bind, parameters)
|
18
22
|
return_type = type_void if void
|
19
23
|
|
20
|
-
|
24
|
+
[method_type, return_type].tap do |types|
|
25
|
+
stack_traces << types
|
26
|
+
end
|
21
27
|
end
|
22
28
|
|
23
29
|
# @rbs (__todo__) -> AST::Members::MethodDefinition::Overload
|
@@ -101,16 +107,17 @@ module RBS
|
|
101
107
|
|
102
108
|
# @rbs (untyped) -> Types::t
|
103
109
|
def parse_class(klass) # rubocop:disable Metrics/MethodLength
|
110
|
+
class_name = UNBOUND_NAME_METHOD.bind_call(klass)
|
104
111
|
if [TrueClass, FalseClass].include?(klass)
|
105
112
|
type_bool
|
106
113
|
elsif klass == NilClass
|
107
114
|
type_nil
|
108
|
-
elsif klass == Object ||
|
115
|
+
elsif klass == Object || class_name.nil?
|
109
116
|
type_untyped
|
110
117
|
else
|
111
118
|
size = GENERICS_SIZE[klass].to_i
|
112
119
|
args = Array.new(size) { type_untyped }
|
113
|
-
Types::ClassInstance.new(name: TypeName.parse(
|
120
|
+
Types::ClassInstance.new(name: TypeName.parse(class_name), args:, location: nil)
|
114
121
|
end
|
115
122
|
end
|
116
123
|
|
@@ -119,6 +126,11 @@ module RBS
|
|
119
126
|
klass = obj_to_class(object)
|
120
127
|
parse_class(klass)
|
121
128
|
end
|
129
|
+
|
130
|
+
# @rbs (BasicObject) -> Class
|
131
|
+
def obj_to_class(obj)
|
132
|
+
UNBOUND_CLASS_METHOD.bind_call(obj)
|
133
|
+
end
|
122
134
|
end
|
123
135
|
end
|
124
136
|
end
|
data/lib/rbs/trace/cli/inline.rb
CHANGED
@@ -13,12 +13,6 @@ module RBS
|
|
13
13
|
# Insert inline comments to `app/**/*.rb`.
|
14
14
|
$ rbs-trace inline --sig-dir=sig --rb-dir=app
|
15
15
|
|
16
|
-
# Generate RBS files with rbs-inline.
|
17
|
-
$ rbs-inline --output --opt-out app
|
18
|
-
|
19
|
-
# Remove method definitions that have been migrated to inline comments.
|
20
|
-
$ rbs subtract --write sig sig/generated/
|
21
|
-
|
22
16
|
Options:
|
23
17
|
USAGE
|
24
18
|
|
data/lib/rbs/trace/helpers.rb
CHANGED
@@ -3,9 +3,6 @@
|
|
3
3
|
module RBS
|
4
4
|
class Trace
|
5
5
|
module Helpers
|
6
|
-
UNBOUND_CLASS_METHOD = Object.instance_method(:class)
|
7
|
-
private_constant :UNBOUND_CLASS_METHOD
|
8
|
-
|
9
6
|
# @rbs (name: TypeName) -> AST::Declarations::Module
|
10
7
|
def new_module_decl(name:)
|
11
8
|
AST::Declarations::Module.new(
|
@@ -46,11 +43,6 @@ module RBS
|
|
46
43
|
)
|
47
44
|
end
|
48
45
|
|
49
|
-
# @rbs (BasicObject) -> Class
|
50
|
-
def obj_to_class(obj)
|
51
|
-
UNBOUND_CLASS_METHOD.bind_call(obj)
|
52
|
-
end
|
53
|
-
|
54
46
|
# @rbs () -> Types::Bases::Void
|
55
47
|
def type_void
|
56
48
|
@type_void = Types::Bases::Void.new(location: nil)
|
@@ -72,14 +72,22 @@ module RBS
|
|
72
72
|
|
73
73
|
# @rbs (Array[Types::t]) -> Types::t
|
74
74
|
def merge_types(types)
|
75
|
+
types = compact_types(types)
|
75
76
|
return types.first if types.one?
|
76
77
|
|
77
|
-
optional = types.any?
|
78
|
+
optional = types.any?(Types::Bases::Nil)
|
78
79
|
types = types.reject { |type| type.is_a?(Types::Bases::Nil) }
|
79
80
|
type = types.one? ? types.first : Types::Union.new(types:, location: nil) #: Types::t
|
80
81
|
|
81
82
|
optional ? Types::Optional.new(type:, location: nil) : type
|
82
83
|
end
|
84
|
+
|
85
|
+
# @rbs (Array[Types::t]) -> Array[Types::t]
|
86
|
+
def compact_types(types)
|
87
|
+
types = types.reject { |t| t.is_a?(Types::Bases::Void) } if types.any? { |t| !t.is_a?(Types::Bases::Void) }
|
88
|
+
types.reject! { |t| t.is_a?(Types::Bases::Any) } if types.any? { |t| !t.is_a?(Types::Bases::Any) }
|
89
|
+
types
|
90
|
+
end
|
83
91
|
end
|
84
92
|
end
|
85
93
|
end
|
@@ -38,7 +38,7 @@ module RBS
|
|
38
38
|
# @rbs (Prism::CallNode) -> void
|
39
39
|
def visit_call_node(node)
|
40
40
|
key = [node.location.start_line, node.name]
|
41
|
-
@void_types[key] =
|
41
|
+
@void_types[key] = void?(node)
|
42
42
|
|
43
43
|
visit_child_nodes(node)
|
44
44
|
end
|
@@ -50,13 +50,16 @@ module RBS
|
|
50
50
|
private
|
51
51
|
|
52
52
|
# @rbs (Prism::CallNode) -> bool
|
53
|
-
def
|
54
|
-
|
55
|
-
|
53
|
+
def void?(node)
|
54
|
+
parent_node = @parents[-1]
|
55
|
+
next_parent_node = @parents[-2]
|
56
|
+
return true if parent_node.nil? || next_parent_node.nil?
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
if next_parent_node.type == :program_node
|
59
|
+
parent_node.type == :statements_node
|
60
|
+
else
|
61
|
+
parent_node.type == :statements_node && parent_node.child_nodes[-1] != node
|
62
|
+
end
|
60
63
|
end
|
61
64
|
end
|
62
65
|
end
|
data/lib/rbs/trace/version.rb
CHANGED
data/lib/rbs/trace.rb
CHANGED
@@ -24,17 +24,15 @@ module RBS
|
|
24
24
|
BUNDLE_PATH = Bundler.bundle_path.to_s #: String
|
25
25
|
# steep:ignore:end
|
26
26
|
RUBY_LIB_PATH = RbConfig::CONFIG["rubylibdir"] #: String
|
27
|
-
PATH_INTERNAL = "<internal" #: String
|
28
|
-
PATH_EVAL = "(eval" #: String
|
29
|
-
PATH_INLINE_TEMPLATE = "inline template" #: String
|
30
27
|
|
31
|
-
private_constant :BUNDLE_PATH, :RUBY_LIB_PATH
|
28
|
+
private_constant :BUNDLE_PATH, :RUBY_LIB_PATH
|
32
29
|
|
33
|
-
# @rbs (?log_level: Symbol, ?raises: bool) -> void
|
34
|
-
def initialize(log_level: nil, raises: false)
|
30
|
+
# @rbs (?log_level: Symbol, ?raises: bool, ?paths: Array[String]) -> void
|
31
|
+
def initialize(log_level: nil, raises: false, paths: default_paths)
|
35
32
|
@log_level = log_level
|
36
33
|
@log_level ||= ENV["RBS_TRACE_DEBUG"] ? :debug : :info
|
37
34
|
@raises = raises
|
35
|
+
@paths = Set.new(paths)
|
38
36
|
end
|
39
37
|
|
40
38
|
# @rbs [T] () { () -> T } -> T
|
@@ -54,7 +52,9 @@ module RBS
|
|
54
52
|
|
55
53
|
# @rbs () -> void
|
56
54
|
def save_comments
|
57
|
-
files.
|
55
|
+
files.each do |path, file|
|
56
|
+
file.rewrite if @paths.include?(path)
|
57
|
+
end
|
58
58
|
end
|
59
59
|
|
60
60
|
# @rbs (out_dir: String) -> void
|
@@ -64,6 +64,11 @@ module RBS
|
|
64
64
|
|
65
65
|
private
|
66
66
|
|
67
|
+
# @rbs () -> Array[String]
|
68
|
+
def default_paths
|
69
|
+
Dir.glob("#{Dir.pwd}/**/*.rb").reject { |path| path.start_with?(BUNDLE_PATH, RUBY_LIB_PATH) }
|
70
|
+
end
|
71
|
+
|
67
72
|
# @rbs () -> TracePoint
|
68
73
|
def trace
|
69
74
|
@trace ||= TracePoint.new(:call, :return) { |tp| record(tp) }
|
@@ -86,7 +91,7 @@ module RBS
|
|
86
91
|
|
87
92
|
# @rbs (TracePoint) -> void
|
88
93
|
def record(tp) # rubocop:disable Metrics/MethodLength
|
89
|
-
return
|
94
|
+
return unless @paths.include?(tp.path)
|
90
95
|
|
91
96
|
file = find_or_new_file(tp.path)
|
92
97
|
# steep:ignore:start
|
@@ -127,18 +132,6 @@ module RBS
|
|
127
132
|
member.overloads << overload
|
128
133
|
end
|
129
134
|
|
130
|
-
# @rbs (String) -> bool
|
131
|
-
def ignore_path?(path)
|
132
|
-
path.start_with?(
|
133
|
-
PATH_INTERNAL,
|
134
|
-
PATH_EVAL,
|
135
|
-
PATH_INLINE_TEMPLATE,
|
136
|
-
BUNDLE_PATH,
|
137
|
-
RUBY_LIB_PATH,
|
138
|
-
__FILE__
|
139
|
-
)
|
140
|
-
end
|
141
|
-
|
142
135
|
# @rbs (String, Symbol) -> bool
|
143
136
|
def void_return_type?(path, method_id)
|
144
137
|
return true if method_id == :initialize
|
@@ -151,6 +144,9 @@ module RBS
|
|
151
144
|
# Returns true if the file does not exist (eval, etc.)
|
152
145
|
return true unless ::File.exist?(caller_path)
|
153
146
|
|
147
|
+
# If the file is not Ruby, assume the return value is used. (erb, haml, etc.)
|
148
|
+
return false if ::File.extname(caller_path) != ".rb"
|
149
|
+
|
154
150
|
@return_value_visitors ||= {} #: Hash[String, ReturnValueVisitor]
|
155
151
|
v = @return_value_visitors.fetch(caller_path) { ReturnValueVisitor.parse_file(caller_path) }
|
156
152
|
v.void_type?(loc.lineno, method_id)
|
@@ -5,10 +5,14 @@ module RBS
|
|
5
5
|
class Builder
|
6
6
|
include Helpers
|
7
7
|
|
8
|
+
UNBOUND_CLASS_METHOD: untyped
|
9
|
+
|
10
|
+
UNBOUND_NAME_METHOD: untyped
|
11
|
+
|
8
12
|
GENERICS_SIZE: untyped
|
9
13
|
|
10
|
-
# @rbs (bind: Binding, parameters: Array[__todo__], void: bool) ->
|
11
|
-
def method_call: (bind: Binding, parameters: Array[__todo__], void: bool) ->
|
14
|
+
# @rbs (bind: Binding, parameters: Array[__todo__], void: bool) -> Array[__todo__]
|
15
|
+
def method_call: (bind: Binding, parameters: Array[__todo__], void: bool) -> Array[__todo__]
|
12
16
|
|
13
17
|
# @rbs (__todo__) -> AST::Members::MethodDefinition::Overload
|
14
18
|
def method_return: (__todo__) -> AST::Members::MethodDefinition::Overload
|
@@ -28,6 +32,9 @@ module RBS
|
|
28
32
|
|
29
33
|
# @rbs (BasicObject) -> Types::t
|
30
34
|
def parse_object: (BasicObject) -> Types::t
|
35
|
+
|
36
|
+
# @rbs (BasicObject) -> Class
|
37
|
+
def obj_to_class: (BasicObject) -> Class
|
31
38
|
end
|
32
39
|
end
|
33
40
|
end
|
@@ -3,8 +3,6 @@
|
|
3
3
|
module RBS
|
4
4
|
class Trace
|
5
5
|
module Helpers
|
6
|
-
UNBOUND_CLASS_METHOD: untyped
|
7
|
-
|
8
6
|
# @rbs (name: TypeName) -> AST::Declarations::Module
|
9
7
|
def new_module_decl: (name: TypeName) -> AST::Declarations::Module
|
10
8
|
|
@@ -14,9 +12,6 @@ module RBS
|
|
14
12
|
# @rbs (name: Symbol, kind: (:singleton | :instance)) -> AST::Members::MethodDefinition
|
15
13
|
def new_method_definition: (name: Symbol, kind: :singleton | :instance) -> AST::Members::MethodDefinition
|
16
14
|
|
17
|
-
# @rbs (BasicObject) -> Class
|
18
|
-
def obj_to_class: (BasicObject) -> Class
|
19
|
-
|
20
15
|
# @rbs () -> Types::Bases::Void
|
21
16
|
def type_void: () -> Types::Bases::Void
|
22
17
|
|
data/sig/generated/rbs/trace.rbs
CHANGED
@@ -11,14 +11,8 @@ module RBS
|
|
11
11
|
# steep:ignore:end
|
12
12
|
RUBY_LIB_PATH: String
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
PATH_EVAL: String
|
17
|
-
|
18
|
-
PATH_INLINE_TEMPLATE: String
|
19
|
-
|
20
|
-
# @rbs (?log_level: Symbol, ?raises: bool) -> void
|
21
|
-
def initialize: (?log_level: Symbol, ?raises: bool) -> void
|
14
|
+
# @rbs (?log_level: Symbol, ?raises: bool, ?paths: Array[String]) -> void
|
15
|
+
def initialize: (?log_level: Symbol, ?raises: bool, ?paths: Array[String]) -> void
|
22
16
|
|
23
17
|
# @rbs [T] () { () -> T } -> T
|
24
18
|
def enable: [T] () { () -> T } -> T
|
@@ -37,6 +31,9 @@ module RBS
|
|
37
31
|
|
38
32
|
private
|
39
33
|
|
34
|
+
# @rbs () -> Array[String]
|
35
|
+
def default_paths: () -> Array[String]
|
36
|
+
|
40
37
|
# @rbs () -> TracePoint
|
41
38
|
def trace: () -> TracePoint
|
42
39
|
|
@@ -58,9 +55,6 @@ module RBS
|
|
58
55
|
# @rbs (TracePoint, AST::Members::MethodDefinition) -> void
|
59
56
|
def return_event: (TracePoint, AST::Members::MethodDefinition) -> void
|
60
57
|
|
61
|
-
# @rbs (String) -> bool
|
62
|
-
def ignore_path?: (String) -> bool
|
63
|
-
|
64
58
|
# @rbs (String, Symbol) -> bool
|
65
59
|
def void_return_type?: (String, Symbol) -> bool
|
66
60
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbs-trace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takumi Shotoku
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-03-30 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: prism
|
@@ -88,8 +88,8 @@ licenses:
|
|
88
88
|
- MIT
|
89
89
|
metadata:
|
90
90
|
homepage_uri: https://github.com/sinsoku/rbs-trace
|
91
|
-
source_code_uri: https://github.com/sinsoku/rbs-trace/tree/v0.
|
92
|
-
changelog_uri: https://github.com/sinsoku/rbs-trace/blob/v0.
|
91
|
+
source_code_uri: https://github.com/sinsoku/rbs-trace/tree/v0.5.0
|
92
|
+
changelog_uri: https://github.com/sinsoku/rbs-trace/blob/v0.5.0/CHANGELOG.md
|
93
93
|
rubygems_mfa_required: 'true'
|
94
94
|
rdoc_options: []
|
95
95
|
require_paths:
|