node_mutation 1.11.0 → 1.12.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d41515d4be39619d95802e531496159773a1202de61c8fa3c3d269d2a72926da
4
- data.tar.gz: 2bd0415eec90cb45cdc2dcfacce1cf6529fcdf9f12e6fcd44054aa273e4c4b0b
3
+ metadata.gz: 377cc05adfb7a9f55647b1850a325d9ddcb20004e2574af39657248bd05a51b4
4
+ data.tar.gz: 233c08e3fa49855270f62c11e1d9587b77886e9a6edded54f27096a9dc951849
5
5
  SHA512:
6
- metadata.gz: 656c00012eac7a7b6d2229933fb7e08fd7f0f9a986e90f7db69cc5129097702a2850cdf5494c6f1dae3d6f7da9d0ba642ffd7eb4362517a5c0f465a0d49a52d3
7
- data.tar.gz: 4faced52fd71462a10c54970afb4412858c355c96bf8713e132f886535d3a1309aa792bc1f4e946c0549492c351c9750fa3ab1d05c3ecd0fda0d58f84c98427f
6
+ metadata.gz: 593a0319dc715d587137e840d66694ed6f8c5d4a73312eb20847eee8383b4f47910f25d1d14f1e3fb95bee3ee1ab6627a08fdd2fa40c837c1a4d8e3422237066
7
+ data.tar.gz: 9aca39fb58ae4b02687a310fdcc3a7f388ebc86bcdce29b8efff24069077e3ed9194c9556bd833737160c8a220af87c010eedfd588e71f98c5b3bdae0d578cd3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # NodeMutation
2
2
 
3
+ ## 1.12.1 (2023-03-23)
4
+
5
+ * Define `Action`, `Location` and `Range` in `NodeMutation::Struct`
6
+
7
+ ## 1.12.0 (2023-03-23)
8
+
9
+ * Support `{key}_pair` for a `hash` node
10
+
3
11
  ## 1.11.0 (2023-03-20)
4
12
 
5
13
  * Calculate position properly for `add_comma`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- node_mutation (1.11.0)
4
+ node_mutation (1.12.1)
5
5
  erubis
6
6
 
7
7
  GEM
@@ -17,41 +17,36 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
17
17
  def rewritten_source(node, code)
18
18
  code.gsub(/{{(.+?)}}/m) do
19
19
  old_code = Regexp.last_match(1)
20
- first_key = old_code.split('.').first
21
- if node.respond_to?(first_key)
22
- evaluated = child_node_by_name(node, old_code)
23
- case evaluated
24
- when Parser::AST::Node
25
- if evaluated.type == :args
26
- evaluated.loc.expression.source[1...-1]
20
+ evaluated = child_node_by_name(node, old_code)
21
+ case evaluated
22
+ when Parser::AST::Node
23
+ if evaluated.type == :args
24
+ evaluated.loc.expression.source[1...-1]
25
+ else
26
+ evaluated.loc.expression.source
27
+ end
28
+ when Array
29
+ if evaluated.size > 0
30
+ file_source = file_content(evaluated.first)
31
+ source = file_source[evaluated.first.loc.expression.begin_pos...evaluated.last.loc.expression.end_pos]
32
+ lines = source.split "\n"
33
+ lines_count = lines.length
34
+ if lines_count > 1 && lines_count == evaluated.size
35
+ new_code = []
36
+ lines.each_with_index { |line, index|
37
+ new_code << (index == 0 ? line : line[evaluated.first.indent - 2..-1])
38
+ }
39
+ new_code.join("\n")
27
40
  else
28
- evaluated.loc.expression.source
41
+ source
29
42
  end
