yard2rbs 0.0.1 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74d0fab907be0a8229347fbda564913a08a6688b3b1c76db58ab98e52a783c3b
4
- data.tar.gz: 1e51981642df3c3ee35cfd8a0e8c9651d6c03db6fff51bb7fd8d995f96101b13
3
+ metadata.gz: 89cede55d743ff594a63059976abb91340df2296817864612b5414ac7d2202ed
4
+ data.tar.gz: 340ea58b5d5425d9257fc43589534f7097e78ae5bad5040695b532eb88365603
5
5
  SHA512:
6
- metadata.gz: c29df8ed7704ff31f8a7640a52f3f50e02ccf654e0d999c25d3c228b162e9488c1abf598e71d63f39ec4c240ee1a2cd685dcd9a2b898d2d6c35b665035865d6c
7
- data.tar.gz: 20c59a4b6462c4d14636587d7426faf377b2931ccb6c9ce7ae6eebaf5725ed58cc5dcc4859c6be00b46e6afd70e8efeec1c233bdba648e0b47a4d12d70b74bbb
6
+ metadata.gz: 06d23c6bf1c51b606a39071c2cdd7b9ee4b72043e2f2b7f36d9b71b27b66e7e9c371b213b0e70bac65c3fb8c1bd9877b8f7175aaac17dcab5cf9b967f9cf80f6
7
+ data.tar.gz: df576094cc163320c461cd04cf3007b480e372b70f5d19353b5c04e7d192bf9c96a215d3129e1cf3e845e5106ed2f44bb21e0c2029eb389093748c444000ff56
@@ -1,13 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "prism"
4
+ require "rbs"
4
5
 
5
6
  # https://ruby.github.io/prism/rb/index.html
6
7
  # https://github.com/ruby/rbs/blob/master/docs/syntax.md
7
8
  # https://github.com/ruby/rbs/blob/master/lib/rbs/prototype/rb.rb
9
+ # https://rubydoc.info/gems/yard/file/docs/GettingStarted.md
8
10
 
9
11
  module Yard2rbs
10
12
  class Converter
13
+ class << self
14
+ # @param input_path [String]
15
+ # @return [String]
16
+ def convert(input_path)
17
+ new(input_path).convert
18
+ end
19
+ end
20
+
11
21
  # @param input_path [String]
12
22
  # @return [void]
13
23
  def initialize(input_path)
@@ -19,6 +29,7 @@ module Yard2rbs
19
29
  # @return [String]
20
30
  def convert
21
31
  @_indent_level = 0
32
+ @_superclasses = []
22
33
  # puts @parse_result.value.inspect
23
34
  process(@parse_result.value)
24
35
  output = @output.join("\n")
@@ -39,12 +50,20 @@ module Yard2rbs
39
50
 
40
51
  when Prism::ClassNode
41
52
  if node.superclass
42
- output("class #{node.constant_path.name} < #{node.superclass.name}")
53
+ case node.superclass
54
+ when Prism::SelfNode
55
+ output("class #{node.constant_path.name} < ::#{@_superclasses.join("::")}")
56
+ else
57
+ output("class #{node.constant_path.name} < #{node.superclass.name}")
58
+ end
43
59
  else
44
60
  output("class #{node.constant_path.name}")
45
61
  end
62
+
46
63
  @_indent_level += 1
64
+ @_superclasses << node.constant_path.name
47
65
  process(node.compact_child_nodes)
66
+ @_superclasses.pop
48
67
  @_indent_level -= 1
49
68
  output("end")
50
69
 
@@ -56,7 +75,9 @@ module Yard2rbs
56
75
  when Prism::ModuleNode
57
76
  output("module #{node.constant_path.name}")
58
77
  @_indent_level += 1
78
+ @_superclasses << node.constant_path.name
59
79
  process(node.compact_child_nodes)
80
+ @_superclasses.pop
60
81
  @_indent_level -= 1
61
82
  output("end")
62
83
 
@@ -66,10 +87,14 @@ module Yard2rbs
66
87
  output("#{node.name}: #{type}")
67
88
 
68
89
  when Prism::ClassVariableWriteNode
69
- output("#{node.name}: untyped")
90
+ types = parse_comments(node)
91
+ type = format_types(types[:returns])
92
+ output("#{node.name}: #{type}")
70
93
 
71
94
  when Prism::InstanceVariableWriteNode
