ruby_mod_kit 0.0.4 → 0.0.6

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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby_mod_kit.yml +1 -0
  3. data/.yardopts +3 -0
  4. data/README.md +89 -0
  5. data/examples/user.rb +4 -16
  6. data/lib/ruby_mod_kit/cli.rb +5 -0
  7. data/lib/ruby_mod_kit/config.rb +6 -1
  8. data/lib/ruby_mod_kit/core_ext/eval.rb +13 -10
  9. data/lib/ruby_mod_kit/core_ext/load.rb +10 -0
  10. data/lib/ruby_mod_kit/corrector.rb +8 -0
  11. data/lib/ruby_mod_kit/corrector_manager.rb +16 -6
  12. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_corrector.rb +4 -0
  13. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rb +3 -1
  14. data/lib/ruby_mod_kit/feature/instance_variable_parameter.rb +2 -0
  15. data/lib/ruby_mod_kit/feature/overload/overload_mission.rb +44 -13
  16. data/lib/ruby_mod_kit/feature/overload.rb +1 -0
  17. data/lib/ruby_mod_kit/feature/type/check/arguments/add_arguments_checker_mission.rb +58 -0
  18. data/lib/ruby_mod_kit/feature/type/check/arguments.rb +25 -0
  19. data/lib/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rb +13 -4
  20. data/lib/ruby_mod_kit/feature/type/parameter_arrow_corrector.rb +41 -5
  21. data/lib/ruby_mod_kit/feature/type/rbs_inline/add_magic_comment_mission.rb +3 -0
  22. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_attr_mission.rb +2 -0
  23. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rb +5 -2
  24. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rb +3 -2
  25. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rb +7 -4
  26. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rb +3 -1
  27. data/lib/ruby_mod_kit/feature/type/rbs_inline.rb +1 -0
  28. data/lib/ruby_mod_kit/feature/type/return_value_colon_corrector.rb +5 -0
  29. data/lib/ruby_mod_kit/feature/type/type_attr_mission.rb +6 -9
  30. data/lib/ruby_mod_kit/feature/type/yard/type_parameter_mission.rb +37 -0
  31. data/lib/ruby_mod_kit/feature/type/yard/type_return_mission.rb +32 -0
  32. data/lib/ruby_mod_kit/feature/type/yard.rb +34 -0
  33. data/lib/ruby_mod_kit/feature/type.rb +2 -0
  34. data/lib/ruby_mod_kit/feature.rb +2 -0
  35. data/lib/ruby_mod_kit/generation.rb +67 -49
  36. data/lib/ruby_mod_kit/memo/def_parent_memo.rb +6 -0
  37. data/lib/ruby_mod_kit/memo/ivar_memo.rb +18 -8
  38. data/lib/ruby_mod_kit/memo/method_memo.rb +8 -1
  39. data/lib/ruby_mod_kit/memo/offset_memo.rb +4 -0
  40. data/lib/ruby_mod_kit/memo/overload_memo.rb +9 -1
  41. data/lib/ruby_mod_kit/memo/parameter_memo.rb +10 -3
  42. data/lib/ruby_mod_kit/memo_pad.rb +34 -0
  43. data/lib/ruby_mod_kit/mission.rb +2 -4
  44. data/lib/ruby_mod_kit/node/base_node.rb +43 -3
  45. data/lib/ruby_mod_kit/node/begin_node.rb +35 -0
  46. data/lib/ruby_mod_kit/node/call_node.rb +4 -0
  47. data/lib/ruby_mod_kit/node/def_node.rb +36 -0
  48. data/lib/ruby_mod_kit/node/def_parent_node.rb +10 -2
  49. data/lib/ruby_mod_kit/node/parameter_node.rb +7 -2
  50. data/lib/ruby_mod_kit/node/program_node.rb +3 -0
  51. data/lib/ruby_mod_kit/node/statements_node.rb +4 -0
  52. data/lib/ruby_mod_kit/node/symbol_node.rb +7 -2
  53. data/lib/ruby_mod_kit/node/untyped_node.rb +4 -0
  54. data/lib/ruby_mod_kit/node/wrap.rb +7 -1
  55. data/lib/ruby_mod_kit/node.rb +1 -0
  56. data/lib/ruby_mod_kit/offset_diff.rb +6 -0
  57. data/lib/ruby_mod_kit/version.rb +1 -1
  58. data/lib/ruby_mod_kit.rb +29 -8
  59. data/sig/generated/ruby_mod_kit/cli.rbs +5 -0
  60. data/sig/generated/ruby_mod_kit/config.rbs +7 -2
  61. data/sig/generated/ruby_mod_kit/core_ext/eval.rbs +11 -2
  62. data/sig/generated/ruby_mod_kit/core_ext/load.rbs +10 -0
  63. data/sig/generated/ruby_mod_kit/corrector.rbs +8 -0
  64. data/sig/generated/ruby_mod_kit/corrector_manager.rbs +7 -1
  65. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_corrector.rbs +4 -0
  66. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rbs +2 -0
  67. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter.rbs +2 -0
  68. data/sig/generated/ruby_mod_kit/feature/overload/overload_mission.rbs +3 -0
  69. data/sig/generated/ruby_mod_kit/feature/overload.rbs +1 -0
  70. data/sig/generated/ruby_mod_kit/feature/type/check/arguments/add_arguments_checker_mission.rbs +18 -0
  71. data/sig/generated/ruby_mod_kit/feature/type/check/arguments.rbs +17 -0
  72. data/sig/generated/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rbs +4 -0
  73. data/sig/generated/ruby_mod_kit/feature/type/parameter_arrow_corrector.rbs +19 -0
  74. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/add_magic_comment_mission.rbs +3 -0
  75. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_attr_mission.rbs +2 -0
  76. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rbs +2 -0
  77. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rbs +2 -0
  78. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rbs +2 -0
  79. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rbs +2 -0
  80. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline.rbs +1 -0
  81. data/sig/generated/ruby_mod_kit/feature/type/return_value_colon_corrector.rbs +4 -0
  82. data/sig/generated/ruby_mod_kit/feature/type/type_attr_mission.rbs +3 -0
  83. data/sig/generated/ruby_mod_kit/feature/type/yard/type_parameter_mission.rbs +18 -0
  84. data/sig/generated/ruby_mod_kit/feature/type/yard/type_return_mission.rbs +18 -0
  85. data/sig/generated/ruby_mod_kit/feature/type/yard.rbs +20 -0
  86. data/sig/generated/ruby_mod_kit/feature/type.rbs +2 -0
  87. data/sig/generated/ruby_mod_kit/feature.rbs +2 -0
  88. data/sig/generated/ruby_mod_kit/generation.rbs +46 -25
  89. data/sig/generated/ruby_mod_kit/memo/def_parent_memo.rbs +6 -0
  90. data/sig/generated/ruby_mod_kit/memo/ivar_memo.rbs +20 -8
  91. data/sig/generated/ruby_mod_kit/memo/method_memo.rbs +8 -1
  92. data/sig/generated/ruby_mod_kit/memo/offset_memo.rbs +4 -0
  93. data/sig/generated/ruby_mod_kit/memo/overload_memo.rbs +8 -0
  94. data/sig/generated/ruby_mod_kit/memo/parameter_memo.rbs +12 -3
  95. data/sig/generated/ruby_mod_kit/memo_pad.rbs +23 -0
  96. data/sig/generated/ruby_mod_kit/mission.rbs +2 -4
  97. data/sig/generated/ruby_mod_kit/node/base_node.rbs +36 -3
  98. data/sig/generated/ruby_mod_kit/node/begin_node.rbs +30 -0
  99. data/sig/generated/ruby_mod_kit/node/call_node.rbs +4 -0
  100. data/sig/generated/ruby_mod_kit/node/def_node.rbs +24 -0
  101. data/sig/generated/ruby_mod_kit/node/def_parent_node.rbs +11 -3
  102. data/sig/generated/ruby_mod_kit/node/parameter_node.rbs +6 -1
  103. data/sig/generated/ruby_mod_kit/node/program_node.rbs +3 -0
  104. data/sig/generated/ruby_mod_kit/node/statements_node.rbs +4 -0
  105. data/sig/generated/ruby_mod_kit/node/symbol_node.rbs +8 -3
  106. data/sig/generated/ruby_mod_kit/node/untyped_node.rbs +4 -0
  107. data/sig/generated/ruby_mod_kit/node/wrap.rbs +4 -0
  108. data/sig/generated/ruby_mod_kit/offset_diff.rbs +6 -0
  109. data/sig/generated/ruby_mod_kit.rbs +31 -6
  110. metadata +15 -2
