rbi 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3ec679e5a50e9325d794c32a93ca12eb08aff102e12b21e6476a172b8001cba
4
- data.tar.gz: 5abffaaba601923ebe58dd49e5c59aba2faf41a73ee4571b15e157c5f220297f
3
+ metadata.gz: f74d8bfd9f52c65d39357d68e286e247a48d53779397c11f310b50ca37b3b925
4
+ data.tar.gz: 0a924a9c84c508cbb70b307a1b8770f00b1c855d68c41c57e0dd74dfd1f75d86
5
5
  SHA512:
6
- metadata.gz: dfebab9782d4817841ec80c87d81ff9919df026de13614fe056bc4ca0cd9ab4546f861c230172023d8f3c185b60b1155e076c7ef22ef420421bd1203879f15b0
7
- data.tar.gz: bae1339fd94ad30d5d6997611b1ac14fc36d9119607a32f954ab2361112c5ec5c31181636409df223c190348477917cf2e27da3d2bae0551295836273e59fcbb
6
+ metadata.gz: 303c4606968022e24e65f0d9a54732431ee7c6cc315dffe592e0196e5c449a5842319d32897231f046ca8266ccaf3dc9743fd7229582988b5a590c381cf4473b
7
+ data.tar.gz: 955d836aea51639220440f984fa0a8c595c763521b84ddca73dfdd08b8b546bc5b61e3fc48a19ddd04e50a7824377cc25960816a9ac2d65454ab8821259acda8
data/Gemfile CHANGED
@@ -5,9 +5,12 @@ source "https://rubygems.org"
5
5
 
6
6
  gemspec
7
7
 
