ruby_mod_kit 0.0.4 → 0.0.5

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +89 -0
  3. data/lib/ruby_mod_kit/core_ext/eval.rb +6 -10
  4. data/lib/ruby_mod_kit/corrector.rb +3 -0
  5. data/lib/ruby_mod_kit/corrector_manager.rb +10 -6
  6. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rb +1 -1
  7. data/lib/ruby_mod_kit/feature/overload/overload_mission.rb +2 -3
  8. data/lib/ruby_mod_kit/feature/type/check/arguments/add_arguments_checker_mission.rb +56 -0
  9. data/lib/ruby_mod_kit/feature/type/check/arguments.rb +23 -0
  10. data/lib/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rb +9 -4
  11. data/lib/ruby_mod_kit/feature/type/parameter_arrow_corrector.rb +27 -5
  12. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rb +3 -2
  13. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rb +1 -2
  14. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rb +5 -4
  15. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rb +1 -1
  16. data/lib/ruby_mod_kit/feature/type/return_value_colon_corrector.rb +1 -0
  17. data/lib/ruby_mod_kit/feature/type/type_attr_mission.rb +3 -9
  18. data/lib/ruby_mod_kit/feature/type/yard/type_parameter_mission.rb +35 -0
  19. data/lib/ruby_mod_kit/feature/type/yard/type_return_mission.rb +30 -0
  20. data/lib/ruby_mod_kit/feature/type/yard.rb +31 -0
  21. data/lib/ruby_mod_kit/generation.rb +55 -20
  22. data/lib/ruby_mod_kit/memo/ivar_memo.rb +2 -0
  23. data/lib/ruby_mod_kit/memo/parameter_memo.rb +4 -2
  24. data/lib/ruby_mod_kit/memo_pad.rb +6 -0
  25. data/lib/ruby_mod_kit/mission.rb +0 -4
  26. data/lib/ruby_mod_kit/node/base_node.rb +11 -2
  27. data/lib/ruby_mod_kit/node/begin_node.rb +31 -0
  28. data/lib/ruby_mod_kit/node/parameter_node.rb +2 -2
  29. data/lib/ruby_mod_kit/node/wrap.rb +3 -1
  30. data/lib/ruby_mod_kit/node.rb +1 -0
  31. data/lib/ruby_mod_kit/version.rb +1 -1
  32. data/lib/ruby_mod_kit.rb +0 -5
  33. data/sig/generated/ruby_mod_kit/core_ext/eval.rbs +4 -2
  34. data/sig/generated/ruby_mod_kit/corrector.rbs +3 -0
  35. data/sig/generated/ruby_mod_kit/corrector_manager.rbs +1 -1
  36. data/sig/generated/ruby_mod_kit/feature/type/check/arguments/add_arguments_checker_mission.rbs +16 -0
  37. data/sig/generated/ruby_mod_kit/feature/type/check/arguments.rbs +15 -0
  38. data/sig/generated/ruby_mod_kit/feature/type/parameter_arrow_corrector.rbs +5 -0
  39. data/sig/generated/ruby_mod_kit/feature/type/yard/type_parameter_mission.rbs +16 -0
  40. data/sig/generated/ruby_mod_kit/feature/type/yard/type_return_mission.rbs +16 -0
  41. data/sig/generated/ruby_mod_kit/feature/type/yard.rbs +17 -0
  42. data/sig/generated/ruby_mod_kit/generation.rbs +34 -10
  43. data/sig/generated/ruby_mod_kit/memo/ivar_memo.rbs +4 -0
  44. data/sig/generated/ruby_mod_kit/memo/parameter_memo.rbs +6 -2
  45. data/sig/generated/ruby_mod_kit/memo_pad.rbs +4 -0
  46. data/sig/generated/ruby_mod_kit/mission.rbs +0 -4
  47. data/sig/generated/ruby_mod_kit/node/base_node.rbs +5 -1
  48. data/sig/generated/ruby_mod_kit/node/begin_node.rbs +26 -0
  49. data/sig/generated/ruby_mod_kit/node/parameter_node.rbs +1 -1
  50. metadata +14 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb9b6cf5cb887308d1237eb07d40b4b2b2514173c5e76d19e13a27687f2c107f