@@ -7,14 +7,27 @@ 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]
13
+ # @return [Array<Symbol>]
11
14
  def correctable_error_types
12
15
  %i[unexpected_token_ignore def_params_term_paren argument_formal_constant]
13
16
  end
14
17
 
18
+ # @rbs return: void
19
+ # @return [void]
20
+ def setup
21
+ super
22
+ @last_parameter_offsets = Set.new
23
+ end
24
+
15
25
  # @rbs parse_error: Prism::ParseError
16
26
  # @rbs generation: Generation
17
27
  # @rbs return: void
28
+ # @param parse_error [Prism::ParseError]
29
+ # @param generation [Generation]
30
+ # @return [void]
18
31
  def correct(parse_error, generation)
19
32
  case parse_error.type
20
33
  when :unexpected_token_ignore
@@ -31,46 +44,69 @@ module RubyModKit
31
44
  # @rbs parse_error: Prism::ParseError
32
45
  # @rbs generation: Generation
33
46
  # @rbs return: void
47
+ # @param parse_error [Prism::ParseError]
48
+ # @param generation [Generation]
49
+ # @return [void]
34
50
  def remove_arrow_before_parameter(parse_error, generation)
35
51
  def_node = generation.root_node.def_node_at(parse_error.location.start_offset) || return
