rbi 0.1.13 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []