rbi 0.1.13 → 0.1.14

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.
@@ -0,0 +1,169 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ class UnexpectedMultipleSigsError < Error
6
+ sig { returns(Node) }
7
+ attr_reader :node
8
+
9
+ sig { params(node: Node).void }
10
+ def initialize(node)
11
+ super(<<~MSG)
12
+ This declaration cannot have more than one sig.
13
+
14
+ #{node.string.chomp}
15
+ MSG
16
+
17
+ @node = node
18
+ end
19
+ end
20
+
21
+ module Rewriters
22
+ class AttrToMethods < Visitor
23
+ extend T::Sig
24
+
25
+ sig { override.params(node: T.nilable(Node)).void }
26
+ def visit(node)
27
+ case node
28
+ when Tree
29
+ visit_all(node.nodes.dup)
30
+
31
+ when Attr
32
+ replace(node, with: node.convert_to_methods)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ sig { params(node: Node, with: T::Array[Node]).void }
39
+ def replace(node, with:)
40
+ tree = node.parent_tree
41
+ raise ReplaceNodeError, "Can't replace #{self} without a parent tree" unless tree
42
+
43
+ node.detach
44
+ with.each { |node| tree << node }
45
+ end
46
+ end
47
+ end
48
+
49
+ class Tree
50
+ extend T::Sig
51
+
52
+ sig { void }
53
+ def replace_attributes_with_methods!
54
+ visitor = Rewriters::AttrToMethods.new
55
+ visitor.visit(self)
56
+ end
57
+ end
58
+
59
+ class Attr
60
+ sig { abstract.returns(T::Array[Method]) }
61
+ def convert_to_methods; end
62
+
63
+ private
64
+
65
+ sig(:final) { returns([T.nilable(Sig), T.nilable(String)]) }
66
+ def parse_sig
67
+ raise UnexpectedMultipleSigsError, self if 1 < sigs.count
68
+
69
+ sig = sigs.first
70
+ return [nil, nil] unless sig
71
+
72
+ attribute_type = case self
73
+ when AttrReader, AttrAccessor then sig.return_type
74
+ when AttrWriter then sig.params.first&.type
75
+ end
76
+
77
+ [sig, attribute_type]
78
+ end
79
+
80
+ sig do
81
+ params(
82
+ name: String,
83
+ sig: T.nilable(Sig),
84
+ visibility: Visibility,
85
+ loc: T.nilable(Loc),
86
+ comments: T::Array[Comment],
87
+ ).returns(Method)
88
+ end
89
+ def create_getter_method(name, sig, visibility, loc, comments)
90
+ Method.new(
91
+ name,
92
+ params: [],
93
+ visibility: visibility,
94
+ sigs: sig ? [sig] : [],
95
+ loc: loc,
96
+ comments: comments,
97
+ )
98
+ end
99
+
100
+ sig do
101
+ params(
102
+ name: String,
103
+ sig: T.nilable(Sig),
104
+ attribute_type: T.nilable(String),
105
+ visibility: Visibility,
106
+ loc: T.nilable(Loc),
107
+ comments: T::Array[Comment],
108
+ ).returns(Method)
109
+ end
110
+ def create_setter_method(name, sig, attribute_type, visibility, loc, comments) # rubocop:disable Metrics/ParameterLists
111
+ sig = if sig # Modify the original sig to correct the name, and remove the return type
112
+ params = attribute_type ? [SigParam.new(name, attribute_type)] : []
113
+
114
+ Sig.new(
115
+ params: params,
116
+ return_type: "void",
117
+ is_abstract: sig.is_abstract,
118
+ is_override: sig.is_override,
119
+ is_overridable: sig.is_overridable,
120
+ is_final: sig.is_final,
121
+ type_params: sig.type_params,
122
+ checked: sig.checked,
123
+ loc: sig.loc,
124
+ )
125
+ end
126
+
127
+ Method.new(
128
+ "#{name}=",
129
+ params: [ReqParam.new(name)],
130
+ visibility: visibility,
131
+ sigs: sig ? [sig] : [],
132
+ loc: loc,
133
+ comments: comments,
134
+ )
135
+ end
136
+ end
137
+
138
+ class AttrAccessor
139
+ sig { override.returns(T::Array[Method]) }
140
+ def convert_to_methods
141
+ sig, attribute_type = parse_sig
142
+
143
+ names.flat_map do |name|
144
+ [
145
+ create_getter_method(name.to_s, sig, visibility, loc, comments),
146
+ create_setter_method(name.to_s, sig, attribute_type, visibility, loc, comments),
147
+ ]
148
+ end
149
+ end
150
+ end
151
+
152
+ class AttrReader
153
+ sig { override.returns(T::Array[Method]) }
154
+ def convert_to_methods
155
+ sig, _ = parse_sig
156
+
157
+ names.map { |name| create_getter_method(name.to_s, sig, visibility, loc, comments) }
158
+ end
159
+ end
160
+
161
+ class AttrWriter
162
+ sig { override.returns(T::Array[Method]) }
163
+ def convert_to_methods
164
+ sig, attribute_type = parse_sig
165
+
166
+ names.map { |name| create_setter_method(name.to_s, sig, attribute_type, visibility, loc, comments) }
167
+ end
168
+ end
169
+ end
@@ -2,6 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RBI
5
+ class GroupNodesError < Error; end
6
+
5
7
  module Rewriters