36
52
  def_parent_node = def_node.parent
37
53
  parameters_node, body_node, = def_node.children
54
+ body_node = body_node.children[0] if body_node.is_a?(Node::BeginNode)
38
55
  return if !def_parent_node || !parameters_node || !body_node
39
56
 
40
57
  last_parameter_node = parameters_node.children.max_by(&:offset) || return
41
58
  last_parameter_offset = last_parameter_node.offset
59
+ return if @last_parameter_offsets.include?(last_parameter_offset)
42
60
 
61
+ @last_parameter_offsets << last_parameter_offset
43
62
  right_node = body_node.children.find { _1.offset >= parse_error.location.end_offset } || return
44
63
  right_offset = right_node.offset
64
+ name = right_node.slice[/\A\w+/]
45
65
  parameter_type = generation[last_parameter_offset...right_offset] || raise(RubyModKit::Error)
46
66
  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
67
+ qualifier = nil
68
+ parameter_type = parameter_type.sub(/\A&\(\((.*)\) *: +(.*)\)\z/) do
69
+ qualifier = "&"
70
+ "(#{::Regexp.last_match(1)}) -> #{::Regexp.last_match(2)}"
71
+ end
72
+ generation[last_parameter_offset, right_offset - last_parameter_offset] = qualifier.to_s
73
+ parameter_memo = generation.memo_pad.parameter_memo(last_parameter_node)
74
+ parameter_memo.name = name.to_sym if name
75
+ parameter_memo.type = parameter_type
76
+ parameter_memo.qualifier = qualifier if qualifier
49
77
  end
50
78
 
51
79
  # @rbs parse_error: Prism::ParseError
52
80
  # @rbs generation: Generation
53
81
  # @rbs return: void
82
+ # @param parse_error [Prism::ParseError]
83
+ # @param generation [Generation]
84
+ # @return [void]
54
85
  def remove_arrow_after_quailifier(parse_error, generation)
55
86
  column = parse_error.location.start_column - 1
56
87
  return if column < 0
57
88
 
58
89
  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
90
+ line =~ /(\A\*(.*?)\s*=>\s*)(\w*)/
91
+ length = ::Regexp.last_match(1)&.length || return
92
+ type = ::Regexp.last_match(2) || return
93
+ name = ::Regexp.last_match(3)
62
94
  offset = parse_error.location.start_offset - 1
63
95
  parameter_position_node = generation.root_node.node_at(offset + length) || return
64
96
 
65
97
  generation[parse_error.location.start_offset, length - 1] = ""
66
98
  parameter_memo = generation.memo_pad.parameter_memo(parameter_position_node)
67
99
  parameter_memo.type = type
100
+ parameter_memo.name = name.to_sym if name
68
101
  parameter_memo.qualifier = "*"
69
102
  end
70
103
 
71
104
  # @rbs parse_error: Prism::ParseError
72
105
  # @rbs generation: Generation
73
106
  # @rbs return: void