8
- group(:development) do
9
- gem('rubocop-shopify', require: false)
10
- gem('rubocop-sorbet', require: false)
11
- gem('byebug')
12
- gem('pry-byebug')
8
+ group(:development, :test) do
9
+ gem("byebug")
10
+ gem("minitest")
11
+ gem("rubocop", "~> 1.7", require: false)
12
+ gem("rubocop-shopify", require: false)
13
+ gem("rubocop-sorbet", require: false)
14
+ gem("sorbet", require: false)
15
+ gem("tapioca", require: false, github: "Shopify/tapioca", branch: "master")
13
16
  end
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
- # Rbi
1
+ # RBI generation framework
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rbi`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ `RBI` provides a Ruby API to compose Ruby interface files consumed by Sorbet.
6
4
 
7
5
  ## Installation
8
6
 
@@ -14,7 +12,7 @@ gem 'rbi'
14
12
 
15
13
  And then execute:
16
14
 
17
- $ bundle
15
+ $ bundle install
18
16
 
19
17
  Or install it yourself as:
20
18
 
@@ -22,17 +20,47 @@ Or install it yourself as:
22
20
 
23
21
  ## Usage
24
22
 
25
- TODO: Write usage instructions here
23
+ ```rb
24
+ require "rbi"
25
+
26
+ rbi = RBI::File.new(strictness: "true") do |file|
27
+ file << RBI::Module.new("Foo") do |mod|
28
+ mod << RBI::Method.new("foo")
29
+ end
30
+ end
31
+
32
+ puts rbi.string
33
+ ```
34
+
35
+ will produce:
36
+
37
+ ```rb
38
+ # typed: true
39
+
40
+ module Foo
41
+ def foo; end
42
+ end
43
+ ```
44
+
45
+ ## Features
46
+
47
+ * RBI generation API
48
+ * RBI parsing with Whitequark
49
+ * RBI formatting
50
+ * RBI validation
51
+ * RBI merging
26
52
 
27
53
  ## Development
28
54
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
55
+ 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.
56
+
57
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
30
58
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
59
+ This repo uses itself (`rbi`) to retrieve and generate gem RBIs. You can run `dev rbi` to update local gem RBIs with RBIs from the central repo.
32
60
 
33
61
  ## Contributing
34
62
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rbi. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rbi. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/rbi/blob/master/CODE_OF_CONDUCT.md).
36
64
 
37
65
  ## License
38
66
 
@@ -40,4 +68,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
40
68
 
41
69
  ## Code of Conduct
42
70
 
43
- Everyone interacting in the Rbi projects codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/rbi/blob/master/CODE_OF_CONDUCT.md).
71
+ Everyone interacting in the Rbi project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/rbi/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile CHANGED
@@ -1,7 +1,9 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
+
3
4
  require "bundler/gem_tasks"
4
5
  require "rake/testtask"
6
+ require "rubocop/rake_task"
5
7
 
6
8
  Rake::TestTask.new(:test) do |t|
7
9
  t.libs << "test"
data/lib/rbi.rb CHANGED
@@ -1,11 +1,22 @@
1
- # typed: true
1
+ # typed: strict
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "sorbet-runtime"
4
- require "thor"
5
-
6
- require "rbi/version"
7
- require "rbi/cli"
5
+ require "stringio"
8
6
 
9
7
  module RBI
10
8
  class Error < StandardError; end
11
9
  end
10
+
11
+ require "rbi/loc"
12
+ require "rbi/model"
13
+ require "rbi/visitor"
14
+ require "rbi/index"
15
+ require "rbi/rewriters/merge_trees"
16
+ require "rbi/rewriters/nest_singleton_methods"
17
+ require "rbi/rewriters/nest_non_public_methods"
18
+ require "rbi/rewriters/group_nodes"
19
+ require "rbi/rewriters/sort_nodes"
20
+ require "rbi/parser"
21
+ require "rbi/printer"
22
+ require "rbi/version"
data/lib/rbi/index.rb ADDED
@@ -0,0 +1,186 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ class Index < Visitor
6
+ extend T::Sig
7
+ include T::Enumerable
8
+
9
+ sig { params(node: Node).returns(Index) }
10
+ def self.index(*node)
11
+ index = Index.new
12
+ index.visit_all(node)
13
+ index
14
+ end
15
+
16
+ sig { void }
17
+ def initialize
18
+ super()
19
+ @index = T.let({}, T::Hash[String, T::Array[Node]])
20
+ end
21
+
22
+ sig { returns(T::Array[String]) }
23
+ def keys
24
+ @index.keys
25
+ end
26
+
27
+ sig { params(id: String).returns(T::Array[Node]) }
28
+ def [](id)
29
+ @index[id] ||= []
30
+ end
31
+
32
+ sig { params(node: T.all(Indexable, Node)).void }
33
+ def index(node)
34
+ node.index_ids.each { |id| self[id] << node }
35
+ end
36
+
37
+ sig { override.params(node: T.nilable(Node)).void }
38
+ def visit(node)
39
+ return unless node
40
+
41
+ case node
42
+ when Scope
43
+ index(node)
44
+ visit_all(node.nodes)
45
+ when Tree
46
+ visit_all(node.nodes)
47
+ when Indexable
48
+ index(node)
49
+ end
50
+ end
51
+ end
52
+
53
+ class Tree
54
+ extend T::Sig
55
+
56
+ sig { returns(Index) }
57
+ def index
58
+ Index.index(self)
59
+ end
60
+ end
61
+
62
+ # A Node that can be refered to by a unique ID inside an index
63
+ module Indexable
64
+ extend T::Sig
65
+ extend T::Helpers
66
+
67
+ interface!
68
+
69
+ # Unique IDs that refer to this node.
70
+ #
71
+ # Some nodes can have multiple ids, for example an attribute accessor matches the ID of the
72
+ # getter and the setter.
73
+ sig { abstract.returns(T::Array[String]) }
74
+ def index_ids; end
75
+ end
76
+
77
+ class Scope
78
+ extend T::Sig
79
+ include Indexable
80
+
81
+ sig { override.returns(T::Array[String]) }
82
+ def index_ids
83
+ [fully_qualified_name]
84
+ end
85
+ end
86
+
87
+ class Const
88
+ extend T::Sig
89
+ include Indexable
90
+
91
+ sig { override.returns(T::Array[String]) }
92
+ def index_ids
93
+ [fully_qualified_name]
94
+ end
95
+ end
96
+
97
+ class Attr
98
+ extend T::Sig
99
+ include Indexable
100
+
101
+ sig { override.returns(T::Array[String]) }
102
+ def index_ids
103
+ fully_qualified_names
104
+ end
105
+ end
106
+
107
+ class Method
108
+ extend T::Sig
109
+ include Indexable
110
+
111
+ sig { override.returns(T::Array[String]) }
112
+ def index_ids
113
+ [fully_qualified_name]
114
+ end
115
+ end
116
+
117
+ class Include
118
+ extend T::Sig
119
+ include Indexable
120
+
121
+ sig { override.returns(T::Array[String]) }
122
+ def index_ids
123
+ names.map { |name| "#{parent_scope&.fully_qualified_name}.include(#{name})" }
124
+ end
125
+ end
126
+
127
+ class Extend
128
+ extend T::Sig
129
+ include Indexable
130
+
131
+ sig { override.returns(T::Array[String]) }
132
+ def index_ids
133
+ names.map { |name| "#{parent_scope&.fully_qualified_name}.extend(#{name})" }
134
+ end
135
+ end
136
+
137
+ class MixesInClassMethods
138
+ extend T::Sig
139
+ include Indexable
140
+
141
+ sig { override.returns(T::Array[String]) }
142
+ def index_ids
143
+ names.map { |name| "#{parent_scope&.fully_qualified_name}.mixes_in_class_method(#{name})" }
144
+ end
145
+ end
146
+
147
+ class Helper
148
+ extend T::Sig
149
+ include Indexable
150
+
151
+ sig { override.returns(T::Array[String]) }
152
+ def index_ids
153
+ [to_s]
154
+ end
155
+ end
156
+
157
+ class TStructConst
158
+ extend T::Sig
159
+ include Indexable
160
+
161
+ sig { override.returns(T::Array[String]) }
162
+ def index_ids
163
+ fully_qualified_names
164
+ end
165
+ end
166
+
167
+ class TStructProp
168
+ extend T::Sig
169
+ include Indexable
170
+
171
+ sig { override.returns(T::Array[String]) }
172
+ def index_ids
173
+ fully_qualified_names
174
+ end
175
+ end
176
+
177
+ class TEnumBlock
178
+ extend T::Sig
179
+ include Indexable
180
+
181
+ sig { override.returns(T::Array[String]) }
182
+ def index_ids
183
+ [to_s]
184
+ end
185
+ end
186
+ end
data/lib/rbi/loc.rb ADDED
@@ -0,0 +1,36 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ class Loc
6
+ extend T::Sig
7
+
8
+ sig { returns(T.nilable(String)) }
9
+ attr_reader :file
10
+
11
+ sig { returns(T.nilable(Integer)) }
12
+ attr_reader :begin_line, :end_line, :begin_column, :end_column
13
+
14
+ sig do
15
+ params(
16
+ file: T.nilable(String),
17
+ begin_line: T.nilable(Integer),
18
+ end_line: T.nilable(Integer),
19
+ begin_column: T.nilable(Integer),
20
+ end_column: T.nilable(Integer)
21
+ ).void
22
+ end
23
+ def initialize(file: nil, begin_line: nil, end_line: nil, begin_column: nil, end_column: nil)
24
+ @file = file
25
+ @begin_line = begin_line
26
+ @end_line = end_line
27
+ @begin_column = begin_column
28
+ @end_column = end_column
29
+ end
30
+
31
+ sig { returns(String) }
32
+ def to_s
33
+ "#{file}:#{begin_line}:#{begin_column}-#{end_line}:#{end_column}"
34
+ end
35
+ end
36
+ end
data/lib/rbi/model.rb ADDED
@@ -0,0 +1,879 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ class Node
6
+ extend T::Sig
7
+ extend T::Helpers
8
+
9
+ abstract!
10
+
11
+ sig { returns(T.nilable(Tree)) }
12
+ attr_accessor :parent_tree
13
+
14
+ sig { returns(T.nilable(Loc)) }
15
+ attr_accessor :loc
16
+
17
+ sig { params(loc: T.nilable(Loc)).void }
18
+ def initialize(loc: nil)
19
+ @parent_tree = nil
20
+ @loc = loc
21
+ end
22
+
23
+ sig { void }
24
+ def detach
25
+ tree = parent_tree
26
+ return unless tree
27
+ tree.nodes.delete(self)
28
+ self.parent_tree = nil
29
+ end
30
+
31
+ sig { params(node: Node).void }
32
+ def replace(node)
33
+ tree = parent_tree
34
+ raise unless tree
35
+ index = tree.nodes.index(self)
36
+ raise unless index
37
+ tree.nodes[index] = node
38
+ node.parent_tree = tree
39
+ self.parent_tree = nil
40
+ end
41
+
42
+ sig { returns(T.nilable(Scope)) }
43
+ def parent_scope
44
+ parent = T.let(parent_tree, T.nilable(Tree))
45
+ parent = parent.parent_tree until parent.is_a?(Scope) || parent.nil?
46
+ parent
47
+ end
48
+ end
49
+
50
+ class Comment < Node
51
+ extend T::Helpers
52
+
53
+ sig { returns(String) }
54
+ attr_accessor :text
55
+
56
+ sig { params(text: String, loc: T.nilable(Loc)).void }
57
+ def initialize(text, loc: nil)
58
+ super(loc: loc)
59
+ @text = text
60
+ end
61
+
62
+ sig { params(other: Object).returns(T::Boolean) }
63
+ def ==(other)
64
+ return false unless other.is_a?(Comment)
65
+ text == other.text
66
+ end
67
+ end
68
+
69
+ class NodeWithComments < Node
70
+ extend T::Sig
71
+ extend T::Helpers
72
+
73
+ abstract!
74
+
75
+ sig { returns(T::Array[Comment]) }
76
+ attr_accessor :comments
77
+
78
+ sig { params(loc: T.nilable(Loc), comments: T::Array[Comment]).void }
79
+ def initialize(loc: nil, comments: [])
80
+ super(loc: loc)
81
+ @comments = comments
82
+ end
83
+ end
84
+
85
+ class Tree < NodeWithComments
86
+ extend T::Sig
87
+
88
+ sig { returns(T::Array[Node]) }
89
+ attr_reader :nodes
90
+
91
+ sig do
92
+ params(
93
+ loc: T.nilable(Loc),
94
+ comments: T::Array[Comment],
95
+ block: T.nilable(T.proc.params(tree: Tree).void)
96
+ ).void
97
+ end
98
+ def initialize(loc: nil, comments: [], &block)
99
+ super(loc: loc, comments: comments)
100
+ @nodes = T.let([], T::Array[Node])
101
+ block&.call(self)
102
+ end
103
+
104
+ sig { params(node: Node).void }
105
+ def <<(node)
106
+ node.parent_tree = self
107
+ @nodes << node
108
+ end
109
+
110
+ sig { returns(T::Boolean) }
111
+ def empty?
112
+ nodes.empty?
113
+ end
114
+ end
115
+
116
+ class File
117
+ extend T::Sig
118
+
119
+ sig { returns(Tree) }
120
+ attr_reader :root
121
+
122
+ sig { returns(T.nilable(String)) }
123
+ attr_reader :strictness
124
+
125
+ sig { returns(T::Array[Comment]) }
126
+ attr_accessor :comments
127
+
128
+ sig do
129
+ params(
130
+ strictness: T.nilable(String),
131
+ comments: T::Array[Comment],
132
+ block: T.nilable(T.proc.params(mod: File).void)
133
+ ).void
134
+ end
135
+ def initialize(strictness: nil, comments: [], &block)
136
+ @root = T.let(Tree.new, Tree)
137
+ @strictness = strictness
138
+ @comments = comments
139
+ block&.call(self)
140
+ end
141
+
142
+ sig { params(node: Node).void }
143
+ def <<(node)
144
+ @root << node
145
+ end
146
+ end
147
+
148
+ # Scopes
149
+
150
+ class Scope < Tree
151
+ extend T::Helpers
152
+
153
+ abstract!
154
+
155
+ sig { abstract.returns(String) }
156
+ def fully_qualified_name; end
157
+
158
+ sig { override.returns(String) }
159
+ def to_s
160
+ fully_qualified_name
161
+ end
162
+ end
163
+
164
+ class Module < Scope
165
+ extend T::Sig
166
+
167
+ sig { returns(String) }
168
+ attr_accessor :name
169
+
170
+ sig do
171
+ params(
172
+ name: String,
173
+ loc: T.nilable(Loc),
174
+ comments: T::Array[Comment],
175
+ block: T.nilable(T.proc.params(mod: Module).void)
176
+ ).void
177
+ end
178
+ def initialize(name, loc: nil, comments: [], &block)
179
+ super(loc: loc, comments: comments) {}
180
+ @name = name
181
+ block&.call(self)
182
+ end
183
+
184
+ sig { override.returns(String) }
185
+ def fully_qualified_name
186
+ return name if name.start_with?("::")
187
+ "#{parent_scope&.fully_qualified_name}::#{name}"
188
+ end
189
+ end
190
+
191
+ class Class < Scope
192
+ extend T::Sig
193
+
194
+ sig { returns(String) }
195
+ attr_accessor :name
196
+
197
+ sig { returns(T.nilable(String)) }
198
+ attr_accessor :superclass_name
199
+
200
+ sig do
201
+ params(
202
+ name: String,
203
+ superclass_name: T.nilable(String),
204
+ loc: T.nilable(Loc),
205
+ comments: T::Array[Comment],
206
+ block: T.nilable(T.proc.params(klass: Class).void)
207
+ ).void
208
+ end
209
+ def initialize(name, superclass_name: nil, loc: nil, comments: [], &block)
210
+ super(loc: loc, comments: comments) {}
211
+ @name = name
212
+ @superclass_name = superclass_name
213
+ block&.call(self)
214
+ end
215
+
216
+ sig { override.returns(String) }
217
+ def fully_qualified_name
218
+ return name if name.start_with?("::")
219
+ "#{parent_scope&.fully_qualified_name}::#{name}"
220
+ end
221
+ end
222
+
223
+ class SingletonClass < Scope
224
+ extend T::Sig
225
+
226
+ sig do
227
+ params(
228
+ loc: T.nilable(Loc),
229
+ comments: T::Array[Comment],
230
+ block: T.nilable(T.proc.params(klass: SingletonClass).void)
231
+ ).void
232
+ end
233
+ def initialize(loc: nil, comments: [], &block)
234
+ super(loc: loc, comments: comments) {}
235
+ block&.call(self)
236
+ end
237
+
238
+ sig { override.returns(String) }
239
+ def fully_qualified_name
240
+ "#{parent_scope&.fully_qualified_name}::<self>"
241
+ end
242
+ end
243
+
244
+ # Consts
245
+
246
+ class Const < NodeWithComments
247
+ extend T::Sig
248
+
249
+ sig { returns(String) }
250
+ attr_reader :name, :value
251
+
252
+ sig { params(name: String, value: String, loc: T.nilable(Loc), comments: T::Array[Comment]).void }
253
+ def initialize(name, value, loc: nil, comments: [])
254
+ super(loc: loc, comments: comments)
255
+ @name = name
256
+ @value = value
257
+ end
258
+
259
+ sig { returns(String) }
260
+ def fully_qualified_name
261
+ return name if name.start_with?("::")
262
+ "#{parent_scope&.fully_qualified_name}::#{name}"
263
+ end
264
+
265
+ sig { override.returns(String) }
266
+ def to_s
267
+ fully_qualified_name
268
+ end
269
+ end
270
+
271
+ # Attributes
272
+
273
+ class Attr < NodeWithComments
274
+ extend T::Sig
275
+ extend T::Helpers
276
+
277
+ abstract!
278
+
279
+ sig { returns(T::Array[Symbol]) }
280
+ attr_accessor :names
281
+
282
+ sig { returns(Visibility) }
283
+ attr_accessor :visibility
284
+
285
+ sig { returns(T::Array[Sig]) }
286
+ attr_reader :sigs
287
+
288
+ sig do
289
+ params(
290
+ name: Symbol,
291
+ names: Symbol,
292
+ visibility: Visibility,
293
+ sigs: T::Array[Sig],
294
+ loc: T.nilable(Loc),
295
+ comments: T::Array[Comment]
296
+ ).void
297
+ end
298
+ def initialize(name, *names, visibility: Visibility::Public, sigs: [], loc: nil, comments: [])
299
+ super(loc: loc, comments: comments)
300
+ @names = T.let([name, *names], T::Array[Symbol])
301
+ @visibility = visibility
302
+ @sigs = sigs
303
+ end
304
+
305
+ sig { abstract.returns(T::Array[String]) }
306
+ def fully_qualified_names; end
307
+ end
308
+
309
+ class AttrAccessor < Attr
310
+ extend T::Sig
311
+
312
+ sig { override.returns(T::Array[String]) }
313
+ def fully_qualified_names
314
+ parent_name = parent_scope&.fully_qualified_name
315
+ names.flat_map { |name| ["#{parent_name}##{name}", "#{parent_name}##{name}="] }
316
+ end
317
+
318
+ sig { override.returns(String) }
319
+ def to_s
320
+ symbols = names.map { |name| ":#{name}" }.join(", ")
321
+ "#{parent_scope&.fully_qualified_name}.attr_accessor(#{symbols})"
322
+ end
323
+ end
324
+
325
+ class AttrReader < Attr
326
+ extend T::Sig
327
+
328
+ sig { override.returns(T::Array[String]) }
329
+ def fully_qualified_names
330
+ parent_name = parent_scope&.fully_qualified_name
331
+ names.map { |name| "#{parent_name}##{name}" }
332
+ end
333
+
334
+ sig { override.returns(String) }
335
+ def to_s
336
+ symbols = names.map { |name| ":#{name}" }.join(", ")
337
+ "#{parent_scope&.fully_qualified_name}.attr_reader(#{symbols})"
338
+ end
339
+ end
340
+
341
+ class AttrWriter < Attr
342
+ extend T::Sig
343
+
344
+ sig { override.returns(T::Array[String]) }
345
+ def fully_qualified_names
346
+ parent_name = parent_scope&.fully_qualified_name
347
+ names.map { |name| "#{parent_name}##{name}=" }
348
+ end
349
+
350
+ sig { override.returns(String) }
351
+ def to_s
352
+ symbols = names.map { |name| ":#{name}" }.join(", ")
353
+ "#{parent_scope&.fully_qualified_name}.attr_writer(#{symbols})"
354
+ end
355
+ end
356
+
357
+ # Methods and args
358
+
359
+ class Method < NodeWithComments
360
+ extend T::Sig
361
+
362
+ sig { returns(String) }
363
+ attr_accessor :name
364
+
365
+ sig { returns(T::Array[Param]) }
366
+ attr_reader :params
367
+
368
+ sig { returns(T::Boolean) }
369
+ attr_accessor :is_singleton
370
+
371
+ sig { returns(Visibility) }
372
+ attr_accessor :visibility
373
+
374
+ sig { returns(T::Array[Sig]) }
375
+ attr_accessor :sigs
376
+
377
+ sig do
378
+ params(
379
+ name: String,
380
+ params: T::Array[Param],
381
+ is_singleton: T::Boolean,
382
+ visibility: Visibility,
383
+ sigs: T::Array[Sig],
384
+ loc: T.nilable(Loc),
385
+ comments: T::Array[Comment],
386
+ block: T.nilable(T.proc.params(mod: Method).void)
387
+ ).void
388
+ end
389
+ def initialize(
390
+ name,
391
+ params: [],
392
+ is_singleton: false,
393
+ visibility: Visibility::Public,
394
+ sigs: [],
395
+ loc: nil,
396
+ comments: [],
397
+ &block
398
+ )
399
+ super(loc: loc, comments: comments)
400
+ @name = name
401
+ @params = params
402
+ @is_singleton = is_singleton
403
+ @visibility = visibility
404
+ @sigs = sigs
405
+ block&.call(self)
406
+ end
407
+
408
+ sig { params(param: Param).void }
409
+ def <<(param)
410
+ @params << param
411
+ end
412
+
413
+ sig { returns(String) }
414
+ def fully_qualified_name
415
+ if is_singleton
416
+ "#{parent_scope&.fully_qualified_name}::#{name}"
417
+ else
418
+ "#{parent_scope&.fully_qualified_name}##{name}"
419
+ end
420
+ end
421
+
422
+ sig { override.returns(String) }
423
+ def to_s
424
+ "#{fully_qualified_name}(#{params.join(", ")})"
425
+ end
426
+ end
427
+
428
+ class Param < NodeWithComments
429
+ extend T::Sig
430
+
431
+ sig { returns(String) }
432
+ attr_reader :name
433
+
434
+ sig { params(name: String, loc: T.nilable(Loc), comments: T::Array[Comment]).void }
435
+ def initialize(name, loc: nil, comments: [])
436
+ super(loc: loc, comments: comments)
437
+ @name = name
438
+ end
439
+
440
+ sig { override.returns(String) }
441
+ def to_s
442
+ name
443
+ end
444
+
445
+ sig { params(other: T.nilable(Object)).returns(T::Boolean) }
446
+ def ==(other)
447
+ return false unless other.instance_of?(Param)
448
+ name == T.cast(other, Param).name
449
+ end
450
+ end
451
+
452
+ class OptParam < Param
453
+ extend T::Sig
454
+
455
+ sig { returns(String) }
456
+ attr_reader :value
457
+
458
+ sig { params(name: String, value: String, loc: T.nilable(Loc), comments: T::Array[Comment]).void }
459
+ def initialize(name, value, loc: nil, comments: [])
460
+ super(name, loc: loc, comments: comments)
461
+ @value = value
462
+ end
463
+
464
+ sig { params(other: T.nilable(Object)).returns(T::Boolean) }
465
+ def ==(other)
466
+ return false unless other.instance_of?(OptParam)
467
+ other = T.cast(other, OptParam)
468
+ return false unless name == other.name
469
+ value == other.value
470
+ end
471
+ end
472
+
473
+ class RestParam < Param
474
+ extend T::Sig
475
+
476
+ sig { params(other: T.nilable(Object)).returns(T::Boolean) }
477
+ def ==(other)
478
+ return false unless other.instance_of?(RestParam)
479
+ name == T.cast(other, RestParam).name
480
+ end
481
+
482
+ sig { override.returns(String) }
483
+ def to_s
484
+ "*#{name}"
485
+ end
486
+ end
487
+
488
+ class KwParam < Param
489
+ extend T::Sig
490
+
491
+ sig { override.returns(String) }
492
+ def to_s
493
+ "#{name}:"
494
+ end
495
+
496
+ sig { params(other: T.nilable(Object)).returns(T::Boolean) }
497
+ def ==(other)
498
+ return false unless other.instance_of?(KwParam)
499
+ name == T.cast(other, KwParam).name
500
+ end
501
+ end
502
+
503
+ class KwOptParam < OptParam
504
+ extend T::Sig
505
+
506
+ sig { override.returns(String) }
507
+ def to_s
508
+ "#{name}:"
509
+ end
510
+
511
+ sig { params(other: T.nilable(Object)).returns(T::Boolean) }
512
+ def ==(other)
513
+ return false unless other.instance_of?(KwOptParam)
514
+ other = T.cast(other, KwOptParam)
515
+ return false unless name == other.name
516
+ value == other.value
517
+ end
518
+ end
519
+
520
+ class KwRestParam < Param
521
+ extend T::Sig
522
+
523
+ sig { override.returns(String) }
524
+ def to_s
525
+ "**#{name}:"
526
+ end
527
+
528
+ sig { params(other: T.nilable(Object)).returns(T::Boolean) }
529
+ def ==(other)
530
+ return false unless other.instance_of?(KwRestParam)
531
+ name == T.cast(other, KwRestParam).name
532
+ end
533
+ end
534
+
535
+ class BlockParam < Param
536
+ extend T::Sig
537
+
538
+ sig { override.returns(String) }
539
+ def to_s
540
+ "&#{name}"
541
+ end
542
+
543
+ sig { params(other: T.nilable(Object)).returns(T::Boolean) }
544
+ def ==(other)
545
+ return false unless other.instance_of?(BlockParam)
546
+ name == T.cast(other, BlockParam).name
547
+ end
548
+ end
549
+
550
+ # Mixins
551
+
552
+ class Mixin < NodeWithComments
553
+ extend T::Sig
554
+ extend T::Helpers
555
+
556
+ abstract!
557
+
558
+ sig { returns(T::Array[String]) }
559
+ attr_accessor :names
560
+
561
+ sig { params(name: String, names: String, loc: T.nilable(Loc), comments: T::Array[Comment]).void }
562
+ def initialize(name, *names, loc: nil, comments: [])
563
+ super(loc: loc, comments: comments)
564
+ @names = T.let([name, *names], T::Array[String])
565
+ end
566
+ end
567
+
568
+ class Include < Mixin
569
+ extend T::Sig
570
+
571
+ sig { override.returns(String) }
572
+ def to_s
573
+ "#{parent_scope&.fully_qualified_name}.include(#{names.join(", ")})"
574
+ end
575
+ end
576
+
577
+ class Extend < Mixin
578
+ extend T::Sig
579
+
580
+ sig { override.returns(String) }
581
+ def to_s
582
+ "#{parent_scope&.fully_qualified_name}.extend(#{names.join(", ")})"
583
+ end
584
+ end
585
+
586
+ # Visibility
587
+
588
+ class Visibility < Node
589
+ extend T::Sig
590
+ extend T::Helpers
591
+
592
+ abstract!
593
+
594
+ sig { returns(Symbol) }
595
+ attr_reader :visibility
596
+
597
+ sig { params(visibility: Symbol, loc: T.nilable(Loc)).void }
598
+ def initialize(visibility, loc: nil)
599
+ super(loc: loc)
600
+ @visibility = visibility
601
+ end
602
+
603
+ sig { params(other: Visibility).returns(T::Boolean) }
604
+ def ==(other)
605
+ visibility == other.visibility
606
+ end
607
+
608
+ Public = T.let(Visibility.new(:public), Visibility)
609
+ Protected = T.let(Visibility.new(:protected), Visibility)
610
+ Private = T.let(Visibility.new(:private), Visibility)
611
+ end
612
+
613
+ # Sorbet's sigs
614
+
615
+ class Sig < Node
616
+ extend T::Sig
617
+
618
+ sig { returns(T::Array[SigParam]) }
619
+ attr_reader :params
620
+
621
+ sig { returns(T.nilable(String)) }
622
+ attr_accessor :return_type
623
+
624
+ sig { returns(T::Boolean) }
625
+ attr_accessor :is_abstract, :is_override, :is_overridable
626
+
627
+ sig { returns(T::Array[String]) }
628
+ attr_reader :type_params
629
+
630
+ sig { returns(T.nilable(Symbol)) }
631
+ attr_accessor :checked
632
+
633
+ sig do
634
+ params(
635
+ params: T::Array[SigParam],
636
+ return_type: T.nilable(String),
637
+ is_abstract: T::Boolean,
638
+ is_override: T::Boolean,
639
+ is_overridable: T::Boolean,
640
+ type_params: T::Array[String],
641
+ checked: T.nilable(Symbol),
642
+ loc: T.nilable(Loc)
643
+ ).void
644
+ end
645
+ def initialize(
646
+ params: [],
647
+ return_type: nil,
648
+ is_abstract: false,
649
+ is_override: false,
650
+ is_overridable: false,
651
+ type_params: [],
652
+ checked: nil,
653
+ loc: nil
654
+ )
655
+ super(loc: loc)
656
+ @params = params
657
+ @return_type = return_type
658
+ @is_abstract = is_abstract
659
+ @is_override = is_override
660
+ @is_overridable = is_overridable
661
+ @type_params = type_params
662
+ @checked = checked
663
+ end
664
+
665
+ sig { params(param: SigParam).void }
666
+ def <<(param)
667
+ @params << param
668
+ end
669
+
670
+ sig { params(other: Object).returns(T::Boolean) }
671
+ def ==(other)
672
+ return false unless other.is_a?(Sig)
673
+ params == other.params && return_type == other.return_type && is_abstract == other.is_abstract &&
674
+ is_override == other.is_override && is_overridable == other.is_overridable &&
675
+ type_params == other.type_params && checked == other.checked
676
+ end
677
+ end
678
+
679
+ class SigParam < Node
680
+ extend T::Sig
681
+
682
+ sig { returns(String) }
683
+ attr_reader :name, :type
684
+
685
+ sig { params(name: String, type: String, loc: T.nilable(Loc)).void }
686
+ def initialize(name, type, loc: nil)
687
+ super(loc: loc)
688
+ @name = name
689
+ @type = type
690
+ end
691
+
692
+ sig { params(other: Object).returns(T::Boolean) }
693
+ def ==(other)
694
+ other.is_a?(SigParam) && name == other.name && type == other.type
695
+ end
696
+ end
697
+
698
+ # Sorbet's T::Struct
699
+
700
+ class TStruct < Class
701
+ extend T::Sig
702
+
703
+ sig do
704
+ params(
705
+ name: String,
706
+ loc: T.nilable(Loc),
707
+ comments: T::Array[Comment],
708
+ block: T.nilable(T.proc.params(klass: TStruct).void)
709
+ ).void
710
+ end
711
+ def initialize(name, loc: nil, comments: [], &block)
712
+ super(name, superclass_name: "::T::Struct", loc: loc, comments: comments) {}
713
+ block&.call(self)
714
+ end
715
+ end
716
+
717
+ class TStructField < NodeWithComments
718
+ extend T::Sig
719
+ extend T::Helpers
720
+
721
+ abstract!
722
+
723
+ sig { returns(String) }
724
+ attr_accessor :name, :type
725
+
726
+ sig { returns(T.nilable(String)) }
727
+ attr_accessor :default
728
+
729
+ sig do
730
+ params(
731
+ name: String,
732
+ type: String,
733
+ default: T.nilable(String),
734
+ loc: T.nilable(Loc),
735
+ comments: T::Array[Comment]
736
+ ).void
737
+ end
738
+ def initialize(name, type, default: nil, loc: nil, comments: [])
739
+ super(loc: loc, comments: comments)
740
+ @name = name
741
+ @type = type
742
+ @default = default
743
+ end
744
+
745
+ sig { abstract.returns(T::Array[String]) }
746
+ def fully_qualified_names; end
747
+ end
748
+
749
+ class TStructConst < TStructField
750
+ extend T::Sig
751
+
752
+ sig { override.returns(T::Array[String]) }
753
+ def fully_qualified_names
754
+ parent_name = parent_scope&.fully_qualified_name
755
+ ["#{parent_name}##{name}"]
756
+ end
757
+
758
+ sig { override.returns(String) }
759
+ def to_s
760
+ "#{parent_scope&.fully_qualified_name}.const(:#{name})"
761
+ end
762
+ end
763
+
764
+ class TStructProp < TStructField
765
+ extend T::Sig
766
+
767
+ sig { override.returns(T::Array[String]) }
768
+ def fully_qualified_names
769
+ parent_name = parent_scope&.fully_qualified_name
770
+ ["#{parent_name}##{name}", "#{parent_name}##{name}="]
771
+ end
772
+
773
+ sig { override.returns(String) }
774
+ def to_s
775
+ "#{parent_scope&.fully_qualified_name}.prop(:#{name})"
776
+ end
777
+ end
778
+
779
+ # Sorbet's T::Enum
780
+
781
+ class TEnum < Class
782
+ extend T::Sig
783
+
784
+ sig do
785
+ params(
786
+ name: String,
787
+ loc: T.nilable(Loc),
788
+ comments: T::Array[Comment],
789
+ block: T.nilable(T.proc.params(klass: TEnum).void)
790
+ ).void
791
+ end
792
+ def initialize(name, loc: nil, comments: [], &block)
793
+ super(name, superclass_name: "::T::Enum", loc: loc, comments: comments) {}
794
+ block&.call(self)
795
+ end
796
+ end
797
+
798
+ class TEnumBlock < NodeWithComments
799
+ extend T::Sig
800
+
801
+ sig { returns(T::Array[String]) }
802
+ attr_reader :names
803
+
804
+ sig { params(names: T::Array[String], loc: T.nilable(Loc), comments: T::Array[Comment]).void }
805
+ def initialize(names = [], loc: nil, comments: [])
806
+ super(loc: loc, comments: comments)
807
+ @names = names
808
+ end
809
+
810
+ sig { returns(T::Boolean) }
811
+ def empty?
812
+ names.empty?
813
+ end
814
+
815
+ sig { params(name: String).void }
816
+ def <<(name)
817
+ @names << name
818
+ end
819
+
820
+ sig { override.returns(String) }
821
+ def to_s
822
+ "#{parent_scope&.fully_qualified_name}.enums"
823
+ end
824
+ end
825
+
826
+ # Sorbet's misc.
827
+
828
+ class Helper < NodeWithComments
829
+ extend T::Helpers
830
+
831
+ sig { returns(String) }
832
+ attr_reader :name
833
+
834
+ sig { params(name: String, loc: T.nilable(Loc), comments: T::Array[Comment]).void }
835
+ def initialize(name, loc: nil, comments: [])
836
+ super(loc: loc, comments: comments)
837
+ @name = name
838
+ end
839
+
840
+ sig { override.returns(String) }
841
+ def to_s
842
+ "#{parent_scope&.fully_qualified_name}.#{name}!"
843
+ end
844
+ end
845
+
846
+ class TypeMember < NodeWithComments
847
+ extend T::Sig
848
+
849
+ sig { returns(String) }
850
+ attr_reader :name, :value
851
+
852
+ sig { params(name: String, value: String, loc: T.nilable(Loc), comments: T::Array[Comment]).void }
853
+ def initialize(name, value, loc: nil, comments: [])
854
+ super(loc: loc, comments: comments)
855
+ @name = name
856
+ @value = value
857
+ end
858
+
859
+ sig { returns(String) }
860
+ def fully_qualified_name
861
+ return name if name.start_with?("::")
862
+ "#{parent_scope&.fully_qualified_name}::#{name}"
863
+ end
864
+
865
+ sig { override.returns(String) }
866
+ def to_s
867
+ fully_qualified_name
868
+ end
869
+ end
870
+
871
+ class MixesInClassMethods < Mixin
872
+ extend T::Sig
873
+
874
+ sig { override.returns(String) }
875
+ def to_s
876
+ "#{parent_scope&.fully_qualified_name}.mixes_in_class_methods(#{names.join(", ")})"
877
+ end
878
+ end
879
+ end