synvert-core 1.4.0 → 1.5.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/.gitignore +0 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +0 -3
- data/Guardfile +0 -9
- data/README.md +30 -12
- data/Rakefile +1 -15
- data/lib/synvert/core/engine/erb.rb +1 -1
- data/lib/synvert/core/engine.rb +1 -1
- data/lib/synvert/core/node_ext.rb +0 -466
- data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +20 -17
- data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +1 -1
- data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +1 -1
- data/lib/synvert/core/rewriter/instance.rb +83 -133
- data/lib/synvert/core/rewriter/scope/query_scope.rb +2 -2
- data/lib/synvert/core/rewriter/scope/within_scope.rb +4 -4
- data/lib/synvert/core/rewriter.rb +0 -10
- data/lib/synvert/core/version.rb +1 -1
- data/lib/synvert/core.rb +4 -6
- data/spec/synvert/core/engine/erb_spec.rb +3 -3
- data/spec/synvert/core/node_ext_spec.rb +0 -795
- data/spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb +21 -1
- data/spec/synvert/core/rewriter/instance_spec.rb +47 -115
- data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +1 -4
- data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +1 -4
- data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +1 -4
- data/synvert-core-ruby.gemspec +4 -2
- metadata +44 -61
- data/lib/synvert/core/array_ext.rb +0 -48
- data/lib/synvert/core/node_query/compiler/array.rb +0 -34
- data/lib/synvert/core/node_query/compiler/attribute.rb +0 -39
- data/lib/synvert/core/node_query/compiler/attribute_list.rb +0 -24
- data/lib/synvert/core/node_query/compiler/basic_selector.rb +0 -28
- data/lib/synvert/core/node_query/compiler/boolean.rb +0 -23
- data/lib/synvert/core/node_query/compiler/comparable.rb +0 -86
- data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +0 -51
- data/lib/synvert/core/node_query/compiler/expression.rb +0 -41
- data/lib/synvert/core/node_query/compiler/float.rb +0 -23
- data/lib/synvert/core/node_query/compiler/identifier.rb +0 -41
- data/lib/synvert/core/node_query/compiler/integer.rb +0 -23
- data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +0 -7
- data/lib/synvert/core/node_query/compiler/nil.rb +0 -23
- data/lib/synvert/core/node_query/compiler/parse_error.rb +0 -7
- data/lib/synvert/core/node_query/compiler/regexp.rb +0 -37
- data/lib/synvert/core/node_query/compiler/selector.rb +0 -113
- data/lib/synvert/core/node_query/compiler/string.rb +0 -23
- data/lib/synvert/core/node_query/compiler/symbol.rb +0 -23
- data/lib/synvert/core/node_query/compiler.rb +0 -25
- data/lib/synvert/core/node_query/lexer.rex +0 -99
- data/lib/synvert/core/node_query/lexer.rex.rb +0 -299
- data/lib/synvert/core/node_query/parser.racc.rb +0 -306
- data/lib/synvert/core/node_query/parser.y +0 -60
- data/lib/synvert/core/node_query.rb +0 -36
- data/lib/synvert/core/rewriter/action/append_action.rb +0 -28
- data/lib/synvert/core/rewriter/action/delete_action.rb +0 -34
- data/lib/synvert/core/rewriter/action/insert_action.rb +0 -34
- data/lib/synvert/core/rewriter/action/insert_after_action.rb +0 -22
- data/lib/synvert/core/rewriter/action/prepend_action.rb +0 -44
- data/lib/synvert/core/rewriter/action/remove_action.rb +0 -56
- data/lib/synvert/core/rewriter/action/replace_action.rb +0 -33
- data/lib/synvert/core/rewriter/action/replace_with_action.rb +0 -36
- data/lib/synvert/core/rewriter/action/wrap_action.rb +0 -37
- data/lib/synvert/core/rewriter/action.rb +0 -102
- data/spec/synvert/core/node_query/lexer_spec.rb +0 -580
- data/spec/synvert/core/node_query/parser_spec.rb +0 -337
- data/spec/synvert/core/rewriter/action/append_action_spec.rb +0 -70
- data/spec/synvert/core/rewriter/action/delete_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/insert_action_spec.rb +0 -70
- data/spec/synvert/core/rewriter/action/insert_after_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/prepend_action_spec.rb +0 -175
- data/spec/synvert/core/rewriter/action/remove_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/replace_action_spec.rb +0 -28
- data/spec/synvert/core/rewriter/action/replace_with_action_spec.rb +0 -59
- data/spec/synvert/core/rewriter/action/wrap_action_spec.rb +0 -31
- data/spec/synvert/core/rewriter/action_spec.rb +0 -14
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# AppendAction appends code to the bottom of node body.
|
5
|
-
class Rewriter::AppendAction < Rewriter::Action
|
6
|
-
private
|
7
|
-
|
8
|
-
END_LENGTH = "\nend".length
|
9
|
-
|
10
|
-
# Calculate the begin the end positions.
|
11
|
-
def calculate_position
|
12
|
-
@begin_pos = :begin == @node.type ? @node.loc.expression.end_pos : @node.loc.expression.end_pos - @node.column - END_LENGTH
|
13
|
-
@end_pos = @begin_pos
|
14
|
-
end
|
15
|
-
|
16
|
-
# Indent of the node.
|
17
|
-
#
|
18
|
-
# @param node [Parser::AST::Node]
|
19
|
-
# @return [String] n times whitesphace
|
20
|
-
def indent(node)
|
21
|
-
if %i[block class def defs].include? node.type
|
22
|
-
' ' * (node.column + DEFAULT_INDENT)
|
23
|
-
else
|
24
|
-
' ' * node.column
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# DeleteAction deletes child nodes.
|
5
|
-
class Rewriter::DeleteAction < Rewriter::Action
|
6
|
-
# Initialize a DeleteAction.
|
7
|
-
#
|
8
|
-
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
-
# @param selectors [Array<Symbol, String>] used to select child nodes
|
10
|
-
# @option and_comma [Boolean] delete extra comma.
|
11
|
-
def initialize(instance, *selectors, and_comma: false)
|
12
|
-
super(instance, nil)
|
13
|
-
@selectors = selectors
|
14
|
-
@and_comma = and_comma
|
15
|
-
end
|
16
|
-
|
17
|
-
# The rewritten code, always empty string.
|
18
|
-
def rewritten_code
|
19
|
-
''
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
# Calculate the begin and end positions.
|
25
|
-
def calculate_position
|
26
|
-
@begin_pos = @selectors.map { |selector| @node.child_node_range(selector) }
|
27
|
-
.compact.map(&:begin_pos).min
|
28
|
-
@end_pos = @selectors.map { |selector| @node.child_node_range(selector) }
|
29
|
-
.compact.map(&:end_pos).max
|
30
|
-
squeeze_spaces
|
31
|
-
remove_comma if @and_comma
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# InsertAction to add code to the node.
|
5
|
-
class Rewriter::InsertAction < Rewriter::Action
|
6
|
-
# Initialize an InsertAction.
|
7
|
-
#
|
8
|
-
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
-
# @param code [String] to be inserted
|
10
|
-
# @param at [String] position to insert, beginning or end
|
11
|
-
# @param to [<Symbol|String>] name of child node
|
12
|
-
def initialize(instance, code, at: 'end', to: nil)
|
13
|
-
super(instance, code)
|
14
|
-
@at = at
|
15
|
-
@to = to
|
16
|
-
end
|
17
|
-
|
18
|
-
# The rewritten source code.
|
19
|
-
#
|
20
|
-
# @return [String] rewritten code.
|
21
|
-
def rewritten_code
|
22
|
-
rewritten_source
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
# Calculate the begin and end positions.
|
28
|
-
def calculate_position
|
29
|
-
node_range = @to ? @node.child_node_range(@to) : @node.loc.expression
|
30
|
-
@begin_pos = @at == 'end' ? node_range.end_pos : node_range.begin_pos
|
31
|
-
@end_pos = @begin_pos
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# InsertAfterAction to insert code next to the node.
|
5
|
-
class Rewriter::InsertAfterAction < Rewriter::Action
|
6
|
-
private
|
7
|
-
|
8
|
-
# Calculate the begin and end positions.
|
9
|
-
def calculate_position
|
10
|
-
@begin_pos = @node.loc.expression.end_pos
|
11
|
-
@end_pos = @begin_pos
|
12
|
-
end
|
13
|
-
|
14
|
-
# Indent of the node.
|
15
|
-
#
|
16
|
-
# @param node [Parser::AST::Node]
|
17
|
-
# @return [String] n times whitesphace
|
18
|
-
def indent(node)
|
19
|
-
' ' * node.column
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# PrependAction to prepend code to the top of node body.
|
5
|
-
class Rewriter::PrependAction < Rewriter::Action
|
6
|
-
private
|
7
|
-
|
8
|
-
DO_LENGTH = ' do'.length
|
9
|
-
|
10
|
-
# Calculate the begin and end positions.
|
11
|
-
def calculate_position
|
12
|
-
@begin_pos =
|
13
|
-
case @node.type
|
14
|
-
when :block
|
15
|
-
if @node.children[1].children.empty?
|
16
|
-
@node.children[0].loc.expression.end_pos + DO_LENGTH
|
17
|
-
else
|
18
|
-
@node.children[1].loc.expression.end_pos
|
19
|
-
end
|
20
|
-
when :class
|
21
|
-
@node.children[1] ? @node.children[1].loc.expression.end_pos : @node.children[0].loc.expression.end_pos
|
22
|
-
when :def
|
23
|
-
@node.children[1].empty? ? @node.loc.name.end_pos : @node.children[1].loc.expression.end_pos
|
24
|
-
when :defs
|
25
|
-
@node.children[2].empty? ? @node.loc.name.end_pos : @node.children[2].loc.expression.end_pos
|
26
|
-
else
|
27
|
-
@node.children.last.loc.expression.end_pos
|
28
|
-
end
|
29
|
-
@end_pos = @begin_pos
|
30
|
-
end
|
31
|
-
|
32
|
-
# Indent of the node.
|
33
|
-
#
|
34
|
-
# @param node [Parser::AST::Node]
|
35
|
-
# @return [String] n times whitesphace
|
36
|
-
def indent(node)
|
37
|
-
if %i[block class def defs].include?(node.type)
|
38
|
-
' ' * (node.column + DEFAULT_INDENT)
|
39
|
-
else
|
40
|
-
' ' * node.column
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# RemoveAction to remove current node.
|
5
|
-
class Rewriter::RemoveAction < Rewriter::Action
|
6
|
-
# Initialize a RemoveAction.
|
7
|
-
#
|
8
|
-
# @param instance [Synvert::Core::Rewriter::RemoveAction]
|
9
|
-
# @param options [Hash] options.
|
10
|
-
# @option and_comma [Boolean] delete extra comma.
|
11
|
-
def initialize(instance, and_comma: false)
|
12
|
-
super(instance, nil)
|
13
|
-
@and_comma = and_comma
|
14
|
-
end
|
15
|
-
|
16
|
-
# The rewritten code, always empty string.
|
17
|
-
def rewritten_code
|
18
|
-
''
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
# Calculate the begin the end positions.
|
24
|
-
def calculate_position
|
25
|
-
if take_whole_line?
|
26
|
-
@begin_pos = start_index
|
27
|
-
@end_pos = end_index
|
28
|
-
squeeze_lines
|
29
|
-
else
|
30
|
-
@begin_pos = @node.loc.expression.begin_pos
|
31
|
-
@end_pos = @node.loc.expression.end_pos
|
32
|
-
squeeze_spaces
|
33
|
-
remove_comma if @and_command
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# Check if the source code of current node takes the whole line.
|
38
|
-
#
|
39
|
-
# @return [Boolean]
|
40
|
-
def take_whole_line?
|
41
|
-
@node.to_source == file_source[start_index...end_index].strip
|
42
|
-
end
|
43
|
-
|
44
|
-
# Get the start position of the line
|
45
|
-
def start_index
|
46
|
-
index = file_source[0..@node.loc.expression.begin_pos].rindex("\n")
|
47
|
-
index ? index + "\n".length : @node.loc.expression.begin_pos
|
48
|
-
end
|
49
|
-
|
50
|
-
# Get the end position of the line
|
51
|
-
def end_index
|
52
|
-
index = file_source[@node.loc.expression.end_pos..-1].index("\n")
|
53
|
-
index ? @node.loc.expression.end_pos + index + "\n".length : @node.loc.expression.end_pos
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# ReplaceAction to replace child node with code.
|
5
|
-
class Rewriter::ReplaceAction < Rewriter::Action
|
6
|
-
# Initailize a ReplaceAction.
|
7
|
-
#
|
8
|
-
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
-
# @param selectors [Array<Symbol|String>] used to select child nodes
|
10
|
-
# @param with [String] the new code
|
11
|
-
def initialize(instance, *selectors, with:)
|
12
|
-
super(instance, with)
|
13
|
-
@selectors = selectors
|
14
|
-
end
|
15
|
-
|
16
|
-
# The rewritten source code.
|
17
|
-
#
|
18
|
-
# @return [String] rewritten code.
|
19
|
-
def rewritten_code
|
20
|
-
rewritten_source
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
# Calculate the begin the end positions.
|
26
|
-
def calculate_position
|
27
|
-
@begin_pos = @selectors.map { |selector| @node.child_node_range(selector).begin_pos }
|
28
|
-
.min
|
29
|
-
@end_pos = @selectors.map { |selector| @node.child_node_range(selector).end_pos }
|
30
|
-
.max
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# ReplaceWithAction to replace code.
|
5
|
-
class Rewriter::ReplaceWithAction < Rewriter::Action
|
6
|
-
# The rewritten source code with proper indent.
|
7
|
-
#
|
8
|
-
# @return [String] rewritten code.
|
9
|
-
def rewritten_code
|
10
|
-
if rewritten_source.include?("\n")
|
11
|
-
new_code = []
|
12
|
-
rewritten_source.split("\n").each_with_index do |line, index|
|
13
|
-
new_code << (index == 0 ? line : indent + line)
|
14
|
-
end
|
15
|
-
new_code.join("\n")
|
16
|
-
else
|
17
|
-
rewritten_source
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
# Calculate the begin the end positions.
|
24
|
-
def calculate_position
|
25
|
-
@begin_pos = @node.loc.expression.begin_pos
|
26
|
-
@end_pos = @node.loc.expression.end_pos
|
27
|
-
end
|
28
|
-
|
29
|
-
# Indent of the node
|
30
|
-
#
|
31
|
-
# @return [String] n times whitesphace
|
32
|
-
def indent
|
33
|
-
' ' * @node.column
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# WrapAction to warp node within a block, class or module.
|
5
|
-
#
|
6
|
-
# Note: if WrapAction is conflicted with another action (begin_pos and end_pos are overlapped),
|
7
|
-
# we have to put those 2 actions into 2 within_file scopes.
|
8
|
-
class Rewriter::WrapAction < Rewriter::Action
|
9
|
-
# Initialize a WrapAction.
|
10
|
-
#
|
11
|
-
# @param instance [Synvert::Core::Rewriter::WrapAction]
|
12
|
-
# @param with [String] new code to wrap
|
13
|
-
# @param indent [Integer, nil] number of whitespaces
|
14
|
-
def initialize(instance, with:, indent: nil)
|
15
|
-
super(instance, with)
|
16
|
-
@indent = indent || @node.column
|
17
|
-
end
|
18
|
-
|
19
|
-
# The rewritten source code.
|
20
|
-
#
|
21
|
-
# @return [String] rewritten code.
|
22
|
-
def rewritten_code
|
23
|
-
"#{@code}\n#{' ' * @indent}" +
|
24
|
-
@node.to_source.split("\n").map { |line| " #{line}" }
|
25
|
-
.join("\n") +
|
26
|
-
"\n#{' ' * @indent}end"
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
# Calculate the begin the end positions.
|
32
|
-
def calculate_position
|
33
|
-
@begin_pos = @node.loc.expression.begin_pos
|
34
|
-
@end_pos = @node.loc.expression.end_pos
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,102 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# Action defines rewriter action, insert, replace or delete code.
|
5
|
-
class Rewriter::Action
|
6
|
-
DEFAULT_INDENT = 2
|
7
|
-
|
8
|
-
# @!attribute [r] begin_pos
|
9
|
-
# @return [Integer] begin position
|
10
|
-
# @!attribute [r] end_pos
|
11
|
-
# @return [Integer] end position
|
12
|
-
attr_reader :begin_pos, :end_pos
|
13
|
-
|
14
|
-
# Initialize an action.
|
15
|
-
#
|
16
|
-
# @param instance [Synvert::Core::Rewriter::Instance]
|
17
|
-
# @param code [String] new code to insert, replace or delete.
|
18
|
-
def initialize(instance, code)
|
19
|
-
@instance = instance
|
20
|
-
@code = code
|
21
|
-
@node = @instance.current_node
|
22
|
-
end
|
23
|
-
|
24
|
-
# Calculate begin and end positions, and return self.
|
25
|
-
#
|
26
|
-
# @return [Synvert::Core::Rewriter::Action] self
|
27
|
-
def process
|
28
|
-
calculate_position
|
29
|
-
self
|
30
|
-
end
|
31
|
-
|
32
|
-
# The rewritten source code with proper indent.
|
33
|
-
#
|
34
|
-
# @return [String] rewritten code.
|
35
|
-
def rewritten_code
|
36
|
-
if rewritten_source.split("\n").length > 1
|
37
|
-
"\n\n" + rewritten_source.split("\n").map { |line| indent(@node) + line }
|
38
|
-
.join("\n")
|
39
|
-
else
|
40
|
-
"\n" + indent(@node) + rewritten_source
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
protected
|
45
|
-
|
46
|
-
# Calculate the begin the end positions.
|
47
|
-
#
|
48
|
-
# @abstract
|
49
|
-
def calculate_position
|
50
|
-
raise NotImplementedError, 'must be implemented by subclasses'
|
51
|
-
end
|
52
|
-
|
53
|
-
# The rewritten source code.
|
54
|
-
#
|
55
|
-
# @return [String] rewritten source code.
|
56
|
-
def rewritten_source
|
57
|
-
@rewritten_source ||= @node.rewritten_source(@code)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Squeeze spaces from source code.
|
61
|
-
def squeeze_spaces
|
62
|
-
if file_source[@begin_pos - 1] == ' ' && file_source[@end_pos] == ' '
|
63
|
-
@begin_pos -= 1
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Squeeze empty lines from source code.
|
68
|
-
def squeeze_lines
|
69
|
-
lines = file_source.split("\n")
|
70
|
-
begin_line = @node.loc.expression.first_line
|
71
|
-
end_line = @node.loc.expression.last_line
|
72
|
-
before_line_is_blank = begin_line == 1 || lines[begin_line - 2] == ''
|
73
|
-
after_line_is_blank = lines[end_line] == ''
|
74
|
-
|
75
|
-
if lines.length > 1 && before_line_is_blank && after_line_is_blank
|
76
|
-
@end_pos += "\n".length
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# Remove unused comma.
|
81
|
-
# e.g. `foobar(foo, bar)`, if we remove `foo`, the comma should also be removed,
|
82
|
-
# the code should be changed to `foobar(bar)`.
|
83
|
-
def remove_comma
|
84
|
-
if ',' == file_source[@begin_pos - 1]
|
85
|
-
@begin_pos -= 1
|
86
|
-
elsif ', ' == file_source[@begin_pos - 2, 2]
|
87
|
-
@begin_pos -= 2
|
88
|
-
elsif ', ' == file_source[@end_pos, 2]
|
89
|
-
@end_pos += 2
|
90
|
-
elsif ',' == file_source[@end_pos]
|
91
|
-
@end_pos += 1
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
# Return file source.
|
96
|
-
#
|
97
|
-
# @return [String]
|
98
|
-
def file_source
|
99
|
-
@file_source ||= @instance.file_source
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|