rbs 4.0.3 → 4.1.0.pre.2
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/c-check.yml +3 -0
- data/.github/workflows/dependabot.yml +1 -1
- data/.github/workflows/jruby.yml +67 -0
- data/.github/workflows/milestone.yml +4 -1
- data/.github/workflows/ruby.yml +40 -0
- data/.github/workflows/rust.yml +3 -2
- data/.github/workflows/truffleruby.yml +54 -0
- data/.github/workflows/typecheck.yml +3 -0
- data/.github/workflows/wasm.yml +53 -0
- data/.github/workflows/windows.yml +3 -0
- data/.gitignore +7 -0
- data/CHANGELOG.md +0 -8
- data/README.md +3 -3
- data/Rakefile +118 -3
- data/Steepfile +7 -0
- data/config.yml +24 -0
- data/core/array.rbs +144 -144
- data/core/builtin.rbs +7 -6
- data/core/class.rbs +5 -3
- data/core/enumerable.rbs +109 -109
- data/core/enumerator/product.rbs +5 -5
- data/core/enumerator.rbs +28 -28
- data/core/file.rbs +24 -1018
- data/core/file_constants.rbs +463 -0
- data/core/file_stat.rbs +534 -0
- data/core/hash.rbs +117 -101
- data/core/integer.rbs +21 -58
- data/core/io.rbs +25 -7
- data/core/kernel.rbs +26 -11
- data/core/module.rbs +88 -74
- data/core/numeric.rbs +3 -0
- data/core/object_space/weak_key_map.rbs +7 -7
- data/core/range.rbs +23 -23
- data/core/rbs/ops.rbs +154 -0
- data/core/rbs/unnamed/argf.rbs +3 -3
- data/core/ruby_vm.rbs +40 -0
- data/core/set.rbs +3 -3
- data/core/struct.rbs +16 -16
- data/core/thread.rbs +6 -6
- data/docs/CONTRIBUTING.md +2 -1
- data/docs/inline.md +65 -7
- data/docs/rbs_by_example.md +20 -20
- data/docs/syntax.md +2 -2
- data/docs/wasm_serialization.md +80 -0
- data/ext/rbs_extension/ast_translation.c +1298 -956
- data/ext/rbs_extension/ast_translation.h +4 -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/ext/rbs_extension/main.c +139 -4
- data/include/rbs/ast.h +323 -298
- data/include/rbs/defines.h +13 -0
- data/include/rbs/lexer.h +1 -0
- data/include/rbs/serialize.h +39 -0
- data/lib/rbs/annotate/rdoc_annotator.rb +27 -31
- data/lib/rbs/ast/ruby/annotations.rb +42 -0
- data/lib/rbs/ast/ruby/comment_block.rb +6 -4
- data/lib/rbs/ast/ruby/declarations.rb +11 -1
- data/lib/rbs/ast/ruby/helpers/location_helper.rb +1 -1
- data/lib/rbs/ast/ruby/members.rb +40 -1
- data/lib/rbs/buffer.rb +48 -11
- data/lib/rbs/cli.rb +3 -5
- data/lib/rbs/collection/config/lockfile_generator.rb +14 -1
- data/lib/rbs/collection/sources/git.rb +6 -0
- data/lib/rbs/definition_builder/method_builder.rb +12 -6
- data/lib/rbs/environment.rb +10 -3
- data/lib/rbs/inline_parser.rb +54 -28
- data/lib/rbs/namespace.rb +47 -11
- data/lib/rbs/prototype/runtime.rb +2 -0
- data/lib/rbs/resolver/type_name_resolver.rb +12 -14
- data/lib/rbs/rewriter.rb +70 -0
- data/lib/rbs/test/type_check.rb +6 -1
- data/lib/rbs/type_name.rb +33 -13
- data/lib/rbs/unit_test/type_assertions.rb +9 -0
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/wasm/deserializer.rb +213 -0
- data/lib/rbs/wasm/location.rb +61 -0
- data/lib/rbs/wasm/parser.rb +137 -0
- data/lib/rbs/wasm/runtime.rb +217 -0
- data/lib/rbs/wasm/serialization_schema.rb +110 -0
- data/lib/rbs.rb +14 -2
- data/rbs.gemspec +19 -2
- data/sig/annotate/rdoc_annotater.rbs +12 -9
- data/sig/ast/ruby/annotations.rbs +49 -0
- data/sig/ast/ruby/members.rbs +21 -1
- data/sig/buffer.rbs +19 -1
- data/sig/collection/config/lockfile_generator.rbs +2 -0
- data/sig/inline_parser.rbs +2 -0
- data/sig/manifest.yaml +0 -1
- data/sig/namespace.rbs +20 -0
- data/sig/parser.rbs +10 -0
- data/sig/resolver/type_name_resolver.rbs +2 -4
- data/sig/rewriter.rbs +45 -0
- data/sig/typename.rbs +15 -0
- data/sig/unit_test/type_assertions.rbs +4 -0
- data/sig/wasm/deserializer.rbs +66 -0
- data/sig/wasm/serialization_schema.rbs +13 -0
- data/src/ast.c +186 -162
- data/src/lexer.c +137 -114
- data/src/lexer.re +1 -0
- data/src/lexstate.c +6 -1
- data/src/parser.c +55 -5
- data/src/serialize.c +958 -0
- data/src/util/rbs_allocator.c +1 -4
- data/stdlib/abbrev/0/array.rbs +1 -1
- data/stdlib/csv/0/csv.rbs +5 -5
- data/stdlib/digest/0/digest.rbs +1 -1
- data/stdlib/etc/0/etc.rbs +18 -4
- data/stdlib/fileutils/0/fileutils.rbs +21 -21
- data/stdlib/json/0/json.rbs +6 -6
- data/stdlib/openssl/0/openssl.rbs +7 -7
- data/stdlib/resolv/0/resolv.rbs +1 -1
- data/stdlib/shellwords/0/shellwords.rbs +1 -1
- data/stdlib/stringio/0/stringio.rbs +32 -10
- data/stdlib/strscan/0/string_scanner.rbs +74 -55
- data/stdlib/tsort/0/cyclic.rbs +1 -1
- data/stdlib/tsort/0/interfaces.rbs +8 -8
- data/stdlib/tsort/0/tsort.rbs +9 -9
- data/stdlib/zlib/0/gzip_reader.rbs +2 -2
- data/wasm/README.md +59 -0
- data/wasm/rbs_wasm.c +411 -0
- metadata +23 -5
- data/.vscode/extensions.json +0 -5
- data/.vscode/settings.json +0 -19
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,42 +196,22 @@ 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)
|
|
179
203
|
return if skip_node?(node)
|
|
180
204
|
|
|
181
|
-
if node.receiver
|
|
205
|
+
if node.receiver && !node.receiver.is_a?(Prism::SelfNode)
|
|
182
206
|
diagnostics << Diagnostic::NotImplementedYet.new(
|
|
183
207
|
rbs_location(node.receiver.location),
|
|
184
|
-
"
|
|
208
|
+
"Method definition with non-self receiver is not supported"
|
|
185
209
|
)
|
|
186
210
|
return
|
|
187
211
|
end
|
|
188
212
|
|
|
213
|
+
kind = node.receiver ? :singleton : :instance #: :singleton | :instance
|
|
214
|
+
|
|
189
215
|
case current = current_module
|
|
190
216
|
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
|
|
191
217
|
leading_block = comments.leading_block!(node)
|
|
@@ -199,7 +225,7 @@ module RBS
|
|
|
199
225
|
method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [], node)
|
|
200
226
|
report_unused_annotation(trailing_unused, *leading_unuseds)
|
|
201
227
|
|
|
202
|
-
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block)
|
|
228
|
+
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block, kind: kind)
|
|
203
229
|
current.members << defn
|
|
204
230
|
|
|
205
231
|
# Skip other comments in `def` node
|
data/lib/rbs/namespace.rb
CHANGED
|
@@ -9,30 +9,65 @@ module RBS
|
|
|
9
9
|
@absolute = absolute ? true : false
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
# Process-wide flyweight cache. Two tries (one per `absolute` flag)
|
|
13
|
+
# keyed on path Symbols, with the cached Namespace stored under the
|
|
14
|
+
# `INTERN_LEAF` sentinel at each path's terminal node.
|
|
15
|
+
@intern_mutex = Mutex.new
|
|
16
|
+
@intern_trie_absolute = {}
|
|
17
|
+
@intern_trie_relative = {}
|
|
18
|
+
INTERN_LEAF = Module.new
|
|
19
|
+
|
|
20
|
+
# Returns a canonical `Namespace` instance for the given `path` /
|
|
21
|
+
# `absolute` pair. Repeated calls with structurally equal arguments
|
|
22
|
+
# return the same object, so callers can rely on `equal?` for fast
|
|
23
|
+
# equality. The path Array is duplicated and frozen on insert.
|
|
24
|
+
def self.[](path, absolute)
|
|
25
|
+
absolute = absolute ? true : false
|
|
26
|
+
|
|
27
|
+
# Lock-free fast path.
|
|
28
|
+
node = absolute ? @intern_trie_absolute : @intern_trie_relative
|
|
29
|
+
path.each do |sym|
|
|
30
|
+
node = node[sym]
|
|
31
|
+
break unless node
|
|
32
|
+
end
|
|
33
|
+
if node && (cached = node[INTERN_LEAF])
|
|
34
|
+
return cached
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
@intern_mutex.synchronize do
|
|
38
|
+
node = absolute ? @intern_trie_absolute : @intern_trie_relative
|
|
39
|
+
path.each { |sym| node = (node[sym] ||= {}) }
|
|
40
|
+
node[INTERN_LEAF] ||= begin
|
|
41
|
+
frozen_path = path.frozen? ? path : path.dup.freeze
|
|
42
|
+
new(path: frozen_path, absolute: absolute)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
12
47
|
def self.empty
|
|
13
|
-
@empty ||=
|
|
48
|
+
@empty ||= self[[], false]
|
|
14
49
|
end
|
|
15
50
|
|
|
16
51
|
def self.root
|
|
17
|
-
@root ||=
|
|
52
|
+
@root ||= self[[], true]
|
|
18
53
|
end
|
|
19
54
|
|
|
20
55
|
def +(other)
|
|
21
56
|
if other.absolute?
|
|
22
57
|
other
|
|
23
58
|
else
|
|
24
|
-
|
|
59
|
+
Namespace[path + other.path, absolute?]
|
|
25
60
|
end
|
|
26
61
|
end
|
|
27
62
|
|
|
28
63
|
def append(component)
|
|
29
|
-
|
|
64
|
+
Namespace[path + [component], absolute?]
|
|
30
65
|
end
|
|
31
66
|
|
|
32
67
|
def parent
|
|
33
68
|
@parent ||= begin
|
|
34
69
|
raise "Parent with empty namespace" if empty?
|
|
35
|
-
|
|
70
|
+
Namespace[path.take(path.size - 1), absolute?]
|
|
36
71
|
end
|
|
37
72
|
end
|
|
38
73
|
|
|
@@ -45,11 +80,11 @@ module RBS
|
|
|
45
80
|
end
|
|
46
81
|
|
|
47
82
|
def absolute!
|
|
48
|
-
|
|
83
|
+
Namespace[path, true]
|
|
49
84
|
end
|
|
50
85
|
|
|
51
86
|
def relative!
|
|
52
|
-
|
|
87
|
+
Namespace[path, false]
|
|
53
88
|
end
|
|
54
89
|
|
|
55
90
|
def empty?
|
|
@@ -57,13 +92,14 @@ module RBS
|
|
|
57
92
|
end
|
|
58
93
|
|
|
59
94
|
def ==(other)
|
|
95
|
+
return true if equal?(other)
|
|
60
96
|
other.is_a?(Namespace) && other.path == path && other.absolute? == absolute?
|
|
61
97
|
end
|
|
62
98
|
|
|
63
99
|
alias eql? ==
|
|
64
100
|
|
|
65
101
|
def hash
|
|
66
|
-
path.hash ^ absolute?.hash
|
|
102
|
+
@hash ||= path.hash ^ absolute?.hash
|
|
67
103
|
end
|
|
68
104
|
|
|
69
105
|
def split
|
|
@@ -87,14 +123,14 @@ module RBS
|
|
|
87
123
|
raise unless name
|
|
88
124
|
raise unless parent
|
|
89
125
|
|
|
90
|
-
TypeName
|
|
126
|
+
TypeName[parent, name]
|
|
91
127
|
end
|
|
92
128
|
|
|
93
129
|
def self.parse(string)
|
|
94
130
|
if string.start_with?("::")
|
|
95
|
-
|
|
131
|
+
self[string.split("::").drop(1).map(&:to_sym), true]
|
|
96
132
|
else
|
|
97
|
-
|
|
133
|
+
self[string.split("::").map(&:to_sym), false]
|
|
98
134
|
end
|
|
99
135
|
end
|
|
100
136
|
|
|
@@ -77,6 +77,8 @@ module RBS
|
|
|
77
77
|
attr_accessor :outline
|
|
78
78
|
|
|
79
79
|
def initialize(patterns:, env:, merge:, todo: false, owners_included: [])
|
|
80
|
+
Kernel.warn("RBS::Prototype::Runtime is deprecated. See https://github.com/ruby/rbs/issues/2841")
|
|
81
|
+
|
|
80
82
|
@patterns = patterns
|
|
81
83
|
@decls = nil
|
|
82
84
|
@modules = {}
|
|
@@ -29,11 +29,9 @@ module RBS
|
|
|
29
29
|
new(all_names, aliases)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def try_cache(
|
|
33
|
-
cache
|
|
34
|
-
|
|
35
|
-
cache[query] = result
|
|
36
|
-
end
|
|
32
|
+
def try_cache(type_name, context)
|
|
33
|
+
inner = cache[context] ||= {}
|
|
34
|
+
inner.fetch(type_name) { inner[type_name] = yield }
|
|
37
35
|
end
|
|
38
36
|
|
|
39
37
|
def resolve(type_name, context:)
|
|
@@ -41,7 +39,7 @@ module RBS
|
|
|
41
39
|
return type_name
|
|
42
40
|
end
|
|
43
41
|
|
|
44
|
-
try_cache(
|
|
42
|
+
try_cache(type_name, context) do
|
|
45
43
|
if type_name.class?
|
|
46
44
|
resolve_namespace0(type_name, context, Set.new) || nil
|
|
47
45
|
else
|
|
@@ -51,7 +49,7 @@ module RBS
|
|
|
51
49
|
resolve_type_name(type_name.name, context)
|
|
52
50
|
else
|
|
53
51
|
if namespace = resolve_namespace0(namespace.to_type_name, context, Set.new)
|
|
54
|
-
type_name = TypeName.
|
|
52
|
+
type_name = TypeName[namespace.to_namespace, type_name.name]
|
|
55
53
|
has_type_name?(type_name)
|
|
56
54
|
end
|
|
57
55
|
end
|
|
@@ -68,7 +66,7 @@ module RBS
|
|
|
68
66
|
raise "Type name must be a class name: #{type_name}"
|
|
69
67
|
end
|
|
70
68
|
|
|
71
|
-
try_cache(
|
|
69
|
+
try_cache(type_name, context) do
|
|
72
70
|
ns = resolve_namespace0(type_name, context, Set.new) or return ns
|
|
73
71
|
end
|
|
74
72
|
end
|
|
@@ -93,10 +91,10 @@ module RBS
|
|
|
93
91
|
resolve_type_name(type_name, outer)
|
|
94
92
|
else
|
|
95
93
|
has_type_name?(inner) or raise "Context must be normalized: #{inner.inspect}"
|
|
96
|
-
has_type_name?(TypeName.
|
|
94
|
+
has_type_name?(TypeName[inner.to_namespace, type_name]) || resolve_type_name(type_name, outer)
|
|
97
95
|
end
|
|
98
96
|
else
|
|
99
|
-
type_name = TypeName.
|
|
97
|
+
type_name = TypeName[Namespace.root, type_name]
|
|
100
98
|
has_type_name?(type_name)
|
|
101
99
|
end
|
|
102
100
|
end
|
|
@@ -109,11 +107,11 @@ module RBS
|
|
|
109
107
|
resolve_head_namespace(head, outer)
|
|
110
108
|
when TypeName
|
|
111
109
|
has_type_name?(inner) or raise "Context must be normalized: #{inner.inspect}"
|
|
112
|
-
type_name = TypeName.
|
|
110
|
+
type_name = TypeName[inner.to_namespace, head]
|
|
113
111
|
has_type_name?(type_name) || aliased_name?(type_name) || resolve_head_namespace(head, outer)
|
|
114
112
|
end
|
|
115
113
|
else
|
|
116
|
-
type_name = TypeName.
|
|
114
|
+
type_name = TypeName[Namespace.root, head]
|
|
117
115
|
has_type_name?(type_name) || aliased_name?(type_name)
|
|
118
116
|
end
|
|
119
117
|
end
|
|
@@ -140,7 +138,7 @@ module RBS
|
|
|
140
138
|
|
|
141
139
|
head =
|
|
142
140
|
if type_name.absolute?
|
|
143
|
-
root_name = TypeName.
|
|
141
|
+
root_name = TypeName[Namespace.root, head]
|
|
144
142
|
has_type_name?(root_name) || aliased_name?(root_name)
|
|
145
143
|
else
|
|
146
144
|
resolve_head_namespace(head, context)
|
|
@@ -152,7 +150,7 @@ module RBS
|
|
|
152
150
|
end
|
|
153
151
|
|
|
154
152
|
tail.inject(head) do |namespace, name|
|
|
155
|
-
type_name = TypeName.
|
|
153
|
+
type_name = TypeName[namespace.to_namespace, name]
|
|
156
154
|
case
|
|
157
155
|
when has_type_name?(type_name)
|
|
158
156
|
type_name
|
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/type_name.rb
CHANGED
|
@@ -22,14 +22,40 @@ module RBS
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# Process-wide flyweight cache. Two-level Hash keyed by canonical
|
|
26
|
+
# Namespace identity (outer uses `compare_by_identity`) and name
|
|
27
|
+
# Symbol.
|
|
28
|
+
@intern_mutex = Mutex.new
|
|
29
|
+
@intern_cache = {} #: Hash[Namespace, Hash[Symbol, TypeName]]
|
|
30
|
+
@intern_cache.compare_by_identity
|
|
31
|
+
|
|
32
|
+
# Returns a canonical `TypeName` instance for the given `namespace` /
|
|
33
|
+
# `name` pair. The namespace is canonicalized through `Namespace.[]`
|
|
34
|
+
# so identity-based lookup works regardless of the caller passing a
|
|
35
|
+
# fresh `Namespace.new` or an already-interned instance.
|
|
36
|
+
def self.[](namespace, name)
|
|
37
|
+
ns = Namespace[namespace.path, namespace.absolute?]
|
|
38
|
+
|
|
39
|
+
inner = @intern_cache[ns]
|
|
40
|
+
if inner && (cached = inner[name])
|
|
41
|
+
return cached
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
@intern_mutex.synchronize do
|
|
45
|
+
inner = (@intern_cache[ns] ||= {})
|
|
46
|
+
inner[name] ||= new(namespace: ns, name: name)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
25
50
|
def ==(other)
|
|
51
|
+
return true if equal?(other)
|
|
26
52
|
other.is_a?(self.class) && other.namespace == namespace && other.name == name
|
|
27
53
|
end
|
|
28
54
|
|
|
29
55
|
alias eql? ==
|
|
30
56
|
|
|
31
57
|
def hash
|
|
32
|
-
namespace.hash ^ name.hash
|
|
58
|
+
@hash ||= namespace.hash ^ name.hash
|
|
33
59
|
end
|
|
34
60
|
|
|
35
61
|
def to_s
|
|
@@ -53,7 +79,7 @@ module RBS
|
|
|
53
79
|
end
|
|
54
80
|
|
|
55
81
|
def absolute!
|
|
56
|
-
|
|
82
|
+
TypeName[namespace.absolute!, name]
|
|
57
83
|
end
|
|
58
84
|
|
|
59
85
|
def absolute?
|
|
@@ -61,7 +87,7 @@ module RBS
|
|
|
61
87
|
end
|
|
62
88
|
|
|
63
89
|
def relative!
|
|
64
|
-
|
|
90
|
+
TypeName[namespace.relative!, name]
|
|
65
91
|
end
|
|
66
92
|
|
|
67
93
|
def interface?
|
|
@@ -69,7 +95,7 @@ module RBS
|
|
|
69
95
|
end
|
|
70
96
|
|
|
71
97
|
def with_prefix(namespace)
|
|
72
|
-
|
|
98
|
+
TypeName[namespace + self.namespace, name]
|
|
73
99
|
end
|
|
74
100
|
|
|
75
101
|
def split
|
|
@@ -80,23 +106,17 @@ module RBS
|
|
|
80
106
|
if other.absolute?
|
|
81
107
|
other
|
|
82
108
|
else
|
|
83
|
-
TypeName.
|
|
84
|
-
namespace: self.to_namespace + other.namespace,
|
|
85
|
-
name: other.name
|
|
86
|
-
)
|
|
109
|
+
TypeName[self.to_namespace + other.namespace, other.name]
|
|
87
110
|
end
|
|
88
111
|
end
|
|
89
|
-
|
|
112
|
+
|
|
90
113
|
def self.parse(string)
|
|
91
114
|
absolute = string.start_with?("::")
|
|
92
115
|
|
|
93
116
|
*path, name = string.delete_prefix("::").split("::").map(&:to_sym)
|
|
94
117
|
raise unless name
|
|
95
118
|
|
|
96
|
-
TypeName
|
|
97
|
-
name: name,
|
|
98
|
-
namespace: RBS::Namespace.new(path: path, absolute: absolute)
|
|
99
|
-
)
|
|
119
|
+
TypeName[Namespace[path, absolute], name]
|
|
100
120
|
end
|
|
101
121
|
end
|
|
102
122
|
end
|
|
@@ -323,6 +323,15 @@ module RBS
|
|
|
323
323
|
assert typecheck.value(constant, definition_type), "`#{constant_name}` (#{constant.inspect}) must be compatible with RBS type definition `#{definition_type}`"
|
|
324
324
|
end
|
|
325
325
|
|
|
326
|
+
def assert_visibility(visibility, method)
|
|
327
|
+
_, definition = target
|
|
328
|
+
method_entry = definition.methods[method]
|
|
329
|
+
|
|
330
|
+
assert method_entry, "Method `#{method}` not found in RBS definition"
|
|
331
|
+
assert visibility == method_entry.accessibility,
|
|
332
|
+
"Expected `#{method}` to be #{visibility}, but was #{method_entry.accessibility}"
|
|
333
|
+
end
|
|
334
|
+
|
|
326
335
|
def assert_type(type, value)
|
|
327
336
|
typecheck = RBS::Test::TypeCheck.new(
|
|
328
337
|
self_class: value.class,
|
data/lib/rbs/version.rb
CHANGED