72
- output("self.#{node.name}: untyped")
95
+ types = parse_comments(node)
96
+ type = format_types(types[:returns])
97
+ output("self.#{node.name}: #{type}")
73
98
 
74
99
  when Prism::DefNode
75
100
  visibility = @_visibility_node&.name
@@ -96,7 +121,7 @@ module Yard2rbs
96
121
 
97
122
  if arg = node.parameters.rest
98
123
  type = format_types(types[:params][arg.name.to_s])
99
- params << "*#{type} #{arg.name}"
124
+ params << "*#{type}"
100
125
  end
101
126
 
102
127
  if node.parameters.keywords
@@ -112,11 +137,19 @@ module Yard2rbs
112
137
 
113
138
  if arg = node.parameters.keyword_rest
114
139
  type = format_types(types[:params][arg.name.to_s])
115
- params << "**#{type} #{arg.name}"
140
+ params << "**#{type}"
116
141
  end
117
142
 
118
143
  if arg = node.parameters.block
119
- block = "{ (?) -> untyped }"
144
+ yieldparams =
145
+ types[:yieldparams].map do |name, types|
146
+ type = format_types(types)
147
+ "#{type} #{name}"
148
+ end
149
+
150
+ return_type = format_types(types[:yieldreturns])
151
+
152
+ block = "{ (#{yieldparams.join(", ")}) -> #{return_type} }"
120
153
  end
121
154
  end
122
155
 
@@ -148,10 +181,12 @@ module Yard2rbs
148
181
  when :attr_accessor, :attr_reader, :attr_writer
149
182
  if node.arguments
150
183
  receiver = "self." if self?(node)
184
+ types = parse_comments(node)
185
+ type = format_types(types[:returns])
151
186
  node.arguments.arguments.each do |arg|
152
187
  output([
153
188
  "#{receiver}#{node.name}",
154
- "#{arg.unescaped}: untyped"
189
+ "#{arg.unescaped}: #{type}"
155
190
  ].compact.join(' '))
156
191
  end
157
192
  end
@@ -211,41 +246,8 @@ module Yard2rbs
211
246
  # @param node [Prism::Node]
212
247
  # @return [Hash]
213
248
  def parse_comments(node)
