ruby_mod_kit 0.0.4 → 0.0.6

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