node_mutation 1.1.0 → 1.2.0
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +1 -3
- data/README.md +8 -4
- data/lib/node_mutation/result.rb +19 -0
- data/lib/node_mutation/version.rb +1 -1
- data/lib/node_mutation.rb +21 -51
- data/sig/node_mutation/result.rbs +9 -0
- data/sig/node_mutation.rbs +2 -4
- metadata +3 -2
- data/lib/node_mutation/action/replace_erb_stmt_with_expr_action.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c27aac4f89bdddee8f7298469d2f26ad17f38c8ed6eb4e76bf4d7af0ea729f98
|
4
|
+
data.tar.gz: da1d0b9a9b830890583d88b0b74cca800eb991c4eb86e9b232eabd75678538b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12d58838fec06d87e0ffad8fce9a1879221726fa57cf15e0e3c4d08541d7a7ef0fff0249601814edc9bad95e73cc5eac46a9f91a55816fee8c3773b0e397b74e
|
7
|
+
data.tar.gz: '02870efef507899a92a021a8532c175c0ba230815f76eba8391421b97cd628697a035b31bd17110564aa1c273f78db795a7f1a9d775742917abce56ee703efee'
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
node_mutation (1.
|
4
|
+
node_mutation (1.2.0)
|
5
5
|
activesupport
|
6
6
|
erubis
|
7
7
|
|
@@ -18,7 +18,6 @@ GEM
|
|
18
18
|
concurrent-ruby (1.1.10)
|
19
19
|
diff-lcs (1.5.0)
|
20
20
|
erubis (2.7.0)
|
21
|
-
fakefs (1.8.0)
|
22
21
|
ffi (1.15.5)
|
23
22
|
formatador (1.1.0)
|
24
23
|
guard (2.18.0)
|
@@ -84,7 +83,6 @@ PLATFORMS
|
|
84
83
|
x86_64-linux
|
85
84
|
|
86
85
|
DEPENDENCIES
|
87
|
-
fakefs
|
88
86
|
guard
|
89
87
|
guard-rspec
|
90
88
|
node_mutation!
|
data/README.md
CHANGED
@@ -25,7 +25,7 @@ Or install it yourself as:
|
|
25
25
|
```ruby
|
26
26
|
require 'node_mutation'
|
27
27
|
|
28
|
-
mutation = NodeMutation.new(
|
28
|
+
mutation = NodeMutation.new(source)
|
29
29
|
```
|
30
30
|
|
31
31
|
2. call the rewrite apis:
|
@@ -45,8 +45,6 @@ mutation.prepend node, '{{arguments.first}}.include FactoryGirl::Syntax::Methods
|
|
45
45
|
mutation.remove(node: Node)
|
46
46
|
# replace child node of the ast node with new code
|
47
47
|
mutation.replace node, :message, with: 'test'
|
48
|
-
# replace erb stmt node with expr code
|
49
|
-
replace_erb_stmt_with_expr node
|
50
48
|
# replace the ast node with new code
|
51
49
|
mutation.replace_with node, 'create {{arguments}}'
|
52
50
|
# wrap node within a block, class or module
|
@@ -56,7 +54,13 @@ mutation.wrap node, with: 'module Foo'
|
|
56
54
|
3. process actions and write the new source code to file:
|
57
55
|
|
58
56
|
```ruby
|
59
|
-
mutation.process
|
57
|
+
result = mutation.process
|
58
|
+
# if it makes any change to the source
|
59
|
+
result.affected?
|
60
|
+
# if any action is conflicted
|
61
|
+
result.conflicted
|
62
|
+
# return the new source if it is affected
|
63
|
+
result.new_source
|
60
64
|
```
|
61
65
|
|
62
66
|
## Write Adapter
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class NodeMutation::Result
|
4
|
+
def initialize(options)
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def affected?
|
9
|
+
@options[:affected]
|
10
|
+
end
|
11
|
+
|
12
|
+
def conflicted?
|
13
|
+
@options[:conflicted]
|
14
|
+
end
|
15
|
+
|
16
|
+
def new_source
|
17
|
+
@options[:new_source]
|
18
|
+
end
|
19
|
+
end
|
data/lib/node_mutation.rb
CHANGED
@@ -22,10 +22,9 @@ class NodeMutation
|
|
22
22
|
autoload :RemoveAction, 'node_mutation/action/remove_action'
|
23
23
|
autoload :PrependAction, 'node_mutation/action/prepend_action'
|
24
24
|
autoload :ReplaceAction, 'node_mutation/action/replace_action'
|
25
|
-
autoload :ReplaceErbStmtWithExprAction, 'node_mutation/action/replace_erb_stmt_with_expr_action'
|
26
25
|
autoload :ReplaceWithAction, 'node_mutation/action/replace_with_action'
|
27
26
|
autoload :WrapAction, 'node_mutation/action/wrap_action'
|
28
|
-
autoload :
|
27
|
+
autoload :Result, 'node_mutation/result'
|
29
28
|
|
30
29
|
attr_reader :actions
|
31
30
|
|
@@ -55,9 +54,9 @@ class NodeMutation
|
|
55
54
|
end
|
56
55
|
|
57
56
|
# Initialize a NodeMutation.
|
58
|
-
# @param
|
59
|
-
def initialize(
|
60
|
-
@
|
57
|
+
# @param source [String] file source
|
58
|
+
def initialize(source)
|
59
|
+
@source = source
|
61
60
|
@actions = []
|
62
61
|
end
|
63
62
|
|
@@ -176,21 +175,6 @@ class NodeMutation
|
|
176
175
|
@actions << ReplaceAction.new(node, *selectors, with: with).process
|
177
176
|
end
|
178
177
|
|
179
|
-
# Replace erb stmt node with expr code.
|
180
|
-
# @param node [Node] ast node
|
181
|
-
# @example
|
182
|
-
# source code of the ast node is
|
183
|
-
# <% form_for post do |f| %>
|
184
|
-
# <% end %>
|
185
|
-
# then we call
|
186
|
-
# replace_erb_stmt_with_expr(node)
|
187
|
-
# the source code will be rewritten to
|
188
|
-
# # <%= form_for post do |f| %>
|
189
|
-
# # <% end %>
|
190
|
-
def replace_erb_stmt_with_expr(node)
|
191
|
-
@actions << ReplaceErbStmtWithExprAction.new(node).process
|
192
|
-
end
|
193
|
-
|
194
178
|
# Replace source code of the ast node with new code.
|
195
179
|
# @param node [Node] ast node
|
196
180
|
# @param code [String] code need to be replaced with.
|
@@ -233,43 +217,29 @@ class NodeMutation
|
|
233
217
|
# if strategy is set to KEEP_RUNNING.
|
234
218
|
# @return {{conflict: Boolean}} if actions are conflicted
|
235
219
|
def process
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
@actions.sort_by! { |action| [action.start, action.end] }
|
240
|
-
conflict_actions = get_conflict_actions
|
241
|
-
if conflict_actions.size > 0 && NodeMutation.strategy == THROW_ERROR
|
242
|
-
raise ConflictActionError, "mutation actions are conflicted"
|
243
|
-
end
|
244
|
-
@actions.reverse_each do |action|
|
245
|
-
source[action.start...action.end] = action.new_code
|
246
|
-
end
|
247
|
-
@actions = []
|
220
|
+
if @actions.length == 0
|
221
|
+
return NodeMutation::Result.new(affected: false)
|
222
|
+
end
|
248
223
|
|
249
|
-
|
224
|
+
conflict_actions = []
|
225
|
+
source = +@source
|
226
|
+
@actions.sort_by! { |action| [action.start, action.end] }
|
227
|
+
conflict_actions = get_conflict_actions
|
228
|
+
if conflict_actions.size > 0 && NodeMutation.strategy == THROW_ERROR
|
229
|
+
raise ConflictActionError, "mutation actions are conflicted"
|
250
230
|
end
|
251
|
-
|
231
|
+
@actions.reverse_each do |action|
|
232
|
+
source[action.start...action.end] = action.new_code
|
233
|
+
end
|
234
|
+
NodeMutation::Result.new(
|
235
|
+
affected: true,
|
236
|
+
conflicted: !conflict_actions.empty?,
|
237
|
+
new_source: source
|
238
|
+
)
|
252
239
|
end
|
253
240
|
|
254
241
|
private
|
255
242
|
|
256
|
-
# Read file source.
|
257
|
-
# @param file_path [String] file path
|
258
|
-
# @return [String] file source
|
259
|
-
def read_source(file_path)
|
260
|
-
source = File.read(file_path, encoding: 'UTF-8')
|
261
|
-
source = Engine::Erb.encode(source) if /\.erb$/.match?(file_path)
|
262
|
-
source
|
263
|
-
end
|
264
|
-
|
265
|
-
# Write file source to file.
|
266
|
-
# @param file_path [String] file path
|
267
|
-
# @param source [String] file source
|
268
|
-
def write_source(file_path, source)
|
269
|
-
source = Engine::ERB.decode(source) if /\.erb/.match?(file_path)
|
270
|
-
File.write(file_path, source.gsub(/ +\n/, "\n"))
|
271
|
-
end
|
272
|
-
|
273
243
|
# It changes source code from bottom to top, and it can change source code twice at the same time,
|
274
244
|
# So if there is an overlap between two actions, it removes the conflict actions and operate them in the next loop.
|
275
245
|
def get_conflict_actions
|
data/sig/node_mutation.rbs
CHANGED
@@ -19,7 +19,7 @@ module NodeMutation[T]
|
|
19
19
|
|
20
20
|
def self.strategry: () -> Integer
|
21
21
|
|
22
|
-
def initialize: (
|
22
|
+
def initialize: (source: String) -> NodeMutation
|
23
23
|
|
24
24
|
def append: (node: T, code: String) -> void
|
25
25
|
|
@@ -35,11 +35,9 @@ module NodeMutation[T]
|
|
35
35
|
|
36
36
|
def replace: (node: T, *selectors: Array[String], with: String) -> void
|
37
37
|
|
38
|
-
def replace_erb_stmt_with_expr: (node: T) -> void
|
39
|
-
|
40
38
|
def replace_with: (node: T, code: String) -> void
|
41
39
|
|
42
40
|
def wrap: (node: T, with: String) -> void
|
43
41
|
|
44
|
-
def process: () ->
|
42
|
+
def process: () -> NodeMutation::Result
|
45
43
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: node_mutation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Huang
|
@@ -62,17 +62,18 @@ files:
|
|
62
62
|
- lib/node_mutation/action/prepend_action.rb
|
63
63
|
- lib/node_mutation/action/remove_action.rb
|
64
64
|
- lib/node_mutation/action/replace_action.rb
|
65
|
-
- lib/node_mutation/action/replace_erb_stmt_with_expr_action.rb
|
66
65
|
- lib/node_mutation/action/replace_with_action.rb
|
67
66
|
- lib/node_mutation/action/wrap_action.rb
|
68
67
|
- lib/node_mutation/adapter.rb
|
69
68
|
- lib/node_mutation/engine.rb
|
70
69
|
- lib/node_mutation/engine/erb.rb
|
71
70
|
- lib/node_mutation/parser_adapter.rb
|
71
|
+
- lib/node_mutation/result.rb
|
72
72
|
- lib/node_mutation/version.rb
|
73
73
|
- node_mutation.gemspec
|
74
74
|
- sig/node_mutation.rbs
|
75
75
|
- sig/node_mutation/adapter.rbs
|
76
|
+
- sig/node_mutation/result.rbs
|
76
77
|
homepage: https://github.com/xinminlabs/node-mutation-ruby
|
77
78
|
licenses: []
|
78
79
|
metadata:
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# ReplaceErbStmtWithExprAction to replace erb stmt code to expr,
|
4
|
-
# @example
|
5
|
-
# e.g. <% form_for ... %> => <%= form_for ... %>.
|
6
|
-
class NodeMutation::ReplaceErbStmtWithExprAction < NodeMutation::Action
|
7
|
-
# Initialize a ReplaceErbStmtWithExprAction.
|
8
|
-
#
|
9
|
-
# @param node [Synvert::Core::Rewriter::Node]
|
10
|
-
def initialize(node)
|
11
|
-
super(node, nil)
|
12
|
-
end
|
13
|
-
|
14
|
-
# The new erb expr code.
|
15
|
-
#
|
16
|
-
# @return [String] new code.
|
17
|
-
def new_code
|
18
|
-
NodeMutation.adapter.file_content(@node)[@start...@end]
|
19
|
-
.sub(NodeMutation::Engine::ERUBY_STMT_SPLITTER, '@output_buffer.append= ')
|
20
|
-
.sub(NodeMutation::Engine::ERUBY_STMT_SPLITTER, NodeMutation::Engine::ERUBY_EXPR_SPLITTER)
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
# Calculate the begin the end positions.
|
26
|
-
def calculate_position
|
27
|
-
node_start = NodeMutation.adapter.get_start(@node)
|
28
|
-
node_source = NodeMutation.adapter.get_source(@node)
|
29
|
-
file_content = NodeMutation.adapter.file_content(@node)
|
30
|
-
|
31
|
-
whitespace_index = node_start
|
32
|
-
while file_content[whitespace_index -= 1] == ' '
|
33
|
-
end
|
34
|
-
@start = whitespace_index - NodeMutation::Engine::ERUBY_STMT_SPLITTER.length + 1
|
35
|
-
|
36
|
-
at_index = node_start + node_source.index('do')
|
37
|
-
while file_content[at_index += 1] != '@'
|
38
|
-
end
|
39
|
-
@end = at_index
|
40
|
-
end
|
41
|
-
end
|