ruby_mod_kit 0.0.2 → 0.0.4

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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby_mod_kit.yml +5 -0
  3. data/lib/ruby_mod_kit/cli.rb +17 -2
  4. data/lib/ruby_mod_kit/config.rb +53 -0
  5. data/lib/ruby_mod_kit/core_ext/eval.rb +6 -0
  6. data/lib/ruby_mod_kit/core_ext/load.rb +12 -4
  7. data/lib/ruby_mod_kit/core_ext.rb +2 -2
  8. data/lib/ruby_mod_kit/corrector.rb +20 -0
  9. data/lib/ruby_mod_kit/corrector_manager.rb +64 -0
  10. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_corrector.rb +40 -0
  11. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rb +42 -0
  12. data/lib/ruby_mod_kit/feature/instance_variable_parameter.rb +27 -0
  13. data/lib/ruby_mod_kit/feature/overload/overload_mission.rb +77 -0
  14. data/lib/ruby_mod_kit/feature/overload.rb +19 -0
  15. data/lib/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rb +52 -0
  16. data/lib/ruby_mod_kit/feature/type/parameter_arrow_corrector.rb +84 -0
  17. data/lib/ruby_mod_kit/feature/type/rbs_inline/add_magic_comment_mission.rb +49 -0
  18. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_attr_mission.rb +46 -0
  19. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rb +29 -0
  20. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rb +41 -0
  21. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rb +36 -0
  22. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rb +30 -0
  23. data/lib/ruby_mod_kit/feature/type/rbs_inline.rb +32 -0
  24. data/lib/ruby_mod_kit/feature/type/return_value_colon_corrector.rb +43 -0
  25. data/lib/ruby_mod_kit/feature/type/type_attr_mission.rb +69 -0
  26. data/lib/ruby_mod_kit/feature/type.rb +31 -0
  27. data/lib/ruby_mod_kit/feature.rb +18 -0
  28. data/lib/ruby_mod_kit/generation.rb +76 -29
  29. data/lib/ruby_mod_kit/memo/def_parent_memo.rb +36 -0
  30. data/lib/ruby_mod_kit/memo/{ivar.rb → ivar_memo.rb} +19 -3
  31. data/lib/ruby_mod_kit/memo/{method.rb → method_memo.rb} +7 -7
  32. data/lib/ruby_mod_kit/memo/offset_memo.rb +1 -1
  33. data/lib/ruby_mod_kit/memo/overload_memo.rb +47 -0
  34. data/lib/ruby_mod_kit/memo/{parameter.rb → parameter_memo.rb} +3 -3
  35. data/lib/ruby_mod_kit/memo.rb +7 -66
  36. data/lib/ruby_mod_kit/memo_pad.rb +72 -0
  37. data/lib/ruby_mod_kit/mission.rb +3 -25
  38. data/lib/ruby_mod_kit/node/base_node.rb +155 -0
  39. data/lib/ruby_mod_kit/node/call_node.rb +11 -7
  40. data/lib/ruby_mod_kit/node/def_node.rb +11 -7
  41. data/lib/ruby_mod_kit/node/def_parent_node.rb +25 -14
  42. data/lib/ruby_mod_kit/node/parameter_node.rb +13 -9
  43. data/lib/ruby_mod_kit/node/program_node.rb +8 -3
  44. data/lib/ruby_mod_kit/node/statements_node.rb +11 -7
  45. data/lib/ruby_mod_kit/node/symbol_node.rb +12 -7
  46. data/lib/ruby_mod_kit/node/untyped_node.rb +11 -7
  47. data/lib/ruby_mod_kit/node/wrap.rb +43 -0
  48. data/lib/ruby_mod_kit/node.rb +4 -150
  49. data/lib/ruby_mod_kit/version.rb +1 -1
  50. data/lib/ruby_mod_kit.rb +27 -8
  51. data/ruby_mod_kit.gemspec +7 -1
  52. data/sig/generated/ruby_mod_kit/cli.rbs +5 -0
  53. data/sig/generated/ruby_mod_kit/config.rbs +21 -0
  54. data/sig/generated/ruby_mod_kit/core_ext/eval.rbs +3 -0
  55. data/sig/generated/ruby_mod_kit/core_ext/load.rbs +7 -4
  56. data/sig/generated/ruby_mod_kit/corrector.rbs +14 -0
  57. data/sig/generated/ruby_mod_kit/corrector_manager.rbs +22 -0
  58. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_corrector.rbs +18 -0
  59. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rbs +14 -0
  60. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter.rbs +14 -0
  61. data/sig/generated/ruby_mod_kit/feature/overload/overload_mission.rbs +21 -0
  62. data/sig/generated/ruby_mod_kit/feature/overload.rbs +11 -0
  63. data/sig/generated/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rbs +24 -0
  64. data/sig/generated/ruby_mod_kit/feature/type/parameter_arrow_corrector.rbs +33 -0
  65. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/add_magic_comment_mission.rbs +21 -0
  66. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_attr_mission.rbs +16 -0
  67. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rbs +16 -0
  68. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rbs +16 -0
  69. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rbs +16 -0
  70. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rbs +16 -0
  71. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline.rbs +13 -0
  72. data/sig/generated/ruby_mod_kit/feature/type/return_value_colon_corrector.rbs +18 -0
  73. data/sig/generated/ruby_mod_kit/feature/type/type_attr_mission.rbs +19 -0
  74. data/sig/generated/ruby_mod_kit/feature/type.rbs +14 -0
  75. data/sig/generated/ruby_mod_kit/feature.rbs +12 -0
  76. data/sig/generated/ruby_mod_kit/generation.rbs +44 -13
  77. data/sig/generated/ruby_mod_kit/memo/def_parent_memo.rbs +24 -0
  78. data/sig/generated/ruby_mod_kit/memo/{ivar.rbs → ivar_memo.rbs} +19 -3
  79. data/sig/generated/ruby_mod_kit/memo/{method.rbs → method_memo.rbs} +8 -8
  80. data/sig/generated/ruby_mod_kit/memo/offset_memo.rbs +1 -1
  81. data/sig/generated/ruby_mod_kit/memo/overload_memo.rbs +34 -0
  82. data/sig/generated/ruby_mod_kit/memo/{parameter.rbs → parameter_memo.rbs} +3 -3
  83. data/sig/generated/ruby_mod_kit/memo_pad.rbs +50 -0
  84. data/sig/generated/ruby_mod_kit/mission.rbs +2 -13
  85. data/sig/generated/ruby_mod_kit/node/base_node.rbs +75 -0
  86. data/sig/generated/ruby_mod_kit/node/call_node.rbs +11 -6
  87. data/sig/generated/ruby_mod_kit/node/def_node.rbs +11 -6
  88. data/sig/generated/ruby_mod_kit/node/def_parent_node.rbs +17 -10
  89. data/sig/generated/ruby_mod_kit/node/parameter_node.rbs +13 -8
  90. data/sig/generated/ruby_mod_kit/node/program_node.rbs +5 -2
  91. data/sig/generated/ruby_mod_kit/node/statements_node.rbs +11 -6
  92. data/sig/generated/ruby_mod_kit/node/symbol_node.rbs +13 -6
  93. data/sig/generated/ruby_mod_kit/node/untyped_node.rbs +11 -6
  94. data/sig/generated/ruby_mod_kit/node/wrap.rbs +12 -0
  95. data/sig/generated/ruby_mod_kit.rbs +10 -3
  96. data/sig/yaml.rbs +3 -0
  97. metadata +63 -30
  98. data/lib/ruby_mod_kit/memo/def_parent.rb +0 -27
  99. data/lib/ruby_mod_kit/mission/fix_parse_error.rb +0 -216
  100. data/lib/ruby_mod_kit/mission/ivar_arg.rb +0 -42
  101. data/lib/ruby_mod_kit/mission/overload.rb +0 -73
  102. data/lib/ruby_mod_kit/mission/type_attr.rb +0 -75
  103. data/lib/ruby_mod_kit/mission/type_parameter.rb +0 -39
  104. data/lib/ruby_mod_kit/mission/type_return.rb +0 -33
  105. data/lib/ruby_mod_kit/transpiler.rb +0 -20
  106. data/sig/generated/examples/user.rbs +0 -60
  107. data/sig/generated/ruby_mod_kit/memo/def_parent.rbs +0 -20
  108. data/sig/generated/ruby_mod_kit/memo/located.rbs +0 -14
  109. data/sig/generated/ruby_mod_kit/memo/parameter_type.rbs +0 -14
  110. data/sig/generated/ruby_mod_kit/memo.rbs +0 -41
  111. data/sig/generated/ruby_mod_kit/mission/fix_parse_error.rbs +0 -73
  112. data/sig/generated/ruby_mod_kit/mission/ivar_arg.rbs +0 -19
  113. data/sig/generated/ruby_mod_kit/mission/overload.rbs +0 -20
  114. data/sig/generated/ruby_mod_kit/mission/type_attr.rbs +0 -18
  115. data/sig/generated/ruby_mod_kit/mission/type_parameter.rbs +0 -18
  116. data/sig/generated/ruby_mod_kit/mission/type_return.rbs +0 -18
  117. data/sig/generated/ruby_mod_kit/node.rbs +0 -63
  118. data/sig/generated/ruby_mod_kit/transpiler.rbs +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83923be4714ddc71e6c09823f58468b46717815164235dc5437d495c62cd6b7c