30
- when Array
31
- if evaluated.size > 0
32
- file_source = file_content(evaluated.first)
33
- source = file_source[evaluated.first.loc.expression.begin_pos...evaluated.last.loc.expression.end_pos]
34
- lines = source.split "\n"
35
- lines_count = lines.length
36
- if lines_count > 1 && lines_count == evaluated.size
37
- new_code = []
38
- lines.each_with_index { |line, index|
39
- new_code << (index == 0 ? line : line[evaluated.first.indent - 2..-1])
40
- }
41
- new_code.join("\n")
42
- else
43
- source
44
- end
45
- end
46
- when String, Symbol, Integer, Float
47
- evaluated
48
- when NilClass
49
- ''
50
- else
51
- raise "can not parse \"#{code}\""
52
43
  end
44
+ when String, Symbol, Integer, Float
45
+ evaluated
46
+ when NilClass
47
+ ''
53
48
  else
54
- raise NodeMutation::MethodNotSupported, "#{first_key} is not supported for #{get_source(node)}"
49
+ raise "can not parse \"#{code}\""
55
50
  end
56
51
  end
57
52
  end
@@ -70,7 +65,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
70
65
  "#{direct_child_name} is not supported for #{get_source(node)}" unless child_node
71
66
  return child_node_range(child_node, nested_child_name) if nested_child_name
72
67
 
73
- return NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
68
+ return NodeMutation::Struct::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
74
69
  end
75
70
 
76
71
  raise NodeMutation::MethodNotSupported,
@@ -79,35 +74,50 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
79
74
  child_node = node.send(direct_child_name)
80
75
  return child_node_range(child_node, nested_child_name) if nested_child_name
81
76
 
82
- return NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
77
+ return NodeMutation::Struct::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
83
78
  end
84
79
 
85
80
  case [node.type, child_name.to_sym]
86
81
  when %i[block pipes], %i[def parentheses], %i[defs parentheses]
87
- NodeMutation::Range.new(node.arguments.first.loc.expression.begin_pos - 1, node.arguments.last.loc.expression.end_pos + 1)
82
+ NodeMutation::Struct::Range.new(
83
+ node.arguments.first.loc.expression.begin_pos - 1,
84
+ node.arguments.last.loc.expression.end_pos + 1
85
+ )
88
86
  when %i[block arguments], %i[def arguments], %i[defs arguments]
89
- NodeMutation::Range.new(node.arguments.first.loc.expression.begin_pos, node.arguments.last.loc.expression.end_pos)
87
+ NodeMutation::Struct::Range.new(
88
+ node.arguments.first.loc.expression.begin_pos,
89
+ node.arguments.last.loc.expression.end_pos
90
+ )
90
91
  when %i[class name], %i[const name], %i[def name], %i[defs name]
91
- NodeMutation::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
92
+ NodeMutation::Struct::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
92
93
  when %i[defs dot]
93
- NodeMutation::Range.new(node.loc.operator.begin_pos, node.loc.operator.end_pos) if node.loc.operator
94
+ NodeMutation::Struct::Range.new(node.loc.operator.begin_pos, node.loc.operator.end_pos) if node.loc.operator
94
95
  when %i[defs self]
95
- NodeMutation::Range.new(node.loc.operator.begin_pos - 'self'.length, node.loc.operator.begin_pos)
96
+ NodeMutation::Struct::Range.new(node.loc.operator.begin_pos - 'self'.length, node.loc.operator.begin_pos)
96
97
  when %i[lvasgn variable], %i[ivasgn variable], %i[cvasgn variable], %i[gvasgn variable]
97
- NodeMutation::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
98
+ NodeMutation::Struct::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
98
99
  when %i[send dot], %i[csend dot]
99
- NodeMutation::Range.new(node.loc.dot.begin_pos, node.loc.dot.end_pos) if node.loc.dot
100
+ NodeMutation::Struct::Range.new(node.loc.dot.begin_pos, node.loc.dot.end_pos) if node.loc.dot
100
101
  when %i[send message], %i[csend message]
101
102
  if node.loc.operator
102
- NodeMutation::Range.new(node.loc.selector.begin_pos, node.loc.operator.end_pos)
103
+ NodeMutation::Struct::Range.new(node.loc.selector.begin_pos, node.loc.operator.end_pos)
103
104
  else