107
+ # @param parse_error [Prism::ParseError]
108
+ # @param generation [Generation]
109
+ # @return [void]
74
110
  def wrap_parameter_type_for_next_parse(parse_error, generation)
75
111
  line = generation.line(parse_error)
76
112
  line = line[parse_error.location.start_column..] || return
@@ -11,6 +11,7 @@ module RubyModKit
11
11
  # @rbs @reloaded: bool
12
12
 
13
13
  # @rbs return: void
14
+ # @return [void]
14
15
  def initialize
15
16
  super
16
17
  @reloaded = false
@@ -18,6 +19,8 @@ module RubyModKit
18
19
 
19
20
  # @rbs generation: Generation
20
21
  # @rbs return: bool
22
+ # @param generation [Generation]
23
+ # @return [Boolean]
21
24
  def perform(generation)
22
25
  return true unless generation.memo_pad.flags[:rbs_annotated]
23
26
 
@@ -10,6 +10,8 @@ module RubyModKit
10
10
  class TypeAttrMission < Mission
11
11
  # @rbs generation: Generation
12
12
  # @rbs return: bool
13
+ # @param generation [Generation]
14
+ # @return [Boolean]
13
15
  def perform(generation)
14
16
  generation.memo_pad.def_parents_memo.each_value do |def_parent_memo|
15
17
  ivars_memo = def_parent_memo.ivars_memo.dup
@@ -10,14 +10,17 @@ module RubyModKit
10
10
  class TypeInstanceVariableMission < Mission
11
11
  # @rbs generation: Generation
12
12
  # @rbs return: bool
13
+ # @param generation [Generation]
14
+ # @return [Boolean]
13
15
  def perform(generation)
14
16
  generation.memo_pad.def_parents_memo.each_value do |def_parent_memo|
15
17
  def_parent_memo.ivars_memo.each do |name, ivar_memo|
16
18
  offset = ivar_memo.offset || next
17
19
  def_parent_node = generation.root_node.def_parent_node_at(offset) || next
18
- body_line_offset = generation.offsets[def_parent_node.location.start_line]
20
+ body_line_offset = generation.line_offset(def_parent_node, 1) || next
19
21
  generation.memo_pad.flags[:rbs_annotated] = true
20
- generation[body_line_offset, 0] = "#{ivar_memo.indent}# @rbs @#{name}: #{ivar_memo.type}\n"
22
+ script = "#{ivar_memo.indent}# @rbs @#{name}: #{ivar_memo.type}\n#{ivar_memo.separator}"
23
+ generation[body_line_offset, 0] = script
21
24
  end
22
25
  end
23
26
  true
@@ -10,13 +10,14 @@ module RubyModKit
10
10
  class TypeOverloadMission < Mission
11
11
  # @rbs generation: Generation
12
12
  # @rbs return: bool
13
+ # @param generation [Generation]
14
+ # @return [Boolean]
13
15
  def perform(generation)
14
16
  generation.memo_pad.overloads_memo.each_value do |overload_memo|
15
17
  overload_memo.correct_offset(generation.root_node)
16
18
  offset = overload_memo.offset
17
19
  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 */] || ""
20
+ indent = generation.line_indent(def_node)
20
21
  offset -= indent.length
21
22
 
22
23
  annotation = +""
@@ -10,22 +10,25 @@ module RubyModKit
10
10
  class TypeParameterMission < Mission
11
11
  # @rbs generation: Generation
12
12
  # @rbs return: bool
13
+ # @param generation [Generation]
14
+ # @return [Boolean]
13
15
  def perform(generation)
14
- generation.memo_pad.parameters_memo.each do |offset, parameter_memo|
16
+ generation.memo_pad.each_parameter_memo do |parameter_memo|
15
17
  next if parameter_memo.untyped?
16
18
 
19
+ offset = parameter_memo.offset
17
20
  def_node = generation.root_node.def_node_at(offset)
18
21
  raise RubyModKit::Error, "DefNode not found" if !def_node || !def_node.is_a?(Node::DefNode)
19
22
 
20
23
  parameter_node = generation.root_node.parameter_node_at(offset)
21
24
  raise RubyModKit::Error, "ParameterNode not found" unless parameter_node
22
25
 
26
+ line_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
23
27
  type = parameter_memo.type
