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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb9b6cf5cb887308d1237eb07d40b4b2b2514173c5e76d19e13a27687f2c107f
4
- data.tar.gz: 418e2d01aec4c8f8b4f0b6241625a0b550aec118a3dbd0618987171bb270e4f7
3
+ metadata.gz: 7d1688dd299feefd22167740d43d09a691ba4e01359edbdfdcb81462ec7c4d47
4
+ data.tar.gz: 1ea7711fddb58f15c1257fb8a63595d300a7c45483af595f4defc48c5a842466
5
5
  SHA512:
6
- metadata.gz: 17a8efaedb26b0b3256fd0b24501298a1f56fdf4dc8d5c33adc8cb6005abf6c5fcca4c0d1d634b34784dd2528ec57c8d2effdaf4042bc522a15359c86b01b804
7
- data.tar.gz: 73758c1ef48bcb7884a6f37859115b952474084abca4b6560f7d21c5380ec4bece1f97e165e6ef27b8270b0f5209877f5b2b63f1cd408ed5b4b6f5cb517d8dc1
6
+ metadata.gz: fa6c821537ec79c43ed5b092f2a0044126c0b925bff381c33971c2462a0578e92b0f681d313d3053c0fbc688f13907a6b10180738fa075bc192e1b582c843479
7
+ data.tar.gz: a84c961311ae15bc60b8db3594a1f412ca7b1a71d4922707d271c7d3eba9338e91338c69f2414a04907c1bc1e2b76581d1298a3effd22706913d4731fe93b084
data/.ruby_mod_kit.yml CHANGED
@@ -3,3 +3,4 @@ features:
3
3
  - overload
4
4
  - type
5
5
  - type/rbs_inline
