ruby_mod_kit 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -8
  3. data/lib/ruby_mod_kit/cli.rb +10 -1
  4. data/lib/ruby_mod_kit/core_ext/eval.rb +36 -0
  5. data/lib/ruby_mod_kit/core_ext/load.rb +74 -0
  6. data/lib/ruby_mod_kit/core_ext.rb +7 -0
  7. data/lib/ruby_mod_kit/corrector.rb +22 -0
  8. data/lib/ruby_mod_kit/corrector_manager.rb +68 -0
  9. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_corrector.rb +42 -0
  10. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rb +49 -0
  11. data/lib/ruby_mod_kit/feature/instance_variable_parameter.rb +27 -0
  12. data/lib/ruby_mod_kit/feature/overload/overload_mission.rb +80 -0
  13. data/lib/ruby_mod_kit/feature/overload.rb +19 -0
  14. data/lib/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rb +49 -0
  15. data/lib/ruby_mod_kit/feature/type/parameter_arrow_corrector.rb +90 -0
  16. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_attr_mission.rb +41 -0
  17. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rb +31 -0
  18. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rb +43 -0
  19. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rb +38 -0
  20. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rb +32 -0
  21. data/lib/ruby_mod_kit/feature/type/rbs_inline.rb +29 -0
  22. data/lib/ruby_mod_kit/feature/type/return_value_colon_corrector.rb +45 -0
  23. data/lib/ruby_mod_kit/feature/type/type_attr_mission.rb +67 -0
  24. data/lib/ruby_mod_kit/feature/type.rb +31 -0
  25. data/lib/ruby_mod_kit/feature.rb +24 -0
  26. data/lib/ruby_mod_kit/generation.rb +60 -22
  27. data/lib/ruby_mod_kit/memo/def_parent_memo.rb +36 -0
  28. data/lib/ruby_mod_kit/memo/{ivar.rb → ivar_memo.rb} +17 -3
  29. data/lib/ruby_mod_kit/memo/{method.rb → method_memo.rb} +7 -7
  30. data/lib/ruby_mod_kit/memo/offset_memo.rb +1 -1
  31. data/lib/ruby_mod_kit/memo/overload_memo.rb +46 -0
  32. data/lib/ruby_mod_kit/memo/{parameter.rb → parameter_memo.rb} +3 -3
  33. data/lib/ruby_mod_kit/memo.rb +7 -64
  34. data/lib/ruby_mod_kit/memo_pad.rb +69 -0
  35. data/lib/ruby_mod_kit/mission.rb +5 -24
  36. data/lib/ruby_mod_kit/node/base_node.rb +137 -0
  37. data/lib/ruby_mod_kit/node/call_node.rb +10 -6
  38. data/lib/ruby_mod_kit/node/def_node.rb +10 -6
  39. data/lib/ruby_mod_kit/node/def_parent_node.rb +41 -0
  40. data/lib/ruby_mod_kit/node/parameter_node.rb +12 -8
  41. data/lib/ruby_mod_kit/node/program_node.rb +2 -2
  42. data/lib/ruby_mod_kit/node/statements_node.rb +10 -6
  43. data/lib/ruby_mod_kit/node/symbol_node.rb +10 -6
  44. data/lib/ruby_mod_kit/node/untyped_node.rb +10 -6
  45. data/lib/ruby_mod_kit/node/wrap.rb +43 -0
  46. data/lib/ruby_mod_kit/node.rb +5 -149
  47. data/lib/ruby_mod_kit/offset_diff.rb +12 -6
  48. data/lib/ruby_mod_kit/version.rb +1 -1
  49. data/lib/ruby_mod_kit.rb +43 -11
  50. data/ruby_mod_kit.gemspec +1 -6
  51. data/sig/generated/ruby_mod_kit/core_ext/eval.rbs +17 -0
  52. data/sig/generated/ruby_mod_kit/core_ext/load.rbs +33 -0
  53. data/sig/generated/ruby_mod_kit/corrector.rbs +16 -0
  54. data/sig/generated/ruby_mod_kit/corrector_manager.rbs +26 -0
  55. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_corrector.rbs +20 -0
  56. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rbs +21 -0
  57. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter.rbs +14 -0
  58. data/sig/generated/ruby_mod_kit/feature/overload/overload_mission.rbs +24 -0
  59. data/sig/generated/ruby_mod_kit/feature/overload.rbs +11 -0
  60. data/sig/generated/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rbs +20 -0
  61. data/sig/generated/ruby_mod_kit/feature/type/parameter_arrow_corrector.rbs +39 -0
  62. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_attr_mission.rbs +19 -0
  63. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rbs +19 -0
  64. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rbs +19 -0
  65. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rbs +19 -0
  66. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rbs +19 -0
  67. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline.rbs +13 -0
  68. data/sig/generated/ruby_mod_kit/feature/type/return_value_colon_corrector.rbs +20 -0
  69. data/sig/generated/ruby_mod_kit/feature/type/type_attr_mission.rbs +20 -0
  70. data/sig/generated/ruby_mod_kit/feature/type.rbs +14 -0
  71. data/sig/generated/ruby_mod_kit/feature.rbs +16 -0
  72. data/sig/generated/ruby_mod_kit/generation.rbs +25 -10
  73. data/sig/generated/ruby_mod_kit/memo/def_parent_memo.rbs +24 -0
  74. data/sig/generated/ruby_mod_kit/memo/{ivar.rbs → ivar_memo.rbs} +15 -3
  75. data/sig/generated/ruby_mod_kit/memo/{method.rbs → method_memo.rbs} +8 -8
  76. data/sig/generated/ruby_mod_kit/memo/offset_memo.rbs +1 -1
  77. data/sig/generated/ruby_mod_kit/memo/overload_memo.rbs +32 -0
  78. data/sig/generated/ruby_mod_kit/memo/{parameter.rbs → parameter_memo.rbs} +3 -3
  79. data/sig/generated/ruby_mod_kit/memo.rbs +2 -36
  80. data/sig/generated/ruby_mod_kit/memo_pad.rbs +46 -0
  81. data/sig/generated/ruby_mod_kit/mission.rbs +4 -12
  82. data/sig/generated/ruby_mod_kit/node/base_node.rbs +65 -0
  83. data/sig/generated/ruby_mod_kit/node/call_node.rbs +11 -6
  84. data/sig/generated/ruby_mod_kit/node/def_node.rbs +11 -6
  85. data/sig/generated/ruby_mod_kit/node/def_parent_node.rbs +31 -0
  86. data/sig/generated/ruby_mod_kit/node/parameter_node.rbs +13 -8
  87. data/sig/generated/ruby_mod_kit/node/program_node.rbs +2 -2
  88. data/sig/generated/ruby_mod_kit/node/statements_node.rbs +11 -6
  89. data/sig/generated/ruby_mod_kit/node/symbol_node.rbs +11 -6
  90. data/sig/generated/ruby_mod_kit/node/untyped_node.rbs +11 -6
  91. data/sig/generated/ruby_mod_kit/node/wrap.rbs +12 -0
  92. data/sig/generated/ruby_mod_kit/node.rbs +2 -58
  93. data/sig/generated/ruby_mod_kit/offset_diff.rbs +3 -1
  94. data/sig/generated/ruby_mod_kit.rbs +13 -2
  95. data/sig/thor.rbs +2 -0
  96. metadata +63 -43
  97. data/lib/ruby_mod_kit/memo/class.rb +0 -27
  98. data/lib/ruby_mod_kit/mission/fix_parse_error.rb +0 -213
  99. data/lib/ruby_mod_kit/mission/ivar_arg.rb +0 -42
  100. data/lib/ruby_mod_kit/mission/overload.rb +0 -73
  101. data/lib/ruby_mod_kit/mission/type_attr.rb +0 -75
  102. data/lib/ruby_mod_kit/mission/type_parameter.rb +0 -39
  103. data/lib/ruby_mod_kit/mission/type_return.rb +0 -33
  104. data/lib/ruby_mod_kit/node/class_node.rb +0 -37
  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/class.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/mission/fix_parse_error.rbs +0 -73
  111. data/sig/generated/ruby_mod_kit/mission/ivar_arg.rbs +0 -19
  112. data/sig/generated/ruby_mod_kit/mission/overload.rbs +0 -20
  113. data/sig/generated/ruby_mod_kit/mission/type_attr.rbs +0 -18
  114. data/sig/generated/ruby_mod_kit/mission/type_parameter.rbs +0 -18
  115. data/sig/generated/ruby_mod_kit/mission/type_return.rbs +0 -18
  116. data/sig/generated/ruby_mod_kit/node/class_node.rbs +0 -29
  117. 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: e3a08a3d1865aa1abd27922326dc12e4cfc6c9a621f0c73882a64c12a80cc3d4