4
- data.tar.gz: d7a12ed80c113de570b7a1a30c39a0f31d13803c140c1b3c1fe946ec26dde484
3
+ metadata.gz: bb9b6cf5cb887308d1237eb07d40b4b2b2514173c5e76d19e13a27687f2c107f
4
+ data.tar.gz: 418e2d01aec4c8f8b4f0b6241625a0b550aec118a3dbd0618987171bb270e4f7
5
5
  SHA512:
6
- metadata.gz: ffbd1485194583c50a78287cbb779437d1bfe8991e31e4eca113b3ec0af2d06682e42ab652bed96b7bd9edd6595116c94ffac3c34693b4575696a5ba89e48e39
7
- data.tar.gz: 8d5cd3e6989aa21225e9bdaeae4ab68658670bbbb727f5a6f965e3b5e83323a1d79b5debb79861b00fc141bb57f3630a678c5caa386583cb7a4fa0d8eefaaf79
6
+ metadata.gz: 17a8efaedb26b0b3256fd0b24501298a1f56fdf4dc8d5c33adc8cb6005abf6c5fcca4c0d1d634b34784dd2528ec57c8d2effdaf4042bc522a15359c86b01b804
7
+ data.tar.gz: 73758c1ef48bcb7884a6f37859115b952474084abca4b6560f7d21c5380ec4bece1f97e165e6ef27b8270b0f5209877f5b2b63f1cd408ed5b4b6f5cb517d8dc1
data/.ruby_mod_kit.yml ADDED
@@ -0,0 +1,5 @@
1
+ features:
2
+ - instance_variable_parameter
3
+ - overload
4
+ - type
5
+ - type/rbs_inline
@@ -12,7 +12,7 @@ module RubyModKit
12
12
  # @rbs *args: String
