rbs 4.0.3 → 4.1.0.pre.1
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/.github/workflows/ruby.yml +34 -6
- data/.github/workflows/rust.yml +0 -2
- data/.github/workflows/windows.yml +0 -3
- data/CHANGELOG.md +0 -8
- data/Rakefile +2 -2
- data/config.yml +24 -0
- data/core/builtin.rbs +1 -0
- data/core/class.rbs +5 -3
- data/core/kernel.rbs +26 -11
- data/core/ruby_vm.rbs +40 -0
- data/docs/inline.md +29 -1
- data/ext/rbs_extension/ast_translation.c +21 -0
- data/ext/rbs_extension/class_constants.c +2 -0
- data/ext/rbs_extension/class_constants.h +1 -0
- data/ext/rbs_extension/extconf.rb +1 -0
- data/include/rbs/ast.h +314 -297
- data/include/rbs/defines.h +13 -0
- data/include/rbs/lexer.h +1 -0
- data/lib/rbs/annotate/rdoc_annotator.rb +27 -31
- data/lib/rbs/ast/ruby/annotations.rb +42 -0
- data/lib/rbs/ast/ruby/declarations.rb +11 -1
- data/lib/rbs/ast/ruby/members.rb +28 -0
- data/lib/rbs/cli.rb +3 -5
- data/lib/rbs/collection/config/lockfile_generator.rb +14 -1
- data/lib/rbs/environment.rb +6 -0
- data/lib/rbs/inline_parser.rb +49 -25
- data/lib/rbs/rewriter.rb +70 -0
- data/lib/rbs/test/type_check.rb +6 -1
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs.rb +1 -0
- data/sig/annotate/rdoc_annotater.rbs +12 -9
- data/sig/ast/ruby/annotations.rbs +49 -0
- data/sig/ast/ruby/members.rbs +15 -0
- data/sig/collection/config/lockfile_generator.rbs +2 -0
- data/sig/inline_parser.rbs +2 -0
- data/sig/manifest.yaml +0 -1
- data/sig/rewriter.rbs +45 -0
- data/src/ast.c +109 -85
- data/src/lexer.c +137 -114
- data/src/lexer.re +1 -0
- data/src/lexstate.c +1 -0
- data/src/parser.c +55 -5
- data/stdlib/openssl/0/openssl.rbs +2 -2
- metadata +3 -1
data/include/rbs/defines.h
CHANGED
|
@@ -83,4 +83,17 @@
|
|
|
83
83
|
#define RBS_ATTRIBUTE_UNUSED
|
|
84
84
|
#endif
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Nullability annotations for pointer types.
|
|
88
|
+
* Clang supports _Nullable and _Nonnull to indicate whether a pointer may be NULL.
|
|
89
|
+
* On other compilers, these expand to nothing.
|
|
90
|
+
*/
|
|
91
|
+
#ifdef __clang__
|
|
92
|
+
#define RBS_NULLABLE _Nullable
|
|
93
|
+
#define RBS_NONNULL _Nonnull
|
|
94
|
+
#else
|
|
95
|
+
#define RBS_NULLABLE
|
|
96
|
+
#define RBS_NONNULL
|
|
97
|
+
#endif
|
|
98
|
+
|
|
86
99
|
#endif
|
data/include/rbs/lexer.h
CHANGED
|
@@ -13,25 +13,22 @@ module RBS
|
|
|
13
13
|
@include_filename = true
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def annotate_file(path, preserve:)
|
|
17
|
-
|
|
16
|
+
def annotate_file(path, preserve: true)
|
|
17
|
+
buffer, _, decls = Parser.parse_signature(path.read())
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
rewriter = Rewriter.new(buffer)
|
|
20
|
+
annotate_decls(decls, rewriter)
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
path.open("w") do |io|
|
|
24
|
-
Writer.new(out: io).preserve!(preserve: preserve).write(decls)
|
|
25
|
-
end
|
|
22
|
+
path.write(rewriter.string)
|
|
26
23
|
end
|
|
27
24
|
|
|
28
|
-
def annotate_decls(decls, outer: [])
|
|
25
|
+
def annotate_decls(decls, rewriter, outer: [])
|
|
29
26
|
decls.each do |decl|
|
|
30
27
|
case decl
|
|
31
28
|
when AST::Declarations::Class, AST::Declarations::Module
|
|
32
|
-
annotate_class(decl, outer: outer)
|
|
29
|
+
annotate_class(decl, rewriter, outer: outer)
|
|
33
30
|
when AST::Declarations::Constant
|
|
34
|
-
annotate_constant(decl, outer: outer)
|
|
31
|
+
annotate_constant(decl, rewriter, outer: outer)
|
|
35
32
|
end
|
|
36
33
|
end
|
|
37
34
|
end
|
|
@@ -244,7 +241,7 @@ module RBS
|
|
|
244
241
|
end
|
|
245
242
|
end
|
|
246
243
|
|
|
247
|
-
def annotate_class(decl, outer:)
|
|
244
|
+
def annotate_class(decl, rewriter, outer:)
|
|
248
245
|
annots = annotations(decl)
|
|
249
246
|
|
|
250
247
|
full_name = resolve_name(decl.name, outer: outer)
|
|
@@ -252,7 +249,7 @@ module RBS
|
|
|
252
249
|
text = resolve_doc_source(annots.copy_annotation, tester: annots) { doc_for_class(full_name, tester: annots) }
|
|
253
250
|
end
|
|
254
251
|
|
|
255
|
-
replace_comment(decl, text)
|
|
252
|
+
replace_comment(decl, text, rewriter)
|
|
256
253
|
|
|
257
254
|
unless annots.skip_all?
|
|
258
255
|
outer_ = outer + [decl.name.to_namespace]
|
|
@@ -260,28 +257,28 @@ module RBS
|
|
|
260
257
|
decl.each_member do |member|
|
|
261
258
|
case member
|
|
262
259
|
when AST::Members::MethodDefinition
|
|
263
|
-
annotate_method(full_name, member)
|
|
260
|
+
annotate_method(full_name, member, rewriter)
|
|
264
261
|
when AST::Members::Alias
|
|
265
|
-
annotate_alias(full_name, member)
|
|
262
|
+
annotate_alias(full_name, member, rewriter)
|
|
266
263
|
when AST::Members::AttrReader, AST::Members::AttrAccessor, AST::Members::AttrWriter
|
|
267
|
-
annotate_attribute(full_name, member)
|
|
264
|
+
annotate_attribute(full_name, member, rewriter)
|
|
268
265
|
end
|
|
269
266
|
end
|
|
270
267
|
|
|
271
|
-
annotate_decls(decl.each_decl.to_a, outer: outer_)
|
|
268
|
+
annotate_decls(decl.each_decl.to_a, rewriter, outer: outer_)
|
|
272
269
|
end
|
|
273
270
|
end
|
|
274
271
|
|
|
275
|
-
def annotate_constant(const, outer:)
|
|
272
|
+
def annotate_constant(const, rewriter, outer:)
|
|
276
273
|
annots = Annotations.new([])
|
|
277
274
|
|
|
278
275
|
full_name = resolve_name(const.name, outer: outer)
|
|
279
276
|
text = doc_for_constant(full_name, tester: annots)
|
|
280
277
|
|
|
281
|
-
replace_comment(const, text)
|
|
278
|
+
replace_comment(const, text, rewriter)
|
|
282
279
|
end
|
|
283
280
|
|
|
284
|
-
def annotate_alias(typename, als)
|
|
281
|
+
def annotate_alias(typename, als, rewriter)
|
|
285
282
|
annots = annotations(als)
|
|
286
283
|
|
|
287
284
|
unless annots.skip?
|
|
@@ -295,7 +292,7 @@ module RBS
|
|
|
295
292
|
end
|
|
296
293
|
end
|
|
297
294
|
|
|
298
|
-
replace_comment(als, text)
|
|
295
|
+
replace_comment(als, text, rewriter)
|
|
299
296
|
end
|
|
300
297
|
|
|
301
298
|
def join_docs(docs, separator: "----")
|
|
@@ -311,7 +308,7 @@ module RBS
|
|
|
311
308
|
end
|
|
312
309
|
end
|
|
313
310
|
|
|
314
|
-
def annotate_method(typename, method)
|
|
311
|
+
def annotate_method(typename, method, rewriter)
|
|
315
312
|
annots = annotations(method)
|
|
316
313
|
|
|
317
314
|
unless annots.skip?
|
|
@@ -337,10 +334,10 @@ module RBS
|
|
|
337
334
|
}
|
|
338
335
|
end
|
|
339
336
|
|
|
340
|
-
replace_comment(method, text)
|
|
337
|
+
replace_comment(method, text, rewriter)
|
|
341
338
|
end
|
|
342
339
|
|
|
343
|
-
def annotate_attribute(typename, attr)
|
|
340
|
+
def annotate_attribute(typename, attr, rewriter)
|
|
344
341
|
annots = annotations(attr)
|
|
345
342
|
|
|
346
343
|
unless annots.skip?
|
|
@@ -368,18 +365,17 @@ module RBS
|
|
|
368
365
|
end
|
|
369
366
|
end
|
|
370
367
|
|
|
371
|
-
replace_comment(attr, text)
|
|
368
|
+
replace_comment(attr, text, rewriter)
|
|
372
369
|
end
|
|
373
370
|
|
|
374
|
-
def replace_comment(commented, string)
|
|
371
|
+
def replace_comment(commented, string, rewriter)
|
|
375
372
|
if string
|
|
376
373
|
if string.empty?
|
|
377
|
-
commented.
|
|
374
|
+
rewriter.delete_comment(commented.comment) if commented.comment
|
|
375
|
+
elsif commented.comment
|
|
376
|
+
rewriter.replace_comment(commented.comment, content: string)
|
|
378
377
|
else
|
|
379
|
-
commented.
|
|
380
|
-
:@comment,
|
|
381
|
-
AST::Comment.new(location: nil, string: string)
|
|
382
|
-
)
|
|
378
|
+
rewriter.add_comment(commented.location || raise, *commented.annotations.filter_map(&:location), content: string)
|
|
383
379
|
end
|
|
384
380
|
end
|
|
385
381
|
end
|
|
@@ -353,6 +353,48 @@ module RBS
|
|
|
353
353
|
end
|
|
354
354
|
end
|
|
355
355
|
|
|
356
|
+
class ModuleSelfAnnotation < Base
|
|
357
|
+
attr_reader :keyword_location, :colon_location, :name, :args, :open_bracket_location, :close_bracket_location, :args_comma_locations, :comment_location
|
|
358
|
+
|
|
359
|
+
def initialize(location:, prefix_location:, keyword_location:, colon_location:, name:, args:, open_bracket_location:, close_bracket_location:, args_comma_locations:, comment_location:)
|
|
360
|
+
super(location, prefix_location)
|
|
361
|
+
@keyword_location = keyword_location
|
|
362
|
+
@colon_location = colon_location
|
|
363
|
+
@name = name
|
|
364
|
+
@args = args
|
|
365
|
+
@open_bracket_location = open_bracket_location
|
|
366
|
+
@close_bracket_location = close_bracket_location
|
|
367
|
+
@args_comma_locations = args_comma_locations
|
|
368
|
+
@comment_location = comment_location
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def map_type_name
|
|
372
|
+
mapped_args = args.map { |type| type.map_type_name { yield _1 } }
|
|
373
|
+
|
|
374
|
+
self.class.new(
|
|
375
|
+
location:,
|
|
376
|
+
prefix_location:,
|
|
377
|
+
keyword_location:,
|
|
378
|
+
colon_location:,
|
|
379
|
+
name: yield(name),
|
|
380
|
+
args: mapped_args,
|
|
381
|
+
open_bracket_location:,
|
|
382
|
+
close_bracket_location:,
|
|
383
|
+
args_comma_locations:,
|
|
384
|
+
comment_location:
|
|
385
|
+
) #: self
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def type_fingerprint
|
|
389
|
+
[
|
|
390
|
+
"annots/module_self",
|
|
391
|
+
name.to_s,
|
|
392
|
+
args.map(&:to_s),
|
|
393
|
+
comment_location&.source
|
|
394
|
+
]
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
356
398
|
class BlockParamTypeAnnotation < Base
|
|
357
399
|
attr_reader :ampersand_location, :name_location, :colon_location, :question_location, :type_location, :type, :comment_location
|
|
358
400
|
|
|
@@ -137,7 +137,17 @@ module RBS
|
|
|
137
137
|
|
|
138
138
|
def type_params = []
|
|
139
139
|
|
|
140
|
-
def self_types
|
|
140
|
+
def self_types
|
|
141
|
+
members.filter_map do |member|
|
|
142
|
+
if member.is_a?(Members::ModuleSelfMember)
|
|
143
|
+
AST::Declarations::Module::Self.new(
|
|
144
|
+
name: member.name,
|
|
145
|
+
args: member.args,
|
|
146
|
+
location: member.location
|
|
147
|
+
)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
141
151
|
|
|
142
152
|
def location
|
|
143
153
|
rbs_location(node.location)
|
data/lib/rbs/ast/ruby/members.rb
CHANGED
|
@@ -717,6 +717,34 @@ module RBS
|
|
|
717
717
|
]
|
|
718
718
|
end
|
|
719
719
|
end
|
|
720
|
+
|
|
721
|
+
class ModuleSelfMember < Base
|
|
722
|
+
attr_reader :annotation
|
|
723
|
+
|
|
724
|
+
def initialize(buffer, annotation)
|
|
725
|
+
super(buffer)
|
|
726
|
+
@annotation = annotation
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
def name
|
|
730
|
+
annotation.name
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
def args
|
|
734
|
+
annotation.args
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
def location
|
|
738
|
+
annotation.location
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
def type_fingerprint
|
|
742
|
+
[
|
|
743
|
+
"members/module_self",
|
|
744
|
+
annotation.type_fingerprint
|
|
745
|
+
]
|
|
746
|
+
end
|
|
747
|
+
end
|
|
720
748
|
end
|
|
721
749
|
end
|
|
722
750
|
end
|
data/lib/rbs/cli.rb
CHANGED
|
@@ -962,8 +962,6 @@ Options:
|
|
|
962
962
|
source = RBS::Annotate::RDocSource.new()
|
|
963
963
|
annotator = RBS::Annotate::RDocAnnotator.new(source: source)
|
|
964
964
|
|
|
965
|
-
preserve = true
|
|
966
|
-
|
|
967
965
|
OptionParser.new do |opts|
|
|
968
966
|
opts.banner = <<-EOB
|
|
969
967
|
Usage: rbs annotate [options...] [files...]
|
|
@@ -984,7 +982,7 @@ Options:
|
|
|
984
982
|
opts.on("-d", "--dir DIRNAME", "Load RDoc from DIRNAME") {|d| source.extra_dirs << Pathname(d) }
|
|
985
983
|
opts.on("--[no-]arglists", "Generate arglists section (defaults to true)") {|b| annotator.include_arg_lists = b }
|
|
986
984
|
opts.on("--[no-]filename", "Include source file name in the documentation (defaults to true)") {|b| annotator.include_filename = b }
|
|
987
|
-
opts.on("--[no-]preserve", "
|
|
985
|
+
opts.on("--[no-]preserve", "[Deprecated] It always preserves the format") { stdout.puts "The `--preserve` option is deprecated. The tool always preserves the format of RBS files." }
|
|
988
986
|
end.parse!(args)
|
|
989
987
|
|
|
990
988
|
source.load()
|
|
@@ -994,11 +992,11 @@ Options:
|
|
|
994
992
|
if path.directory?
|
|
995
993
|
Pathname.glob((path + "**/*.rbs").to_s).each do |path|
|
|
996
994
|
stdout.puts "Processing #{path}..."
|
|
997
|
-
annotator.annotate_file(path
|
|
995
|
+
annotator.annotate_file(path)
|
|
998
996
|
end
|
|
999
997
|
else
|
|
1000
998
|
stdout.puts "Processing #{path}..."
|
|
1001
|
-
annotator.annotate_file(path
|
|
999
|
+
annotator.annotate_file(path)
|
|
1002
1000
|
end
|
|
1003
1001
|
end
|
|
1004
1002
|
|
|
@@ -21,6 +21,17 @@ module RBS
|
|
|
21
21
|
"pstore" => nil,
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
NONGEM_STDLIBS = Set[
|
|
25
|
+
"cgi-escape",
|
|
26
|
+
"coverage",
|
|
27
|
+
"monitor",
|
|
28
|
+
"objspace",
|
|
29
|
+
"pathname",
|
|
30
|
+
"pty",
|
|
31
|
+
"ripper",
|
|
32
|
+
"socket",
|
|
33
|
+
]
|
|
34
|
+
|
|
24
35
|
class GemfileLockMismatchError < StandardError
|
|
25
36
|
def initialize(expected:, actual:)
|
|
26
37
|
@expected = expected
|
|
@@ -168,7 +179,9 @@ module RBS
|
|
|
168
179
|
end
|
|
169
180
|
end
|
|
170
181
|
else
|
|
171
|
-
|
|
182
|
+
unless NONGEM_STDLIBS.include?(name)
|
|
183
|
+
RBS.logger.warn "Cannot find `#{name}` gem. Using incorrect Bundler context? (#{definition.lockfile})"
|
|
184
|
+
end
|
|
172
185
|
end
|
|
173
186
|
end
|
|
174
187
|
|
data/lib/rbs/environment.rb
CHANGED
|
@@ -854,6 +854,12 @@ module RBS
|
|
|
854
854
|
member.buffer,
|
|
855
855
|
resolved_annotation
|
|
856
856
|
)
|
|
857
|
+
when AST::Ruby::Members::ModuleSelfMember
|
|
858
|
+
resolved_annotation = member.annotation.map_type_name {|name| absolute_type_name(resolver, nil, name, context: context) }
|
|
859
|
+
AST::Ruby::Members::ModuleSelfMember.new(
|
|
860
|
+
member.buffer,
|
|
861
|
+
resolved_annotation
|
|
862
|
+
)
|
|
857
863
|
else
|
|
858
864
|
raise "Unknown member type: #{member.class}"
|
|
859
865
|
end
|
data/lib/rbs/inline_parser.rb
CHANGED
|
@@ -119,7 +119,53 @@ module RBS
|
|
|
119
119
|
|
|
120
120
|
class_decl = AST::Ruby::Declarations::ClassDecl.new(buffer, class_name, node, super_class)
|
|
121
121
|
insert_declaration(class_decl)
|
|
122
|
-
|
|
122
|
+
visit_class_or_module_body(class_decl, node)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def visit_module_node(node)
|
|
126
|
+
return if skip_node?(node)
|
|
127
|
+
|
|
128
|
+
unless module_name = constant_as_type_name(node.constant_path)
|
|
129
|
+
diagnostics << Diagnostic::NonConstantModuleName.new(
|
|
130
|
+
rbs_location(node.constant_path.location),
|
|
131
|
+
"Module name must be a constant"
|
|
132
|
+
)
|
|
133
|
+
return
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
module_decl = AST::Ruby::Declarations::ModuleDecl.new(buffer, module_name, node)
|
|
137
|
+
|
|
138
|
+
if leading_ref = comments.leading_block(node)
|
|
139
|
+
unused_annotations = [] #: Array[AST::Ruby::CommentBlock::AnnotationSyntaxError | AST::Ruby::Annotations::leading_annotation]
|
|
140
|
+
|
|
141
|
+
leading_ref.block.each_paragraph([]) do |paragraph|
|
|
142
|
+
case paragraph
|
|
143
|
+
when AST::Ruby::Annotations::ModuleSelfAnnotation
|
|
144
|
+
module_decl.members << AST::Ruby::Members::ModuleSelfMember.new(buffer, paragraph)
|
|
145
|
+
when Location
|
|
146
|
+
# Skip
|
|
147
|
+
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
148
|
+
unused_annotations << paragraph
|
|
149
|
+
when AST::Ruby::Annotations::SkipAnnotation
|
|
150
|
+
# Already handled by skip_node?
|
|
151
|
+
else
|
|
152
|
+
unused_annotations << paragraph
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
unless unused_annotations.empty?
|
|
157
|
+
report_unused_annotation(*unused_annotations)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
leading_ref.associate!
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
insert_declaration(module_decl)
|
|
164
|
+
visit_class_or_module_body(module_decl, node)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def visit_class_or_module_body(decl, node)
|
|
168
|
+
push_module_nesting(decl) do
|
|
123
169
|
visit_child_nodes(node)
|
|
124
170
|
|
|
125
171
|
node.child_nodes.each do |child_node|
|
|
@@ -137,7 +183,7 @@ module RBS
|
|
|
137
183
|
block.each_paragraph([]) do |paragraph|
|
|
138
184
|
case paragraph
|
|
139
185
|
when AST::Ruby::Annotations::InstanceVariableAnnotation
|
|
140
|
-
|
|
186
|
+
decl.members << AST::Ruby::Members::InstanceVariableMember.new(buffer, paragraph)
|
|
141
187
|
when Location
|
|
142
188
|
# Skip
|
|
143
189
|
when AST::Ruby::CommentBlock::AnnotationSyntaxError
|
|
@@ -150,29 +196,7 @@ module RBS
|
|
|
150
196
|
report_unused_annotation(*unused_annotations)
|
|
151
197
|
end
|
|
152
198
|
|
|
153
|
-
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def visit_module_node(node)
|
|
157
|
-
return if skip_node?(node)
|
|
158
|
-
|
|
159
|
-
unless module_name = constant_as_type_name(node.constant_path)
|
|
160
|
-
diagnostics << Diagnostic::NonConstantModuleName.new(
|
|
161
|
-
rbs_location(node.constant_path.location),
|
|
162
|
-
"Module name must be a constant"
|
|
163
|
-
)
|
|
164
|
-
return
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
module_decl = AST::Ruby::Declarations::ModuleDecl.new(buffer, module_name, node)
|
|
168
|
-
insert_declaration(module_decl)
|
|
169
|
-
push_module_nesting(module_decl) do
|
|
170
|
-
visit_child_nodes(node)
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
comments.each_enclosed_block(node) do |block|
|
|
174
|
-
report_unused_block(block)
|
|
175
|
-
end
|
|
199
|
+
decl.members.sort_by! { _1.location.start_line }
|
|
176
200
|
end
|
|
177
201
|
|
|
178
202
|
def visit_def_node(node)
|
data/lib/rbs/rewriter.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RBS
|
|
4
|
+
class Rewriter
|
|
5
|
+
attr_reader :buffer
|
|
6
|
+
|
|
7
|
+
def initialize(buffer)
|
|
8
|
+
raise "Rewriter only supports toplevel buffers" if buffer.parent
|
|
9
|
+
|
|
10
|
+
@buffer = buffer
|
|
11
|
+
@rewrites = []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def rewrite(location, string)
|
|
15
|
+
@rewrites.each do |existing_location, _|
|
|
16
|
+
if location.start_pos < existing_location.end_pos && existing_location.start_pos < location.end_pos
|
|
17
|
+
raise "Overlapping rewrites: #{existing_location} and #{location}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
@rewrites << [location, string]
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_comment(*locations, content:)
|
|
26
|
+
earliest = locations.min_by(&:start_pos) or raise "At least one location is required"
|
|
27
|
+
insert_pos = earliest.start_pos
|
|
28
|
+
indent = " " * earliest.start_column
|
|
29
|
+
|
|
30
|
+
formatted = format_comment(content, indent)
|
|
31
|
+
|
|
32
|
+
loc = Location.new(buffer, insert_pos, insert_pos)
|
|
33
|
+
rewrite(loc, "#{formatted}\n#{indent}")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def replace_comment(comment, content:)
|
|
37
|
+
location = comment.location or raise "Comment must have a location"
|
|
38
|
+
indent = " " * location.start_column
|
|
39
|
+
|
|
40
|
+
rewrite(location, format_comment(content, indent))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def delete_comment(comment)
|
|
44
|
+
location = comment.location or raise "Comment must have a location"
|
|
45
|
+
line_start = location.start_pos - location.start_column
|
|
46
|
+
line_end = location.end_pos + 1
|
|
47
|
+
loc = Location.new(buffer, line_start, line_end)
|
|
48
|
+
rewrite(loc, "")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def string
|
|
52
|
+
result = buffer.content.dup
|
|
53
|
+
|
|
54
|
+
@rewrites.sort_by { |location, _| location.start_pos }.reverse_each do |location, replacement|
|
|
55
|
+
result[location.start_pos...location.end_pos] = replacement
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
result
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def format_comment(content, indent)
|
|
64
|
+
content.lines.map do |line|
|
|
65
|
+
line = line.chomp
|
|
66
|
+
line.empty? ? "#" : "# #{line}"
|
|
67
|
+
end.join("\n#{indent}")
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
data/lib/rbs/test/type_check.rb
CHANGED
|
@@ -356,7 +356,12 @@ module RBS
|
|
|
356
356
|
when Types::Variable
|
|
357
357
|
true
|
|
358
358
|
when Types::Literal
|
|
359
|
-
|
|
359
|
+
begin
|
|
360
|
+
type.literal == val
|
|
361
|
+
rescue NoMethodError
|
|
362
|
+
raise if defined?(val.==)
|
|
363
|
+
false
|
|
364
|
+
end
|
|
360
365
|
when Types::Union
|
|
361
366
|
type.types.any? {|type| value(val, type) }
|
|
362
367
|
when Types::Intersection
|
data/lib/rbs/version.rb
CHANGED
data/lib/rbs.rb
CHANGED
|
@@ -8,9 +8,10 @@ module RBS
|
|
|
8
8
|
|
|
9
9
|
def initialize: (source: RDocSource) -> void
|
|
10
10
|
|
|
11
|
-
def annotate_file: (Pathname
|
|
11
|
+
def annotate_file: (Pathname) -> void
|
|
12
|
+
| %a{deprecated: it preserves the format by default} (Pathname, preserve: bool) -> void
|
|
12
13
|
|
|
13
|
-
def annotate_decls: (Array[AST::Declarations::t], ?outer: Array[Namespace]) -> void
|
|
14
|
+
def annotate_decls: (Array[AST::Declarations::t], Rewriter, ?outer: Array[Namespace]) -> void
|
|
14
15
|
|
|
15
16
|
interface _PathTester
|
|
16
17
|
def test_path: (String) -> bool
|
|
@@ -50,15 +51,15 @@ module RBS
|
|
|
50
51
|
|
|
51
52
|
def resolve_doc_source: (Annotations::Copy?, tester: _PathTester) { () -> String? } -> String?
|
|
52
53
|
|
|
53
|
-
def annotate_class: (AST::Declarations::Class | AST::Declarations::Module, outer: Array[Namespace]) -> void
|
|
54
|
+
def annotate_class: (AST::Declarations::Class | AST::Declarations::Module, Rewriter, outer: Array[Namespace]) -> void
|
|
54
55
|
|
|
55
|
-
def annotate_constant: (AST::Declarations::Constant, outer: Array[Namespace]) -> void
|
|
56
|
+
def annotate_constant: (AST::Declarations::Constant, Rewriter, outer: Array[Namespace]) -> void
|
|
56
57
|
|
|
57
|
-
def annotate_method: (TypeName, AST::Members::MethodDefinition) -> void
|
|
58
|
+
def annotate_method: (TypeName, AST::Members::MethodDefinition, Rewriter) -> void
|
|
58
59
|
|
|
59
|
-
def annotate_alias: (TypeName, AST::Members::Alias) -> void
|
|
60
|
+
def annotate_alias: (TypeName, AST::Members::Alias, Rewriter) -> void
|
|
60
61
|
|
|
61
|
-
def annotate_attribute: (TypeName, AST::Members::AttrReader | AST::Members::AttrWriter | AST::Members::AttrAccessor) -> void
|
|
62
|
+
def annotate_attribute: (TypeName, AST::Members::AttrReader | AST::Members::AttrWriter | AST::Members::AttrAccessor, Rewriter) -> void
|
|
62
63
|
|
|
63
64
|
def annotations: (_Annotated) -> Annotations
|
|
64
65
|
|
|
@@ -70,10 +71,12 @@ module RBS
|
|
|
70
71
|
# - If empty string is given as `comment`, it deletes the original comment.
|
|
71
72
|
# - If `nil` is given as `comment`, it keeps the original comment.
|
|
72
73
|
#
|
|
73
|
-
def replace_comment: (
|
|
74
|
+
def replace_comment: (_Commented, String?, Rewriter) -> void
|
|
74
75
|
|
|
75
76
|
interface _Commented
|
|
76
|
-
def comment: () -> AST::Comment?
|
|
77
|
+
%a{pure} def comment: () -> AST::Comment?
|
|
78
|
+
%a{pure} def location: () -> Location[untyped, untyped]?
|
|
79
|
+
def annotations: () -> Array[AST::Annotation]
|
|
77
80
|
end
|
|
78
81
|
|
|
79
82
|
def resolve_name: (TypeName, outer: Array[Namespace]) -> TypeName
|
|
@@ -7,6 +7,7 @@ module RBS
|
|
|
7
7
|
| SkipAnnotation
|
|
8
8
|
| ReturnTypeAnnotation
|
|
9
9
|
| InstanceVariableAnnotation
|
|
10
|
+
| ModuleSelfAnnotation
|
|
10
11
|
| ParamTypeAnnotation
|
|
11
12
|
| SplatParamTypeAnnotation
|
|
12
13
|
| DoubleSplatParamTypeAnnotation
|
|
@@ -237,6 +238,54 @@ module RBS
|
|
|
237
238
|
def type_fingerprint: () -> untyped
|
|
238
239
|
end
|
|
239
240
|
|
|
241
|
+
# `@rbs module-self: NAME[ARGS] -- comment` annotation in leading comments
|
|
242
|
+
#
|
|
243
|
+
# ```
|
|
244
|
+
# @rbs module-self: _Each[String, Integer] -- comment
|
|
245
|
+
# ^^^^ -- prefix_location
|
|
246
|
+
# ^^^^^^^^^^^ -- keyword_location
|
|
247
|
+
# ^ -- colon_location
|
|
248
|
+
# ^ -- open_bracket_location
|
|
249
|
+
# ^ -- args_comma_locations[0]
|
|
250
|
+
# ^ -- close_bracket_location
|
|
251
|
+
# ^^^^^^^^^^ -- comment_location
|
|
252
|
+
# ```
|
|
253
|
+
#
|
|
254
|
+
class ModuleSelfAnnotation < Base
|
|
255
|
+
attr_reader keyword_location: Location
|
|
256
|
+
|
|
257
|
+
attr_reader colon_location: Location
|
|
258
|
+
|
|
259
|
+
attr_reader name: TypeName
|
|
260
|
+
|
|
261
|
+
attr_reader args: Array[Types::t]
|
|
262
|
+
|
|
263
|
+
attr_reader open_bracket_location: Location?
|
|
264
|
+
|
|
265
|
+
attr_reader close_bracket_location: Location?
|
|
266
|
+
|
|
267
|
+
attr_reader args_comma_locations: Array[Location]
|
|
268
|
+
|
|
269
|
+
attr_reader comment_location: Location?
|
|
270
|
+
|
|
271
|
+
def initialize: (
|
|
272
|
+
location: Location,
|
|
273
|
+
prefix_location: Location,
|
|
274
|
+
keyword_location: Location,
|
|
275
|
+
colon_location: Location,
|
|
276
|
+
name: TypeName,
|
|
277
|
+
args: Array[Types::t],
|
|
278
|
+
open_bracket_location: Location?,
|
|
279
|
+
close_bracket_location: Location?,
|
|
280
|
+
args_comma_locations: Array[Location],
|
|
281
|
+
comment_location: Location?,
|
|
282
|
+
) -> void
|
|
283
|
+
|
|
284
|
+
def map_type_name: () { (TypeName) -> TypeName } -> self
|
|
285
|
+
|
|
286
|
+
def type_fingerprint: () -> untyped
|
|
287
|
+
end
|
|
288
|
+
|
|
240
289
|
class ParamTypeAnnotation < Base
|
|
241
290
|
attr_reader name_location: Location
|
|
242
291
|
|