4
- data.tar.gz: 418e2d01aec4c8f8b4f0b6241625a0b550aec118a3dbd0618987171bb270e4f7
3
+ metadata.gz: e5888d6187dc2620b37315d72fddee6b134bbd14181277ff600e864eb9c06ca0
4
+ data.tar.gz: 7ffb4ec96c231e6122eeaa7d47601f67a28620951ed08e9d3b3888e9fa684fbc
5
5
  SHA512:
6
- metadata.gz: 17a8efaedb26b0b3256fd0b24501298a1f56fdf4dc8d5c33adc8cb6005abf6c5fcca4c0d1d634b34784dd2528ec57c8d2effdaf4042bc522a15359c86b01b804
7
- data.tar.gz: 73758c1ef48bcb7884a6f37859115b952474084abca4b6560f7d21c5380ec4bece1f97e165e6ef27b8270b0f5209877f5b2b63f1cd408ed5b4b6f5cb517d8dc1
6
+ metadata.gz: 3c2e632593d2d0a7061f8a71a7e65131a1b72434ac3853467024503d13c57328abe88ade105b2532baf94d44bd428bd02b4eae9e0c50462d4dca6bebc767d4f9
7
+ data.tar.gz: 81b17d66702c1fc89c77bc3270f74608fca6ed8e9a12f26c04ea69f7d0bdceb4b91b104bfa45b0f944e5ba5dae79e789de720b8a5605df0d4ac4bb4e48e62d6d
data/README.md CHANGED
@@ -15,6 +15,95 @@ If bundler is not being used to manage dependencies, install the gem by executin
15
15
 
16
16
  ## Usage
17
17
 
18
+ ### as library
19
+
20
+ `RubyModKit.transpile` returns transpiled script.
21
+
22
+ ```
23
+ require "ruby_mod_kit"
24
+ eval(
25
+ RubyModKit.transpile(<<~RBM),
26
+ class Foo
27
+ getter @foo: Integer
28
+ def initialize(@foo)
29
+ end
30
+ end
31
+ RBM
32
+ )
33
+ p Foo.new(1).foo # => 1
34
+ ```
35
+
36
+ `require "ruby_mod_kit/core_ext/eval"` gives `RubyModKit.eval`.
37
+
38
+ ```
39
+ require "ruby_mod_kit/core_ext/eval"
40
+ RubyModKit.eval(<<~RBM)
41
+ class Foo
42
+ getter @foo: Integer
43
+ def initialize(@foo)
44
+ end
45
+ end
46
+ RBM
47
+ p Foo.new(1).foo # => 1
48
+ ```
49
+
50
+ `require "ruby_mod_kit/core_ext/load"` gives `RubyModKit.load` and `RubyModKit.require`.
51
+
52
+ ```
53
+ require "ruby_mod_kit/core_ext/load"
54
+ require "tmpdir"
55
+
56
+ script = <<~RBM
57
+ class Foo
58
+ getter @foo: Integer
59
+ def initialize(@foo)
60
+ end
61
+ end
62
+ RBM
63
+
64
+ Dir.mktmpdir do |tmpdir|
65
+ File.write("#{tmpdir}/some_lib.rbm", script)
66
+ $LOAD_PATH << tmpdir
67
+ RubyModKit.require "some_lib"
68
+ end
69
+
70
+ p Foo.new(1).foo # => 1
71
+ ```
72
+
73
+ And `require "ruby_mod_kit/core_ext"` is more powerfull but dangerous. It overwrites `eval`, `require` and `load`.
74
+
75
+ ```
76
+ require "ruby_mod_kit/core_ext"
77
+ eval(<<~RBM)
78
+ class Foo
79
+ getter @foo: Integer
80
+ def initialize(@foo)
81
+ end
82
+ end
83
+ RBM
84
+ p Foo.new(1).foo # => 1
85
+ ```
86
+
87
+ ```
88
+ require "ruby_mod_kit/core_ext"
89
+ require "tmpdir"
90
+
91
+ script = <<~RBM
92
+ class Foo
93
+ getter @foo: Integer
94
+ def initialize(@foo)
95
+ end
96
+ end
97
+ RBM
98
+
99
+ Dir.mktmpdir do |tmpdir|
100
+ File.write("#{tmpdir}/some_lib.rbm", script)
101
+ $LOAD_PATH << tmpdir
102
+ require "some_lib"
103
+ end
104
+
105
+ p Foo.new(1).foo # => 1
106
+ ```
18
107
  ### as command line tool
19
108
 
20
109
  #### `transpile`
