ruby_mod_kit 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby_mod_kit.yml +5 -0
  3. data/README.md +89 -0
  4. data/lib/ruby_mod_kit/cli.rb +17 -2
  5. data/lib/ruby_mod_kit/config.rb +53 -0
  6. data/lib/ruby_mod_kit/core_ext/eval.rb +6 -10
  7. data/lib/ruby_mod_kit/corrector.rb +4 -3
  8. data/lib/ruby_mod_kit/corrector_manager.rb +18 -18
  9. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_corrector.rb +5 -7
  10. data/lib/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rb +4 -11
  11. data/lib/ruby_mod_kit/feature/overload/overload_mission.rb +8 -12
  12. data/lib/ruby_mod_kit/feature/type/check/arguments/add_arguments_checker_mission.rb +56 -0
  13. data/lib/ruby_mod_kit/feature/type/check/arguments.rb +23 -0
  14. data/lib/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rb +20 -12
  15. data/lib/ruby_mod_kit/feature/type/parameter_arrow_corrector.rb +35 -19
  16. data/lib/ruby_mod_kit/feature/type/rbs_inline/add_magic_comment_mission.rb +49 -0
  17. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_attr_mission.rb +12 -7
  18. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rb +7 -8
  19. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rb +6 -9
  20. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rb +9 -10
  21. data/lib/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rb +5 -7
  22. data/lib/ruby_mod_kit/feature/type/rbs_inline.rb +3 -0
  23. data/lib/ruby_mod_kit/feature/type/return_value_colon_corrector.rb +5 -6
  24. data/lib/ruby_mod_kit/feature/type/type_attr_mission.rb +13 -17
  25. data/lib/ruby_mod_kit/feature/type/yard/type_parameter_mission.rb +35 -0
  26. data/lib/ruby_mod_kit/feature/type/yard/type_return_mission.rb +30 -0
  27. data/lib/ruby_mod_kit/feature/type/yard.rb +31 -0
  28. data/lib/ruby_mod_kit/feature.rb +0 -6
  29. data/lib/ruby_mod_kit/generation.rb +83 -39
  30. data/lib/ruby_mod_kit/memo/ivar_memo.rb +4 -0
  31. data/lib/ruby_mod_kit/memo/overload_memo.rb +1 -0
  32. data/lib/ruby_mod_kit/memo/parameter_memo.rb +4 -2
  33. data/lib/ruby_mod_kit/memo.rb +0 -2
  34. data/lib/ruby_mod_kit/memo_pad.rb +9 -0
  35. data/lib/ruby_mod_kit/mission.rb +1 -8
  36. data/lib/ruby_mod_kit/node/base_node.rb +39 -12
  37. data/lib/ruby_mod_kit/node/begin_node.rb +31 -0
  38. data/lib/ruby_mod_kit/node/call_node.rb +1 -1
  39. data/lib/ruby_mod_kit/node/def_node.rb +1 -1
  40. data/lib/ruby_mod_kit/node/def_parent_node.rb +13 -6
  41. data/lib/ruby_mod_kit/node/parameter_node.rb +3 -3
  42. data/lib/ruby_mod_kit/node/program_node.rb +6 -1
  43. data/lib/ruby_mod_kit/node/statements_node.rb +1 -1
  44. data/lib/ruby_mod_kit/node/symbol_node.rb +2 -1
  45. data/lib/ruby_mod_kit/node/untyped_node.rb +1 -1
  46. data/lib/ruby_mod_kit/node/wrap.rb +3 -1
  47. data/lib/ruby_mod_kit/node.rb +1 -2
  48. data/lib/ruby_mod_kit/version.rb +1 -1
  49. data/lib/ruby_mod_kit.rb +11 -11
  50. data/ruby_mod_kit.gemspec +7 -1
  51. data/sig/generated/ruby_mod_kit/cli.rbs +5 -0
  52. data/sig/generated/ruby_mod_kit/config.rbs +21 -0
  53. data/sig/generated/ruby_mod_kit/core_ext/eval.rbs +4 -2
  54. data/sig/generated/ruby_mod_kit/corrector.rbs +4 -3
  55. data/sig/generated/ruby_mod_kit/corrector_manager.rbs +3 -7
  56. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_corrector.rbs +1 -3
  57. data/sig/generated/ruby_mod_kit/feature/instance_variable_parameter/instance_variable_parameter_mission.rbs +1 -8
  58. data/sig/generated/ruby_mod_kit/feature/overload/overload_mission.rbs +1 -4
  59. data/sig/generated/ruby_mod_kit/feature/type/check/arguments/add_arguments_checker_mission.rbs +16 -0
  60. data/sig/generated/ruby_mod_kit/feature/type/check/arguments.rbs +15 -0
  61. data/sig/generated/ruby_mod_kit/feature/type/instance_variable_colon_corrector.rbs +7 -3
  62. data/sig/generated/ruby_mod_kit/feature/type/parameter_arrow_corrector.rbs +8 -9
  63. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/add_magic_comment_mission.rbs +21 -0
  64. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_attr_mission.rbs +1 -4
  65. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_instance_variable_mission.rbs +1 -4
  66. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_overload_mission.rbs +1 -4
  67. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_parameter_mission.rbs +1 -4
  68. data/sig/generated/ruby_mod_kit/feature/type/rbs_inline/type_return_mission.rbs +1 -4
  69. data/sig/generated/ruby_mod_kit/feature/type/return_value_colon_corrector.rbs +1 -3
  70. data/sig/generated/ruby_mod_kit/feature/type/type_attr_mission.rbs +3 -4
  71. data/sig/generated/ruby_mod_kit/feature/type/yard/type_parameter_mission.rbs +16 -0
  72. data/sig/generated/ruby_mod_kit/feature/type/yard/type_return_mission.rbs +16 -0
  73. data/sig/generated/ruby_mod_kit/feature/type/yard.rbs +17 -0
  74. data/sig/generated/ruby_mod_kit/feature.rbs +0 -4
  75. data/sig/generated/ruby_mod_kit/generation.rbs +55 -15
  76. data/sig/generated/ruby_mod_kit/memo/ivar_memo.rbs +8 -0
  77. data/sig/generated/ruby_mod_kit/memo/overload_memo.rbs +2 -0
  78. data/sig/generated/ruby_mod_kit/memo/parameter_memo.rbs +6 -2
  79. data/sig/generated/ruby_mod_kit/memo_pad.rbs +8 -0
  80. data/sig/generated/ruby_mod_kit/mission.rbs +1 -8
  81. data/sig/generated/ruby_mod_kit/node/base_node.rbs +22 -8
  82. data/sig/generated/ruby_mod_kit/node/begin_node.rbs +26 -0
  83. data/sig/generated/ruby_mod_kit/node/def_parent_node.rbs +5 -0
  84. data/sig/generated/ruby_mod_kit/node/parameter_node.rbs +1 -1
  85. data/sig/generated/ruby_mod_kit/node/program_node.rbs +3 -0
  86. data/sig/generated/ruby_mod_kit/node/symbol_node.rbs +2 -0
  87. data/sig/generated/ruby_mod_kit.rbs +6 -3
  88. data/sig/yaml.rbs +3 -0
  89. metadata +21 -5
  90. data/sig/generated/ruby_mod_kit/memo.rbs +0 -7
  91. data/sig/generated/ruby_mod_kit/node.rbs +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36509ee4c00db1106b7447ba1d4fe09ee2fd2a8f8ce763c40b1da185f19cfc61