4
- data.tar.gz: d30dd20e654a68c233f33925f6f27938a3920675df07dea1377f31ba8fa42ab6
3
+ metadata.gz: 36509ee4c00db1106b7447ba1d4fe09ee2fd2a8f8ce763c40b1da185f19cfc61
4
+ data.tar.gz: eccbdb68bb6159aa95c7fda5d171e4089b9dfa9b262ef136caf019fa3c339d7f
5
5
  SHA512:
6
- metadata.gz: cc67818cecc1c39a1aaf1f925a8ebd59dab9220a77e0d1e2dd19be99ea7b8b72e582e4a8d794966ab411125b229084f339f85cd427eebf33e29f88ee576eb111
7
- data.tar.gz: ed11c866fba06fe283e1957ba41c2138194cdc3d5049dfe9cefdee662519d3e222ef5ac8b9b5f491e579fef4db049c11b3b46074f5f7fe8585c7cf2c84ab94d5
6
+ metadata.gz: a8b12f06259193345becd29a14a1c6397481c41b390daed390cf4ed0bc7016afe0fbcf9ba95a9c3639b37150c98791d3e501cf2490725bfc5cf3c405fdc99f94
7
+ data.tar.gz: 684d9b858ac50e78b40f92a2d1cb8ddaafb99983bbdafc7788d786878af5b03c2187995bbe312de59495c9e4f796c352a9e203428d91018075a88791a79320eb
data/README.md CHANGED
@@ -20,20 +20,26 @@ If bundler is not being used to manage dependencies, install the gem by executin
20
20
  #### `transpile`
