rbs-inline 0.4.0 → 0.6.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 +8 -5
- data/Rakefile +12 -0
- data/lib/rbs/inline/annotation_parser/tokenizer.rb +361 -0
- data/lib/rbs/inline/annotation_parser.rb +548 -326
- data/lib/rbs/inline/ast/annotations.rb +433 -138
- data/lib/rbs/inline/ast/comment_lines.rb +17 -20
- data/lib/rbs/inline/ast/declarations.rb +301 -28
- data/lib/rbs/inline/ast/members.rb +130 -121
- data/lib/rbs/inline/ast/tree.rb +37 -22
- data/lib/rbs/inline/cli.rb +12 -12
- data/lib/rbs/inline/node_utils.rb +1 -1
- data/lib/rbs/inline/parser.rb +165 -67
- data/lib/rbs/inline/version.rb +1 -1
- data/lib/rbs/inline/writer.rb +395 -118
- data/lib/rbs/inline.rb +1 -0
- data/rbs_collection.lock.yaml +2 -2
- data/sig/generated/rbs/inline/annotation_parser/tokenizer.rbs +221 -0
- data/sig/generated/rbs/inline/annotation_parser.rbs +148 -92
- data/sig/generated/rbs/inline/ast/annotations.rbs +143 -37
- data/sig/generated/rbs/inline/ast/comment_lines.rbs +8 -4
- data/sig/generated/rbs/inline/ast/declarations.rbs +133 -10
- data/sig/generated/rbs/inline/ast/members.rbs +26 -15
- data/sig/generated/rbs/inline/ast/tree.rbs +23 -17
- data/sig/generated/rbs/inline/cli.rbs +3 -3
- data/sig/generated/rbs/inline/node_utils.rbs +1 -1
- data/sig/generated/rbs/inline/parser.rbs +35 -18
- data/sig/generated/rbs/inline/writer.rbs +62 -22
- metadata +5 -3
data/lib/rbs/inline/cli.rb
CHANGED
@@ -17,22 +17,22 @@ module RBS
|
|
17
17
|
#
|
18
18
|
#
|
19
19
|
class PathCalculator
|
20
|
-
attr_reader :pwd
|
20
|
+
attr_reader :pwd #: Pathname
|
21
21
|
|
22
|
-
attr_reader :base_paths
|
22
|
+
attr_reader :base_paths #: Array[Pathname]
|
23
23
|
|
24
|
-
attr_reader :output_path
|
24
|
+
attr_reader :output_path #: Pathname
|
25
25
|
|
26
26
|
# @rbs pwd: Pathname
|
27
27
|
# @rbs base_paths: Array[Pathname]
|
28
28
|
# @rbs output_path: Pathname
|
29
|
-
def initialize(pwd, base_paths, output_path)
|
29
|
+
def initialize(pwd, base_paths, output_path) #: void
|
30
30
|
@pwd = pwd
|
31
31
|
@base_paths = base_paths
|
32
32
|
@output_path = output_path
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
#: (Pathname) -> Pathname?
|
36
36
|
def calculate(path)
|
37
37
|
path = pwd + path if path.relative?
|
38
38
|
path = path.cleanpath
|
@@ -49,18 +49,18 @@ module RBS
|
|
49
49
|
|
50
50
|
# @rbs path: Pathname
|
51
51
|
# @rbs prefix: Pathname
|
52
|
-
# @rbs
|
52
|
+
# @rbs return: bool
|
53
53
|
def has_prefix?(path, prefix:)
|
54
54
|
path.descend.include?(prefix)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
attr_reader :stdout, :stderr
|
59
|
-
attr_reader :logger
|
58
|
+
attr_reader :stdout, :stderr #: IO
|
59
|
+
attr_reader :logger #: Logger
|
60
60
|
|
61
61
|
# @rbs stdout: IO
|
62
62
|
# @rbs stderr: IO
|
63
|
-
def initialize(stdout: STDOUT, stderr: STDERR)
|
63
|
+
def initialize(stdout: STDOUT, stderr: STDERR) #: void
|
64
64
|
@stdout = stdout
|
65
65
|
@stderr = stderr
|
66
66
|
@logger = Logger.new(stderr)
|
@@ -68,7 +68,7 @@ module RBS
|
|
68
68
|
end
|
69
69
|
|
70
70
|
# @rbs args: Array[String]
|
71
|
-
# @rbs
|
71
|
+
# @rbs return: Integer
|
72
72
|
def run(args)
|
73
73
|
base_paths = [Pathname("lib"), Pathname("app")]
|
74
74
|
output_path = nil #: Pathname?
|
@@ -139,10 +139,10 @@ module RBS
|
|
139
139
|
|
140
140
|
logger.debug { "Parsing ruby file #{target}..." }
|
141
141
|
|
142
|
-
if (uses, decls = Parser.parse(Prism.parse_file(target.to_s), opt_in: opt_in))
|
142
|
+
if (uses, decls, rbs_decls = Parser.parse(Prism.parse_file(target.to_s), opt_in: opt_in))
|
143
143
|
writer = Writer.new()
|
144
144
|
writer.header("Generated from #{target.relative? ? target : target.relative_path_from(Pathname.pwd)} with RBS::Inline")
|
145
|
-
writer.write(uses, decls)
|
145
|
+
writer.write(uses, decls, rbs_decls)
|
146
146
|
|
147
147
|
if output
|
148
148
|
unless output.parent.directory?
|
data/lib/rbs/inline/parser.rb
CHANGED
@@ -5,13 +5,18 @@
|
|
5
5
|
module RBS
|
6
6
|
module Inline
|
7
7
|
class Parser < Prism::Visitor
|
8
|
+
# @rbs! type with_members = AST::Declarations::ModuleDecl
|
9
|
+
# | AST::Declarations::ClassDecl
|
10
|
+
# | AST::Declarations::SingletonClassDecl
|
11
|
+
# | AST::Declarations::BlockDecl
|
12
|
+
|
8
13
|
# The top level declarations
|
9
14
|
#
|
10
|
-
attr_reader :decls
|
15
|
+
attr_reader :decls #: Array[AST::Declarations::t]
|
11
16
|
|
12
17
|
# The surrounding declarations
|
13
18
|
#
|
14
|
-
attr_reader :surrounding_decls
|
19
|
+
attr_reader :surrounding_decls #: Array[with_members]
|
15
20
|
|
16
21
|
# ParsingResult associated with the line number at the end
|
17
22
|
#
|
@@ -23,24 +28,35 @@ module RBS
|
|
23
28
|
# > [!IMPORTANT]
|
24
29
|
# > The values will be removed during parsing.
|
25
30
|
#
|
26
|
-
attr_reader :comments
|
31
|
+
attr_reader :comments #: Hash[Integer, AnnotationParser::ParsingResult]
|
27
32
|
|
28
33
|
# The current visibility applied to single `def` node
|
29
34
|
#
|
30
35
|
# Assuming it's directly inside `private` or `public` calls.
|
31
36
|
# `nil` when the `def` node is not inside `private` or `public` calls.
|
32
37
|
#
|
33
|
-
attr_reader :current_visibility
|
38
|
+
attr_reader :current_visibility #: RBS::AST::Members::visibility?
|
34
39
|
|
35
|
-
def initialize()
|
40
|
+
def initialize() #: void
|
36
41
|
@decls = []
|
37
42
|
@surrounding_decls = []
|
38
43
|
@comments = {}
|
39
44
|
end
|
40
45
|
|
46
|
+
# Parses the given Prism result to a three tuple
|
47
|
+
#
|
48
|
+
# Returns a three tuple of:
|
49
|
+
#
|
50
|
+
# 1. An array of `use` directives
|
51
|
+
# 2. An array of declarations
|
52
|
+
# 3. An array of RBS declarations given as `@rbs!` annotation at top-level
|
53
|
+
#
|
54
|
+
# Note that only RBS declarations are allowed in the top-level `@rbs!` annotations.
|
55
|
+
# RBS *members* are ignored in the array.
|
56
|
+
#
|
41
57
|
# @rbs result: ParseResult
|
42
58
|
# @rbs opt_in: bool -- `true` for *opt-out* mode, `false` for *opt-in* mode.
|
43
|
-
# @rbs
|
59
|
+
# @rbs return: [Array[AST::Annotations::Use], Array[AST::Declarations::t], Array[RBS::AST::Declarations::t]]?
|
44
60
|
def self.parse(result, opt_in:)
|
45
61
|
instance = Parser.new()
|
46
62
|
|
@@ -61,7 +77,7 @@ module RBS
|
|
61
77
|
|
62
78
|
uses = [] #: Array[AST::Annotations::Use]
|
63
79
|
annots.each do |annot|
|
64
|
-
annot.
|
80
|
+
annot.each_annotation do |annotation|
|
65
81
|
if annotation.is_a?(AST::Annotations::Use)
|
66
82
|
uses << annotation
|
67
83
|
end
|
@@ -70,24 +86,44 @@ module RBS
|
|
70
86
|
|
71
87
|
instance.visit(result.value)
|
72
88
|
|
89
|
+
rbs_embeddeds = [] #: Array[AST::Members::RBSEmbedded]
|
90
|
+
|
91
|
+
instance.comments.each_value do |comment|
|
92
|
+
comment.each_annotation do |annotation|
|
93
|
+
if annotation.is_a?(AST::Annotations::Embedded)
|
94
|
+
rbs_embeddeds << AST::Members::RBSEmbedded.new(comment, annotation)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
rbs_decls = rbs_embeddeds.flat_map do |embedded|
|
100
|
+
if (members = embedded.members).is_a?(Array)
|
101
|
+
members.select do |member|
|
102
|
+
member.is_a?(RBS::AST::Declarations::Base)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
[]
|
106
|
+
end #: Array[RBS::AST::Declarations::t]
|
107
|
+
end
|
108
|
+
|
73
109
|
[
|
74
110
|
uses,
|
75
|
-
instance.decls
|
111
|
+
instance.decls,
|
112
|
+
rbs_decls
|
76
113
|
]
|
77
114
|
end
|
78
115
|
|
79
|
-
# @rbs
|
116
|
+
# @rbs return: with_members?
|
80
117
|
def current_class_module_decl
|
81
118
|
surrounding_decls.last
|
82
119
|
end
|
83
120
|
|
84
|
-
# @rbs
|
121
|
+
# @rbs return: with_members
|
85
122
|
def current_class_module_decl!
|
86
123
|
current_class_module_decl or raise
|
87
124
|
end
|
88
125
|
|
89
|
-
|
90
|
-
#:: (AST::Declarations::ConstantDecl) -> void
|
126
|
+
#: (with_members) { () -> void } -> void
|
91
127
|
def push_class_module_decl(decl)
|
92
128
|
if current = current_class_module_decl
|
93
129
|
current.members << decl
|
@@ -96,7 +132,7 @@ module RBS
|
|
96
132
|
end
|
97
133
|
|
98
134
|
if block_given?
|
99
|
-
surrounding_decls.push(
|
135
|
+
surrounding_decls.push(decl)
|
100
136
|
begin
|
101
137
|
yield
|
102
138
|
ensure
|
@@ -114,11 +150,11 @@ module RBS
|
|
114
150
|
# @rbs members: Array[AST::Members::t | AST::Declarations::t] --
|
115
151
|
# The destination.
|
116
152
|
# The method doesn't insert declarations, but have it to please type checker.
|
117
|
-
def load_inner_annotations(start_line, end_line, members)
|
153
|
+
def load_inner_annotations(start_line, end_line, members) #: void
|
118
154
|
comments = inner_annotations(start_line, end_line)
|
119
155
|
|
120
156
|
comments.each do |comment|
|
121
|
-
comment.
|
157
|
+
comment.each_annotation do |annotation|
|
122
158
|
case annotation
|
123
159
|
when AST::Annotations::IvarType
|
124
160
|
members << AST::Members::RBSIvar.new(comment, annotation)
|
@@ -133,51 +169,53 @@ module RBS
|
|
133
169
|
|
134
170
|
# @rbs override
|
135
171
|
def visit_class_node(node)
|
136
|
-
|
172
|
+
process_nesting_node(node) do
|
173
|
+
visit node.constant_path
|
174
|
+
visit node.superclass
|
137
175
|
|
138
|
-
|
139
|
-
|
176
|
+
associated_comment = comments.delete(node.location.start_line - 1)
|
177
|
+
if node.superclass
|
178
|
+
app_comment = application_annotation(node.superclass)
|
179
|
+
end
|
140
180
|
|
141
|
-
|
142
|
-
if node.superclass
|
143
|
-
app_comment = application_annotation(node.superclass)
|
144
|
-
end
|
181
|
+
class_decl = AST::Declarations::ClassDecl.new(node, associated_comment, app_comment)
|
145
182
|
|
146
|
-
|
183
|
+
push_class_module_decl(class_decl) do
|
184
|
+
visit node.body
|
185
|
+
end
|
147
186
|
|
148
|
-
|
149
|
-
visit node.body
|
187
|
+
load_inner_annotations(node.location.start_line, node.location.end_line, class_decl.members)
|
150
188
|
end
|
151
|
-
|
152
|
-
load_inner_annotations(node.location.start_line, node.location.end_line, class_decl.members)
|
153
189
|
end
|
154
190
|
|
155
191
|
# @rbs override
|
156
192
|
def visit_singleton_class_node(node)
|
157
|
-
|
193
|
+
process_nesting_node(node) do
|
194
|
+
associated_comment = comments.delete(node.location.start_line - 1)
|
195
|
+
singleton_decl = AST::Declarations::SingletonClassDecl.new(node, associated_comment)
|
158
196
|
|
159
|
-
|
160
|
-
|
197
|
+
push_class_module_decl(singleton_decl) do
|
198
|
+
visit node.body
|
199
|
+
end
|
161
200
|
|
162
|
-
|
163
|
-
visit node.body
|
201
|
+
load_inner_annotations(node.location.start_line, node.location.end_line, singleton_decl.members)
|
164
202
|
end
|
165
203
|
end
|
166
204
|
|
167
205
|
# @rbs override
|
168
206
|
def visit_module_node(node)
|
169
|
-
|
207
|
+
process_nesting_node(node) do
|
208
|
+
visit node.constant_path
|
170
209
|
|
171
|
-
|
210
|
+
associated_comment = comments.delete(node.location.start_line - 1)
|
172
211
|
|
173
|
-
|
212
|
+
module_decl = AST::Declarations::ModuleDecl.new(node, associated_comment)
|
213
|
+
push_class_module_decl(module_decl) do
|
214
|
+
visit node.body
|
215
|
+
end
|
174
216
|
|
175
|
-
|
176
|
-
push_class_module_decl(module_decl) do
|
177
|
-
visit node.body
|
217
|
+
load_inner_annotations(node.location.start_line, node.location.end_line, module_decl.members)
|
178
218
|
end
|
179
|
-
|
180
|
-
load_inner_annotations(node.location.start_line, node.location.end_line, module_decl.members)
|
181
219
|
end
|
182
220
|
|
183
221
|
# Returns an array of annotations from comments that is located between start_line and end_line
|
@@ -191,7 +229,7 @@ module RBS
|
|
191
229
|
#
|
192
230
|
# @rbs start_line: Integer
|
193
231
|
# @rbs end_line: Integer
|
194
|
-
def inner_annotations(start_line, end_line)
|
232
|
+
def inner_annotations(start_line, end_line) #: Array[AnnotationParser::ParsingResult]
|
195
233
|
annotations = comments.each_value.select do |annotation|
|
196
234
|
range = annotation.line_range
|
197
235
|
start_line < range.begin && range.end < end_line
|
@@ -204,25 +242,27 @@ module RBS
|
|
204
242
|
|
205
243
|
# @rbs override
|
206
244
|
def visit_def_node(node)
|
207
|
-
|
208
|
-
|
245
|
+
process_nesting_node(node) do
|
246
|
+
return unless current_class_module_decl
|
209
247
|
|
210
|
-
|
248
|
+
current_decl = current_class_module_decl!
|
211
249
|
|
212
|
-
|
213
|
-
|
214
|
-
|
250
|
+
if node.location
|
251
|
+
associated_comment = comments.delete(node.location.start_line - 1)
|
252
|
+
end
|
215
253
|
|
216
|
-
|
254
|
+
assertion = assertion_annotation(node.rparen_loc || node&.parameters&.location || node.name_loc)
|
217
255
|
|
218
|
-
|
256
|
+
current_decl.members << AST::Members::RubyDef.new(node, associated_comment, current_visibility, assertion)
|
219
257
|
|
220
|
-
|
258
|
+
super
|
259
|
+
end
|
221
260
|
end
|
222
261
|
|
223
262
|
# @rbs override
|
224
263
|
def visit_alias_method_node(node)
|
225
264
|
return if ignored_node?(node)
|
265
|
+
return unless current_class_module_decl
|
226
266
|
|
227
267
|
if node.location
|
228
268
|
comment = comments.delete(node.location.start_line - 1)
|
@@ -256,9 +296,9 @@ module RBS
|
|
256
296
|
end
|
257
297
|
if assertion_comment && comment_line
|
258
298
|
comments.delete(comment_line)
|
259
|
-
assertion = assertion_comment.
|
260
|
-
annotation.is_a?(AST::Annotations::
|
261
|
-
end #: AST::Annotations::
|
299
|
+
assertion = assertion_comment.each_annotation.find do |annotation|
|
300
|
+
annotation.is_a?(AST::Annotations::TypeAssertion)
|
301
|
+
end #: AST::Annotations::TypeAssertion?
|
262
302
|
end
|
263
303
|
|
264
304
|
current_class_module_decl!.members << AST::Members::RubyAttr.new(node, comment, assertion)
|
@@ -296,8 +336,8 @@ module RBS
|
|
296
336
|
end
|
297
337
|
|
298
338
|
# @rbs new_visibility: RBS::AST::Members::visibility?
|
299
|
-
# @rbs block:
|
300
|
-
# @rbs
|
339
|
+
# @rbs &block: () -> void
|
340
|
+
# @rbs return: void
|
301
341
|
def push_visibility(new_visibility, &block)
|
302
342
|
old_visibility = current_visibility
|
303
343
|
|
@@ -309,11 +349,21 @@ module RBS
|
|
309
349
|
end
|
310
350
|
end
|
311
351
|
|
352
|
+
# @rbs [A] (Node) { () -> A } -> A?
|
353
|
+
def process_nesting_node(node)
|
354
|
+
yield unless ignored_node?(node)
|
355
|
+
ensure
|
356
|
+
# Delete all inner annotations
|
357
|
+
inner_annotations(node.location.start_line, node.location.end_line)
|
358
|
+
comments.delete(node.location.start_line)
|
359
|
+
comments.delete(node.location.end_line)
|
360
|
+
end
|
361
|
+
|
312
362
|
# @rbs node: Node
|
313
|
-
# @rbs
|
363
|
+
# @rbs return: bool
|
314
364
|
def ignored_node?(node)
|
315
365
|
if comment = comments.fetch(node.location.start_line - 1, nil)
|
316
|
-
comment.
|
366
|
+
comment.each_annotation.any? { _1.is_a?(AST::Annotations::Skip) }
|
317
367
|
else
|
318
368
|
false
|
319
369
|
end
|
@@ -324,7 +374,7 @@ module RBS
|
|
324
374
|
# The application annotation is removed from `comments`.
|
325
375
|
#
|
326
376
|
# @rbs node: Node
|
327
|
-
# @rbs
|
377
|
+
# @rbs return: AST::Annotations::Application?
|
328
378
|
def application_annotation(node)
|
329
379
|
comment_line, app_comment = comments.find do |_, comment|
|
330
380
|
comment.line_range.begin == node.location.end_line
|
@@ -332,18 +382,18 @@ module RBS
|
|
332
382
|
|
333
383
|
if app_comment && comment_line
|
334
384
|
comments.delete(comment_line)
|
335
|
-
app_comment.
|
385
|
+
app_comment.each_annotation.find do |annotation|
|
336
386
|
annotation.is_a?(AST::Annotations::Application)
|
337
387
|
end #: AST::Annotations::Application?
|
338
388
|
end
|
339
389
|
end
|
340
390
|
|
341
|
-
# Fetch
|
391
|
+
# Fetch TypeAssertion annotation which is associated to `node`
|
342
392
|
#
|
343
393
|
# The assertion annotation is removed from `comments`.
|
344
394
|
#
|
345
395
|
# @rbs node: Node | Location
|
346
|
-
# @rbs
|
396
|
+
# @rbs return: AST::Annotations::TypeAssertion?
|
347
397
|
def assertion_annotation(node)
|
348
398
|
if node.is_a?(Prism::Location)
|
349
399
|
location = node
|
@@ -356,9 +406,9 @@ module RBS
|
|
356
406
|
|
357
407
|
if app_comment && comment_line
|
358
408
|
comments.delete(comment_line)
|
359
|
-
app_comment.
|
360
|
-
annotation.is_a?(AST::Annotations::
|
361
|
-
end #: AST::Annotations::
|
409
|
+
app_comment.each_annotation.find do |annotation|
|
410
|
+
annotation.is_a?(AST::Annotations::TypeAssertion)
|
411
|
+
end #: AST::Annotations::TypeAssertion?
|
362
412
|
end
|
363
413
|
end
|
364
414
|
|
@@ -367,10 +417,58 @@ module RBS
|
|
367
417
|
return if ignored_node?(node)
|
368
418
|
|
369
419
|
comment = comments.delete(node.location.start_line - 1)
|
370
|
-
assertion = assertion_annotation(node)
|
371
420
|
|
372
|
-
|
373
|
-
|
421
|
+
case
|
422
|
+
when data_node = AST::Declarations::DataAssignDecl.data_define?(node)
|
423
|
+
type_decls = {} #: Hash[Integer, AST::Annotations::TypeAssertion]
|
424
|
+
|
425
|
+
inner_annotations(node.location.start_line, node.location.end_line).flat_map do |comment|
|
426
|
+
comment.each_annotation do |annotation|
|
427
|
+
if annotation.is_a?(AST::Annotations::TypeAssertion)
|
428
|
+
start_line = annotation.source.comments[0].location.start_line
|
429
|
+
type_decls[start_line] = annotation
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
decl = AST::Declarations::DataAssignDecl.new(node, data_node, comment, type_decls)
|
435
|
+
when struct_node = AST::Declarations::StructAssignDecl.struct_new?(node)
|
436
|
+
type_decls = {} #: Hash[Integer, AST::Annotations::TypeAssertion]
|
437
|
+
|
438
|
+
inner_annotations(node.location.start_line, node.location.end_line).flat_map do |comment|
|
439
|
+
comment.each_annotation do |annotation|
|
440
|
+
if annotation.is_a?(AST::Annotations::TypeAssertion)
|
441
|
+
start_line = annotation.source.comments[0].location.start_line
|
442
|
+
type_decls[start_line] = annotation
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
decl = AST::Declarations::StructAssignDecl.new(node, struct_node, comment, type_decls)
|
448
|
+
else
|
449
|
+
assertion = assertion_annotation(node)
|
450
|
+
decl = AST::Declarations::ConstantDecl.new(node, comment, assertion)
|
451
|
+
end
|
452
|
+
|
453
|
+
if current = current_class_module_decl
|
454
|
+
current.members << decl
|
455
|
+
else
|
456
|
+
decls << decl
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
# @rbs override
|
461
|
+
def visit_block_node(node)
|
462
|
+
process_nesting_node(node) do
|
463
|
+
comment = comments.delete(node.location.start_line - 1)
|
464
|
+
block = AST::Declarations::BlockDecl.new(node, comment)
|
465
|
+
|
466
|
+
push_class_module_decl(block) do
|
467
|
+
super
|
468
|
+
end
|
469
|
+
|
470
|
+
load_inner_annotations(node.location.start_line, node.location.end_line, block.members)
|
471
|
+
end
|
374
472
|
end
|
375
473
|
end
|
376
474
|
end
|