rbs-trace 0.1.0 → 0.3.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 +7 -0
- data/CHANGELOG.md +18 -0
- data/README.md +30 -0
- data/Rakefile +16 -1
- data/Steepfile +6 -0
- data/gemfiles/3.1.gemfile +12 -0
- data/gemfiles/3.1.gemfile.lock +68 -0
- data/lib/rbs/trace/declaration.rb +62 -22
- data/lib/rbs/trace/definition.rb +8 -3
- data/lib/rbs/trace/file.rb +6 -0
- data/lib/rbs/trace/method_tracing.rb +49 -17
- data/lib/rbs/trace/version.rb +1 -1
- data/rbs_collection.lock.yaml +36 -0
- data/rbs_collection.yaml +17 -0
- data/sig/generated/rbs/trace/declaration.rbs +36 -0
- data/sig/generated/rbs/trace/definition.rbs +25 -0
- data/sig/generated/rbs/trace/file.rbs +27 -0
- data/sig/generated/rbs/trace/method_tracing.rbs +63 -0
- data/sig/generated/rbs/trace/version.rbs +7 -0
- data/sig/generated/rbs/trace.rbs +8 -0
- data/sig/generated/rbs-trace.rbs +2 -0
- metadata +18 -8
- data/.ruby-version +0 -1
- data/sig/rbs/trace.rbs +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64b5ec23a4828eaf4ac618e5589d1d68578e85d11033efb676350ad19cbd660d
|
4
|
+
data.tar.gz: e313d83a44217fec2c8db6e33f84c03fff39ae7c300c9168f64fdaf62c61c416
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eef77ab67d92f461c1faa8266227678985cf79afef932abf02beb90f63e766de36cf688a7f23ba5457b63de67de46caf974a285325bbd03c9b74ef9d08504bd3
|
7
|
+
data.tar.gz: dc73fef50a753cad90f0f00d83613f7199bc297ea4f159fd65d042d8ea3fe36c8ee9f76cf6af441c0eeae3fa25beada143527158858521c05becb84847aa635a
|
data/.rubocop.yml
CHANGED
@@ -3,6 +3,7 @@ require:
|
|
3
3
|
- rubocop-rspec
|
4
4
|
|
5
5
|
AllCops:
|
6
|
+
TargetRubyVersion: 3.1
|
6
7
|
NewCops: enable
|
7
8
|
|
8
9
|
Style/StringLiterals:
|
@@ -23,3 +24,9 @@ Naming/MethodParameterName:
|
|
23
24
|
Naming/FileName:
|
24
25
|
Exclude:
|
25
26
|
- "lib/rbs-trace.rb"
|
27
|
+
|
28
|
+
Layout/LeadingCommentSpace:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/AccessorGrouping:
|
32
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.0] - 2024-10-10
|
4
|
+
|
5
|
+
- feat: Support eval
|
6
|
+
- feat: Support subclasses of BasicObject
|
7
|
+
- feat: Support generics with Array and Hash
|
8
|
+
- docs: Add steps to integrate with Minitest
|
9
|
+
- docs: Fix RubyGems metadata
|
10
|
+
- ci: Add Ruby 3.1 to matrix
|
11
|
+
|
12
|
+
## [0.2.0] - 2024-09-11
|
13
|
+
|
14
|
+
- feat: Support Union type
|
15
|
+
- feat: Support Optional type
|
16
|
+
- fix: Fix a bug that generated invalid RBS
|
17
|
+
- fix: Fix errors to parse methods with anonymous arguments
|
18
|
+
- fix: Consider the case where the caller cannot be found
|
19
|
+
- fix: Ignore a method generated by `class_eval`
|
20
|
+
|
3
21
|
## [0.1.0] - 2024-09-07
|
4
22
|
|
5
23
|
- Initial release
|
data/README.md
CHANGED
@@ -69,6 +69,8 @@ class User
|
|
69
69
|
end
|
70
70
|
```
|
71
71
|
|
72
|
+
## Integration
|
73
|
+
|
72
74
|
### RSpec
|
73
75
|
|
74
76
|
Add the following code to `spec/support/rbs_trace.rb`.
|
@@ -93,6 +95,34 @@ Then run RSpec with the environment variables.
|
|
93
95
|
$ RBS_TRACE=1 bundle exec rspec
|
94
96
|
```
|
95
97
|
|
98
|
+
### Minitest
|
99
|
+
|
100
|
+
Add the following code to `test_helper.rb`.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
tracing = RBS::Trace::MethodTracing.new
|
104
|
+
tracing.enable
|
105
|
+
|
106
|
+
Minitest.after_run do
|
107
|
+
tracing.disable
|
108
|
+
tracing.insert_rbs
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
## Tips
|
113
|
+
|
114
|
+
### Insert RBS declarations for specific files only
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
tracing.files.each do |path, file|
|
118
|
+
file.rewrite if path.include?("app/models/")
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
### Enable debug logging
|
123
|
+
|
124
|
+
If you want to enable debug logging, specify the environment variable `RBS_TRACE_DEBUG`.
|
125
|
+
|
96
126
|
## Development
|
97
127
|
|
98
128
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/Rakefile
CHANGED
@@ -9,4 +9,19 @@ require "rubocop/rake_task"
|
|
9
9
|
|
10
10
|
RuboCop::RakeTask.new
|
11
11
|
|
12
|
-
|
12
|
+
desc "Generate rbs files"
|
13
|
+
task :rbs_inline do
|
14
|
+
sh "rbs-inline --output --opt-out lib"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Run Steep"
|
18
|
+
task :steep do
|
19
|
+
sh "steep check"
|
20
|
+
end
|
21
|
+
|
22
|
+
default = if RUBY_VERSION.start_with?("3.3")
|
23
|
+
%i[spec rubocop rbs_inline steep]
|
24
|
+
else
|
25
|
+
%i[spec rubocop]
|
26
|
+
end
|
27
|
+
task(default:)
|
data/Steepfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in rbs-trace.gemspec
|
6
|
+
gemspec(path: "..")
|
7
|
+
|
8
|
+
gem "rake"
|
9
|
+
gem "rspec"
|
10
|
+
gem "rubocop", require: false
|
11
|
+
gem "rubocop-rake", require: false
|
12
|
+
gem "rubocop-rspec", require: false
|
@@ -0,0 +1,68 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
rbs-trace (0.3.0)
|
5
|
+
prism (>= 0.3.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
ast (2.4.2)
|
11
|
+
diff-lcs (1.5.1)
|
12
|
+
json (2.7.2)
|
13
|
+
language_server-protocol (3.17.0.3)
|
14
|
+
parallel (1.26.3)
|
15
|
+
parser (3.3.5.0)
|
16
|
+
ast (~> 2.4.1)
|
17
|
+
racc
|
18
|
+
prism (1.0.0)
|
19
|
+
racc (1.8.1)
|
20
|
+
rainbow (3.1.1)
|
21
|
+
rake (13.2.1)
|
22
|
+
regexp_parser (2.9.2)
|
23
|
+
rspec (3.13.0)
|
24
|
+
rspec-core (~> 3.13.0)
|
25
|
+
rspec-expectations (~> 3.13.0)
|
26
|
+
rspec-mocks (~> 3.13.0)
|
27
|
+
rspec-core (3.13.1)
|
28
|
+
rspec-support (~> 3.13.0)
|
29
|
+
rspec-expectations (3.13.3)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.13.0)
|
32
|
+
rspec-mocks (3.13.1)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.13.0)
|
35
|
+
rspec-support (3.13.1)
|
36
|
+
rubocop (1.66.1)
|
37
|
+
json (~> 2.3)
|
38
|
+
language_server-protocol (>= 3.17.0)
|
39
|
+
parallel (~> 1.10)
|
40
|
+
parser (>= 3.3.0.2)
|
41
|
+
rainbow (>= 2.2.2, < 4.0)
|
42
|
+
regexp_parser (>= 2.4, < 3.0)
|
43
|
+
rubocop-ast (>= 1.32.2, < 2.0)
|
44
|
+
ruby-progressbar (~> 1.7)
|
45
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
46
|
+
rubocop-ast (1.32.3)
|
47
|
+
parser (>= 3.3.1.0)
|
48
|
+
rubocop-rake (0.6.0)
|
49
|
+
rubocop (~> 1.0)
|
50
|
+
rubocop-rspec (3.0.5)
|
51
|
+
rubocop (~> 1.61)
|
52
|
+
ruby-progressbar (1.13.0)
|
53
|
+
unicode-display_width (2.5.0)
|
54
|
+
|
55
|
+
PLATFORMS
|
56
|
+
arm64-darwin-23
|
57
|
+
ruby
|
58
|
+
|
59
|
+
DEPENDENCIES
|
60
|
+
rake
|
61
|
+
rbs-trace!
|
62
|
+
rspec
|
63
|
+
rubocop
|
64
|
+
rubocop-rake
|
65
|
+
rubocop-rspec
|
66
|
+
|
67
|
+
BUNDLED WITH
|
68
|
+
2.5.17
|
@@ -3,33 +3,46 @@
|
|
3
3
|
module RBS
|
4
4
|
module Trace
|
5
5
|
class Declaration
|
6
|
-
METHOD_KINDS = %i[req opt rest keyreq key keyrest].freeze
|
6
|
+
METHOD_KINDS = %i[req opt rest keyreq key keyrest].freeze #: Array[Symbol]
|
7
7
|
private_constant :METHOD_KINDS
|
8
8
|
|
9
|
-
|
9
|
+
attr_reader :parameters #: Array[untyped]
|
10
|
+
attr_reader :void #: bool
|
11
|
+
attr_accessor :return_type #: Array[Object]
|
10
12
|
|
13
|
+
# @rbs (Array[untyped], ?void: bool) -> void
|
11
14
|
def initialize(parameters, void: false)
|
12
15
|
@parameters = parameters
|
13
16
|
@void = void
|
14
17
|
end
|
15
18
|
|
19
|
+
# @rbs () -> String
|
16
20
|
def to_rbs
|
17
|
-
|
18
|
-
"void"
|
19
|
-
elsif @return_type == NilClass
|
20
|
-
"nil"
|
21
|
-
elsif @return_type == TrueClass || @return_type == FalseClass
|
22
|
-
"bool"
|
23
|
-
else
|
24
|
-
@return_type
|
25
|
-
end
|
21
|
+
return_rbs = void ? "void" : convert_type(return_type)
|
26
22
|
|
27
|
-
"(#{parameters_rbs}) -> #{
|
23
|
+
"(#{parameters_rbs}) -> #{return_rbs}"
|
24
|
+
end
|
25
|
+
|
26
|
+
# @rbs (Declaration) -> Declaration
|
27
|
+
def merge(other) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
28
|
+
new_parameters = @parameters.map.with_index do |parameter, index|
|
29
|
+
kind = parameter[0]
|
30
|
+
name = parameter[1]
|
31
|
+
klass = parameter[2]
|
32
|
+
other_klass = other.parameters[index][2]
|
33
|
+
|
34
|
+
merged_klass = (klass + other_klass).uniq
|
35
|
+
[kind, name, merged_klass]
|
36
|
+
end
|
37
|
+
Declaration.new(new_parameters, void: void && other.void).tap do |decl|
|
38
|
+
decl.return_type = (return_type + other.return_type).uniq
|
39
|
+
end
|
28
40
|
end
|
29
41
|
|
30
42
|
private
|
31
43
|
|
32
44
|
# TODO: support block argument
|
45
|
+
# @rbs () -> String
|
33
46
|
def parameters_rbs
|
34
47
|
converted = {}
|
35
48
|
@parameters.each do |kind, name, klass|
|
@@ -40,24 +53,51 @@ module RBS
|
|
40
53
|
METHOD_KINDS.flat_map { |kind| converted[kind] }.compact.join(", ")
|
41
54
|
end
|
42
55
|
|
43
|
-
|
44
|
-
@parameters.select { |kind, _name, _klass| kind == selected }
|
45
|
-
end
|
46
|
-
|
56
|
+
# @rbs (Symbol, Symbol, Array[Object]) -> String?
|
47
57
|
def convert(kind, name, klass) # rubocop:disable Metrics/MethodLength
|
58
|
+
type = convert_type(klass)
|
48
59
|
case kind
|
49
60
|
when :req
|
50
|
-
|
61
|
+
type
|
51
62
|
when :opt
|
52
|
-
"?#{
|
63
|
+
"?#{type}"
|
53
64
|
when :rest
|
54
|
-
"*#{
|
65
|
+
"*#{type}"
|
55
66
|
when :keyreq
|
56
|
-
"#{name}: #{
|
67
|
+
"#{name}: #{type}"
|
57
68
|
when :key
|
58
|
-
"?#{name}: #{
|
69
|
+
"?#{name}: #{type}"
|
59
70
|
when :keyrest
|
60
|
-
"**#{
|
71
|
+
"**#{type}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @rbs (Array[Object]) -> String
|
76
|
+
def convert_type(klass) # rubocop:disable Metrics
|
77
|
+
optional = klass.any? { |k| k == NilClass }
|
78
|
+
types = klass.filter_map do |k|
|
79
|
+
if k == NilClass
|
80
|
+
nil
|
81
|
+
elsif [TrueClass, FalseClass].include?(k) # steep:ignore ArgumentTypeMismatch
|
82
|
+
"bool"
|
83
|
+
elsif [Array, Hash].include?(k) # steep:ignore ArgumentTypeMismatch
|
84
|
+
"#{k}[untyped]"
|
85
|
+
elsif k == Object
|
86
|
+
"untyped"
|
87
|
+
else
|
88
|
+
k.name # steep:ignore NoMethod
|
89
|
+
end
|
90
|
+
end.uniq
|
91
|
+
type = types.join("|")
|
92
|
+
|
93
|
+
if types.size > 1 && optional
|
94
|
+
"(#{type})?"
|
95
|
+
elsif types.empty?
|
96
|
+
"nil"
|
97
|
+
elsif optional
|
98
|
+
"#{type}?"
|
99
|
+
else
|
100
|
+
type
|
61
101
|
end
|
62
102
|
end
|
63
103
|
end
|
data/lib/rbs/trace/definition.rb
CHANGED
@@ -3,25 +3,30 @@
|
|
3
3
|
module RBS
|
4
4
|
module Trace
|
5
5
|
class Definition
|
6
|
-
attr_reader :klass
|
6
|
+
attr_reader :klass #: Class
|
7
|
+
attr_reader :name #: Symbol
|
8
|
+
attr_reader :lineno #: Integer
|
7
9
|
|
10
|
+
# @rbs (klass: Object, name: Symbol, lineno: Integer) -> void
|
8
11
|
def initialize(klass:, name:, lineno:)
|
9
12
|
@klass = klass
|
10
13
|
@name = name
|
11
14
|
@lineno = lineno
|
12
15
|
end
|
13
16
|
|
17
|
+
# @rbs () -> Array[Declaration]
|
14
18
|
def decls
|
15
19
|
@decls ||= []
|
16
20
|
end
|
17
21
|
|
22
|
+
# @rbs (?Integer) -> String
|
18
23
|
def rbs_comment(indent = 0)
|
19
24
|
"#{" " * indent}# @rbs #{rbs}\n"
|
20
25
|
end
|
21
26
|
|
27
|
+
# @rbs () -> String
|
22
28
|
def rbs
|
23
|
-
|
24
|
-
@decls.first.to_rbs
|
29
|
+
@decls.inject { |result, decl| result.merge(decl) }.to_rbs
|
25
30
|
end
|
26
31
|
end
|
27
32
|
end
|
data/lib/rbs/trace/file.rb
CHANGED
@@ -3,14 +3,17 @@
|
|
3
3
|
module RBS
|
4
4
|
module Trace
|
5
5
|
class File
|
6
|
+
# @rbs (String) -> void
|
6
7
|
def initialize(path)
|
7
8
|
@path = path
|
8
9
|
end
|
9
10
|
|
11
|
+
# @rbs () -> Hash[String, Definition]
|
10
12
|
def definitions
|
11
13
|
@definitions ||= {}
|
12
14
|
end
|
13
15
|
|
16
|
+
# @rbs () -> String
|
14
17
|
def with_rbs
|
15
18
|
lines = ::File.readlines(@path)
|
16
19
|
reverse_definitions.each do |d|
|
@@ -25,18 +28,21 @@ module RBS
|
|
25
28
|
lines.join
|
26
29
|
end
|
27
30
|
|
31
|
+
# @rbs () -> void
|
28
32
|
def rewrite
|
29
33
|
::File.write(@path, with_rbs)
|
30
34
|
end
|
31
35
|
|
32
36
|
private
|
33
37
|
|
38
|
+
# @rbs (Array[String], Definition) -> boolish
|
34
39
|
def skip_insert?(lines, definition)
|
35
40
|
prev = definition.lineno - 2
|
36
41
|
|
37
42
|
definition.decls.empty? || lines[prev]&.include?("# @rbs")
|
38
43
|
end
|
39
44
|
|
45
|
+
# @rbs () -> Enumerator[Definition, void]
|
40
46
|
def reverse_definitions
|
41
47
|
@definitions.values.sort_by { |d| -d.lineno }
|
42
48
|
end
|
@@ -4,31 +4,38 @@ module RBS
|
|
4
4
|
module Trace
|
5
5
|
class MethodTracing # rubocop:disable Metrics/ClassLength
|
6
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
|
7
|
+
class_variable_write_node constant_write_node call_node
|
8
|
+
embedded_statements_node].freeze #: Array[Symbol]
|
8
9
|
private_constant :ASSIGNED_NODE_TYPES
|
9
10
|
|
11
|
+
# @rbs [T] () { () -> T } -> T
|
10
12
|
def enable(&)
|
11
13
|
trace.enable(&)
|
12
14
|
end
|
13
15
|
|
16
|
+
# @rbs () -> void
|
14
17
|
def disable
|
15
18
|
trace.disable
|
16
19
|
end
|
17
20
|
|
21
|
+
# @rbs () -> Hash[String, File]
|
18
22
|
def files
|
19
23
|
@files ||= {}
|
20
24
|
end
|
21
25
|
|
26
|
+
# @rbs () -> void
|
22
27
|
def insert_rbs
|
23
28
|
files.each_value(&:rewrite)
|
24
29
|
end
|
25
30
|
|
26
31
|
private
|
27
32
|
|
33
|
+
# @rbs () -> TracePoint
|
28
34
|
def trace
|
29
35
|
@trace ||= TracePoint.new(:call, :return, :raise) { |tp| record(tp) }
|
30
36
|
end
|
31
37
|
|
38
|
+
# @rbs () -> Logger
|
32
39
|
def logger
|
33
40
|
return @logger if defined?(@logger)
|
34
41
|
|
@@ -36,15 +43,18 @@ module RBS
|
|
36
43
|
@logger = Logger.new($stdout, level:)
|
37
44
|
end
|
38
45
|
|
46
|
+
# @rbs () -> Array[Declaration]
|
39
47
|
def stack_traces
|
40
48
|
@stack_traces ||= []
|
41
49
|
end
|
42
50
|
|
51
|
+
# @rbs (String) -> File
|
43
52
|
def find_or_new_file(path)
|
44
53
|
files[path] ||= File.new(path)
|
45
54
|
files[path]
|
46
55
|
end
|
47
56
|
|
57
|
+
# @rbs (File, TracePoint) -> Definition
|
48
58
|
def find_or_new_definition(file, tp)
|
49
59
|
name = tp.method_id
|
50
60
|
is_singleton = tp.defined_class.singleton_class?
|
@@ -52,10 +62,10 @@ module RBS
|
|
52
62
|
mark = is_singleton ? "." : "#"
|
53
63
|
signature = "#{klass}#{mark}#{name}"
|
54
64
|
|
55
|
-
|
56
|
-
file.definitions[signature] ||= Definition.new(klass:, name:, lineno:)
|
65
|
+
file.definitions[signature] ||= Definition.new(klass:, name:, lineno: tp.lineno)
|
57
66
|
end
|
58
67
|
|
68
|
+
# @rbs (TracePoint) -> void
|
59
69
|
def record(tp) # rubocop:disable Metrics/MethodLength
|
60
70
|
return if ignore_path?(tp.path)
|
61
71
|
|
@@ -72,62 +82,81 @@ module RBS
|
|
72
82
|
logger.debug(e)
|
73
83
|
end
|
74
84
|
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
78
91
|
klass = case kind
|
79
92
|
when :rest
|
80
|
-
value.map(
|
93
|
+
value ? value.map { |v| obj_to_class(v) }.uniq : [Object]
|
81
94
|
when :keyrest
|
82
|
-
value.map { |_, v| v
|
95
|
+
value ? value.map { |_, v| obj_to_class(v) }.uniq : [Object]
|
83
96
|
when :block
|
84
97
|
# TODO: support block argument
|
98
|
+
next
|
85
99
|
else
|
86
|
-
value
|
100
|
+
[obj_to_class(value)]
|
87
101
|
end
|
88
102
|
[kind, name, klass]
|
89
103
|
end
|
90
104
|
stack_traces << Declaration.new(parameters, void: !assign_return_value?(tp.path, tp.method_id))
|
91
105
|
end
|
92
106
|
|
107
|
+
# @rbs (TracePoint, Definition) -> void
|
93
108
|
def return_event(tp, definition)
|
94
109
|
decl = stack_traces.pop
|
95
110
|
# TODO: check usecase where decl is nil
|
96
111
|
return unless decl
|
97
112
|
|
98
|
-
decl.return_type = tp.event == :return ? tp.return_value
|
113
|
+
decl.return_type = tp.event == :return ? [obj_to_class(tp.return_value)] : [NilClass]
|
99
114
|
definition.decls << decl
|
100
115
|
end
|
101
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
|
102
123
|
def ignore_path?(path)
|
103
|
-
bundle_path = Bundler.bundle_path.to_s
|
124
|
+
bundle_path = Bundler.bundle_path.to_s # steep:ignore UnknownConstant
|
104
125
|
ruby_lib_path = RbConfig::CONFIG["rubylibdir"]
|
105
126
|
|
106
127
|
path.start_with?("<internal") ||
|
128
|
+
path.start_with?("(eval") ||
|
107
129
|
path.start_with?(bundle_path) ||
|
108
130
|
path.start_with?(ruby_lib_path) ||
|
109
131
|
path.start_with?(__FILE__)
|
110
132
|
end
|
111
133
|
|
112
|
-
|
134
|
+
# @rbs (String, Symbol) -> bool
|
135
|
+
def assign_return_value?(path, method_id) # rubocop:disable Metrics
|
113
136
|
is_initialize = method_id == :initialize
|
114
137
|
return false if is_initialize
|
115
138
|
|
116
|
-
|
117
|
-
|
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
|
118
147
|
|
119
|
-
node = parsed_nodes(loc.path)
|
120
148
|
method_name = is_initialize ? :new : method_id
|
121
149
|
parents = find_parents(node, method_name:, lineno: loc.lineno)
|
122
150
|
return false unless parents
|
123
151
|
|
124
152
|
parent = parents[1]
|
125
|
-
ASSIGNED_NODE_TYPES.include?(parent.type)
|
153
|
+
ASSIGNED_NODE_TYPES.include?(parent.type) # steep:ignore NoMethod
|
126
154
|
end
|
127
155
|
|
156
|
+
# @rbs (Prism::Node, method_name: Symbol, lineno: Integer, ?parents: Array[Prism::Node]) -> Array[Prism::Node]?
|
128
157
|
def find_parents(node, method_name:, lineno:, parents: [])
|
129
158
|
result = nil
|
130
|
-
node.compact_child_nodes.each do |child|
|
159
|
+
node.compact_child_nodes.each do |child| # steep:ignore NoMethod
|
131
160
|
break if result
|
132
161
|
|
133
162
|
found = child.type == :call_node && child.name == method_name && child.location.start_line == lineno
|
@@ -136,7 +165,10 @@ module RBS
|
|
136
165
|
result
|
137
166
|
end
|
138
167
|
|
168
|
+
# @rbs (String) -> Prism::ProgramNode?
|
139
169
|
def parsed_nodes(path)
|
170
|
+
return unless ::File.exist?(path)
|
171
|
+
|
140
172
|
@parsed_nodes ||= {}
|
141
173
|
@parsed_nodes[path] ||= Prism.parse_file(path)
|
142
174
|
@parsed_nodes[path].value
|
data/lib/rbs/trace/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
path: ".gem_rbs_collection"
|
3
|
+
gems:
|
4
|
+
- name: diff-lcs
|
5
|
+
version: '1.5'
|
6
|
+
source:
|
7
|
+
type: git
|
8
|
+
name: ruby/gem_rbs_collection
|
9
|
+
revision: f18921b7bd1280daab3ab218b7e3939748515eb1
|
10
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
11
|
+
repo_dir: gems
|
12
|
+
- name: fileutils
|
13
|
+
version: '0'
|
14
|
+
source:
|
15
|
+
type: stdlib
|
16
|
+
- name: logger
|
17
|
+
version: '0'
|
18
|
+
source:
|
19
|
+
type: stdlib
|
20
|
+
- name: monitor
|
21
|
+
version: '0'
|
22
|
+
source:
|
23
|
+
type: stdlib
|
24
|
+
- name: prism
|
25
|
+
version: 0.30.0
|
26
|
+
source:
|
27
|
+
type: rubygems
|
28
|
+
- name: rake
|
29
|
+
version: '13.0'
|
30
|
+
source:
|
31
|
+
type: git
|
32
|
+
name: ruby/gem_rbs_collection
|
33
|
+
revision: f18921b7bd1280daab3ab218b7e3939748515eb1
|
34
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
35
|
+
repo_dir: gems
|
36
|
+
gemfile_lock_path: Gemfile.lock
|
data/rbs_collection.yaml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Download sources
|
2
|
+
sources:
|
3
|
+
- type: git
|
4
|
+
name: ruby/gem_rbs_collection
|
5
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
6
|
+
revision: main
|
7
|
+
repo_dir: gems
|
8
|
+
|
9
|
+
# You can specify local directories as sources also.
|
10
|
+
# - type: local
|
11
|
+
# path: path/to/your/local/repository
|
12
|
+
|
13
|
+
# A directory to install the downloaded RBSs
|
14
|
+
path: .gem_rbs_collection
|
15
|
+
|
16
|
+
gems:
|
17
|
+
- name: logger
|
@@ -0,0 +1,36 @@
|
|
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
|
@@ -0,0 +1,25 @@
|
|
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
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Generated from lib/rbs/trace/file.rb with RBS::Inline
|
2
|
+
|
3
|
+
module RBS
|
4
|
+
module Trace
|
5
|
+
class File
|
6
|
+
# @rbs (String) -> void
|
7
|
+
def initialize: (String) -> void
|
8
|
+
|
9
|
+
# @rbs () -> Hash[String, Definition]
|
10
|
+
def definitions: () -> Hash[String, Definition]
|
11
|
+
|
12
|
+
# @rbs () -> String
|
13
|
+
def with_rbs: () -> String
|
14
|
+
|
15
|
+
# @rbs () -> void
|
16
|
+
def rewrite: () -> void
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# @rbs (Array[String], Definition) -> boolish
|
21
|
+
def skip_insert?: (Array[String], Definition) -> boolish
|
22
|
+
|
23
|
+
# @rbs () -> Enumerator[Definition, void]
|
24
|
+
def reverse_definitions: () -> Enumerator[Definition, void]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,63 @@
|
|
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
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbs-trace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takumi Shotoku
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09
|
11
|
+
date: 2024-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prism
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
version: 0.3.0
|
27
27
|
description: |
|
28
28
|
RBS::Trace collects argument types and return value types using TracePoint, and inserts
|
29
|
-
inline RBS type declarations into files.
|
29
|
+
inline RBS type declarations into files.
|
30
30
|
email:
|
31
31
|
- sinsoku.listy@gmail.com
|
32
32
|
executables: []
|
@@ -35,12 +35,14 @@ extra_rdoc_files: []
|
|
35
35
|
files:
|
36
36
|
- ".rspec"
|
37
37
|
- ".rubocop.yml"
|
38
|
-
- ".ruby-version"
|
39
38
|
- CHANGELOG.md
|
40
39
|
- CODE_OF_CONDUCT.md
|
41
40
|
- LICENSE.txt
|
42
41
|
- README.md
|
43
42
|
- Rakefile
|
43
|
+
- Steepfile
|
44
|
+
- gemfiles/3.1.gemfile
|
45
|
+
- gemfiles/3.1.gemfile.lock
|
44
46
|
- lib/rbs-trace.rb
|
45
47
|
- lib/rbs/trace.rb
|
46
48
|
- lib/rbs/trace/declaration.rb
|
@@ -48,14 +50,22 @@ files:
|
|
48
50
|
- lib/rbs/trace/file.rb
|
49
51
|
- lib/rbs/trace/method_tracing.rb
|
50
52
|
- lib/rbs/trace/version.rb
|
51
|
-
-
|
53
|
+
- rbs_collection.lock.yaml
|
54
|
+
- rbs_collection.yaml
|
55
|
+
- sig/generated/rbs-trace.rbs
|
56
|
+
- sig/generated/rbs/trace.rbs
|
57
|
+
- sig/generated/rbs/trace/declaration.rbs
|
58
|
+
- sig/generated/rbs/trace/definition.rbs
|
59
|
+
- sig/generated/rbs/trace/file.rbs
|
60
|
+
- sig/generated/rbs/trace/method_tracing.rbs
|
61
|
+
- sig/generated/rbs/trace/version.rbs
|
52
62
|
homepage: https://github.com/sinsoku/rbs-trace
|
53
63
|
licenses:
|
54
64
|
- MIT
|
55
65
|
metadata:
|
56
66
|
homepage_uri: https://github.com/sinsoku/rbs-trace
|
57
|
-
source_code_uri: https://github.com/sinsoku/rbs-trace/
|
58
|
-
changelog_uri: https://github.com/sinsoku/rbs-trace/
|
67
|
+
source_code_uri: https://github.com/sinsoku/rbs-trace/tree/v0.3.0
|
68
|
+
changelog_uri: https://github.com/sinsoku/rbs-trace/blob/v0.3.0/CHANGELOG.md
|
59
69
|
rubygems_mfa_required: 'true'
|
60
70
|
post_install_message:
|
61
71
|
rdoc_options: []
|
@@ -65,7 +75,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
65
75
|
requirements:
|
66
76
|
- - ">="
|
67
77
|
- !ruby/object:Gem::Version
|
68
|
-
version: 3.
|
78
|
+
version: 3.1.0
|
69
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
80
|
requirements:
|
71
81
|
- - ">="
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
3.3.3
|