13
13
  # @rbs return: void
14
14
  def exec(*args)
15
- RubyModKit.execute_file(*args)
15
+ RubyModKit.execute_file(*args, config: config)
16
16
  end
17
17
 
18
18
  desc "transpile", "transpile rbm files"
@@ -28,9 +28,24 @@ module RubyModKit
28
28
  else
29
29
  options[:output]
30
30
  end
31
+ config = self.config
31
32
  args.each do |path|
32
- RubyModKit.transpile_file(path, output: output || RubyModKit.rb_path(path))
33
+ RubyModKit.transpile_file(path, output: output || RubyModKit.rb_path(path), config: config)
33
34
  end
34
35
  end
36
+
37
+ private
38
+
39
+ # @rbs return: Config | nil
40
+ def config
41
+ if options[:config]
42
+ config_path = options[:config]
43
+ if_none = :raise
44
+ else
45
+ config_path = "."
46
+ if_none = nil
47
+ end
48
+ Config.load(config_path, if_none: if_none)
49
+ end
35
50
  end
36
51
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ require "yaml"
6
+
7
+ module RubyModKit
8
+ # config class
9
+ class Config
10
+ # @rbs @features: Array[Config]
11
+
12
+ attr_reader :features #: Array[Config]
13
+
14
+ DEFAULT_FEATURES = %w[instance_variable_parameter overload type type/rbs_inline].freeze #: Array[String]
15
+
16
+ # @rbs features: Array[String]
17
+ # @rbs return: void
18
+ def initialize(features: DEFAULT_FEATURES)
19
+ @features = features.sort.map do |feature_name|
20
+ raise ArgumentError, "invalid feature: #{feature_name}" if feature_name.include?(".")
21
+
22
+ require "ruby_mod_kit/feature/#{feature_name}"
23
+ const_name = feature_name
24
+ .gsub(/[A-Za-z0-9]+/) { (::Regexp.last_match(0) || "").capitalize }
25
+ .gsub("_", "").gsub("/", "::")
26
+ Feature.const_get(const_name).new
27
+ end
28
+ end
29
+
30
+ class << self
31
+ # @rbs path: String
32
+ # @rbs if_none: nil | Symbol
33
+ # @rbs return: Config | nil
34
+ def load(path, if_none: nil)
35
+ return load(File.join(path, ".ruby_mod_kit.yml"), if_none: if_none) if File.directory?(path)
36
+
37
+ unless File.exist?(path)
38
+ case if_none
39
+ when nil
40
+ return nil
41
+ when :raise
42
+ raise LoadError, "Can't load #{path}"
43
+ else
44
+ raise ArgumentError, "unexpected if_none: #{if_none.inspect}"
45
+ end
46
+ end
47
+
48
+ options = YAML.safe_load(File.read(path), symbolize_names: true)
49
+ new(**options) if options.is_a?(Hash)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -4,6 +4,7 @@
4
4
 