104
- NodeMutation::Range.new(node.loc.selector.begin_pos, node.loc.selector.end_pos)
105
+ NodeMutation::Struct::Range.new(node.loc.selector.begin_pos, node.loc.selector.end_pos)
105
106
  end
106
107
  when %i[send parentheses], %i[csend parentheses]
107
108
  if node.loc.begin && node.loc.end
108
- NodeMutation::Range.new(node.loc.begin.begin_pos, node.loc.end.end_pos)
109
+ NodeMutation::Struct::Range.new(node.loc.begin.begin_pos, node.loc.end.end_pos)
109
110
  end
110
111
  else
112
+ if node.type == :hash && child_name.to_s.end_with?('_pair')
113
+ pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == child_name.to_s[0..-6] }
114
+ raise NodeMutation::MethodNotSupported,
115
+ "#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
116
+ return child_node_range(pair, nested_child_name) if nested_child_name
117
+
118
+ return NodeMutation::Struct::Range.new(pair_node.loc.expression.begin_pos, pair_node.loc.expression.end_pos)
119
+ end
120
+
111
121
  raise NodeMutation::MethodNotSupported,
112
122
  "#{direct_child_name} is not supported for #{get_source(node)}" unless node.respond_to?(direct_child_name)
113
123
 
@@ -119,7 +129,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
119
129
 
120
130
  if child_node.is_a?(Parser::AST::Node)
121
131
  return(
122
- NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
132
+ NodeMutation::Struct::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
123
133
  )
124
134
  end
125
135
 
@@ -127,7 +137,10 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
127
137
  return nil if child_node.empty?
128
138
 
129
139
  return(
130
- NodeMutation::Range.new(child_node.first.loc.expression.begin_pos, child_node.last.loc.expression.end_pos)
140
+ NodeMutation::Struct::Range.new(
141
+ child_node.first.loc.expression.begin_pos,
142
+ child_node.last.loc.expression.end_pos
143
+ )
131
144
  )
132
145
  end
133
146
  end
@@ -142,12 +155,12 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
142
155
 
143
156
  def get_start_loc(node)
144
157
  begin_loc = node.loc.expression.begin
145
- NodeMutation::Location.new(begin_loc.line, begin_loc.column)
158
+ NodeMutation::Struct::Location.new(begin_loc.line, begin_loc.column)
146
159
  end
147
160
 
148
161
  def get_end_loc(node)
149
162
  end_loc = node.loc.expression.end
150
- NodeMutation::Location.new(end_loc.line, end_loc.column)
163
+ NodeMutation::Struct::Location.new(end_loc.line, end_loc.column)
151
164
  end
152
165
 
153
166
  def get_indent(node)
@@ -178,6 +191,15 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
178
191
  return child_node
179
192
  end
180
193
 
194
+ if node.is_a?(Parser::AST::Node) && node.type == :hash && direct_child_name.end_with?('_pair')
195
+ pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == direct_child_name[0..-6] }
196
+ raise NodeMutation::MethodNotSupported,
197
+ "#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
198
+ return child_node_by_name(pair_node, nested_child_name) if nested_child_name
199
+
200
+ return pair_node
201
+ end
202
+
181
203
  if node.respond_to?(direct_child_name)
182
204
  child_node = node.send(direct_child_name)
183
205
  elsif direct_child_name.include?('(') && direct_child_name.include?(')')
@@ -1,41 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeMutation::Result
4
- attr_accessor :file_path
4
+ attr_accessor :file_path, :new_source
5
+ attr_reader :actions
5
6
 
6
- def initialize(options)
7
- @options = options
7
+ def initialize(affected:, conflicted:)
8
+ @affected = affected
9
+ @conflicted = conflicted
10
+ @actions = []
8
11
  end
9
12
 
10
13
  def affected?
11
- @options[:affected]
14
+ @affected
12
15
  end
13
16
 