4
- data.tar.gz: eccbdb68bb6159aa95c7fda5d171e4089b9dfa9b262ef136caf019fa3c339d7f
3
+ metadata.gz: e5888d6187dc2620b37315d72fddee6b134bbd14181277ff600e864eb9c06ca0
4
+ data.tar.gz: 7ffb4ec96c231e6122eeaa7d47601f67a28620951ed08e9d3b3888e9fa684fbc
5
5
  SHA512:
6
- metadata.gz: a8b12f06259193345becd29a14a1c6397481c41b390daed390cf4ed0bc7016afe0fbcf9ba95a9c3639b37150c98791d3e501cf2490725bfc5cf3c405fdc99f94
7
- data.tar.gz: 684d9b858ac50e78b40f92a2d1cb8ddaafb99983bbdafc7788d786878af5b03c2187995bbe312de59495c9e4f796c352a9e203428d91018075a88791a79320eb
6
+ metadata.gz: 3c2e632593d2d0a7061f8a71a7e65131a1b72434ac3853467024503d13c57328abe88ade105b2532baf94d44bd428bd02b4eae9e0c50462d4dca6bebc767d4f9
7
+ data.tar.gz: 81b17d66702c1fc89c77bc3270f74608fca6ed8e9a12f26c04ea69f7d0bdceb4b91b104bfa45b0f944e5ba5dae79e789de720b8a5605df0d4ac4bb4e48e62d6d
data/.ruby_mod_kit.yml ADDED
@@ -0,0 +1,5 @@
1
+ features:
2
+ - instance_variable_parameter
3
+ - overload
4
+ - type
5
+ - type/rbs_inline
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`
@@ -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
@@ -12,19 +12,15 @@ module RubyModKit
12
12
  module_function
13
13
 
14
14
  # @rbs expr: String
15
- # @rbs *rest: Object
15
+ # @rbs binding: Binding
16
+ # @rbs fname: String
17
+ # @rbs lineno: Integer
16
18
  # @rbs transpile: bool
17
19
  # @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
20
+ def eval(expr, binding = TOPLEVEL_BINDING, fname = "(eval)", lineno = 1, transpile: true)
21
+ expr = RubyModKit.transpile(expr, filename: fname) if transpile
23
22
 
24
- case rest
25
- in [] | [Binding] | [Binding, String] | [Binding, String, Integer]
26
- super(expr, *rest)
27
- end
23
+ super(expr, binding, fname, lineno)
28
24
  end
29
25
  end
30
26
  end
@@ -12,11 +12,12 @@ module RubyModKit
12
12
 
13
13
  # @rbs _parse_error: Prism::ParseError
14
14
  # @rbs _generation: Generation
15
- # @rbs _root_node: Node::ProgramNode
16
- # @rbs _memo_pad: MemoPad
17
15
  # @rbs return: void
18
- def correct(_parse_error, _generation, _root_node, _memo_pad)
16
+ def correct(_parse_error, _generation)
19
17
  raise RubyModKit::Error, "Unexpected type #{self.class}"
20
18
  end
19
+
20
+ # @rbs return: void
21
+ def setup; end
21
22
  end
22
23
  end
@@ -5,13 +5,13 @@
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
13
  def initialize(features)
14
- @previous_error_messages = []
14
+ @previous_source = +""
15
15
  @correctors_error_map = {}
16
16
  features.each do |feature|
17
17
  feature.create_correctors.each do |corrector|
@@ -23,20 +23,21 @@ module RubyModKit
23
23
  end
24
24
 
25
25
  # @rbs generation: Generation
26
- # @rbs root_node: Node::ProgramNode
27
- # @rbs parse_result: Prism::ParseResult
28
- # @rbs memo_pad: MemoPad
29
26
  # @rbs return: bool
30
- def perform(generation, root_node, parse_result, memo_pad)
31
- return true if parse_result.errors.empty?
27
+ def perform(generation)
28
+ return true if generation.errors.empty?
32
29
 
33
- check_prev_errors(generation, parse_result)
34
- @previous_error_messages = parse_result.errors.map(&:message)
30
+ check_prev_errors(generation)
31
+ @previous_source = generation.script.dup
35
32
 
36
- parse_result.errors.each do |parse_error|
33
+ @correctors_error_map.each_value do |correctors|
34
+ correctors.each(&:setup)
35
+ end
36
+
37
+ generation.errors.each do |parse_error|
37
38
  correctors = @correctors_error_map[parse_error.type] || next
38
39
  correctors.each do |corrector|
39
- corrector.correct(parse_error, generation, root_node, memo_pad)
40
+ corrector.correct(parse_error, generation)
40
41
  end
41
42
  end
42
43
 
@@ -44,19 +45,18 @@ module RubyModKit
44
45
  end
45
46
 
46
47
  # @rbs generation: Generation
47
- # @rbs parse_result: Prism::ParseResult
48
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)
49
+ def check_prev_errors(generation)
50
+ return if @previous_source.empty?
51
+ return if generation.errors.empty?
52
+ return if @previous_source != generation.script
53
53
 
54
54
  message = +""
55
- parse_result.errors.each do |parse_error|
55
+ generation.errors.each do |parse_error|
56
56
  message << "\n" unless message.empty?
57
57
  message << "#{generation.name}:#{parse_error.location.start_line}:#{parse_error.message} "
58
58
  message << "(#{parse_error.type})"
59
- line = parse_result.source.lines[parse_error.location.start_line - 1]
59
+ line = generation.line(parse_error)
60
60
  if line
61
61
  message << "\n#{line.chomp}\n"
62
62
  message << "#{" " * parse_error.location.start_column}^#{"~" * [parse_error.location.length - 1, 0].max}"
@@ -14,26 +14,24 @@ module RubyModKit
14
14
 
15
15
  # @rbs parse_error: Prism::ParseError
16
16
  # @rbs generation: Generation
17
- # @rbs root_node: Node::ProgramNode
18
- # @rbs memo_pad: MemoPad
19
17
  # @rbs return: void
20
- def correct(parse_error, generation, root_node, memo_pad)
18
+ def correct(parse_error, generation)
21
19
  src_offset = parse_error.location.start_offset
22
20
 
23
21
  name = parse_error.location.slice[1..]
24
22
  raise RubyModKit::Error unless name
25
23
 
26
- parameter_position_node = root_node.node_at(src_offset)
24
+ parameter_position_node = generation.root_node.node_at(src_offset)
27
25
  raise RubyModKit::Error unless parameter_position_node
28
26
 
29
27
  generation[src_offset, parse_error.location.length] = name
30
- parameter_memo = memo_pad.parameter_memo(parameter_position_node)
28
+ parameter_memo = generation.memo_pad.parameter_memo(parameter_position_node)
31
29
  parameter_memo.ivar_parameter = true
32
30
 
33
31
  return unless parameter_memo.untyped?
34
32
 
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
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
37
35
  parameter_memo.type = ivar_memo_type
38
36
  end
39
37
  end
@@ -7,24 +7,17 @@ module RubyModKit
7
7
  class InstanceVariableParameter
8
8
  # The mission for instance variable arguments
9
9
  class InstanceVariableParameterMission < Mission
10
- # @rbs @assignment: String
11
-
12
- attr_reader :assignment #: String
13
-
14
10
  # @rbs generation: Generation
15
- # @rbs root_node: Node::ProgramNode
16
- # @rbs _parse_result: Prism::ParseResult
17
- # @rbs memo_pad: MemoPad
18
11
  # @rbs return: bool
19
- def perform(generation, root_node, _parse_result, memo_pad)
20
- memo_pad.parameters_memo.each_value do |parameter_memo|
12
+ def perform(generation)
13
+ generation.memo_pad.each_parameter_memo do |parameter_memo|
21
14
  next unless parameter_memo.ivar_parameter
22
15
 
23
16
  offset = parameter_memo.offset
24
- parameter_node = root_node.parameter_node_at(offset)
17
+ parameter_node = generation.root_node.parameter_node_at(offset)
25
18
  raise RubyModKit::Error unless parameter_node
26
19
 
27
- def_node = root_node.def_node_at(offset)
20
+ def_node = generation.root_node.def_node_at(offset)
28
21
  raise RubyModKit::Error, "DefNode not found" unless def_node
29
22
 
30
23
  def_body_location = def_node.body_location
@@ -20,15 +20,12 @@ module RubyModKit
20
20
  end
21
21
 
22
22
  # @rbs generation: Generation
23
- # @rbs root_node: Node::ProgramNode
24
- # @rbs parse_result: Prism::ParseResult
25
- # @rbs memo_pad: MemoPad
26
23
  # @rbs return: bool
27
- def perform(generation, root_node, parse_result, memo_pad)
24
+ def perform(generation)
28
25
  return true if @modified
29
26
 
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]
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]
32
29
  end
33
30
  method_memo_groups.each_value do |method_memos|
34
31
  next if method_memos.length <= 1
@@ -36,16 +33,15 @@ module RubyModKit
36
33
  @modified = true
37
34
  first_method_memo = method_memos.first
38
35
  name = first_method_memo.name
39
- first_def_node = root_node.def_node_at(first_method_memo.offset)
36
+ first_def_node = generation.root_node.def_node_at(first_method_memo.offset)
40
37
  raise RubyModKit::Error unless first_def_node.is_a?(Node::DefNode)
41
38
  raise RubyModKit::Error unless name.is_a?(Symbol)
42
39
 
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]
40
+ indent = generation.line_indent(first_def_node)
41
+ src_offset = generation.line_offset(first_def_node) || raise(RubyModKit::Error)
46
42
  script = +""
47
43
 
48
- overload_memo = memo_pad.overload_memo(first_method_memo.offset, name)
44
+ overload_memo = generation.memo_pad.overload_memo(first_method_memo.offset, name)
49
45
 
50
46
  method_memos.each do |method_memo|
51
47
  type = method_memo.type
@@ -57,7 +53,7 @@ module RubyModKit
57
53
  overload_prefix = +"#{OVERLOAD_METHOD_MAP[name] || name}_"
58
54
  method_memos.each_with_index do |method_memo, i|
59
55
  overload_name = "#{overload_prefix}_overload#{i}"
60
- def_node = root_node.def_node_at(method_memo.offset)
56
+ def_node = generation.root_node.def_node_at(method_memo.offset)
61
57
  raise RubyModKit::Error if !def_node || !def_node.is_a?(Node::DefNode)
62
58
 
63
59
  name_loc = def_node.name_loc
@@ -0,0 +1,56 @@
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
+ def perform(generation)
14
+ # reload if line break is added
15
+ line_break_added = false
16
+
17
+ generation.memo_pad.methods_memo.each do |offset, method_memo|
18
+ def_node = generation.root_node.def_node_at(offset)
19
+ raise RubyModKit::Error, "DefNode not found" unless def_node
20
+ next if method_memo.parameters.empty?
21
+
22
+ def_line = generation.line(def_node.location.start_line - 1)
23
+ def_indent = def_line[/\A\s*/] || ""
24
+
25
+ location = def_node.body_location || def_node.end_keyword_loc
26
+ next unless location
27
+
28
+ def_right_loc = def_node.rparen_loc || def_node.name_loc
29
+ offset = location.start_offset - location.start_column
30
+ indent = "#{def_indent} "
31
+ if location.start_line == def_right_loc.end_line
32
+ between_def_and_loc = generation[def_right_loc.end_offset...location.start_offset]
33
+ length = between_def_and_loc[/\A[ ^t]*;[ ^t]*\z/]&.length
34
+ if length
35
+ line_break_added = true
36
+ generation[def_right_loc.end_offset, length] = "\n#{def_indent}"
37
+ end
38
+ end
39
+ next if line_break_added
40
+
41
+ method_memo.parameters.each do |parameter_memo|
42
+ next if parameter_memo.untyped? || !parameter_memo.name
43
+ next if parameter_memo.qualifier # TODO: qualifier support
44
+
45
+ type = parameter_memo.type
46
+ type = type.gsub(/\[([^\[\]]+)\]/, "") # TODO: type variable support
47
+ generation[offset, 0] = "#{indent}#{parameter_memo.name} => #{type}\n"
48
+ end
49
+ end
50
+ !line_break_added
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module RubyModKit
6
+ class Feature
7
+ class Type
8
+ module Check
9
+ # namespace for arguments type checker
10
+ class Arguments < Feature
11
+ # @rbs return: Array[Mission]
12
+ def create_missions
13
+ [
14
+ AddArgumentsCheckerMission.new,
15
+ ]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ require_relative "arguments/add_arguments_checker_mission"
@@ -7,6 +7,10 @@ module RubyModKit
7
7
  class Type
8
8
  # the class to correct `@var: Type` -> `# @rbs @var: Type`