24
- src_offset = generation.offsets[def_node.location.start_line - 1]
25
- indent = def_node.offset - src_offset
28
+ indent = generation.line_indent(def_node)
26
29
  qualified_name = "#{parameter_memo.qualifier}#{parameter_node.name}"
27
30
  generation.memo_pad.flags[:rbs_annotated] = true
28
- generation[src_offset, 0] = "#{" " * indent}# @rbs #{qualified_name}: #{type}\n"
31
+ generation[line_offset, 0] = "#{indent}# @rbs #{qualified_name}: #{type}\n"
29
32
  end
30
33
  true
31
34
  end
@@ -10,13 +10,15 @@ module RubyModKit
10
10
  class TypeReturnMission < Mission
11
11
  # @rbs generation: Generation
12
12
  # @rbs return: bool
13
+ # @param generation [Generation]
14
+ # @return [Boolean]
13
15
  def perform(generation)
14
16
  generation.memo_pad.methods_memo.each do |offset, method_memo|
15
17
  def_node = generation.root_node.def_node_at(offset)
16
18
  raise RubyModKit::Error, "DefNode not found" if !def_node || !def_node.is_a?(Node::DefNode)
17
19
  next if method_memo.untyped?
18
20
 
19
- src_offset = generation.offsets[def_node.location.start_line - 1]
21
+ src_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
20
22
  indent = offset - src_offset
21
23
  generation.memo_pad.flags[:rbs_annotated] = true
22
24
  generation[src_offset, 0] = "#{" " * indent}# @rbs return: #{method_memo.type}\n"
@@ -8,6 +8,7 @@ module RubyModKit
8
8
  # namespace for type with rbs-line feature
9
9
  class RbsInline < Feature
10
10
  # @rbs return: Array[Mission]
11
+ # @return [Array<Mission>]
11
12
  def create_missions
