rbs-trace 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|