ruby_mod_kit 0.0.2 → 0.0.4

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