@@ -12,19 +12,15 @@ module RubyModKit
12
12
  module_function
13
13
 
14
14
  # @rbs expr: String
15
- # @rbs *rest: Object
15
+ # @rbs binding: Binding
16
+ # @rbs fname: String
17
+ # @rbs lineno: Integer
16
18
  # @rbs transpile: bool
17
19
  # @rbs return: Object
18
- def eval(expr, *rest, transpile: true)
19
- if transpile
20
- fname = rest[1].is_a?(String) ? rest[1] : "(eval)"
21
- expr = RubyModKit.transpile(expr, filename: fname)
22
- end
20
+ def eval(expr, binding = TOPLEVEL_BINDING, fname = "(eval)", lineno = 1, transpile: true)
21
+ expr = RubyModKit.transpile(expr, filename: fname) if transpile
23
22
 
24
- case rest
25
- in [] | [Binding] | [Binding, String] | [Binding, String, Integer]
26
- super(expr, *rest)
27
- end
23
+ super(expr, binding, fname, lineno)
28
24
  end
29
25
  end
30
26
  end
@@ -16,5 +16,8 @@ module RubyModKit
16
16
  def correct(_parse_error, _generation)
17
17
  raise RubyModKit::Error, "Unexpected type #{self.class}"
18
18
  end
19
+
20
+ # @rbs return: void
21
+ def setup; end
19
22
  end
20
23
  end
@@ -5,13 +5,13 @@
5
5
  module RubyModKit
6
6
  # the class to manege parse error correctors
7
7
  class CorrectorManager
8
- # @rbs @previous_error_messages: Array[String]
8
+ # @rbs @previous_source: String
9
9
  # @rbs @correctors_error_map: Hash[Symbol, Array[Corrector]]
10
10
 
11
11
  # @rbs features: Array[Feature]
12
12
  # @rbs return: void
13
13
  def initialize(features)
14
- @previous_error_messages = []
14
+ @previous_source = +""
15
15
  @correctors_error_map = {}
16
16
  features.each do |feature|
17
17
  feature.create_correctors.each do |corrector|
@@ -28,7 +28,11 @@ module RubyModKit
28
28
  return true if generation.errors.empty?
29
29
 
30
30
  check_prev_errors(generation)
31
- @previous_error_messages = generation.errors.map(&:message)
31
+ @previous_source = generation.script.dup
32
+
33
+ @correctors_error_map.each_value do |correctors|
34
+ correctors.each(&:setup)
35
+ end
32
36
 
33
37
  generation.errors.each do |parse_error|
34
38
  correctors = @correctors_error_map[parse_error.type] || next
@@ -43,16 +47,16 @@ module RubyModKit
43
47
  # @rbs generation: Generation
44
48
  # @rbs return: void
45
49
  def check_prev_errors(generation)
46
- return if @previous_error_messages.empty?
50
+ return if @previous_source.empty?
47
51
  return if generation.errors.empty?
48
- return if @previous_error_messages != generation.errors.map(&:message)
52
+ return if @previous_source != generation.script
49
53
 
50
54
  message = +""
51
55
  generation.errors.each do |parse_error|
52
56
  message << "\n" unless message.empty?
53
57
  message << "#{generation.name}:#{parse_error.location.start_line}:#{parse_error.message} "
54
58
  message << "(#{parse_error.type})"
55
- line = generation.lines[parse_error.location.start_line - 1]
59
+ line = generation.line(parse_error)
56
60
  if line
57
61
  message << "\n#{line.chomp}\n"
58
62
  message << "#{" " * parse_error.location.start_column}^#{"~" * [parse_error.location.length - 1, 0].max}"
@@ -10,7 +10,7 @@ module RubyModKit
10
10
  # @rbs generation: Generation
11
11
  # @rbs return: bool
12
12
  def perform(generation)
13
- generation.memo_pad.parameters_memo.each_value do |parameter_memo|
13
+ generation.memo_pad.each_parameter_memo do |parameter_memo|
14
14
  next unless parameter_memo.ivar_parameter
15
15
 
16
16
  offset = parameter_memo.offset
@@ -37,9 +37,8 @@ module RubyModKit
37
37
  raise RubyModKit::Error unless first_def_node.is_a?(Node::DefNode)
38
38
  raise RubyModKit::Error unless name.is_a?(Symbol)
39
39
 