6
8
  class GroupNodes < Visitor
7
9
  extend T::Sig
@@ -12,8 +14,7 @@ module RBI
12
14
 
13
15
  case node
14
16
  when Tree
15
- kinds = node.nodes.map(&:group_kind)
16
- kinds.compact!
17
+ kinds = node.nodes.map { |child| group_kind(child) }
17
18
  kinds.uniq!
18
19
 
19
20
  groups = {}
@@ -22,12 +23,54 @@ module RBI
22
23
  node.nodes.dup.each do |child|
23
24
  visit(child)
24
25
  child.detach
25
- groups[child.group_kind] << child
26
+ groups[group_kind(child)] << child
26
27
  end
27
28
 
28
29
  groups.each { |_, group| node << group }
29
30
  end
30
31
  end
32
+
33
+ private
34
+
35
+ sig { params(node: Node).returns(Group::Kind) }
36
+ def group_kind(node)
37
+ case node
38
+ when Group
39
+ node.kind
40
+ when Include, Extend
41
+ Group::Kind::Mixins
42
+ when RequiresAncestor
43
+ Group::Kind::RequiredAncestors
44
+ when Helper
45
+ Group::Kind::Helpers
46
+ when TypeMember
47
+ Group::Kind::TypeMembers
48
+ when MixesInClassMethods
49
+ Group::Kind::MixesInClassMethods
50
+ when Send
51
+ Group::Kind::Sends
52
+ when Attr
53
+ Group::Kind::Attrs
54
+ when TStructField
55
+ Group::Kind::TStructFields
56
+ when TEnumBlock
57
+ Group::Kind::TEnums
58
+ when VisibilityGroup
59
+ Group::Kind::Methods
60
+ when Method
61
+ if node.name == "initialize"
62
+ Group::Kind::Inits
63
+ else
64
+ Group::Kind::Methods
65
+ end
66
+ when SingletonClass
67
+ Group::Kind::SingletonClasses
68
+ when Scope, Const
69
+ Group::Kind::Consts
70
+ else
71
+ raise GroupNodesError, "Unknown group for #{self}"
72
+ end
73
+ end
31
74
  end
32
75
  end
33
76
 
@@ -41,50 +84,6 @@ module RBI
41
84
  end
42
85
  end
43
86
 
44
- class Node
45
- extend T::Sig
46
-
47
- sig { returns(Group::Kind) }
48
- def group_kind
49
- case self
50
- when Group
51
- kind
52
- when Include, Extend
53
- Group::Kind::Mixins
54
- when RequiresAncestor
55
- Group::Kind::RequiredAncestors
56
- when Helper
57
- Group::Kind::Helpers
58
- when TypeMember
59
- Group::Kind::TypeMembers
60
- when MixesInClassMethods
61
- Group::Kind::MixesInClassMethods
62
- when Send
63
- Group::Kind::Sends
64
- when Attr
65
- Group::Kind::Attrs
66
- when TStructField
67
- Group::Kind::TStructFields
68
- when TEnumBlock
69
- Group::Kind::TEnums
70
- when VisibilityGroup
71
- Group::Kind::Methods
72
- when Method
73
- if name == "initialize"
74
- Group::Kind::Inits
75
- else
76
- Group::Kind::Methods
77
- end
78
- when SingletonClass
79
- Group::Kind::SingletonClasses
80
- when Scope, Const
81
- Group::Kind::Consts
82
- else
83
- raise "Unknown group for #{self}"
84
- end
85
- end
86
- end
87
-
88
87
  class Group < Tree