12
13
  [
13
14
  TypeInstanceVariableMission.new,
@@ -8,6 +8,7 @@ module RubyModKit
8
8
  # the class to correct `def foo: Some ...` -> `def foo ...`
9
9
  class ReturnValueColonCorrector < Corrector
10
10
  # @rbs return: Array[Symbol]
11
+ # @return [Array<Symbol>]
11
12
  def correctable_error_types
12
13
  %i[unexpected_token_ignore]
13
14
  end
@@ -15,10 +16,14 @@ module RubyModKit
15
16
  # @rbs parse_error: Prism::ParseError
16
17
  # @rbs generation: Generation
17
18
  # @rbs return: void
19
+ # @param parse_error [Prism::ParseError]
20
+ # @param generation [Generation]
21
+ # @return [void]
18
22
  def correct(parse_error, generation)
19
23
  return if parse_error.location.slice != ":"
20
24
 
21
25
  def_node = generation.root_node.statements_node_at(parse_error.location.start_offset)&.parent
26
+ def_node = def_node.parent if def_node.is_a?(Node::BeginNode)
22
27
  return unless def_node.is_a?(Node::DefNode)
23
28
 
24
29
  lparen_loc = def_node.lparen_loc
@@ -10,6 +10,7 @@ module RubyModKit
10
10
  # @rbs @modified: bool
11
11
 
12
12
  # @rbs return: void
13
+ # @return [void]
13
14
  def initialize
14
15
  super
15
16
  @modified = false
@@ -17,6 +18,8 @@ module RubyModKit
17
18
 
18
19
  # @rbs generation: Generation
19
20
  # @rbs return: bool
21
+ # @param generation [Generation]
22
+ # @return [Boolean]
20
23
  def perform(generation)
21
24
  return true if @modified
22
25
 
@@ -29,19 +32,13 @@ module RubyModKit
29
32
  ivars_memo.keep_if { |_, ivar_memo| ivar_memo.attr_kind }
30
33
  next if ivars_memo.empty?
31
34
 
32
- add_first_separator_line = false
33
35
  if attr_adding_line == 0
34
36
  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 != ""
37
+ attr_adding_line += 1 while generation.line(attr_adding_line) =~ /\A\s*#.*|\A$/
41
38
  end
42
39
  line = generation.line(attr_adding_line) || next
43
40
  add_separator_line = line != "\n" && line !~ /\A\s*end$/
44
- offset = generation.src_offset(attr_adding_line) || next
41
+ offset = generation.line_offset(attr_adding_line) || next
45
42
 
46
43
  body_node = def_parent_node.body_node
47
44
  if body_node
@@ -50,9 +47,9 @@ module RubyModKit
50
47
  else
51
48
  def_parent_line = generation.line(def_parent_node)
52
49
  indent = " #{def_parent_line[/\A\s*/]}"
50
+ generation[offset, 0] = "\n"
53
51
  end
54
52
 
55
- generation[offset, 0] = "\n" if add_first_separator_line
56
53
  ivars_memo.each do |name, ivar_memo|
57
54
  attr = ivar_memo.attr_kind
58
55
  attr = "#{ivar_memo.visibility} #{attr}" if ivar_memo.visibility
@@ -0,0 +1,37 @@
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
+ # @param generation [Generation]
14
+ # @return [Boolean]
15
+ def perform(generation)
16
+ generation.memo_pad.each_parameter_memo do |parameter_memo|
17
+ next if parameter_memo.untyped?
18
+
19
+ offset = parameter_memo.offset
20
+ def_node = generation.root_node.def_node_at(offset)
21
+ raise RubyModKit::Error, "DefNode not found" if !def_node || !def_node.is_a?(Node::DefNode)
22
+
23
+ parameter_node = generation.root_node.parameter_node_at(offset)
24
+ raise RubyModKit::Error, "ParameterNode not found" unless parameter_node
25
+
26
+ line_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
27
+ indent = generation.line_indent(def_node)
28
+ script = "#{indent}# @param #{parameter_node.name} [#{Yard.rbs2yard(parameter_memo.type)}]\n"
29
+ generation[line_offset, 0] = script
30
+ end
31
+ true
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
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
+ # @param generation [Generation]
14
+ # @return [Boolean]
15
+ def perform(generation)
16
+ generation.memo_pad.methods_memo.each do |offset, method_memo|
17
+ def_node = generation.root_node.def_node_at(offset)
18
+ raise RubyModKit::Error, "DefNode not found" if !def_node || !def_node.is_a?(Node::DefNode)
19
+ next if method_memo.untyped?
20
+
21
+ src_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
22
+ indent = offset - src_offset
23
+ generation.memo_pad.flags[:rbs_annotated] = true
24
+ generation[src_offset, 0] = "#{" " * indent}# @return [#{Yard.rbs2yard(method_memo.type)}]\n"
25
+ end
26
+ true
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,34 @@
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
+ # @return [Array<Mission>]
12
+ def create_missions
13
+ [
14
+ TypeParameterMission.new,
15
+ TypeReturnMission.new,
16
+ ]
17
+ end
18
+
19
+ class << self
20
+ # @rbs type: String
21
+ # @rbs return: String
22
+ # @param type [String]
23
+ # @return [String]
24
+ def rbs2yard(type)
25
+ type.gsub(/\s*\|\s*/, ", ").tr("[]", "<>").gsub(/(?<=^|\W)bool(?=$|\W)/, "Boolean")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ require_relative "yard/type_parameter_mission"
34
+ require_relative "yard/type_return_mission"
@@ -7,6 +7,7 @@ module RubyModKit
7
7
  # namespace for type feature
8
8
  class Type < Feature
9
9
  # @rbs return: Array[Corrector]
10
+ # @return [Array<Corrector>]
10
11
  def create_correctors
11
12
  [
12
13
  InstanceVariableColonCorrector.new,
@@ -16,6 +17,7 @@ module RubyModKit
16
17
  end
17
18
 
18
19
  # @rbs return: Array[Mission]
20
+ # @return [Array<Mission>]
19
21
  def create_missions
20
22
  [
21
23
  TypeAttrMission.new,
@@ -6,11 +6,13 @@ module RubyModKit
6
6
  # the base class of feature
7
7
  class Feature
8
8
  # @rbs return: Array[Corrector]
9
+ # @return [Array<Corrector>]
9
10
  def create_correctors
10
11
  []
11
12
  end
12
13
 
13
14
  # @rbs return: Array[Mission]
15
+ # @return [Array<Mission>]
14
16
  def create_missions
15
17
  []
16
18
  end
@@ -18,6 +18,7 @@ module RubyModKit
18
18
  # @rbs @errors: Array[Prism::ParseError]
19
19
  # @rbs @lines: Array[String]
20
20
  # @rbs @offsets: Array[Integer]
21
+ # @rbs @source: String
21
22
 
22
23
  attr_reader :script #: String
23
24
  attr_reader :memo_pad #: MemoPad
@@ -35,6 +36,15 @@ module RubyModKit
35
36
  # @rbs corrector_manager: CorrectorManager | nil
36
37
  # @rbs features: Array[Feature] | nil
37
38
  # @rbs return: void
39
+ # @param script [String]
40
+ # @param missions [Array<Mission>]
41
+ # @param memo_pad [MemoPad, nil]
42
+ # @param generation_num [Integer]
43
+ # @param config [Config, nil]
44
+ # @param filename [String, nil]
45
+ # @param corrector_manager [CorrectorManager, nil]
46
+ # @param features [Array<Feature>, nil]
47
+ # @return [void]
38
48
  def initialize(script, missions: [], memo_pad: nil, generation_num: 0, config: nil,
39
49
  filename: nil, corrector_manager: nil, features: nil)
40
50
  @script = script
@@ -51,11 +61,13 @@ module RubyModKit
51
61
  @errors = parse_result.errors
52
62
  @lines = parse_result.source.lines
53
63
  @offsets = parse_result.source.offsets
64
+ @source = @script.dup
54
65
  @root_node = Node::ProgramNode.new(parse_result.value)
55
66
  init_missions
56
67
  end
57
68
 
58
69
  # @rbs return: void
70
+ # @return [void]
59
71
  def init_missions
60
72
  return unless first_generation?
61
73
 
@@ -67,20 +79,19 @@ module RubyModKit
67
79
  end
68
80
 
69
81
  # @rbs return: bool
82
+ # @return [Boolean]
70
83
  def first_generation?
71
84
  @generation_num == 0
72
85
  end
73
86
 
74
87
  # @rbs return: Generation
88
+ # @return [Generation]
75
89
  def succ
76
90
  if @errors.empty?
77
91
  perform_missions
78
92
  else
79
93
  perform_corrector
80
94
  end
81
- @missions.each do |mission|
82
- mission.succ(@offset_diff)
83
- end
84
95
  @memo_pad.succ(@offset_diff)
85
96
 
86
97
  Generation.new(
@@ -96,11 +107,13 @@ module RubyModKit
96
107
  end
97
108
 
98
109
  # @rbs return: String
110
+ # @return [String]
99
111
  def name
100
112
  "#{@filename || "(eval)"}[gen #{@generation_num}]"
101
113
  end
102
114
 
103
115
  # @rbs return: bool
116
+ # @return [Boolean]
104
117
  def completed?
105
118
  @errors.empty? && @missions.empty?
106
119
  end
@@ -109,24 +122,22 @@ module RubyModKit
109
122
  # @rbs length: Integer
110
123
  # @rbs str: String
111
124
  # @rbs return: String
125
+ # @param src_offset [Integer]
126
+ # @param length [Integer]
127
+ # @param str [String]
128
+ # @return [String]
112
129
  def []=(src_offset, length, str)
113
130
  diff = str.length - length
114
131
  @script[@offset_diff[src_offset], length] = str
115
132
  @offset_diff.insert(src_offset, diff)
116
133
  end
117
134
 
118
- # @rbs src_range: Range[Integer]
135
+ # @rbs src_range: Range[Integer | nil]
119
136
  # @rbs return: String
137
+ # @param src_range [Range<Integer, nil>]
138
+ # @return [String]
120
139
  def [](src_range)
121
- dst_range = Range.new(@offset_diff[src_range.first], @offset_diff[src_range.last], src_range.exclude_end?)
122
- @script[dst_range] || raise(RubyModKit::Error, "Invalid range")
123
- end
124
-
125
- # @rbs offset: Integer
126
- # @rbs return: String
127
- def line_by_offset(offset)
128
- offset = @offset_diff[offset]
129
- (@script.match(/.*\n?/, offset) && Regexp.last_match(0)) || raise(RubyModKit::Error)
140
+ @source[src_range] || raise(RubyModKit::Error, "Invalid range")
130
141
  end
131
142
 
132
143
  # @rbs (Integer) -> String
@@ -134,62 +145,63 @@ module RubyModKit
134
145
  # | (Prism::ParseError) -> String
135
146
  def line(*args)
136
147
  case args
137
- in [Integer]
138
- line__overload0(*args)
139
- in [Node::BaseNode]
140
- line__overload1(*args)
141
- in [Prism::ParseError]
142
- line__overload2(*args)
148
+ in [Integer => line_num]
149
+ @lines[line_num] || raise(RubyModKit::Error)
150
+ in [Node::BaseNode => node]
151
+ line(node.location.start_line - 1)
152
+ in [Prism::ParseError => parse_error]
153
+ begin
154
+ line(parse_error.location.start_line - 1)
155
+ rescue RubyModKit::Error
156
+ ""
157
+ end
143
158
  end
144
159
  end
145
160
 
146
- # @rbs line_num: Integer
147
- # @rbs return: String
148
- def line__overload0(line_num)
149
- line_by_offset(@offsets[line_num])
150
- end
151
-
152
- # @rbs node: Node::BaseNode
153
- # @rbs return: String
154
- def line__overload1(node)
155
- line(node.location.start_line - 1)
156
- end
157
-
158
- # @rbs parse_error: Prism::ParseError
159
- # @rbs return: String
160
- def line__overload2(parse_error)
161
- line(parse_error.location.start_line - 1)
162
- end
163
-
164
161
  # @rbs (Integer) -> (Integer | nil)
162
+ # | (Node::BaseNode) -> (Integer | nil)
163
+ # | (Node::BaseNode, Integer) -> (Integer | nil)
165
164
  # | (Prism::ParseError) -> (Integer | nil)
166
- def src_offset(*args)
165
+ def line_offset(*args)
167
166
  case args
168
- in [Integer]
169
- src_offset__overload0(*args)
170
- in [Prism::ParseError]
171
- src_offset__overload1(*args)
167
+ in [Integer => line_num]
168
+ @offsets[line_num]
169
+ in [Node::BaseNode => node]
170
+ line_offset(node, 0)
171
+ in [Node::BaseNode => node, Integer => line_offset]
172
+ line_offset(node.location.start_line - 1 + line_offset)
173
+ in [Prism::ParseError => parse_error]
174
+ line_offset(parse_error.location.start_line - 1)
172
175
  end
173
176
  end
174
177
 
175
- # @rbs line_num: Integer
178
+ # @rbs node: Node::BaseNode
176
179
  # @rbs return: Integer | nil
177
- def src_offset__overload0(line_num)
178
- @offsets[line_num]
180
+ # @param node [Node::BaseNode]
181
+ # @return [Integer, nil]
182
+ def end_line_offset(node)
183
+ line_offset(node.location.end_line - 1)
179
184
  end
180
185
 
181
- # @rbs parse_error: Prism::ParseError
182
- # @rbs return: Integer | nil
183
- def src_offset__overload1(parse_error)
184
- src_offset(parse_error.location.start_line - 1)
186
+ # @rbs (Integer) -> String
187
+ # | (Node::BaseNode) -> String
188
+ def line_indent(*args)
189
+ case args
190
+ in [Integer => line_num]
191
+ line(line_num)[/\A[ \t]*/] || ""
192
+ in [Node::BaseNode => node]
193
+ line_indent(node.location.start_line - 1)
194
+ end
185
195
  end
186
196
 
187
197
  # @rbs return: void
198
+ # @return [void]
188
199
  def perform_corrector
189
200
  @corrector_manager.perform(self)
190
201
  end
191
202
 
192
203
  # @rbs return: void
204
+ # @return [void]
193
205
  def perform_missions
194
206
  @missions.delete_if do |mission|
195
207
  mission.perform(self) || break
@@ -198,6 +210,8 @@ module RubyModKit
198
210
 
199
211
  # @rbs mission: Mission
200
212
  # @rbs return: void
213
+ # @param mission [Mission]
214
+ # @return [void]
201
215
  def add_mission(mission)
202
216
  @missions << mission
203
217
  end
@@ -207,6 +221,10 @@ module RubyModKit
207
221
  # @rbs filename: String | nil
208
222
  # @rbs config: Config | nil
209
223
  # @rbs return: Generation
224
+ # @param src [String]
225
+ # @param filename [String, nil]
226
+ # @param config [Config, nil]
227
+ # @return [Generation]
210
228
  def resolve(src, filename: nil, config: nil)
211
229
  generation = Generation.new(src.dup, filename: filename, config: config)
212
230
  generation = generation.succ until generation.completed?