14
17
  def conflicted?
15
- @options[:conflicted]
18
+ @conflicted
16
19
  end
17
20
 
18
- def actions
19
- @options[:actions]
20
- end
21
-
22
- def new_source
23
- @options[:new_source]
21
+ def actions=(actions)
22
+ @actions = actions.map { |action| NodeMutation::Struct::Action.new(action.start, action.end, action.new_code) }
24
23
  end
25
24
 
26
25
  def to_json(*args)
27
- to_hash.to_json(*args)
28
- end
29
-
30
- def to_hash
31
- hash = { file_path: file_path }
32
- @options.each do |key, value|
33
- if key == :actions
34
- hash[:actions] = value.map { |action| { start: action.start, end: action.end, new_code: action.new_code } }
35
- else
36
- hash[key] = value
37
- end
38
- end
39
- hash
26
+ data = { affected: affected?, conflicted: conflicted? }
27
+ data[:new_source] = new_source if new_source
28
+ data[:actions] = actions unless actions.empty?
29
+ data.to_json(*args)
40
30
  end
41
31
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NodeMutation::Struct
4
+ Action = Struct.new(:start, :end, :new_code)
5
+ Location = Struct.new(:line, :column)
6
+ Range = Struct.new(:start, :end)
7
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeMutation
4
- VERSION = "1.11.0"
4
+ VERSION = "1.12.1"
5
5
  end
data/lib/node_mutation.rb CHANGED
@@ -18,10 +18,9 @@ class NodeMutation
18
18
  autoload :ReplaceWithAction, 'node_mutation/action/replace_with_action'
19
19
  autoload :WrapAction, 'node_mutation/action/wrap_action'
20
20
  autoload :NoopAction, 'node_mutation/action/noop_action'
21
- autoload :Range, 'node_mutation/range'
22
- autoload :Location, 'node_mutation/location'
23
21
  autoload :Result, 'node_mutation/result'
24
22
  autoload :Strategy, 'node_mutation/strategy'
23
+ autoload :Struct, 'node_mutation/struct'
25
24
 
26
25
  attr_reader :actions
27
26
 
@@ -229,7 +228,9 @@ class NodeMutation
229
228
  @actions.reverse_each do |action|
230
229
  source[action.start...action.end] = action.new_code if action.new_code
231
230
  end
232
- NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?, new_source: source)
231
+ result = NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?)
232
+ result.new_source = source
233
+ result
233
234
  end
234
235
 
235
236
  # Test actions and return the actions.
@@ -241,7 +242,7 @@ class NodeMutation
241
242
  # @return {NodeMutation::Result}
242
243
  def test
243
244
  if @actions.length == 0
244
- return NodeMutation::Result.new(affected: false, conflicted: false, actions: [])
245
+ return NodeMutation::Result.new(affected: false, conflicted: false)
245
246
  end
246
247
 
247
248
  @actions.sort_by! { |action| [action.start, action.end] }
@@ -250,7 +251,9 @@ class NodeMutation
250
251
  raise ConflictActionError, "mutation actions are conflicted"
251
252
  end
252
253
 
253
- NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?, actions: @actions)
254
+ result = NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?)
255
+ result.actions = @actions
256
+ result
254
257
  end
255
258
 
256
259
  private
@@ -5,15 +5,15 @@ class NodeMutation::Adapter[T]
5
5
 
6
6
  def file_content: (node: T) -> String
7
7
 
8
- def child_node_range: (node: T, child_name: String) -> NodeMutation::Range
8
+ def child_node_range: (node: T, child_name: String) -> NodeMutation::Struct::Range
9
9
 
10
10
  def get_start: (node: T) -> Integer
11
11
 
12
12
  def get_end: (node: T) -> Integer
13
13
 
14
- def get_start_loc: (node: T) -> NodeMutation::Location
14
+ def get_start_loc: (node: T) -> NodeMutation::Struct::Location
15
15
 