89
88
  extend T::Sig
90
89
 
@@ -348,6 +348,8 @@ module RBI
348
348
  end
349
349
  end
350
350
 
351
+ class DuplicateNodeError < Error; end
352
+
351
353
  class Scope
352
354
  extend T::Sig
353
355
 
@@ -364,7 +366,7 @@ module RBI
364
366
  when SingletonClass
365
367
  SingletonClass.new(loc: loc, comments: comments)
366
368
  else
367
- raise "Can't duplicate node #{self}"
369
+ raise DuplicateNodeError, "Can't duplicate node #{self}"
368
370
  end
369
371
  end
370
372
  end
@@ -592,6 +594,9 @@ module RBI
592
594
  sig { returns(Tree) }
593
595
  attr_reader :left, :right
594
596
 
597
+ sig { returns(String) }
598
+ attr_reader :left_name, :right_name
599
+
595
600
  sig { params(left_name: String, right_name: String).void }
596
601
  def initialize(left_name: "left", right_name: "right")
597
602
  super()
@@ -602,15 +607,6 @@ module RBI
602
607
  @right = T.let(Tree.new, Tree)
603
608
  @right.parent_tree = self
604
609
  end
605
-
606
- sig { override.params(v: Printer).void }
607
- def accept_printer(v)
608
- v.printl("<<<<<<< #{@left_name}")
609
- v.visit(left)
610
- v.printl("=======")
611
- v.visit(right)
612
- v.printl(">>>>>>> #{@right_name}")
613
- end
614
610
  end
615
611
 
616
612
  # A conflict between two scope headers
@@ -631,6 +627,9 @@ module RBI
631
627
  sig { returns(Scope) }
632
628
  attr_reader :left, :right
633
629
 
630
+ sig { returns(String) }
631
+ attr_reader :left_name, :right_name
632
+
634
633
  sig do
