rbs-inline 0.2.0 → 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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/rbs/inline/ast/annotations.rb +21 -0
- data/lib/rbs/inline/ast/comment_lines.rb +19 -2
- data/lib/rbs/inline/ast/declarations.rb +6 -13
- data/lib/rbs/inline/ast/members.rb +9 -26
- data/lib/rbs/inline/ast/tree.rb +88 -4
- data/lib/rbs/inline/cli.rb +17 -4
- data/lib/rbs/inline/node_utils.rb +4 -0
- data/lib/rbs/inline/parser.rb +26 -8
- data/lib/rbs/inline/version.rb +1 -1
- data/lib/rbs/inline/writer.rb +81 -9
- data/lib/rbs/inline.rb +3 -0
- data/rbs_collection.lock.yaml +3 -7
- data/rbs_collection.yaml +2 -0
- data/sig/generated/rbs/inline/ast/annotations.rbs +2 -0
- data/sig/{rbs → generated/rbs}/inline/ast/comment_lines.rbs +8 -4
- data/sig/generated/rbs/inline/ast/declarations.rbs +4 -1
- data/sig/generated/rbs/inline/ast/members.rbs +8 -10
- data/sig/{rbs → generated/rbs}/inline/ast/tree.rbs +49 -21
- data/sig/generated/rbs/inline/node_utils.rbs +11 -0
- data/sig/generated/rbs/inline/parser.rbs +8 -4
- data/sig/generated/rbs/inline/version.rbs +7 -0
- data/sig/generated/rbs/inline/writer.rbs +72 -0
- data/sig/generated/rbs/inline.rbs +7 -0
- metadata +20 -16
- data/sig/rbs/inline/annotation_parser.rbs +0 -0
- data/sig/rbs/inline/node_utils.rbs +0 -7
- data/sig/rbs/inline/writer.rbs +0 -27
- data/sig/rbs/inline.rbs +0 -41
- data/yard-samples/hello.rb +0 -6
- data/yard-samples/sample1.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 713b2bd4c5ddd833fa1bd1a71505924081013101a8a41200a88fed55751146ba
|
4
|
+
data.tar.gz: 44ffe7a91c0c0afeb7e163a02de508c50f96a609ae7c64593a6b739109ac11b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6507f727be79bcae3890c8b8c3c3865544022058e44d5bfd060efb5df0c91e50f2b5e43a11f284c7ea3de1066bdd0ed7e269a14c20b45cc05cafa7ad60ecffb7
|
7
|
+
data.tar.gz: aad87cafa19657b4d4b055527924146cb232cd96c56081bcbb24c1e1b0ff2fc24a449bdfe2132a43c2e5f5ac2affca8d615d0946b135676979556eaca4887aec
|
data/README.md
CHANGED
@@ -80,12 +80,12 @@ The gem works as a transpiler from annotated Ruby code to RBS files. Run `rbs-in
|
|
80
80
|
$ bundle exec rbs-inline lib
|
81
81
|
|
82
82
|
# Save generated RBS files under sig/generated
|
83
|
-
$ bundle exec rbs-inline --output
|
83
|
+
$ bundle exec rbs-inline --output lib
|
84
84
|
```
|
85
85
|
|
86
86
|
You may want to use `fswatch` or likes to automatically generate RBS files when you edit the Ruby code.
|
87
87
|
|
88
|
-
$ fswatch -0 lib | xargs -0 -n1 bundle exec rbs-inline --output
|
88
|
+
$ fswatch -0 lib | xargs -0 -n1 bundle exec rbs-inline --output
|
89
89
|
|
90
90
|
## More materials
|
91
91
|
|
@@ -4,6 +4,27 @@ module RBS
|
|
4
4
|
module Inline
|
5
5
|
module AST
|
6
6
|
module Annotations
|
7
|
+
# @rbs!
|
8
|
+
# type t = VarType
|
9
|
+
# | ReturnType
|
10
|
+
# | Use
|
11
|
+
# | Inherits
|
12
|
+
# | Generic
|
13
|
+
# | ModuleSelf
|
14
|
+
# | Skip
|
15
|
+
# | Assertion
|
16
|
+
# | Application
|
17
|
+
# | RBSAnnotation
|
18
|
+
# | Override
|
19
|
+
# | IvarType
|
20
|
+
# | Yields
|
21
|
+
# | Embedded
|
22
|
+
# # | Def
|
23
|
+
# # | AttrReader | AttrWriter | AttrAccessor
|
24
|
+
# # | Include | Extend | Prepend
|
25
|
+
# # | Alias
|
26
|
+
|
27
|
+
|
7
28
|
class Base
|
8
29
|
attr_reader :source #:: CommentLines
|
9
30
|
attr_reader :tree #:: Tree
|
@@ -1,9 +1,24 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
|
1
3
|
module RBS
|
2
4
|
module Inline
|
3
5
|
module AST
|
6
|
+
# CommentLines represents consecutive comments
|
7
|
+
#
|
8
|
+
# The comments construct one String.
|
9
|
+
#
|
10
|
+
# ```ruby
|
11
|
+
# # Hello <-- Comment1
|
12
|
+
# # World <-- Comment2
|
13
|
+
# ```
|
14
|
+
#
|
15
|
+
# We want to get a String of comment1 and comment2, `"Hello\nWorld".
|
16
|
+
# And want to translate a location in the string into the location in comment1 and comment2.
|
17
|
+
#
|
4
18
|
class CommentLines
|
5
|
-
attr_reader :comments
|
19
|
+
attr_reader :comments #:: Array[[Prism::Comment, Integer]]
|
6
20
|
|
21
|
+
# @rbs comments: Array[Prism::Comment]
|
7
22
|
def initialize(comments)
|
8
23
|
offsets = comments.map do |comment|
|
9
24
|
comment.location.slice.index(/[^#\s]/) || 1
|
@@ -18,10 +33,12 @@ module RBS
|
|
18
33
|
end
|
19
34
|
end
|
20
35
|
|
21
|
-
def string
|
36
|
+
def string #:: String
|
22
37
|
comments.map {|comment, offset| comment.location.slice[offset..] }.join("\n")
|
23
38
|
end
|
24
39
|
|
40
|
+
# @rbs index: Integer
|
41
|
+
# @rbs returns [Prism::Comment, Integer]?
|
25
42
|
def comment_location(index)
|
26
43
|
comments.each do |comment, offset|
|
27
44
|
comment_length = comment.location.length
|
@@ -9,23 +9,13 @@ module RBS
|
|
9
9
|
# @rbs returns TypeName?
|
10
10
|
def type_name(node)
|
11
11
|
case node
|
12
|
-
when Prism::ConstantReadNode
|
13
|
-
TypeName(node.
|
14
|
-
when Prism::ConstantPathNode
|
15
|
-
if node.parent
|
16
|
-
if parent = type_name(node.parent)
|
17
|
-
if child = type_name(node.child)
|
18
|
-
return parent + child
|
19
|
-
end
|
20
|
-
end
|
21
|
-
else
|
22
|
-
type_name(node.child)&.absolute!
|
23
|
-
end
|
12
|
+
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
13
|
+
TypeName(node.full_name)
|
24
14
|
end
|
25
15
|
end
|
26
16
|
end
|
27
17
|
|
28
|
-
# @rbs! type t = ClassDecl | ModuleDecl | ConstantDecl
|
18
|
+
# @rbs! type t = ClassDecl | ModuleDecl | ConstantDecl | SingletonClassDecl
|
29
19
|
|
30
20
|
# @rbs!
|
31
21
|
# interface _WithComments
|
@@ -237,6 +227,9 @@ module RBS
|
|
237
227
|
node.location.start_line
|
238
228
|
end
|
239
229
|
end
|
230
|
+
|
231
|
+
class SingletonClassDecl < ModuleOrClass #[Prism::SingletonClassNode]
|
232
|
+
end
|
240
233
|
end
|
241
234
|
end
|
242
235
|
end
|
@@ -4,6 +4,11 @@ module RBS
|
|
4
4
|
module Inline
|
5
5
|
module AST
|
6
6
|
module Members
|
7
|
+
# @rbs!
|
8
|
+
# type ruby = RubyDef | RubyAlias | RubyMixin | RubyAttr | RubyPublic | RubyPrivate
|
9
|
+
# type rbs = RBSIvar | RBSEmbedded
|
10
|
+
# type t = ruby | rbs
|
11
|
+
|
7
12
|
class Base
|
8
13
|
attr_reader :location #:: Prism::Location
|
9
14
|
|
@@ -64,27 +69,6 @@ module RBS
|
|
64
69
|
end
|
65
70
|
end
|
66
71
|
|
67
|
-
# Returns the `kind` of the method definition
|
68
|
-
#
|
69
|
-
# [FIXME] It only supports `self` receiver.
|
70
|
-
#
|
71
|
-
# ```rb
|
72
|
-
# def self.foo = () # :singleton
|
73
|
-
# def object.foo = () # Not supported (returns :instance)
|
74
|
-
# ```
|
75
|
-
#
|
76
|
-
def method_kind #:: RBS::AST::Members::MethodDefinition::kind
|
77
|
-
# FIXME: really hacky implementation
|
78
|
-
case node.receiver
|
79
|
-
when Prism::SelfNode
|
80
|
-
:singleton
|
81
|
-
when nil
|
82
|
-
:instance
|
83
|
-
else
|
84
|
-
:instance
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
72
|
def return_type #:: Types::t?
|
89
73
|
if assertion
|
90
74
|
if assertion.type?
|
@@ -341,6 +325,8 @@ module RBS
|
|
341
325
|
end
|
342
326
|
|
343
327
|
class RubyMixin < RubyBase
|
328
|
+
include Declarations::ConstantUtil
|
329
|
+
|
344
330
|
# CallNode that calls `include`, `prepend`, and `extend` method
|
345
331
|
attr_reader :node #:: Prism::CallNode
|
346
332
|
|
@@ -371,11 +357,8 @@ module RBS
|
|
371
357
|
return unless node.arguments.arguments.size == 1
|
372
358
|
|
373
359
|
arg = node.arguments.arguments[0] || raise
|
374
|
-
|
375
|
-
|
376
|
-
else
|
377
|
-
raise
|
378
|
-
end
|
360
|
+
type_name = type_name(arg)
|
361
|
+
return unless type_name
|
379
362
|
|
380
363
|
args = [] #: Array[Types::t]
|
381
364
|
if application
|
data/lib/rbs/inline/ast/tree.rb
CHANGED
@@ -1,17 +1,28 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
|
1
3
|
module RBS
|
2
4
|
module Inline
|
3
5
|
module AST
|
4
6
|
class Tree
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
# @rbs!
|
8
|
+
# type token = [Symbol, String]
|
9
|
+
# type tree = token | Tree | Types::t | MethodType | nil
|
10
|
+
|
11
|
+
attr_reader :trees #:: Array[tree]
|
12
|
+
attr_reader :type #:: Symbol
|
13
|
+
|
14
|
+
# Children but without `tWHITESPACE` tokens
|
15
|
+
attr_reader :non_trivia_trees #:: Array[tree]
|
8
16
|
|
17
|
+
# @rbs type: Symbol
|
9
18
|
def initialize(type)
|
10
19
|
@type = type
|
11
20
|
@trees = []
|
12
21
|
@non_trivia_trees = []
|
13
22
|
end
|
14
23
|
|
24
|
+
# @rbs tok: tree
|
25
|
+
# @rbs returns self
|
15
26
|
def <<(tok)
|
16
27
|
trees << tok
|
17
28
|
unless tok.is_a?(Array) && tok[0] == :tWHITESPACE
|
@@ -20,7 +31,8 @@ module RBS
|
|
20
31
|
self
|
21
32
|
end
|
22
33
|
|
23
|
-
|
34
|
+
# Returns the source code associated to the tree
|
35
|
+
def to_s #:: String
|
24
36
|
buf = +""
|
25
37
|
|
26
38
|
trees.each do |tree|
|
@@ -39,6 +51,12 @@ module RBS
|
|
39
51
|
buf
|
40
52
|
end
|
41
53
|
|
54
|
+
# Returns n-th token from the children
|
55
|
+
#
|
56
|
+
# Raises if the value is not a token or nil.
|
57
|
+
#
|
58
|
+
# @rbs index: Integer
|
59
|
+
# @rbs returns token?
|
42
60
|
def nth_token(index)
|
43
61
|
tok = non_trivia_trees[index]
|
44
62
|
case tok
|
@@ -49,6 +67,12 @@ module RBS
|
|
49
67
|
end
|
50
68
|
end
|
51
69
|
|
70
|
+
# Returns n-th token from the children
|
71
|
+
#
|
72
|
+
# Returns `nil` if the value is not a token.
|
73
|
+
#
|
74
|
+
# @rbs index: Integer
|
75
|
+
# @rbs returns token?
|
52
76
|
def nth_token?(index)
|
53
77
|
tok = non_trivia_trees[index]
|
54
78
|
case tok
|
@@ -59,10 +83,22 @@ module RBS
|
|
59
83
|
end
|
60
84
|
end
|
61
85
|
|
86
|
+
# Returns n-th token from the children
|
87
|
+
#
|
88
|
+
# Raises if the value is not token.
|
89
|
+
#
|
90
|
+
# @rbs index: Integer
|
91
|
+
# @rbs returns token
|
62
92
|
def nth_token!(index)
|
63
93
|
nth_token(index) || raise
|
64
94
|
end
|
65
95
|
|
96
|
+
# Returns n-th tree from the children
|
97
|
+
#
|
98
|
+
# Raises if the value is not a tree or nil.
|
99
|
+
#
|
100
|
+
# @rbs index: Integer
|
101
|
+
# @rbs returns Tree?
|
66
102
|
def nth_tree(index)
|
67
103
|
tok = non_trivia_trees[index]
|
68
104
|
case tok
|
@@ -73,6 +109,12 @@ module RBS
|
|
73
109
|
end
|
74
110
|
end
|
75
111
|
|
112
|
+
# Returns n-th tree from the children
|
113
|
+
#
|
114
|
+
# Returns `nil` if the value is not a tree or nil.
|
115
|
+
#
|
116
|
+
# @rbs index: Integer
|
117
|
+
# @rbs returns Tree?
|
76
118
|
def nth_tree?(index)
|
77
119
|
tok = non_trivia_trees[index]
|
78
120
|
case tok
|
@@ -83,11 +125,23 @@ module RBS
|
|
83
125
|
end
|
84
126
|
end
|
85
127
|
|
128
|
+
# Returns n-th tree from the children
|
129
|
+
#
|
130
|
+
# Raises if the value is not a tree.
|
131
|
+
#
|
132
|
+
# @rbs index: Integer
|
133
|
+
# @rbs returns Tree
|
86
134
|
def nth_tree!(index)
|
87
135
|
nth_tree(index) || raise
|
88
136
|
end
|
89
137
|
|
90
138
|
|
139
|
+
# Returns n-th type from the children
|
140
|
+
#
|
141
|
+
# Raises if the value is not a type or nil.
|
142
|
+
#
|
143
|
+
# @rbs index: Integer
|
144
|
+
# @rbs returns Types::t?
|
91
145
|
def nth_type(index)
|
92
146
|
tok = non_trivia_trees[index]
|
93
147
|
case tok
|
@@ -98,6 +152,12 @@ module RBS
|
|
98
152
|
end
|
99
153
|
end
|
100
154
|
|
155
|
+
# Returns n-th type from the children
|
156
|
+
#
|
157
|
+
# Returns `nil` if the value is not a type.
|
158
|
+
#
|
159
|
+
# @rbs index: Integer
|
160
|
+
# @rbs returns Types::t?
|
101
161
|
def nth_type?(index)
|
102
162
|
tok = non_trivia_trees[index]
|
103
163
|
case tok
|
@@ -108,10 +168,22 @@ module RBS
|
|
108
168
|
end
|
109
169
|
end
|
110
170
|
|
171
|
+
# Returns n-th type from the children
|
172
|
+
#
|
173
|
+
# Raises if the value is not a type.
|
174
|
+
#
|
175
|
+
# @rbs index: Integer
|
176
|
+
# @rbs returns Types::t
|
111
177
|
def nth_type!(index)
|
112
178
|
nth_type(index) || raise
|
113
179
|
end
|
114
180
|
|
181
|
+
# Returns n-th method type from the children
|
182
|
+
#
|
183
|
+
# Raises if the value is not a method type or `nil`.
|
184
|
+
#
|
185
|
+
# @rbs index: Integer
|
186
|
+
# @rbs returns MethodType?
|
115
187
|
def nth_method_type(index)
|
116
188
|
tok = non_trivia_trees[index]
|
117
189
|
case tok
|
@@ -122,6 +194,12 @@ module RBS
|
|
122
194
|
end
|
123
195
|
end
|
124
196
|
|
197
|
+
# Returns n-th method type from the children
|
198
|
+
#
|
199
|
+
# Returns `nil` if the value is not a method type.
|
200
|
+
#
|
201
|
+
# @rbs index: Integer
|
202
|
+
# @rbs returns MethodType?
|
125
203
|
def nth_method_type?(index)
|
126
204
|
tok = non_trivia_trees[index]
|
127
205
|
case tok
|
@@ -132,6 +210,12 @@ module RBS
|
|
132
210
|
end
|
133
211
|
end
|
134
212
|
|
213
|
+
# Returns n-th method tree from the children
|
214
|
+
#
|
215
|
+
# Raises if the value is not a method tree.
|
216
|
+
#
|
217
|
+
# @rbs index: Integer
|
218
|
+
# @rbs returns MethodType
|
135
219
|
def nth_method_type!(index)
|
136
220
|
nth_method_type(index) || raise
|
137
221
|
end
|
data/lib/rbs/inline/cli.rb
CHANGED
@@ -72,15 +72,28 @@ module RBS
|
|
72
72
|
def run(args)
|
73
73
|
base_paths = [Pathname("lib"), Pathname("app")]
|
74
74
|
output_path = nil #: Pathname?
|
75
|
+
opt_in = true
|
75
76
|
|
76
77
|
OptionParser.new do |opts|
|
77
|
-
opts.on("--base=
|
78
|
+
opts.on("--base=BASE", "The path to calculate relative path of files (defaults to #{base_paths.join(File::PATH_SEPARATOR)})") do |str|
|
78
79
|
# @type var str: String
|
79
80
|
base_paths = str.split(File::PATH_SEPARATOR).map {|path| Pathname(path) }
|
80
81
|
end
|
81
82
|
|
82
|
-
opts.on("--output=
|
83
|
-
|
83
|
+
opts.on("--output[=DEST]", "Save the generated RBS files under `sig/generated` or DEST if specified (defaults to output to STDOUT)") do
|
84
|
+
if _1
|
85
|
+
output_path = Pathname(_1)
|
86
|
+
else
|
87
|
+
output_path = Pathname("sig/generated")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
opts.on("--opt-out", "Generates RBS files by default. Opt-out with `# rbs_inline: disabled` comment") do
|
92
|
+
opt_in = false
|
93
|
+
end
|
94
|
+
|
95
|
+
opts.on("--opt-in", "Generates RBS files only for files with `# rbs_inline: enabled` comment (default)") do
|
96
|
+
opt_in = true
|
84
97
|
end
|
85
98
|
|
86
99
|
opts.on("--verbose") do
|
@@ -126,7 +139,7 @@ module RBS
|
|
126
139
|
|
127
140
|
logger.debug { "Parsing ruby file #{target}..." }
|
128
141
|
|
129
|
-
if (uses, decls = Parser.parse(Prism.parse_file(target.to_s)))
|
142
|
+
if (uses, decls = Parser.parse(Prism.parse_file(target.to_s), opt_in: opt_in))
|
130
143
|
writer = Writer.new()
|
131
144
|
writer.header("Generated from #{target.relative? ? target : target.relative_path_from(Pathname.pwd)} with RBS::Inline")
|
132
145
|
writer.write(uses, decls)
|
data/lib/rbs/inline/parser.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
|
1
3
|
# @rbs use Prism::*
|
2
4
|
|
3
5
|
module RBS
|
@@ -36,22 +38,26 @@ module RBS
|
|
36
38
|
@comments = {}
|
37
39
|
end
|
38
40
|
|
39
|
-
# @rbs result: ParseResult
|
41
|
+
# @rbs result: ParseResult
|
42
|
+
# @rbs opt_in: bool -- `true` for *opt-out* mode, `false` for *opt-in* mode.
|
40
43
|
# @rbs returns [Array[AST::Annotations::Use], Array[AST::Declarations::t]]?
|
41
|
-
def self.parse(result)
|
44
|
+
def self.parse(result, opt_in:)
|
42
45
|
instance = Parser.new()
|
43
46
|
|
44
|
-
# pp result
|
45
|
-
|
46
47
|
annots = AnnotationParser.parse(result.comments)
|
47
48
|
annots.each do |result|
|
48
49
|
instance.comments[result.line_range.end] = result
|
49
50
|
end
|
50
51
|
|
51
|
-
|
52
|
-
|
52
|
+
with_enable_magic_comment = result.comments.any? {|comment| comment.location.slice =~ /\A# rbs_inline: enabled\Z/}
|
53
|
+
with_disable_magic_comment = result.comments.any? {|comment| comment.location.slice =~ /\A# rbs_inline: disabled\Z/}
|
53
54
|
|
54
|
-
return
|
55
|
+
return if with_disable_magic_comment # Skips if `rbs_inline: disabled`
|
56
|
+
|
57
|
+
if opt_in
|
58
|
+
# opt-in means the `rbs_inline: enable` is required.
|
59
|
+
return unless with_enable_magic_comment
|
60
|
+
end
|
55
61
|
|
56
62
|
uses = [] #: Array[AST::Annotations::Use]
|
57
63
|
annots.each do |annot|
|
@@ -80,7 +86,7 @@ module RBS
|
|
80
86
|
current_class_module_decl or raise
|
81
87
|
end
|
82
88
|
|
83
|
-
#:: (AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl) { () -> void } -> void
|
89
|
+
#:: (AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl | AST::Declarations::SingletonClassDecl) { () -> void } -> void
|
84
90
|
#:: (AST::Declarations::ConstantDecl) -> void
|
85
91
|
def push_class_module_decl(decl)
|
86
92
|
if current = current_class_module_decl
|
@@ -146,6 +152,18 @@ module RBS
|
|
146
152
|
load_inner_annotations(node.location.start_line, node.location.end_line, class_decl.members)
|
147
153
|
end
|
148
154
|
|
155
|
+
# @rbs override
|
156
|
+
def visit_singleton_class_node(node)
|
157
|
+
return if ignored_node?(node)
|
158
|
+
|
159
|
+
associated_comment = comments.delete(node.location.start_line - 1)
|
160
|
+
singleton_decl = AST::Declarations::SingletonClassDecl.new(node, associated_comment)
|
161
|
+
|
162
|
+
push_class_module_decl(singleton_decl) do
|
163
|
+
visit node.body
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
149
167
|
# @rbs override
|
150
168
|
def visit_module_node(node)
|
151
169
|
return if ignored_node?(node)
|