16
- def get_end_loc: (node: T) -> NodeMutation::Location
16
+ def get_end_loc: (node: T) -> NodeMutation::Struct::Location
17
17
 
18
18
  def get_indent: (node: T) -> Integer
19
19
  end
@@ -1,5 +1,7 @@
1
1
  class NodeMutation::Result
2
2
  attr_accessor file_path (): String
3
+ attr_accessor new_source (): String
4
+ attr_accessor actions (): Array[NodeMutation::Struct::Action]
3
5
 
4
6
  def initialize: (source: String) -> NodeMutation::Result
5
7
 
@@ -7,9 +9,5 @@ class NodeMutation::Result
7
9
 
8
10
  def conflicted?: () -> bool
9
11
 
10
- def new_source: () -> String
11
-
12
- def actions: () -> Array[Hash]
13
-
14
12
  def to_json: (*args) -> String
15
13
  end
@@ -0,0 +1,7 @@
1
+ class NodeMutation::Strategy
2
+ KEEP_RUNNING: Integer
3
+
4
+ THROW_ERROR: Integer
5
+
6
+ ALLOW_INSERT_AT_SAME_POSITION: Integer
7
+ end
@@ -0,0 +1,17 @@
1
+ class NodeMutation::Struct
2
+ class Action < ::Struct
3
+ prop :start, Integer
4
+ prop :end, Integer
5
+ prop :new_code, String
6
+ end
7
+
8
+ class Location < ::Struct
9
+ prop :line, Integer
10
+ prop :column, Integer
11
+ end
12
+
13
+ class Range < ::Struct
14
+ prop :start, Integer
15
+ prop :end, Integer
16
+ end
17
+ end
@@ -1,5 +1,5 @@
1
1
  module NodeMutation[T]
2
- VERSION: Stringo
2
+ VERSION: String
3
3
 
4
4
  class MethodNotSupported < StandardError
5
5
  end
@@ -7,10 +7,6 @@ module NodeMutation[T]
7
7
  class ConflictActionError < StandardError
8
8
  end
9
9
 
10
- KEEP_RUNNING: Integer
11
-
12
- THROW_ERROR: Integer
13
-
14
10
  attr_reader actions: Array[NodeMutation::Action]
15
11
 
16
12
  def self.configure: (options: { adapter: NodeMutation::Adapter, strategy: Integer, tab_width: Integer }) -> void
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: node_mutation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.0
4
+ version: 1.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-03-20 00:00:00.000000000 Z
11
+ date: 2023-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubis
@@ -51,16 +51,17 @@ files:
51
51
  - lib/node_mutation/action/replace_with_action.rb
52
52
  - lib/node_mutation/action/wrap_action.rb
53
53
  - lib/node_mutation/adapter.rb
54
- - lib/node_mutation/location.rb
55
54
  - lib/node_mutation/parser_adapter.rb
56
- - lib/node_mutation/range.rb
57
55
  - lib/node_mutation/result.rb
58
56
  - lib/node_mutation/strategy.rb
57
+ - lib/node_mutation/struct.rb
59
58
  - lib/node_mutation/version.rb
60
59
  - node_mutation.gemspec
61
60
  - sig/node_mutation.rbs
62
61
  - sig/node_mutation/adapter.rbs
63
62
  - sig/node_mutation/result.rbs
63
+ - sig/node_mutation/strategy.rbs
64
+ - sig/node_mutation/struct.rbs
64
65
  homepage: https://github.com/xinminlabs/node-mutation-ruby
65
66
  licenses: []
66
67
  metadata:
@@ -82,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
83
  - !ruby/object:Gem::Version
83
84
  version: '0'
84
85
  requirements: []
85
- rubygems_version: 3.4.6
86
+ rubygems_version: 3.4.7
86
87
  signing_key:
87
88
  specification_version: 4
88
89
  summary: ast node mutation apis
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- NodeMutation::Location = Struct.new(:line, :column)
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- NodeMutation::Range = Struct.new(:start, :end)