21
21
 
22
22
  You can get transpiled ruby script from .rbm file by `ruby_mod_kit transpile` command.
23
+ `transpile` command outputs script to stdout by default. `--output` can change output target.
24
+ `--output=.rb` is a special pattern that means "Output the original script file name with the extension changed to .rb".
23
25
 
24
- ```
25
- ruby_mod_kit transpile path/to/script.rbm
26
- ```
26
+ These below have the same meaning: "Output ruby script to stdout".
27
+
28
+ $ ruby_mod_kit transpile path/to/script.rbm
29
+ $ ruby_mod_kit transpile --output=- path/to/script.rbm
30
+ $ ruby_mod_kit transpile --output=/dev/stdout path/to/script.rbm
31
+
32
+ These below have the same meaning: "Output ruby script to `path/to/script.rb`".
33
+
34
+ $ ruby_mod_kit transpile path/to/script.rbm > path/to/script.rb
35
+ $ ruby_mod_kit transpile --output=path/to/script.rb path/to/script.rbm
36
+ $ ruby_mod_kit transpile --output=.rb path/to/script.rbm
27
37
 
28
38
  #### `exec`
29
39
 
30
40
  You can run transpiled ruby script by `ruby_mod_kit exec` command.
31
41
 
32
- ```
33
- ruby_mod_kit transpile path/to/script.rbm
34
- ```
35
-
36
- The command also creates/updates ruby script before running.
42
+ $ ruby_mod_kit exec path/to/script.rbm
37
43
 
38
44
  ## Feature
39
45
 
@@ -16,11 +16,20 @@ module RubyModKit
16
16
  end
17
17
 
18
18
  desc "transpile", "transpile rbm files"
19
+ method_option :output, type: :string
19
20
  # @rbs *args: String
20
21
  # @rbs return: void
21
22
  def transpile(*args)
23
+ output = case options[:output]
24
+ when nil, "-", "/dev/stdout"
25
+ $stdout
26
+ when ".rb"
27
+ nil
28
+ else
29
+ options[:output]
30
+ end
22
31
  args.each do |path|
23
- RubyModKit.transpile_file(path)
32
+ RubyModKit.transpile_file(path, output: output || RubyModKit.rb_path(path))
24
33
  end
25
34
  end