5
5
  require "ruby_mod_kit"
6
6
 
7
+ # Define RubyMotKit.eval
7
8
  module RubyModKit
8
9
  module CoreExt
9
10
  # the extension for eval
@@ -27,4 +28,9 @@ module RubyModKit
27
28
  end
28
29
  end
29
30
  end
31
+
32
+ class << self
33
+ include(CoreExt::Eval)
34
+ public :eval
35
+ end
30
36
  end
@@ -3,8 +3,9 @@
3
3
  # rbs_inline: enabled
4
4
 
5
5
  require "ruby_mod_kit"
6
- require "ruby_mod_kit/core_ext/eval"
6
+ require_relative "eval"
7
7
 
8
+ # Define RubyMotKit.load/require
8
9
  module RubyModKit
9
10
  module CoreExt
10
11
  # the extension for load/require
@@ -15,23 +16,25 @@ module RubyModKit
15
16
 
16
17
  # @rbs path: String
17
18
  # @rbs wrap: bool
18
- # @rbs return: void
19
+ # @rbs return: bool
19
20
  def load(path, wrap = false) # rubocop:disable Style/OptionalBooleanParameter
20
21
  return super unless path.end_with?(".rbm")
21
22
 
22
23
  b = wrap ? binding : TOPLEVEL_BINDING
23
24
  RubyModKit::CoreExt::Eval.eval(File.read(path), b, path)
25
+ true
24
26
  end