40
- start_line = first_def_node.location.start_line - 1
41
- indent = generation.lines[start_line][/\A */] || ""
42
- src_offset = generation.offsets[start_line]
40
+ indent = generation.line_indent(first_def_node)
41
+ src_offset = generation.line_offset(first_def_node) || raise(RubyModKit::Error)
43
42
  script = +""
44
43
 
45
44
  overload_memo = generation.memo_pad.overload_memo(first_method_memo.offset, name)
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ module Check
9
+ # The mission to add magic comment
10
+ class AddArgumentsCheckerMission < Mission
11
+ # @rbs generation: Generation
12
+ # @rbs return: bool
13
+ def perform(generation)
14
+ # reload if line break is added
15
+ line_break_added = false
16
+
17
+ generation.memo_pad.methods_memo.each do |offset, method_memo|
18
+ def_node = generation.root_node.def_node_at(offset)
19
+ raise RubyModKit::Error, "DefNode not found" unless def_node
20
+ next if method_memo.parameters.empty?
21
+
22
+ def_line = generation.line(def_node.location.start_line - 1)
23
+ def_indent = def_line[/\A\s*/] || ""
24
+
25
+ location = def_node.body_location || def_node.end_keyword_loc
26
+ next unless location
27
+
28
+ def_right_loc = def_node.rparen_loc || def_node.name_loc
29
+ offset = location.start_offset - location.start_column
30
+ indent = "#{def_indent} "
31
+ if location.start_line == def_right_loc.end_line
32
+ between_def_and_loc = generation[def_right_loc.end_offset...location.start_offset]
33
+ length = between_def_and_loc[/\A[ ^t]*;[ ^t]*\z/]&.length
34
+ if length
35
+ line_break_added = true
36
+ generation[def_right_loc.end_offset, length] = "\n#{def_indent}"
37
+ end
38
+ end
39
+ next if line_break_added
40
+
41
+ method_memo.parameters.each do |parameter_memo|
42
+ next if parameter_memo.untyped? || !parameter_memo.name
43
+ next if parameter_memo.qualifier # TODO: qualifier support
44
+
45
+ type = parameter_memo.type
46
+ type = type.gsub(/\[([^\[\]]+)\]/, "") # TODO: type variable support
47
+ generation[offset, 0] = "#{indent}#{parameter_memo.name} => #{type}\n"
48
+ end
49
+ end
50
+ !line_break_added
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ module Check
9
+ # namespace for arguments type checker
10
+ class Arguments < Feature
11
+ # @rbs return: Array[Mission]
12
+ def create_missions
13
+ [
14
+ AddArgumentsCheckerMission.new,
15
+ ]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ require_relative "arguments/add_arguments_checker_mission"
@@ -9,7 +9,7 @@ module RubyModKit
9
9
  class InstanceVariableColonCorrector < Corrector
10
10
  VISIBILITIES = %i[private public protected].freeze #: Array[Symbol]
11
11
  ATTR_PATTERNS = %i[attr_reader reader getter attr_writer writer setter attr_accessor accessor property].freeze #: Array[Symbol]