214
- params = {}
215
- returns = []
216
-
217
- comments = node.location.comments
218
- comments&.each do |comment|
219
- line = comment.slice
220
-
221
- case line
222
- when /@param/
223
- if matches = line.match(/# @param ([^\s]+) \[([^\]]+)\].*/)
224
- types = matches[2].split(',').map(&:strip)
225
- params[matches[1]] = convert_types(types)
226
- end
227
- when /@return/
228
- if matches = line.match(/# @return \[([^\]]+)\].*/)
229
- types = matches[1].split(',').map(&:strip)
230
- returns += convert_types(types)
231
- end
232
- end
233
- end
234
-
235
- {
236
- params: params,
237
- returns: returns,
238
- }
239
- end
240
-
241
- # @param types [String]
242
- # @return [Array<String>]
243
- def convert_types(types)
244
- types.map do |type|
245
- type.
246
- gsub(/Array\<([^>]+)\>/, 'Array[\1]').
247
- gsub(/Hash\<([^>]+),\s*([^>]+)\>/, 'Hash[\1,\2]')
248
- end
249
+ comments = node.location.comments.map(&:slice)
250
+ YardParser.parse(comments)
249
251
  end
250
252
 
251
253
  # @param types [Array<String>]
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Yard2rbs
4
4
  # @return [String]
5
- VERSION = "0.0.1"
5
+ VERSION = "0.0.3"
6
6
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO:
4
+ # * Convert YARD "Boolean" to RBS "bool"
5
+ # * Make some classes top level via :: (e.g. String -> ::String)
6
+
7
+ module Yard2rbs
8
+ class YardParser
9
+ class << self
10
+ # @param comments [Array<String>]
11
+ # @return [Hash<Symbol, Array<String> | Hash<String, String>>]
12
+ def parse(comments)
13
+ params = {}
14
+ returns = []
15
+
16
+ yieldparams = {}
17
+ yieldreturns = []
18
+
19
+ comments&.each do |comment|
20
+ case comment
21
+ when /@param/
22
+ if matches = comment.match(/# @param ([^\s]+) \[([^\]]+)\].*/)
23
+ params[matches[1]] = convert(matches[2])
24
+ end
25
+
26
+ when /@return/
27
+ if matches = comment.match(/# @return \[([^\]]+)\].*/)
28
+ returns += convert(matches[1])
29
+ end
30
+
31
+ when /@yieldparam/
32
+ if matches = comment.match(/# @yieldparam ([^\s]+) \[([^\]]+)\].*/)
33
+ yieldparams[matches[1]] = convert(matches[2])
34
+ end
35
+
36
+ when /@yieldreturn/
37
+ if matches = comment.match(/# @yieldreturn \[([^\]]+)\].*/)
38
+ yieldreturns += convert(matches[1])
39
+ end
40
+ end
41
+ end
42
+
43
+ {
44
+ params:,
45
+ returns:,
46
+
47
+ yieldparams:,
48
+ yieldreturns:,
49
+ }
50
+ end
51
+
52
+ # Converts YARD type string into RBS type array
53
+ # e.g. Input: "String, Array<String>, Hash<String, String>"
54
+ # Output: ["String", "Array[String]", "Hash[String, String]"]
55
+ #
56
+ # @param types_str [String]
57
+ # @return [Array<String>]
58
+ def convert(types_str)
59
+ types = []
60
+
61
+ nested_level = 0
62
+ current_type = []
63
+ types_str.each_char.with_index(1) do |char, index|
64
+ case char
65
+ when ','
66
+ if nested_level > 0
67
+ current_type << char
68
+ else
69
+ types << current_type.join
70
+ current_type = []
71
+ end
72
+ when '<'
73
+ nested_level += 1
74
+ current_type << "["
75
+ when '>'
76
+ nested_level -= 1
77
+ current_type << "]"
78
+ when ' '
79
+ if current_type.any?
80
+ current_type << " "
81
+ end
82
+ else
83
+ current_type << char
84
+ end
85
+
86
+ if index == types_str.size
87
+ types << current_type.join
88
+ end
89
+ end
90
+
91
+ types
92
+ end
93
+ end
94
+ end
95
+ end
data/lib/yard2rbs.rb CHANGED
@@ -1,19 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "yard2rbs/converter"
4
+ require_relative "yard2rbs/yard_parser"
4
5
  require_relative "yard2rbs/version"
5
6
 
6
- require "rbs"
7
-
8
7
  module Yard2rbs
9
8
  class << self
10
9
  # @param file_paths [Array<String>]
11
10
  # @return [Boolean]
12
11
  def convert(file_paths)
13
- # TODO: Clear out rbs/ directory
14
-
15
12
  file_paths.each do |file_path|
16
- output = Converter.new(file_path).convert
13
+ output = Converter.convert(file_path)
17
14
  next if output.empty?
18
15
 
19
16
  input_dirname = File.dirname(file_path)
@@ -1,5 +1,6 @@
1
1
  module Yard2rbs
2
2
  class Converter
3
+ def self.convert: (String input_path) -> String
3
4
  def initialize: (String input_path) -> void
4
5
  def convert: () -> String
5
6
  private
@@ -8,7 +9,6 @@ module Yard2rbs
8
9
  def output: (String str) -> String
9
10
  def self?: (Prism::Node node) -> Boolean
10
11
  def parse_comments: (Prism::Node node) -> Hash
11
- def convert_types: (String types) -> Array[String]
12
12
  def format_types: (Array[String] types) -> String
13
13
  end
14
14
  end
@@ -0,0 +1,6 @@
1
+ module Yard2rbs
2
+ class YardParser
3
+ def self.parse: (Array[String] comments) -> Hash[Symbol, Array[String] | Hash[String, String]]
4
+ def self.convert: (String types_str) -> Array[String]
5
+ end
6
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yard2rbs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kieran Pilkington
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-20 00:00:00.000000000 Z
11
+ date: 2024-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prism
@@ -54,9 +54,11 @@ files:
54
54
  - lib/yard2rbs.rb
55
55
  - lib/yard2rbs/converter.rb
56
56
  - lib/yard2rbs/version.rb
57
+ - lib/yard2rbs/yard_parser.rb
57
58
  - sig/lib/yard2rbs.rbs
58
59
  - sig/lib/yard2rbs/converter.rbs
59
60
  - sig/lib/yard2rbs/version.rbs
61
+ - sig/lib/yard2rbs/yard_parser.rbs
60
62
  homepage:
61
63
  licenses:
62
64
  - MIT