635
634
  params(
636
635
  left: Scope,
@@ -646,26 +645,5 @@ module RBI
646
645
  @left_name = left_name
647
646
  @right_name = right_name
648
647
  end
649
-
650
- sig { override.params(v: Printer).void }
651
- def accept_printer(v)
652
- previous_node = v.previous_node
653
- v.printn if previous_node && (!previous_node.oneline? || !oneline?)
654
-
655
- v.printl("# #{loc}") if loc && v.print_locs
656
- v.visit_all(comments)
657
-
658
- v.printl("<<<<<<< #{@left_name}")
659
- left.print_header(v)
660
- v.printl("=======")
661
- right.print_header(v)
662
- v.printl(">>>>>>> #{@right_name}")
663
- left.print_body(v)
664
- end
665
-
666
- sig { override.returns(T::Boolean) }
667
- def oneline?
668
- left.oneline?
669
- end
670
648
  end
671
649
  end
data/lib/rbi/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RBI
5
- VERSION = "0.1.13"
5
+ VERSION = "0.1.14"
6
6
  end
data/lib/rbi/visitor.rb CHANGED
@@ -2,18 +2,244 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RBI
5
+ class VisitorError < Error; end
6
+
5
7
  class Visitor
6
8
  extend T::Helpers
7
9
  extend T::Sig
8
10
 
9
11
  abstract!
10
12
 
11
- sig { abstract.params(node: T.nilable(Node)).void }
12
- def visit(node); end
13
+ sig { params(node: T.nilable(Node)).void }
14
+ def visit(node)
15
+ return unless node
16
+
17
+ case node
18
+ when BlankLine
19
+ visit_blank_line(node)
20
+ when Comment
21
+ visit_comment(node)
22
+ when Module
23
+ visit_module(node)
24
+ when Class
25
+ visit_class(node)
26
+ when SingletonClass
27
+ visit_singleton_class(node)
28
+ when Struct
29
+ visit_struct(node)
30
+ when Group
31
+ visit_group(node)
32
+ when VisibilityGroup
33
+ visit_visibility_group(node)
34
+ when ConflictTree
35
+ visit_conflict_tree(node)
36
+ when ScopeConflict
37
+ visit_scope_conflict(node)
38
+ when Tree
39
+ visit_tree(node)
40
+ when Const
41
+ visit_const(node)
42
+ when AttrAccessor
43
+ visit_attr_accessor(node)
44
+ when AttrReader
45
+ visit_attr_reader(node)
46
+ when AttrWriter
47
+ visit_attr_writer(node)
48
+ when Method
49
+ visit_method(node)
50
+ when ReqParam
51
+ visit_req_param(node)
52
+ when OptParam
53
+ visit_opt_param(node)
54
+ when RestParam
55
+ visit_rest_param(node)
56
+ when KwParam
57
+ visit_kw_param(node)
58
+ when KwOptParam
59
+ visit_kw_opt_param(node)
60
+ when KwRestParam
61
+ visit_kw_rest_param(node)
62
+ when BlockParam
63
+ visit_block_param(node)
64
+ when Include
65
+ visit_include(node)
66
+ when Extend
67
+ visit_extend(node)
68
+ when Public
69
+ visit_public(node)
70
+ when Protected
71
+ visit_protected(node)
72
+ when Private
73
+ visit_private(node)
74
+ when Send
75
+ visit_send(node)
76
+ when KwArg
77
+ visit_kw_arg(node)
78
+ when Arg
79
+ visit_arg(node)
80
+ when Sig
81
+ visit_sig(node)
82
+ when SigParam
83
+ visit_sig_param(node)
84
+ when TStruct
85
+ visit_tstruct(node)
86
+ when TStructConst
87
+ visit_tstruct_const(node)
88
+ when TStructProp
89
+ visit_tstruct_prop(node)
90
+ when TEnum
91
+ visit_tenum(node)
92
+ when TEnumBlock
93
+ visit_tenum_block(node)
94
+ when Helper
95
+ visit_helper(node)
96
+ when TypeMember
97
+ visit_type_member(node)
98
+ when MixesInClassMethods
99
+ visit_mixes_in_class_methods(node)
100
+ when RequiresAncestor
101
+ visit_requires_ancestor(node)
102
+ else
103
+ raise VisitorError, "Unhandled node: #{node.class}"
104
+ end
105
+ end
13
106
 
14
107
  sig { params(nodes: T::Array[Node]).void }
15
108
  def visit_all(nodes)
16
109
  nodes.each { |node| visit(node) }
17
110
  end
111
+
112
+ sig { params(file: File).void }
113
+ def visit_file(file)
114
+ visit(file.root)
115
+ end
116
+
117
+ private
118
+
119
+ sig { params(node: Comment).void }
120
+ def visit_comment(node); end
121
+
122
+ sig { params(node: BlankLine).void }
123
+ def visit_blank_line(node); end
124
+
125
+ sig { params(node: Module).void }
126
+ def visit_module(node); end
127
+
128
+ sig { params(node: Class).void }
129
+ def visit_class(node); end
130
+
131
+ sig { params(node: SingletonClass).void }
132
+ def visit_singleton_class(node); end
133
+
134
+ sig { params(node: Struct).void }
135
+ def visit_struct(node); end
136
+
137
+ sig { params(node: Tree).void }
138
+ def visit_tree(node); end
139
+
140
+ sig { params(node: Const).void }
141
+ def visit_const(node); end
142
+
143
+ sig { params(node: AttrAccessor).void }
144
+ def visit_attr_accessor(node); end
145
+
146
+ sig { params(node: AttrReader).void }
147
+ def visit_attr_reader(node); end
148
+
149
+ sig { params(node: AttrWriter).void }
150
+ def visit_attr_writer(node); end
151
+
152
+ sig { params(node: Method).void }
153
+ def visit_method(node); end
154
+
155
+ sig { params(node: ReqParam).void }
156
+ def visit_req_param(node); end
157
+
158
+ sig { params(node: OptParam).void }
159
+ def visit_opt_param(node); end
160
+
161
+ sig { params(node: RestParam).void }
162
+ def visit_rest_param(node); end
163
+
164
+ sig { params(node: KwParam).void }
165
+ def visit_kw_param(node); end
166
+
167
+ sig { params(node: KwOptParam).void }
168
+ def visit_kw_opt_param(node); end
169
+
170
+ sig { params(node: KwRestParam).void }
171
+ def visit_kw_rest_param(node); end
172
+
173
+ sig { params(node: BlockParam).void }
174
+ def visit_block_param(node); end
175
+
176
+ sig { params(node: Include).void }
177
+ def visit_include(node); end
178
+
179
+ sig { params(node: Extend).void }
180
+ def visit_extend(node); end
181
+
182
+ sig { params(node: Public).void }
183
+ def visit_public(node); end
184
+
185
+ sig { params(node: Protected).void }
186
+ def visit_protected(node); end
187
+
188
+ sig { params(node: Private).void }
189
+ def visit_private(node); end
190
+
191
+ sig { params(node: Send).void }
192
+ def visit_send(node); end
193
+
194
+ sig { params(node: Arg).void }
195
+ def visit_arg(node); end
196
+
197
+ sig { params(node: KwArg).void }
198
+ def visit_kw_arg(node); end
199
+
200
+ sig { params(node: Sig).void }
201
+ def visit_sig(node); end
202
+
203
+ sig { params(node: SigParam).void }
204
+ def visit_sig_param(node); end
205
+
206
+ sig { params(node: TStruct).void }
207
+ def visit_tstruct(node); end
208
+
209
+ sig { params(node: TStructConst).void }
210
+ def visit_tstruct_const(node); end
211
+
212
+ sig { params(node: TStructProp).void }
213
+ def visit_tstruct_prop(node); end
214
+
215
+ sig { params(node: TEnum).void }
216
+ def visit_tenum(node); end
217
+
218
+ sig { params(node: TEnumBlock).void }
219
+ def visit_tenum_block(node); end
220
+
221
+ sig { params(node: Helper).void }
222
+ def visit_helper(node); end
223
+
224
+ sig { params(node: TypeMember).void }
225
+ def visit_type_member(node); end
226
+
227
+ sig { params(node: MixesInClassMethods).void }
228
+ def visit_mixes_in_class_methods(node); end
229
+
230
+ sig { params(node: RequiresAncestor).void }
231
+ def visit_requires_ancestor(node); end
232
+
233
+ sig { params(node: Group).void }
234
+ def visit_group(node); end
235
+
236
+ sig { params(node: VisibilityGroup).void }
237
+ def visit_visibility_group(node); end
238
+
239
+ sig { params(node: ConflictTree).void }
240
+ def visit_conflict_tree(node); end
241
+
242
+ sig { params(node: ScopeConflict).void }
243
+ def visit_scope_conflict(node); end
18
244
  end
19
245
  end
data/lib/rbi.rb CHANGED
@@ -3,6 +3,13 @@
3
3
 
4
4
  require "sorbet-runtime"
5
5
  require "stringio"
6
+
7
+ module RBI
8
+ class Error < StandardError
9
+ extend T::Sig
10
+ end
11
+ end
12
+
6
13
  require "rbi/loc"
7
14
  require "rbi/model"
8
15
  require "rbi/visitor"
@@ -16,6 +23,7 @@ require "rbi/rewriters/nest_singleton_methods"
16
23
  require "rbi/rewriters/nest_non_public_methods"
17
24
  require "rbi/rewriters/group_nodes"
18
25
  require "rbi/rewriters/remove_known_definitions"
26
+ require "rbi/rewriters/attr_to_methods"
19
27
  require "rbi/rewriters/sort_nodes"
20
28
  require "rbi/parser"
21
29
  require "rbi/printer"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Terrasa
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-06 00:00:00.000000000 Z
11
+ date: 2024-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prism
@@ -44,7 +44,7 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: 0.5.9204
47
- description:
47
+ description:
48
48
  email:
49
49
  - ruby@shopify.com
50
50
  executables: []
@@ -63,6 +63,7 @@ files:
63
63
  - lib/rbi/printer.rb
64
64
  - lib/rbi/rewriters/add_sig_templates.rb
65
65
  - lib/rbi/rewriters/annotate.rb
66
+ - lib/rbi/rewriters/attr_to_methods.rb
66
67
  - lib/rbi/rewriters/deannotate.rb
67
68
  - lib/rbi/rewriters/filter_versions.rb
68
69
  - lib/rbi/rewriters/group_nodes.rb
@@ -78,7 +79,7 @@ licenses:
78
79
  - MIT
79
80
  metadata:
80
81
  allowed_push_host: https://rubygems.org
81
- post_install_message:
82
+ post_install_message:
82
83
  rdoc_options: []
83
84
  require_paths:
84
85
  - lib
@@ -93,8 +94,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
94
  - !ruby/object:Gem::Version
94
95
  version: '0'
95
96
  requirements: []
96
- rubygems_version: 3.5.9
97
- signing_key:
97
+ rubygems_version: 3.5.15
98
+ signing_key:
98
99
  specification_version: 4
99
100
  summary: RBI generation framework
100
101
  test_files: []