12
- REGEXP = /(\A\s*)(?:(#{VISIBILITIES.join("|")}) )?(?:(#{ATTR_PATTERNS.join("|")}) )?@(\w*)\s*:\s*(.*)\n/.freeze #: Regexp
12
+ REGEXP = /(\A\s*)(?:(#{VISIBILITIES.join("|")}) )?(?:(#{ATTR_PATTERNS.join("|")}) )?@(\w*)\s*:\s*(.*)\n(\n+)?/.freeze #: Regexp
13
13
 
14
14
  # @rbs return: Array[Symbol]
15
15
  def correctable_error_types
@@ -22,11 +22,14 @@ module RubyModKit
22
22
  def correct(parse_error, generation)
23
23
  return if parse_error.location.slice != ":"
24
24
 
25
- def_parent_node = generation.root_node.statements_node_at(parse_error.location.start_offset)&.parent
25
+ def_parent_node = generation.root_node.def_parent_node_at(
26
+ parse_error.location.start_offset,
27
+ allowed: [Node::CallNode, Node::UntypedNode, Node::StatementsNode],
28
+ )
26
29
  return unless def_parent_node.is_a?(Node::DefParentNode)
27
30
 
28
- line = generation.line(parse_error)
29
- line_offset = generation.src_offset(parse_error) || return
31
+ line_offset = generation.line_offset(parse_error) || return
32
+ line = generation[line_offset..]
30
33
  return if line !~ REGEXP
31
34
 
32
35
  length = ::Regexp.last_match(0)&.length
@@ -35,6 +38,7 @@ module RubyModKit
35
38
  attr_kind = ::Regexp.last_match(3)
36
39
  ivar_name = ::Regexp.last_match(4)
37
40
  type = ::Regexp.last_match(5)
41
+ separator = ::Regexp.last_match(6)
38
42
  return if !length || !indent || !ivar_name || !type
39
43
 
40
44
  ivar_memo = generation.memo_pad.def_parent_memo(def_parent_node).ivar_memo(ivar_name.to_sym)
@@ -43,6 +47,7 @@ module RubyModKit
43
47
  ivar_memo.indent = indent
44
48
  ivar_memo.attr_kind = attr_kind if attr_kind
45
49
  ivar_memo.visibility = visibility.to_sym if visibility
50
+ ivar_memo.separator = separator if separator
46
51
 
47
52
  generation[line_offset, length] = ""
48
53
  end
@@ -7,11 +7,19 @@ module RubyModKit
7
7
  class Type
8
8
  # the class to correct `def foo(Bar => bar, *Buz => buz)` -> `def foo(bar, *buz)`
9
9
  class ParameterArrowCorrector < Corrector
10
+ # @rbs @last_parameter_offsets: Set[Integer]
11
+
10
12
  # @rbs return: Array[Symbol]
11
13
  def correctable_error_types
12
14
  %i[unexpected_token_ignore def_params_term_paren argument_formal_constant]
13
15
  end
14
16
 
17
+ # @rbs return: void
18
+ def setup
19
+ super
20
+ @last_parameter_offsets = Set.new
21
+ end
22
+
15
23
  # @rbs parse_error: Prism::ParseError
16
24
  # @rbs generation: Generation
17
25
  # @rbs return: void
@@ -35,17 +43,29 @@ module RubyModKit
35
43
  def_node = generation.root_node.def_node_at(parse_error.location.start_offset) || return
36
44
  def_parent_node = def_node.parent
37
45
  parameters_node, body_node, = def_node.children
46
+ body_node = body_node.children[0] if body_node.is_a?(Node::BeginNode)
38
47
  return if !def_parent_node || !parameters_node || !body_node
39
48
 
40
49
  last_parameter_node = parameters_node.children.max_by(&:offset) || return
41
50
  last_parameter_offset = last_parameter_node.offset
51
+ return if @last_parameter_offsets.include?(last_parameter_offset)
42
52
 
53
+ @last_parameter_offsets << last_parameter_offset
43
54
  right_node = body_node.children.find { _1.offset >= parse_error.location.end_offset } || return
44
55
  right_offset = right_node.offset
56
+ name = right_node.slice[/\A\w+/]
45
57
  parameter_type = generation[last_parameter_offset...right_offset] || raise(RubyModKit::Error)
46
58
  parameter_type = parameter_type.sub(/\s*=>\s*\z/, "")
47
- generation[last_parameter_offset, right_offset - last_parameter_offset] = ""
48
- generation.memo_pad.parameter_memo(last_parameter_node).type = parameter_type
59
+ qualifier = nil
60
+ parameter_type = parameter_type.sub(/\A&\(\((.*)\) *: +(.*)\)\z/) do
61
+ qualifier = "&"
62
+ "(#{::Regexp.last_match(1)}) -> #{::Regexp.last_match(2)}"
63
+ end
64
+ generation[last_parameter_offset, right_offset - last_parameter_offset] = qualifier.to_s
65
+ parameter_memo = generation.memo_pad.parameter_memo(last_parameter_node)
66
+ parameter_memo.name = name.to_sym if name
67
+ parameter_memo.type = parameter_type
68
+ parameter_memo.qualifier = qualifier if qualifier
49
69
  end
50
70
 
51
71
  # @rbs parse_error: Prism::ParseError
@@ -56,15 +76,17 @@ module RubyModKit
56
76
  return if column < 0
57
77
 
58
78
  line = generation.line(parse_error)[column..] || return
59
- line =~ /\A\*(.*?)\s*=>\s*/
60
- length = ::Regexp.last_match(0)&.length || return
61
- type = ::Regexp.last_match(1) || return
79
+ line =~ /(\A\*(.*?)\s*=>\s*)(\w*)/
80
+ length = ::Regexp.last_match(1)&.length || return
81
+ type = ::Regexp.last_match(2) || return
82
+ name = ::Regexp.last_match(3)
62
83
  offset = parse_error.location.start_offset - 1
63
84
  parameter_position_node = generation.root_node.node_at(offset + length) || return
64
85
 
65
86
  generation[parse_error.location.start_offset, length - 1] = ""
66
87
  parameter_memo = generation.memo_pad.parameter_memo(parameter_position_node)
67
88
  parameter_memo.type = type
89
+ parameter_memo.name = name.to_sym if name
68
90
  parameter_memo.qualifier = "*"
69
91
  end
70
92
 
@@ -15,9 +15,10 @@ module RubyModKit
15
15
  def_parent_memo.ivars_memo.each do |name, ivar_memo|
16
16
  offset = ivar_memo.offset || next
17
17
  def_parent_node = generation.root_node.def_parent_node_at(offset) || next
18
- body_line_offset = generation.offsets[def_parent_node.location.start_line]
18
+ body_line_offset = generation.line_offset(def_parent_node, 1) || next
19
19
  generation.memo_pad.flags[:rbs_annotated] = true
20
- generation[body_line_offset, 0] = "#{ivar_memo.indent}# @rbs @#{name}: #{ivar_memo.type}\n"
20
+ script = "#{ivar_memo.indent}# @rbs @#{name}: #{ivar_memo.type}\n#{ivar_memo.separator}"
21
+ generation[body_line_offset, 0] = script
21
22
  end
22
23
  end
23
24
  true
@@ -15,8 +15,7 @@ module RubyModKit
15
15
  overload_memo.correct_offset(generation.root_node)
16
16
  offset = overload_memo.offset
17
17
  def_node = generation.root_node.def_node_at(offset) || raise(RubyModKit::Error)
18
- start_line = def_node.location.start_line - 1
19
- indent = generation.lines[start_line][/\A */] || ""
18
+ indent = generation.line_indent(def_node)
20
19
  offset -= indent.length
21
20
 
22
21
  annotation = +""
@@ -11,21 +11,22 @@ module RubyModKit
11
11
  # @rbs generation: Generation
12
12
  # @rbs return: bool
13
13
  def perform(generation)
14
- generation.memo_pad.parameters_memo.each do |offset, parameter_memo|
14
+ generation.memo_pad.each_parameter_memo do |parameter_memo|
15
15
  next if parameter_memo.untyped?
16
16
 
17
+ offset = parameter_memo.offset
17
18
  def_node = generation.root_node.def_node_at(offset)
18
19
  raise RubyModKit::Error, "DefNode not found" if !def_node || !def_node.is_a?(Node::DefNode)
19
20
 
20
21
  parameter_node = generation.root_node.parameter_node_at(offset)
21
22
  raise RubyModKit::Error, "ParameterNode not found" unless parameter_node
22
23
 
24
+ line_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
23
25
  type = parameter_memo.type
24
- src_offset = generation.offsets[def_node.location.start_line - 1]
25
- indent = def_node.offset - src_offset
26
+ indent = generation.line_indent(def_node)
26
27
  qualified_name = "#{parameter_memo.qualifier}#{parameter_node.name}"
27
28
  generation.memo_pad.flags[:rbs_annotated] = true
28
- generation[src_offset, 0] = "#{" " * indent}# @rbs #{qualified_name}: #{type}\n"
29
+ generation[line_offset, 0] = "#{indent}# @rbs #{qualified_name}: #{type}\n"
29
30
  end
30
31
  true
31
32
  end
@@ -16,7 +16,7 @@ module RubyModKit
16
16
  raise RubyModKit::Error, "DefNode not found" if !def_node || !def_node.is_a?(Node::DefNode)
17
17
  next if method_memo.untyped?
18
18
 
19
- src_offset = generation.offsets[def_node.location.start_line - 1]
19
+ src_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
20
20
  indent = offset - src_offset
21
21
  generation.memo_pad.flags[:rbs_annotated] = true
22
22
  generation[src_offset, 0] = "#{" " * indent}# @rbs return: #{method_memo.type}\n"
@@ -19,6 +19,7 @@ module RubyModKit
19
19
  return if parse_error.location.slice != ":"
20
20
 
21
21
  def_node = generation.root_node.statements_node_at(parse_error.location.start_offset)&.parent
22
+ def_node = def_node.parent if def_node.is_a?(Node::BeginNode)
22
23
  return unless def_node.is_a?(Node::DefNode)
23
24
 
24
25
  lparen_loc = def_node.lparen_loc
@@ -29,19 +29,13 @@ module RubyModKit
29
29
  ivars_memo.keep_if { |_, ivar_memo| ivar_memo.attr_kind }
30
30
  next if ivars_memo.empty?
31
31
 
32
- add_first_separator_line = false
33
32
  if attr_adding_line == 0
34
33
  attr_adding_line = def_parent_node.location.start_line
35
- prev_line = nil
36
- while generation.line(attr_adding_line) =~ /\A\s*#.*|\A$/
37
- prev_line = ::Regexp.last_match(0)
38
- attr_adding_line += 1
39
- end
40
- add_first_separator_line = prev_line != ""
34
+ attr_adding_line += 1 while generation.line(attr_adding_line) =~ /\A\s*#.*|\A$/
41
35
  end
42
36
  line = generation.line(attr_adding_line) || next
43
37
  add_separator_line = line != "\n" && line !~ /\A\s*end$/
44
- offset = generation.src_offset(attr_adding_line) || next
38
+ offset = generation.line_offset(attr_adding_line) || next
45
39
 
46
40
  body_node = def_parent_node.body_node
47
41
  if body_node
@@ -50,9 +44,9 @@ module RubyModKit
50
44
  else
51
45
  def_parent_line = generation.line(def_parent_node)
52
46
  indent = " #{def_parent_line[/\A\s*/]}"
47
+ generation[offset, 0] = "\n"
53
48
  end
54
49
 
55
- generation[offset, 0] = "\n" if add_first_separator_line
56
50
  ivars_memo.each do |name, ivar_memo|
57
51
  attr = ivar_memo.attr_kind
58
52
  attr = "#{ivar_memo.visibility} #{attr}" if ivar_memo.visibility
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ class Yard
9
+ # The mission for parameter types
10
+ class TypeParameterMission < Mission
11
+ # @rbs generation: Generation
12
+ # @rbs return: bool
13
+ def perform(generation)
14
+ generation.memo_pad.each_parameter_memo do |parameter_memo|
15
+ next if parameter_memo.untyped?
16
+
17
+ offset = parameter_memo.offset
18
+ def_node = generation.root_node.def_node_at(offset)
19
+ raise RubyModKit::Error, "DefNode not found" if !def_node || !def_node.is_a?(Node::DefNode)
20
+
21
+ parameter_node = generation.root_node.parameter_node_at(offset)
22
+ raise RubyModKit::Error, "ParameterNode not found" unless parameter_node
23
+
24
+ line_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
25
+ indent = generation.line_indent(def_node)
26
+ script = "#{indent}# @param #{parameter_node.name} [#{Yard.rbs2yard(parameter_memo.type)}]\n"
27
+ generation[line_offset, 0] = script
28
+ end
29
+ true
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ class Yard
9
+ # The mission for return value type
10
+ class TypeReturnMission < Mission
11
+ # @rbs generation: Generation
12
+ # @rbs return: bool
13
+ def perform(generation)
14
+ generation.memo_pad.methods_memo.each do |offset, method_memo|
15
+ def_node = generation.root_node.def_node_at(offset)
16
+ raise RubyModKit::Error, "DefNode not found" if !def_node || !def_node.is_a?(Node::DefNode)
17
+ next if method_memo.untyped?
18
+
19
+ src_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
20
+ indent = offset - src_offset
21
+ generation.memo_pad.flags[:rbs_annotated] = true
22
+ generation[src_offset, 0] = "#{" " * indent}# @return [#{Yard.rbs2yard(method_memo.type)}]\n"
23
+ end
24
+ true
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ # namespace for type with rbs-line feature
9
+ class Yard < Feature
10
+ # @rbs return: Array[Mission]
11
+ def create_missions
12
+ [
13
+ TypeParameterMission.new,
14
+ TypeReturnMission.new,
15
+ ]
16
+ end
17
+
18
+ class << self
19
+ # @rbs type: String
20
+ # @rbs return: String
21
+ def rbs2yard(type)
22
+ type.gsub(/\s*\|\s*/, ", ").tr("[]", "<>").gsub(/(?<=^|\W)bool(?=$|\W)/, "Boolean")
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ require_relative "yard/type_parameter_mission"
31
+ require_relative "yard/type_return_mission"