26
35
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ require "ruby_mod_kit"
6
+
7
+ # Define RubyMotKit.eval
8
+ module RubyModKit
9
+ module CoreExt
10
+ # the extension for eval
11
+ module Eval
12
+ module_function
13
+
14
+ # @rbs expr: String
15
+ # @rbs *rest: Object
16
+ # @rbs transpile: bool
17
+ # @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
23
+
24
+ case rest
25
+ in [] | [Binding] | [Binding, String] | [Binding, String, Integer]
26
+ super(expr, *rest)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ class << self
33
+ include(CoreExt::Eval)
34
+ public :eval
35
+ end
36
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ require "ruby_mod_kit"
6
+ require_relative "eval"
7
+
8
+ # Define RubyMotKit.load/require
9
+ module RubyModKit
10
+ module CoreExt
11
+ # the extension for load/require
12
+ module Load
13
+ LOADABLE_EXTS = %w[.rb .rbm .so .o .dll].freeze #: Array[String]
14
+
15
+ module_function
16
+
17
+ # @rbs path: String
18
+ # @rbs wrap: bool
19
+ # @rbs return: bool
20
+ def load(path, wrap = false) # rubocop:disable Style/OptionalBooleanParameter
21
+ return super unless path.end_with?(".rbm")
22
+
23
+ b = wrap ? binding : TOPLEVEL_BINDING
24
+ RubyModKit::CoreExt::Eval.eval(File.read(path), b, path)
25
+ true
26
+ end
27
+
28
+ # @rbs path: String
29
+ # @rbs return: bool
30
+ def require(path)
31
+ require_path = Load.require_path(path)
32
+ return super unless require_path&.end_with?(".rbm")
33
+ return false if Load.loaded_features.include?(require_path)
34
+
35
+ Load.loaded_features << require_path
36
+ load(require_path)
37
+ true
38
+ end
39
+
40
+ class << self
41
+ # @rbs return: Array[String]
42
+ def loaded_features
43
+ $LOADED_FEATURES
44
+ end
45
+
46
+ # @rbs return: Array[String]
47
+ def load_path
48
+ $LOAD_PATH
49
+ end
50
+
51
+ # @rbs path: String
52
+ # @rbs expanded: bool
53
+ # @rbs return: String | nil
54
+ def require_path(path, expanded: false)
55
+ if !expanded && !File.absolute_path?(path)
56
+ return load_path.each.lazy.map { require_path(File.join(_1, path), expanded: true) }.find(&:itself)
57
+ end
58
+
59
+ pathes = if path.end_with?(*LOADABLE_EXTS)
60
+ [path]
61
+ else
62
+ LOADABLE_EXTS.map { "#{path}#{_1}" }
63
+ end
64
+ pathes.find { File.exist?(_1) }
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ class << self
71
+ include(CoreExt::Load)
72
+ public :load, :require, :require_relative
73
+ end
74
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "core_ext/eval"
4
+ require_relative "core_ext/load"
5
+
6
+ Object.prepend(RubyModKit::CoreExt::Eval)
7
+ Object.prepend(RubyModKit::CoreExt::Load)
@@ -0,0 +1,22 @@
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 _root_node: Node::ProgramNode
16
+ # @rbs _memo_pad: MemoPad
17
+ # @rbs return: void
18
+ def correct(_parse_error, _generation, _root_node, _memo_pad)
19
+ raise RubyModKit::Error, "Unexpected type #{self.class}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,68 @@
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 root_node: Node::ProgramNode
27
+ # @rbs parse_result: Prism::ParseResult
28
+ # @rbs memo_pad: MemoPad
29
+ # @rbs return: bool
30
+ def perform(generation, root_node, parse_result, memo_pad)
31
+ return true if parse_result.errors.empty?
32
+
33
+ check_prev_errors(generation, parse_result)
34
+ @previous_error_messages = parse_result.errors.map(&:message)
35
+
36
+ parse_result.errors.each do |parse_error|
37
+ correctors = @correctors_error_map[parse_error.type] || next
38
+ correctors.each do |corrector|
39
+ corrector.correct(parse_error, generation, root_node, memo_pad)
40
+ end
41
+ end
42
+
43
+ false
44
+ end
45
+
46
+ # @rbs generation: Generation
47
+ # @rbs parse_result: Prism::ParseResult
48
+ # @rbs return: void
49
+ def check_prev_errors(generation, parse_result)
50
+ return if @previous_error_messages.empty?
51
+ return if parse_result.errors.empty?
52
+ return if @previous_error_messages != parse_result.errors.map(&:message)
53
+
54
+ message = +""
55
+ parse_result.errors.each do |parse_error|
56
+ message << "\n" unless message.empty?
57
+ message << "#{generation.name}:#{parse_error.location.start_line}:#{parse_error.message} "
58
+ message << "(#{parse_error.type})"
59
+ line = parse_result.source.lines[parse_error.location.start_line - 1]
60
+ if line
61
+ message << "\n#{line.chomp}\n"
62
+ message << "#{" " * parse_error.location.start_column}^#{"~" * [parse_error.location.length - 1, 0].max}"
63
+ end
64
+ end
65
+ raise RubyModKit::SyntaxError, message
66
+ end
67
+ end
68
+ 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 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 root_node: Node::ProgramNode
18
+ # @rbs memo_pad: MemoPad
19
+ # @rbs return: void
20
+ def correct(parse_error, generation, root_node, memo_pad)
21
+ src_offset = parse_error.location.start_offset
22
+
23
+ name = parse_error.location.slice[1..]
24
+ raise RubyModKit::Error unless name
25
+
26
+ parameter_position_node = root_node.node_at(src_offset)
27
+ raise RubyModKit::Error unless parameter_position_node
28
+
29
+ generation[src_offset, parse_error.location.length] = name
30
+ parameter_memo = memo_pad.parameter_memo(parameter_position_node)
31
+ parameter_memo.ivar_parameter = true
32
+
33
+ return unless parameter_memo.untyped?
34
+
35
+ def_parent_node = root_node.def_parent_node_at(parse_error.location.start_offset) || return
36
+ ivar_memo_type = memo_pad.def_parent_memo(def_parent_node).ivar_memo(name.to_sym).type || return
37
+ parameter_memo.type = ivar_memo_type
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,49 @@
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 @assignment: String
11
+
12
+ attr_reader :assignment #: String
13
+
14
+ # @rbs generation: Generation
15
+ # @rbs root_node: Node::ProgramNode
16
+ # @rbs _parse_result: Prism::ParseResult
17
+ # @rbs memo_pad: MemoPad
18
+ # @rbs return: bool
19
+ def perform(generation, root_node, _parse_result, memo_pad)
20
+ memo_pad.parameters_memo.each_value do |parameter_memo|
21
+ next unless parameter_memo.ivar_parameter
22
+
23
+ offset = parameter_memo.offset
24
+ parameter_node = root_node.parameter_node_at(offset)
25
+ raise RubyModKit::Error unless parameter_node
26
+
27
+ def_node = root_node.def_node_at(offset)
28
+ raise RubyModKit::Error, "DefNode not found" unless def_node
29
+
30
+ def_body_location = def_node.body_location
31
+ end_loc = def_node.end_keyword_loc
32
+ if def_body_location
33
+ indent = def_body_location.start_column
34
+ src_offset = def_body_location.start_offset - indent
35
+ elsif end_loc
36
+ indent = end_loc.start_column + 2
37
+ src_offset = end_loc.start_offset - indent + 2
38
+ end
39
+ raise RubyModKit::Error if !src_offset || !indent
40
+
41
+ name = parameter_node.name
42
+ generation[src_offset, 0] = "#{" " * indent}@#{name} = #{name}\n"
43
+ end
44
+ true
45
+ end
46
+ end
47
+ end
48
+ end
49
+ 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,80 @@
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 root_node: Node::ProgramNode
24
+ # @rbs parse_result: Prism::ParseResult
25
+ # @rbs memo_pad: MemoPad
26
+ # @rbs return: bool
27
+ def perform(generation, root_node, parse_result, memo_pad)
28
+ return true if @modified
29
+
30
+ method_memo_groups = memo_pad.methods_memo.each_value.group_by do |method_memo|
31
+ [root_node.def_parent_node_at(method_memo.offset), method_memo.name]
32
+ end
33
+ method_memo_groups.each_value do |method_memos|
34
+ next if method_memos.length <= 1
35
+
36
+ @modified = true
37
+ first_method_memo = method_memos.first
38
+ name = first_method_memo.name
39
+ first_def_node = root_node.def_node_at(first_method_memo.offset)
40
+ raise RubyModKit::Error unless first_def_node.is_a?(Node::DefNode)
41
+ raise RubyModKit::Error unless name.is_a?(Symbol)
42
+
43
+ start_line = first_def_node.location.start_line - 1
44
+ indent = parse_result.source.lines[start_line][/\A */] || ""
45
+ src_offset = parse_result.source.offsets[start_line]
46
+ script = +""
47
+
48
+ overload_memo = memo_pad.overload_memo(first_method_memo.offset, name)
49
+
50
+ method_memos.each do |method_memo|
51
+ type = method_memo.type
52
+ type = "(#{type})" if type.include?(" ")
53
+ overload_memo.add_overload_type(method_memo.parameters.map(&:type), type)
54
+ end
55
+
56
+ script << "def #{name}(*args)\n case args\n"
57
+ overload_prefix = +"#{OVERLOAD_METHOD_MAP[name] || name}_"
58
+ method_memos.each_with_index do |method_memo, i|
59
+ overload_name = "#{overload_prefix}_overload#{i}"
60
+ def_node = root_node.def_node_at(method_memo.offset)
61
+ raise RubyModKit::Error if !def_node || !def_node.is_a?(Node::DefNode)
62
+
63
+ name_loc = def_node.name_loc
64
+ generation[name_loc.start_offset, name_loc.length] = overload_name
65
+ script << " in [#{method_memo.parameters.map(&:type).join(", ")}]\n"
66
+ script << " #{overload_name}(*args)\n"
67
+ end
68
+ script << " end\nend\n\n"
69
+
70
+ script.gsub!(/^(?=.)/, indent)
71
+ generation[src_offset, 0] = script
72
+ end
73
+
74
+ # if script has been changed, request reparsing before proceeding to the next mission
75
+ !@modified
76
+ end
77
+ end
78
+ end
79
+ end
80
+ 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,49 @@
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
+ # @rbs return: Array[Symbol]
11
+ def correctable_error_types
12
+ %i[unexpected_token_ignore]
13
+ end
14
+
15
+ # @rbs parse_error: Prism::ParseError
16
+ # @rbs generation: Generation
17
+ # @rbs root_node: Node::ProgramNode
18
+ # @rbs memo_pad: MemoPad
19
+ # @rbs return: void
20
+ def correct(parse_error, generation, root_node, memo_pad)
21
+ return if parse_error.location.slice != ":"
22
+
23
+ def_parent_node = root_node.statements_node_at(parse_error.location.start_offset)&.parent
24
+ return unless def_parent_node.is_a?(Node::DefParentNode)
25
+
26
+ line = generation.line(parse_error)
27
+ line_offset = generation.src_offset(parse_error) || return
28
+ attr_patterns = %i[attr_reader reader getter attr_writer writer setter attr_accessor accessor property]
29
+ return if line !~ /(\A\s*)(?:(#{attr_patterns.join("|")}) )?@(\w*)\s*:\s*(.*)\n/
30
+
31
+ length = ::Regexp.last_match(0)&.length
32
+ indent = ::Regexp.last_match(1)
33
+ attr_kind = ::Regexp.last_match(2)
34
+ ivar_name = ::Regexp.last_match(3)
35
+ type = ::Regexp.last_match(4)
36
+ return if !length || !indent || !ivar_name || !type
37
+
38
+ ivar_memo = memo_pad.def_parent_memo(def_parent_node).ivar_memo(ivar_name.to_sym)
39
+ ivar_memo.type = type
40
+ ivar_memo.offset = line_offset
41
+ ivar_memo.indent = indent
42
+ ivar_memo.attr_kind = attr_kind if attr_kind
43
+
44
+ generation[line_offset, length] = ""
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,90 @@
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 root_node: Node::ProgramNode
18
+ # @rbs memo_pad: MemoPad
19
+ # @rbs return: void
20
+ def correct(parse_error, generation, root_node, memo_pad)
21
+ case parse_error.type
22
+ when :unexpected_token_ignore
23
+ return if parse_error.location.slice != "=>"
24
+
25
+ remove_arrow_before_parameter(parse_error, generation, root_node, memo_pad)
26
+ when :def_params_term_paren
27
+ remove_arrow_after_quailifier(parse_error, generation, root_node, memo_pad)
28
+ when :argument_formal_constant
29
+ wrap_parameter_type_for_next_parse(parse_error, generation)
30
+ end
31
+ end
32
+
33
+ # @rbs parse_error: Prism::ParseError
34
+ # @rbs generation: Generation
35
+ # @rbs root_node: Node::ProgramNode
36
+ # @rbs memo_pad: MemoPad
37
+ # @rbs return: void
38
+ def remove_arrow_before_parameter(parse_error, generation, root_node, memo_pad)
39
+ def_node = root_node.def_node_at(parse_error.location.start_offset) || return
40
+ def_parent_node = def_node.parent
41
+ parameters_node, body_node, = def_node.children
42
+ return if !def_parent_node || !parameters_node || !body_node
43
+
44
+ last_parameter_node = parameters_node.children.max_by(&:offset) || return
45
+ last_parameter_offset = last_parameter_node.offset
46
+
47
+ right_node = body_node.children.find { _1.offset >= parse_error.location.end_offset } || return
48
+ right_offset = right_node.offset
49
+ parameter_type = generation[last_parameter_offset...right_offset] || raise(RubyModKit::Error)
50
+ parameter_type = parameter_type.sub(/\s*=>\s*\z/, "")
51
+ generation[last_parameter_offset, right_offset - last_parameter_offset] = ""
52
+ memo_pad.parameter_memo(last_parameter_node).type = parameter_type
53
+ end
54
+
55
+ # @rbs parse_error: Prism::ParseError
56
+ # @rbs generation: Generation
57
+ # @rbs root_node: Node::ProgramNode
58
+ # @rbs memo_pad: MemoPad
59
+ # @rbs return: void
60
+ def remove_arrow_after_quailifier(parse_error, generation, root_node, memo_pad)
61
+ column = parse_error.location.start_column - 1
62
+ return if column < 0
63
+
64
+ line = generation.line(parse_error)[column..] || return
65
+ line =~ /\A\*(.*?)\s*=>\s*/
66
+ length = ::Regexp.last_match(0)&.length || return
67
+ type = ::Regexp.last_match(1) || return
68
+ offset = parse_error.location.start_offset - 1
69
+ parameter_position_node = root_node.node_at(offset + length) || return
70
+
71
+ generation[parse_error.location.start_offset, length - 1] = ""
72
+ parameter_memo = memo_pad.parameter_memo(parameter_position_node)
73
+ parameter_memo.type = type
74
+ parameter_memo.qualifier = "*"
75
+ end
76
+
77
+ # @rbs parse_error: Prism::ParseError
78
+ # @rbs generation: Generation
79
+ # @rbs return: void
80
+ def wrap_parameter_type_for_next_parse(parse_error, generation)
81
+ line = generation.line(parse_error)
82
+ line = line[parse_error.location.start_column..] || return
83
+ parameter_type = line[/(\A[A-Z]\w*(?:::[A-Z]\w*)+)(?:\s*=>\s*)/, 1] || return
84
+ src_offset = parse_error.location.start_offset
85
+ generation[src_offset, parameter_type.length] = "(#{parameter_type})"
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,41 @@
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 for parameter types
10
+ class TypeAttrMission < Mission
11
+ # @rbs generation: Generation
12
+ # @rbs root_node: Node::ProgramNode
13
+ # @rbs _parse_result: Prism::ParseResult
14
+ # @rbs memo_pad: MemoPad
15
+ # @rbs return: bool
16
+ def perform(generation, root_node, _parse_result, memo_pad)
17
+ memo_pad.def_parents_memo.each_value do |def_parent_memo|
18
+ ivars_memo = def_parent_memo.ivars_memo.dup
19
+ def_parent_node = root_node.def_parent_node_at(def_parent_memo.offset) || raise(RubyModKit::Error)
20
+ def_parent_node.body_node&.children&.each do |call_node|
21
+ break if ivars_memo.empty?
22
+ next unless call_node.is_a?(Node::CallNode)
23
+ next unless %i[attr_reader attr_writer attr_accessor].include?(call_node.name)
24
+
25
+ argument_nodes = call_node.children[0].children
26
+ next if argument_nodes.size != 1 || !argument_nodes[0].is_a?(Node::SymbolNode)
27
+
28
+ name = argument_nodes[0].value || next
29
+ ivar_memo = ivars_memo.delete(name) || next
30
+ line = generation.line(call_node)
31
+ length = line[/\A\s*(#{call_node.name}\s+:#{name})(?=\n\z)/, 1]&.length || next
32
+ generation[call_node.location.start_offset + length, 0] = " #: #{ivar_memo.type}"
33
+ end
34
+ end
35
+ true
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end