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