6
+ - type/yard
data/.yardopts ADDED
@@ -0,0 +1,3 @@
1
+ --tag rbs:rbs
2
+ --exclude lib/ruby_mod_kit/core_ext.rb
3
+ --exclude lib/internal/
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`
data/examples/user.rb CHANGED
@@ -50,25 +50,13 @@ class Pos
50
50
  # | (Integer) -> Pos
51
51
  def *(*args)
52
52
  case args
53
- in [Pos]
54
- _mul__overload0(*args)
55
- in [Integer]
56
- _mul__overload1(*args)
53
+ in [Pos => other]
54
+ (@x * other.x) + (@y * other.y) + (@z * other.z)
55
+ in [Integer => n]
56
+ Pos.new(@x * n, @y * n, @z * n)
57
57
  end
58
58
  end
59
59
 
60
- # @rbs other: Pos
61
- # @rbs return: Integer
62
- def _mul__overload0(other)
63
- (@x * other.x) + (@y * other.y) + (@z * other.z)
64
- end
65
-
66
- # @rbs n: Integer
67
- # @rbs return: Pos
68
- def _mul__overload1(n)
69
- Pos.new(@x * n, @y * n, @z * n)
70
- end
71
-
72
60
  # @rbs return: String
73
61
  def to_s
74
62
  "#<Pos: (#{@x}, #{@y}, #{@z})>"
@@ -11,6 +11,8 @@ module RubyModKit
11
11
  desc "exec", "execute rbm file"
12
12
  # @rbs *args: String
13
13
  # @rbs return: void
14
+ # @param args [String]
15
+ # @return [void]
14
16
  def exec(*args)
15
17
  RubyModKit.execute_file(*args, config: config)
16
18
  end
@@ -19,6 +21,8 @@ module RubyModKit
19
21
  method_option :output, type: :string
20
22
  # @rbs *args: String
21
23
  # @rbs return: void
24
+ # @param args [String]
25
+ # @return [void]
22
26
  def transpile(*args)
23
27
  output = case options[:output]
24
28
  when nil, "-", "/dev/stdout"
@@ -37,6 +41,7 @@ module RubyModKit
37
41
  private
38
42
 
39
43
  # @rbs return: Config | nil
44
+ # @return [Config, nil]
40
45
  def config
41
46
  if options[:config]
42
47
  config_path = options[:config]
@@ -15,6 +15,8 @@ module RubyModKit
15
15
 
16
16
  # @rbs features: Array[String]
17
17
  # @rbs return: void
18
+ # @param features [Array<String>]
19
+ # @return [void]
18
20
  def initialize(features: DEFAULT_FEATURES)
19
21
  @features = features.sort.map do |feature_name|
20
22
  raise ArgumentError, "invalid feature: #{feature_name}" if feature_name.include?(".")
@@ -29,8 +31,11 @@ module RubyModKit
29
31
 
30
32
  class << self
31
33
  # @rbs path: String
32
- # @rbs if_none: nil | Symbol
34
+ # @rbs if_none: Symbol | nil
33
35
  # @rbs return: Config | nil
36
+ # @param path [String]
37
+ # @param if_none [Symbol, nil]
38
+ # @return [Config, nil]
34
39
  def load(path, if_none: nil)
35
40
  return load(File.join(path, ".ruby_mod_kit.yml"), if_none: if_none) if File.directory?(path)
36
41
 
@@ -6,25 +6,28 @@ require "ruby_mod_kit"
6
6
 
7
7
  # Define RubyMotKit.eval
8
8
  module RubyModKit
9
+ # the namespace for language core extensions
9
10
  module CoreExt
10
11
  # the extension for eval
11
12
  module Eval
12
13
  module_function
13
14
 
14
15
  # @rbs expr: String
15
- # @rbs *rest: Object
16
+ # @rbs binding: Binding
17
+ # @rbs fname: String
18
+ # @rbs lineno: Integer
16
19
  # @rbs transpile: bool
17
20
  # @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
21
+ # @param expr [String]
22
+ # @param binding [Binding]
23
+ # @param fname [String]
24
+ # @param lineno [Integer]
25
+ # @param transpile [Boolean]
26
+ # @return [Object]
27
+ def eval(expr, binding = TOPLEVEL_BINDING, fname = "(eval)", lineno = 1, transpile: true)
28
+ expr = RubyModKit.transpile(expr, filename: fname) if transpile
23
29
 
24
- case rest
25
- in [] | [Binding] | [Binding, String] | [Binding, String, Integer]
26
- super(expr, *rest)
27
- end
30
+ super(expr, binding, fname, lineno)
28
31
  end
29
32
  end
30
33
  end
@@ -17,6 +17,9 @@ module RubyModKit
17
17
  # @rbs path: String
18
18
  # @rbs wrap: bool
19
19
  # @rbs return: bool
20
+ # @param path [String]
21
+ # @param wrap [Boolean]
22
+ # @return [Boolean]
20
23
  def load(path, wrap = false) # rubocop:disable Style/OptionalBooleanParameter
21
24
  return super unless path.end_with?(".rbm")
22
25
 
@@ -27,6 +30,8 @@ module RubyModKit
27
30
 
28
31
  # @rbs path: String
29
32
  # @rbs return: bool
33
+ # @param path [String]
34
+ # @return [Boolean]
30
35
  def require(path)
31
36
  require_path = Load.require_path(path)
32
37
  return super unless require_path&.end_with?(".rbm")
@@ -39,11 +44,13 @@ module RubyModKit
39
44
 
40
45
  class << self
41
46
  # @rbs return: Array[String]
47
+ # @return [Array<String>]
42
48
  def loaded_features
43
49
  $LOADED_FEATURES
44
50
  end
45
51
 
46
52
  # @rbs return: Array[String]
53
+ # @return [Array<String>]
47
54
  def load_path
48
55
  $LOAD_PATH
49
56
  end
@@ -51,6 +58,9 @@ module RubyModKit
51
58
  # @rbs path: String
52
59
  # @rbs expanded: bool
53
60
  # @rbs return: String | nil
61
+ # @param path [String]
62
+ # @param expanded [Boolean]
63
+ # @return [String, nil]
54
64
  def require_path(path, expanded: false)
55
65
  if !expanded && !File.absolute_path?(path)
56
66
  return load_path.each.lazy.map { require_path(File.join(_1, path), expanded: true) }.find(&:itself)
@@ -6,6 +6,7 @@ module RubyModKit
6
6
  # the base class of corrector
7
7
  class Corrector
8
8
  # @rbs return: Array[Symbol]
9
+ # @return [Array<Symbol>]
9
10
  def correctable_error_types
10
11
  []
11
12
  end
@@ -13,8 +14,15 @@ module RubyModKit
13
14
  # @rbs _parse_error: Prism::ParseError
14
15
  # @rbs _generation: Generation
15
16
  # @rbs return: void
17
+ # @param _parse_error [Prism::ParseError]
18
+ # @param _generation [Generation]
19
+ # @return [void]
16
20
  def correct(_parse_error, _generation)
17
21
  raise RubyModKit::Error, "Unexpected type #{self.class}"
18
22
  end
23
+
24
+ # @rbs return: void
25
+ # @return [void]
26
+ def setup; end
19
27
  end
20
28
  end
@@ -5,13 +5,15 @@
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
+ # @param features [Array<Feature>]
14
+ # @return [void]
13
15
  def initialize(features)
14
- @previous_error_messages = []
16
+ @previous_source = +""
15
17
  @correctors_error_map = {}
16
18
  features.each do |feature|
17
19
  feature.create_correctors.each do |corrector|
@@ -24,11 +26,17 @@ module RubyModKit
24
26
 
25
27
  # @rbs generation: Generation
26
28
  # @rbs return: bool
29
+ # @param generation [Generation]
30
+ # @return [Boolean]
27
31
  def perform(generation)
28
32
  return true if generation.errors.empty?
29
33
 
30
34
  check_prev_errors(generation)
31
- @previous_error_messages = generation.errors.map(&:message)
35
+ @previous_source = generation.script.dup
36
+
37
+ @correctors_error_map.each_value do |correctors|
38
+ correctors.each(&:setup)
39
+ end
32
40
 
33
41
  generation.errors.each do |parse_error|
34
42
  correctors = @correctors_error_map[parse_error.type] || next
@@ -42,17 +50,19 @@ module RubyModKit
42
50
 
43
51
  # @rbs generation: Generation
44
52
  # @rbs return: void
53
+ # @param generation [Generation]
54
+ # @return [void]
45
55
  def check_prev_errors(generation)
46
- return if @previous_error_messages.empty?
56
+ return if @previous_source.empty?
47
57
  return if generation.errors.empty?
48
- return if @previous_error_messages != generation.errors.map(&:message)
58
+ return if @previous_source != generation.script
49
59
 
50
60
  message = +""
51
61
  generation.errors.each do |parse_error|
52
62
  message << "\n" unless message.empty?
53
63
  message << "#{generation.name}:#{parse_error.location.start_line}:#{parse_error.message} "
54
64
  message << "(#{parse_error.type})"
55
- line = generation.lines[parse_error.location.start_line - 1]
65
+ line = generation.line(parse_error)
56
66
  if line
57
67
  message << "\n#{line.chomp}\n"
58
68
  message << "#{" " * parse_error.location.start_column}^#{"~" * [parse_error.location.length - 1, 0].max}"
@@ -8,6 +8,7 @@ module RubyModKit
8
8
  # the class to correct `def foo(@bar) ...` -> `def foo(bar) ...`
9
9
  class InstanceVariableParameterCorrector < Corrector
10
10
  # @rbs return: Array[Symbol]
11
+ # @return [Array<Symbol>]
11
12
  def correctable_error_types
12
13
  %i[argument_formal_ivar]
13
14
  end
@@ -15,6 +16,9 @@ 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
  src_offset = parse_error.location.start_offset
20
24
 
@@ -9,8 +9,10 @@ module RubyModKit
9
9
  class InstanceVariableParameterMission < Mission
10
10
  # @rbs generation: Generation
11
11
  # @rbs return: bool
12
+ # @param generation [Generation]
13
+ # @return [Boolean]
12
14
  def perform(generation)
13
- generation.memo_pad.parameters_memo.each_value do |parameter_memo|
15
+ generation.memo_pad.each_parameter_memo do |parameter_memo|
14
16
  next unless parameter_memo.ivar_parameter
15
17
 
16
18
  offset = parameter_memo.offset
@@ -7,6 +7,7 @@ module RubyModKit
7
7
  # namespace for instance_variable parameter feature
8
8
  class InstanceVariableParameter < Feature
9
9
  # @rbs return: Array[Corrector]
10
+ # @return [Array<Corrector>]
10
11
  def create_correctors
11
12
  [
12
13
  InstanceVariableParameterCorrector.new,
@@ -14,6 +15,7 @@ module RubyModKit
14
15
  end
15
16
 
16
17
  # @rbs return: Array[Mission]
18
+ # @return [Array<Mission>]
17
19
  def create_missions
18
20
  [
19
21
  InstanceVariableParameterMission.new,
@@ -14,6 +14,7 @@ module RubyModKit
14
14
  }.freeze #: Hash[Symbol, String]
15
15
 
16
16
  # @rbs return: void
17
+ # @return [void]
17
18
  def initialize
18
19
  super
19
20
  @modified = false
@@ -21,8 +22,19 @@ module RubyModKit
21
22
 
22
23
  # @rbs generation: Generation
23
24
  # @rbs return: bool
25
+ # @param generation [Generation]
26
+ # @return [Boolean]
24
27
  def perform(generation)
25
- return true if @modified
28
+ if @modified
29
+ generation.memo_pad.overloads_memo.each_value do |overload_memo|
30
+ overload_memo.correct_offset(generation.root_node)
31
+ def_node = generation.root_node.def_node_at(overload_memo.offset)
32
+ raise RubyModKit::Error unless def_node.is_a?(Node::DefNode)
33
+
34
+ generation[def_node.end_offset, 0] = "\n" if def_node.parent.children[-1].offset > def_node.end_offset
35
+ end
36
+ return true
37
+ end
26
38
 
27
39
  method_memo_groups = generation.memo_pad.methods_memo.each_value.group_by do |method_memo|
28
40
  [generation.root_node.def_parent_node_at(method_memo.offset), method_memo.name]
@@ -37,9 +49,8 @@ module RubyModKit
37
49
  raise RubyModKit::Error unless first_def_node.is_a?(Node::DefNode)
38
50
  raise RubyModKit::Error unless name.is_a?(Symbol)
39
51
 
40
- start_line = first_def_node.location.start_line - 1
41
- indent = generation.lines[start_line][/\A */] || ""
42
- src_offset = generation.offsets[start_line]
52
+ indent = generation.line_indent(first_def_node)
53
+ src_offset = generation.line_offset(first_def_node) || raise(RubyModKit::Error)
43
54
  script = +""
44
55
 
45
56
  overload_memo = generation.memo_pad.overload_memo(first_method_memo.offset, name)
@@ -51,18 +62,38 @@ module RubyModKit
51
62
  end
52
63
 
53
64
  script << "def #{name}(*args)\n case args\n"
54
- overload_prefix = +"#{OVERLOAD_METHOD_MAP[name] || name}_"
55
- method_memos.each_with_index do |method_memo, i|
56
- overload_name = "#{overload_prefix}_overload#{i}"
65
+ method_memos.each do |method_memo|
57
66
  def_node = generation.root_node.def_node_at(method_memo.offset)
58
- raise RubyModKit::Error if !def_node || !def_node.is_a?(Node::DefNode)
67
+ body_node = def_node&.body_node
68
+ raise RubyModKit::Error unless def_node
69
+
70
+ def_start_offset = generation.line_offset(def_node) || raise(RubyModKit::Error)
71
+ def_end_offset = generation.end_line_offset(def_node) || raise(RubyModKit::Error)
72
+ def_end_offset += generation[def_end_offset..][/.*\n*/]&.size || 0
73
+ generation[def_start_offset, def_end_offset - def_start_offset] = ""
74
+ generation.memo_pad.delete(method_memo)
75
+
76
+ params = method_memo.parameters.map { |param| "#{param.type} => #{param.name}" }
77
+ script << " in [#{params.join(", ")}]\n"
78
+
79
+ body = nil
80
+ case body_node
81
+ when Node::StatementsNode
82
+ src_indent = generation.line_indent(body_node)
83
+ body = "#{src_indent}#{body_node.slice}\n".gsub(/^#{src_indent}/, " ")
84
+ when Node::BeginNode
85
+ src_indent = generation.line_indent(body_node)
86
+ src_line_offset = generation.line_offset(body_node.children[0]) || raise(RubyModKit::Error)
87
+ body = body_node.slice[(src_line_offset - body_node.offset)..]
88
+ body = "#{src_indent}begin\n#{body}\n".gsub(/^#{src_indent}/, " ")
89
+ when nil
90
+ body = ""
91
+ end
92
+ raise RubyModKit::Error unless body
59
93
 
60
- name_loc = def_node.name_loc
61
- generation[name_loc.start_offset, name_loc.length] = overload_name
62
- script << " in [#{method_memo.parameters.map(&:type).join(", ")}]\n"
63
- script << " #{overload_name}(*args)\n"
94
+ script << body
64
95
  end
65
- script << " end\nend\n\n"
96
+ script << " end\nend\n"
66
97
 
67
98
  script.gsub!(/^(?=.)/, indent)
68
99
  generation[src_offset, 0] = script
@@ -7,6 +7,7 @@ module RubyModKit
7
7
  # namespace for overload feature
8
8
  class Overload < Feature
9
9
  # @rbs return: Array[Mission]
10
+ # @return [Array<Mission>]
10
11
  def create_missions
11
12
  [
12
13
  OverloadMission.new,
@@ -0,0 +1,58 @@
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
+ # @param generation [Generation]
14
+ # @return [Boolean]
15
+ def perform(generation)
16
+ # reload if line break is added
17
+ line_break_added = false
18
+
19
+ generation.memo_pad.methods_memo.each do |offset, method_memo|
20
+ def_node = generation.root_node.def_node_at(offset)
21
+ raise RubyModKit::Error, "DefNode not found" unless def_node
22
+ next if method_memo.parameters.empty?
23
+
24
+ def_line = generation.line(def_node.location.start_line - 1)
25
+ def_indent = def_line[/\A\s*/] || ""
26
+
27
+ location = def_node.body_location || def_node.end_keyword_loc
28
+ next unless location
29
+
30
+ def_right_loc = def_node.rparen_loc || def_node.name_loc
31
+ offset = location.start_offset - location.start_column
32
+ indent = "#{def_indent} "
33
+ if location.start_line == def_right_loc.end_line
34
+ between_def_and_loc = generation[def_right_loc.end_offset...location.start_offset]
35
+ length = between_def_and_loc[/\A[ ^t]*;[ ^t]*\z/]&.length
36
+ if length
37
+ line_break_added = true
38
+ generation[def_right_loc.end_offset, length] = "\n#{def_indent}"
39
+ end
40
+ end
41
+ next if line_break_added
42
+
43
+ method_memo.parameters.each do |parameter_memo|
44
+ next if parameter_memo.untyped? || !parameter_memo.name
45
+ next if parameter_memo.qualifier # TODO: qualifier support
46
+
47
+ type = parameter_memo.type
48
+ type = type.gsub(/\[([^\[\]]+)\]/, "") # TODO: type variable support
49
+ generation[offset, 0] = "#{indent}#{parameter_memo.name} => #{type}\n"
50
+ end
51
+ end
52
+ !line_break_added
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ # namespace for type checker
9
+ module Check
10
+ # namespace for arguments type checker
11
+ class Arguments < Feature
12
+ # @rbs return: Array[Mission]
13
+ # @return [Array<Mission>]
14
+ def create_missions
15
+ [
16
+ AddArgumentsCheckerMission.new,
17
+ ]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ require_relative "arguments/add_arguments_checker_mission"
@@ -9,9 +9,10 @@ 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
+ # @return [Array<Symbol>]
15
16
  def correctable_error_types
16
17
  %i[unexpected_token_ignore]
17
18
  end
@@ -19,14 +20,20 @@ module RubyModKit
19
20
  # @rbs parse_error: Prism::ParseError
20
21
  # @rbs generation: Generation
21
22
  # @rbs return: void
23
+ # @param parse_error [Prism::ParseError]
24
+ # @param generation [Generation]
25
+ # @return [void]
22
26
  def correct(parse_error, generation)
23
27
  return if parse_error.location.slice != ":"
24
28
 
25
- def_parent_node = generation.root_node.statements_node_at(parse_error.location.start_offset)&.parent
29
+ def_parent_node = generation.root_node.def_parent_node_at(
30
+ parse_error.location.start_offset,
31
+ allowed: [Node::CallNode, Node::UntypedNode, Node::StatementsNode],
32
+ )
26
33
  return unless def_parent_node.is_a?(Node::DefParentNode)
27
34
 
28
- line = generation.line(parse_error)
29
- line_offset = generation.src_offset(parse_error) || return
35
+ line_offset = generation.line_offset(parse_error) || return
36
+ line = generation[line_offset..]
30
37
  return if line !~ REGEXP
31
38
 
32
39
  length = ::Regexp.last_match(0)&.length
@@ -35,6 +42,7 @@ module RubyModKit
35
42
  attr_kind = ::Regexp.last_match(3)
36
43
  ivar_name = ::Regexp.last_match(4)
37
44
  type = ::Regexp.last_match(5)
45
+ separator = ::Regexp.last_match(6)
38
46
  return if !length || !indent || !ivar_name || !type
39
47
 
40
48
  ivar_memo = generation.memo_pad.def_parent_memo(def_parent_node).ivar_memo(ivar_name.to_sym)
@@ -43,6 +51,7 @@ module RubyModKit
43
51
  ivar_memo.indent = indent
44
52
  ivar_memo.attr_kind = attr_kind if attr_kind
45
53
  ivar_memo.visibility = visibility.to_sym if visibility
54
+ ivar_memo.separator = separator if separator
46
55
 
47
56
  generation[line_offset, length] = ""
48
57
  end