25
27
 
26
28
  # @rbs path: String
27
- # @rbs return: void
29
+ # @rbs return: bool
28
30
  def require(path)
29
31
  require_path = Load.require_path(path)
30
32
  return super unless require_path&.end_with?(".rbm")
31
- return if Load.loaded_features.include?(require_path)
33
+ return false if Load.loaded_features.include?(require_path)
32
34
 
33
35
  Load.loaded_features << require_path
34
36
  load(require_path)
37
+ true
35
38
  end
36
39
 
37
40
  class << self
@@ -63,4 +66,9 @@ module RubyModKit
63
66
  end
64
67
  end
65
68
  end
69
+
70
+ class << self
71
+ include(CoreExt::Load)
72
+ public :load, :require, :require_relative
73
+ end
66
74
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "ruby_mod_kit/core_ext/eval"
4
- require "ruby_mod_kit/core_ext/load"
3
+ require_relative "core_ext/eval"
4
+ require_relative "core_ext/load"
5
5
 
6
6
  Object.prepend(RubyModKit::CoreExt::Eval)
7
7
  Object.prepend(RubyModKit::CoreExt::Load)
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ # the base class of corrector
7
+ class Corrector
8
+ # @rbs return: Array[Symbol]
9
+ def correctable_error_types
10
+ []
11
+ end
12
+
13
+ # @rbs _parse_error: Prism::ParseError
14
+ # @rbs _generation: Generation
15
+ # @rbs return: void
16
+ def correct(_parse_error, _generation)
17
+ raise RubyModKit::Error, "Unexpected type #{self.class}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ # the class to manege parse error correctors
7
+ class CorrectorManager
8
+ # @rbs @previous_error_messages: Array[String]
9
+ # @rbs @correctors_error_map: Hash[Symbol, Array[Corrector]]
10
+
11
+ # @rbs features: Array[Feature]
12
+ # @rbs return: void
13
+ def initialize(features)
14
+ @previous_error_messages = []
15
+ @correctors_error_map = {}
16
+ features.each do |feature|
17
+ feature.create_correctors.each do |corrector|
18
+ corrector.correctable_error_types.each do |error_type|
19
+ (@correctors_error_map[error_type] ||= []) << corrector
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # @rbs generation: Generation
26
+ # @rbs return: bool
27
+ def perform(generation)
28
+ return true if generation.errors.empty?
29
+
30
+ check_prev_errors(generation)
31
+ @previous_error_messages = generation.errors.map(&:message)
32
+
33
+ generation.errors.each do |parse_error|
34
+ correctors = @correctors_error_map[parse_error.type] || next
35
+ correctors.each do |corrector|
36
+ corrector.correct(parse_error, generation)
37
+ end
38
+ end
39
+
40
+ false
41
+ end
42
+
43
+ # @rbs generation: Generation
44
+ # @rbs return: void
45
+ def check_prev_errors(generation)
46
+ return if @previous_error_messages.empty?
47
+ return if generation.errors.empty?
48
+ return if @previous_error_messages != generation.errors.map(&:message)
49
+
50
+ message = +""
51
+ generation.errors.each do |parse_error|
52
+ message << "\n" unless message.empty?
53
+ message << "#{generation.name}:#{parse_error.location.start_line}:#{parse_error.message} "
54
+ message << "(#{parse_error.type})"
55
+ line = generation.lines[parse_error.location.start_line - 1]
56
+ if line
57
+ message << "\n#{line.chomp}\n"
58
+ message << "#{" " * parse_error.location.start_column}^#{"~" * [parse_error.location.length - 1, 0].max}"
59
+ end
60
+ end
61
+ raise RubyModKit::SyntaxError, message
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class InstanceVariableParameter
8
+ # the class to correct `def foo(@bar) ...` -> `def foo(bar) ...`
9
+ class InstanceVariableParameterCorrector < Corrector
10
+ # @rbs return: Array[Symbol]
11
+ def correctable_error_types
12
+ %i[argument_formal_ivar]
13
+ end
14
+
15
+ # @rbs parse_error: Prism::ParseError
16
+ # @rbs generation: Generation
17
+ # @rbs return: void
18
+ def correct(parse_error, generation)
19
+ src_offset = parse_error.location.start_offset
20
+
21
+ name = parse_error.location.slice[1..]
22
+ raise RubyModKit::Error unless name
23
+
24
+ parameter_position_node = generation.root_node.node_at(src_offset)
25
+ raise RubyModKit::Error unless parameter_position_node
26
+
27
+ generation[src_offset, parse_error.location.length] = name
28
+ parameter_memo = generation.memo_pad.parameter_memo(parameter_position_node)
29
+ parameter_memo.ivar_parameter = true
30
+
31
+ return unless parameter_memo.untyped?
32
+
33
+ def_parent_node = generation.root_node.def_parent_node_at(parse_error.location.start_offset) || return
34
+ ivar_memo_type = generation.memo_pad.def_parent_memo(def_parent_node).ivar_memo(name.to_sym).type || return
35
+ parameter_memo.type = ivar_memo_type
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class InstanceVariableParameter
8
+ # The mission for instance variable arguments
9
+ class InstanceVariableParameterMission < Mission
10
+ # @rbs generation: Generation
11
+ # @rbs return: bool
12
+ def perform(generation)
13
+ generation.memo_pad.parameters_memo.each_value do |parameter_memo|
14
+ next unless parameter_memo.ivar_parameter
15
+
16
+ offset = parameter_memo.offset
17
+ parameter_node = generation.root_node.parameter_node_at(offset)
18
+ raise RubyModKit::Error unless parameter_node
19
+
20
+ def_node = generation.root_node.def_node_at(offset)
21
+ raise RubyModKit::Error, "DefNode not found" unless def_node
22
+
23
+ def_body_location = def_node.body_location
24
+ end_loc = def_node.end_keyword_loc
25
+ if def_body_location
26
+ indent = def_body_location.start_column
27
+ src_offset = def_body_location.start_offset - indent
28
+ elsif end_loc
29
+ indent = end_loc.start_column + 2
30
+ src_offset = end_loc.start_offset - indent + 2
31
+ end
32
+ raise RubyModKit::Error if !src_offset || !indent
33
+
34
+ name = parameter_node.name
35
+ generation[src_offset, 0] = "#{" " * indent}@#{name} = #{name}\n"
36
+ end
37
+ true
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ # namespace for instance_variable parameter feature
8
+ class InstanceVariableParameter < Feature
9
+ # @rbs return: Array[Corrector]
10
+ def create_correctors
11
+ [
12
+ InstanceVariableParameterCorrector.new,
13
+ ]
14
+ end
15
+
16
+ # @rbs return: Array[Mission]
17
+ def create_missions
18
+ [
19
+ InstanceVariableParameterMission.new,
20
+ ]
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ require_relative "instance_variable_parameter/instance_variable_parameter_corrector"
27
+ require_relative "instance_variable_parameter/instance_variable_parameter_mission"
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Overload
8
+ # The mission for overload
9
+ class OverloadMission < Mission
10
+ # @rbs @modified: bool
11
+
12
+ OVERLOAD_METHOD_MAP = {
13
+ "*": "_mul",
14
+ }.freeze #: Hash[Symbol, String]
15
+
16
+ # @rbs return: void
17
+ def initialize
18
+ super
19
+ @modified = false
20
+ end
21
+
22
+ # @rbs generation: Generation
23
+ # @rbs return: bool
24
+ def perform(generation)
25
+ return true if @modified
26
+
27
+ method_memo_groups = generation.memo_pad.methods_memo.each_value.group_by do |method_memo|
28
+ [generation.root_node.def_parent_node_at(method_memo.offset), method_memo.name]
29
+ end
30
+ method_memo_groups.each_value do |method_memos|
31
+ next if method_memos.length <= 1
32
+
33
+ @modified = true
34
+ first_method_memo = method_memos.first
35
+ name = first_method_memo.name
36
+ first_def_node = generation.root_node.def_node_at(first_method_memo.offset)
37
+ raise RubyModKit::Error unless first_def_node.is_a?(Node::DefNode)
38
+ raise RubyModKit::Error unless name.is_a?(Symbol)
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]
43
+ script = +""
44
+
45
+ overload_memo = generation.memo_pad.overload_memo(first_method_memo.offset, name)
46
+
47
+ method_memos.each do |method_memo|
48
+ type = method_memo.type
49
+ type = "(#{type})" if type.include?(" ")
50
+ overload_memo.add_overload_type(method_memo.parameters.map(&:type), type)
51
+ end
52
+
53
+ 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}"
57
+ def_node = generation.root_node.def_node_at(method_memo.offset)
58
+ raise RubyModKit::Error if !def_node || !def_node.is_a?(Node::DefNode)
59
+
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"
64
+ end
65
+ script << " end\nend\n\n"
66
+
67
+ script.gsub!(/^(?=.)/, indent)
68
+ generation[src_offset, 0] = script
69
+ end
70
+
71
+ # if script has been changed, request reparsing before proceeding to the next mission
72
+ !@modified
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ # namespace for overload feature
8
+ class Overload < Feature
9
+ # @rbs return: Array[Mission]
10
+ def create_missions
11
+ [
12
+ OverloadMission.new,
13
+ ]
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ require_relative "overload/overload_mission"
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ # the class to correct `@var: Type` -> `# @rbs @var: Type`
9
+ class InstanceVariableColonCorrector < Corrector
10
+ VISIBILITIES = %i[private public protected].freeze #: Array[Symbol]
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
13
+
14
+ # @rbs return: Array[Symbol]
15
+ def correctable_error_types
16
+ %i[unexpected_token_ignore]
17
+ end
18
+
19
+ # @rbs parse_error: Prism::ParseError
20
+ # @rbs generation: Generation
21
+ # @rbs return: void
22
+ def correct(parse_error, generation)
23
+ return if parse_error.location.slice != ":"
24
+
25
+ def_parent_node = generation.root_node.statements_node_at(parse_error.location.start_offset)&.parent
26
+ return unless def_parent_node.is_a?(Node::DefParentNode)
27
+
28
+ line = generation.line(parse_error)
29
+ line_offset = generation.src_offset(parse_error) || return
30
+ return if line !~ REGEXP
31
+
32
+ length = ::Regexp.last_match(0)&.length
33
+ indent = ::Regexp.last_match(1)
34
+ visibility = ::Regexp.last_match(2)
35
+ attr_kind = ::Regexp.last_match(3)
36
+ ivar_name = ::Regexp.last_match(4)
37
+ type = ::Regexp.last_match(5)
38
+ return if !length || !indent || !ivar_name || !type
39
+
40
+ ivar_memo = generation.memo_pad.def_parent_memo(def_parent_node).ivar_memo(ivar_name.to_sym)
41
+ ivar_memo.type = type
42
+ ivar_memo.offset = line_offset
43
+ ivar_memo.indent = indent
44
+ ivar_memo.attr_kind = attr_kind if attr_kind
45
+ ivar_memo.visibility = visibility.to_sym if visibility
46
+
47
+ generation[line_offset, length] = ""
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ # the class to correct `def foo(Bar => bar, *Buz => buz)` -> `def foo(bar, *buz)`
9
+ class ParameterArrowCorrector < Corrector
10
+ # @rbs return: Array[Symbol]
11
+ def correctable_error_types
12
+ %i[unexpected_token_ignore def_params_term_paren argument_formal_constant]
13
+ end
14
+
15
+ # @rbs parse_error: Prism::ParseError
16
+ # @rbs generation: Generation
17
+ # @rbs return: void
18
+ def correct(parse_error, generation)
19
+ case parse_error.type
20
+ when :unexpected_token_ignore
21
+ return if parse_error.location.slice != "=>"
22
+
23
+ remove_arrow_before_parameter(parse_error, generation)
24
+ when :def_params_term_paren
25
+ remove_arrow_after_quailifier(parse_error, generation)
26
+ when :argument_formal_constant
27
+ wrap_parameter_type_for_next_parse(parse_error, generation)
28
+ end
29
+ end
30
+
31
+ # @rbs parse_error: Prism::ParseError
32
+ # @rbs generation: Generation
33
+ # @rbs return: void
34
+ def remove_arrow_before_parameter(parse_error, generation)
35
+ def_node = generation.root_node.def_node_at(parse_error.location.start_offset) || return
36
+ def_parent_node = def_node.parent
37
+ parameters_node, body_node, = def_node.children
38
+ return if !def_parent_node || !parameters_node || !body_node
39
+
40
+ last_parameter_node = parameters_node.children.max_by(&:offset) || return
41
+ last_parameter_offset = last_parameter_node.offset
42
+
43
+ right_node = body_node.children.find { _1.offset >= parse_error.location.end_offset } || return
44
+ right_offset = right_node.offset
45
+ parameter_type = generation[last_parameter_offset...right_offset] || raise(RubyModKit::Error)
46
+ 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
49
+ end
50
+
51
+ # @rbs parse_error: Prism::ParseError
52
+ # @rbs generation: Generation
53
+ # @rbs return: void
54
+ def remove_arrow_after_quailifier(parse_error, generation)
55
+ column = parse_error.location.start_column - 1
56
+ return if column < 0
57
+
58
+ 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
62
+ offset = parse_error.location.start_offset - 1
63
+ parameter_position_node = generation.root_node.node_at(offset + length) || return
64
+
65
+ generation[parse_error.location.start_offset, length - 1] = ""
66
+ parameter_memo = generation.memo_pad.parameter_memo(parameter_position_node)
67
+ parameter_memo.type = type
68
+ parameter_memo.qualifier = "*"
69
+ end
70
+
71
+ # @rbs parse_error: Prism::ParseError
72
+ # @rbs generation: Generation
73
+ # @rbs return: void
74
+ def wrap_parameter_type_for_next_parse(parse_error, generation)
75
+ line = generation.line(parse_error)
76
+ line = line[parse_error.location.start_column..] || return
77
+ parameter_type = line[/(\A[A-Z]\w*(?:::[A-Z]\w*)+)(?:\s*=>\s*)/, 1] || return
78
+ src_offset = parse_error.location.start_offset
79
+ generation[src_offset, parameter_type.length] = "(#{parameter_type})"
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ class RbsInline
9
+ # The mission to add magic comment
10
+ class AddMagicCommentMission < Mission
11
+ # @rbs @reloaded: bool
12
+
13
+ # @rbs return: void
14
+ def initialize
15
+ super
16
+ @reloaded = false
17
+ end
18
+
19
+ # @rbs generation: Generation
20
+ # @rbs return: bool
21
+ def perform(generation)
22
+ return true unless generation.memo_pad.flags[:rbs_annotated]
23
+
24
+ unless @reloaded
25
+ @reloaded = true
26
+ return false
27
+ end
28
+
29
+ offset = 0
30
+ separated = false
31
+ generation.lines.each do |line|
32
+ break if line =~ /^# @rbs/
33
+ break if line !~ /^#( rbs_inline: enabled)?|(^$)/
34
+ return true if ::Regexp.last_match(1)
35
+
36
+ separated = !::Regexp.last_match(2).nil?
37
+
38
+ offset += line.length
39
+ end
40
+ script = +""
41
+ script << "\n" unless separated
42
+ generation[offset, 0] = "# rbs_inline: enabled\n\n"
43
+ true
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end