9
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(\n+)?/.freeze #: Regexp
13
+
10
14
  # @rbs return: Array[Symbol]
11
15
  def correctable_error_types
12
16
  %i[unexpected_token_ignore]
@@ -14,32 +18,36 @@ module RubyModKit
14
18
 
15
19
  # @rbs parse_error: Prism::ParseError
16
20
  # @rbs generation: Generation
17
- # @rbs root_node: Node::ProgramNode
18
- # @rbs memo_pad: MemoPad
19
21
  # @rbs return: void
20
- def correct(parse_error, generation, root_node, memo_pad)
22
+ def correct(parse_error, generation)
21
23
  return if parse_error.location.slice != ":"
22
24
 
23
- def_parent_node = root_node.statements_node_at(parse_error.location.start_offset)&.parent
25
+ def_parent_node = generation.root_node.def_parent_node_at(
26
+ parse_error.location.start_offset,
27
+ allowed: [Node::CallNode, Node::UntypedNode, Node::StatementsNode],
28
+ )
24
29
  return unless def_parent_node.is_a?(Node::DefParentNode)
25
30
 
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/
31
+ line_offset = generation.line_offset(parse_error) || return
32
+ line = generation[line_offset..]
33
+ return if line !~ REGEXP
30
34
 
31
35
  length = ::Regexp.last_match(0)&.length
32
36
  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)
37
+ visibility = ::Regexp.last_match(2)
38
+ attr_kind = ::Regexp.last_match(3)
39
+ ivar_name = ::Regexp.last_match(4)
40
+ type = ::Regexp.last_match(5)
41
+ separator = ::Regexp.last_match(6)
36
42
  return if !length || !indent || !ivar_name || !type
37
43
 
38
- ivar_memo = memo_pad.def_parent_memo(def_parent_node).ivar_memo(ivar_name.to_sym)
44
+ ivar_memo = generation.memo_pad.def_parent_memo(def_parent_node).ivar_memo(ivar_name.to_sym)
39
45
  ivar_memo.type = type
40
46
  ivar_memo.offset = line_offset
41
47
  ivar_memo.indent = indent
42
48
  ivar_memo.attr_kind = attr_kind if attr_kind
49
+ ivar_memo.visibility = visibility.to_sym if visibility
50
+ ivar_memo.separator = separator if separator
43
51
 
44
52
  generation[line_offset, length] = ""
45
53
  end