synvert-core 0.1.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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +2 -0
- data/lib/synvert/core.rb +24 -0
- data/lib/synvert/core/cli.rb +147 -0
- data/lib/synvert/core/configuration.rb +25 -0
- data/lib/synvert/core/exceptions.rb +13 -0
- data/lib/synvert/core/node_ext.rb +319 -0
- data/lib/synvert/core/rewriter.rb +200 -0
- data/lib/synvert/core/rewriter/action.rb +224 -0
- data/lib/synvert/core/rewriter/condition.rb +56 -0
- data/lib/synvert/core/rewriter/gem_spec.rb +42 -0
- data/lib/synvert/core/rewriter/instance.rb +185 -0
- data/lib/synvert/core/rewriter/scope.rb +46 -0
- data/lib/synvert/core/version.rb +7 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/parser_helper.rb +5 -0
- data/spec/synvert/core/node_ext_spec.rb +201 -0
- data/spec/synvert/core/rewriter/action_spec.rb +225 -0
- data/spec/synvert/core/rewriter/condition_spec.rb +106 -0
- data/spec/synvert/core/rewriter/gem_spec_spec.rb +52 -0
- data/spec/synvert/core/rewriter/instance_spec.rb +163 -0
- data/spec/synvert/core/rewriter/scope_spec.rb +42 -0
- data/spec/synvert/core/rewriter_spec.rb +153 -0
- data/synvert-core.gemspec +27 -0
- metadata +153 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Synvert::Core
|
4
|
+
# GemSpec checks and compares gem version.
|
5
|
+
class Rewriter::GemSpec
|
6
|
+
OPERATORS = {eq: '==', lt: '<', gt: '>', lte: '<=', gte: '>=', ne: '!='}
|
7
|
+
|
8
|
+
# Initialize a gem_spec.
|
9
|
+
#
|
10
|
+
# @param name [String] gem name
|
11
|
+
# @param comparator [Hash] comparator to gem version, e.g. {eg: '2.0.0'},
|
12
|
+
# comparator key can be eq, lt, gt, lte, gte or ne.
|
13
|
+
def initialize(name, comparator)
|
14
|
+
@name = name
|
15
|
+
if Hash === comparator
|
16
|
+
@operator = comparator.keys.first
|
17
|
+
@version = Gem::Version.new comparator.values.first
|
18
|
+
else
|
19
|
+
@operator = :eq
|
20
|
+
@version = Gem::Version.new comparator
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check if the specified gem version in Gemfile.lock matches gem_spec comparator.
|
25
|
+
#
|
26
|
+
# @return [Boolean] true if matches, otherwise false.
|
27
|
+
# @raise [Synvert::Core::GemfileLockNotFound] raise if Gemfile.lock does not exist.
|
28
|
+
def match?
|
29
|
+
gemfile_lock_path = File.join(Configuration.instance.get(:path), 'Gemfile.lock')
|
30
|
+
if File.exists? gemfile_lock_path
|
31
|
+
parser = Bundler::LockfileParser.new(File.read(gemfile_lock_path))
|
32
|
+
if spec = parser.specs.find { |spec| spec.name == @name }
|
33
|
+
Gem::Version.new(spec.version).send(OPERATORS[@operator], @version)
|
34
|
+
else
|
35
|
+
false
|
36
|
+
end
|
37
|
+
else
|
38
|
+
raise GemfileLockNotFound.new 'Gemfile.lock does not exist'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Synvert::Core
|
4
|
+
# Instance is an execution unit, it finds specified ast nodes,
|
5
|
+
# checks if the nodes match some conditions, then add, replace or remove code.
|
6
|
+
#
|
7
|
+
# One instance can contains one or many [Synvert::Core::Rewriter::Scope] and [Synvert::Rewriter::Condition].
|
8
|
+
class Rewriter::Instance
|
9
|
+
# @!attribute [rw] current_node
|
10
|
+
# @return current parsing node
|
11
|
+
# @!attribute [rw] current_source
|
12
|
+
# @return current source code of file
|
13
|
+
# @!attribute [rw] current_file
|
14
|
+
# @return current filename
|
15
|
+
attr_accessor :current_node, :current_source, :current_file
|
16
|
+
|
17
|
+
# Initialize an instance.
|
18
|
+
#
|
19
|
+
# @param file_pattern [String] pattern to find files, e.g. spec/**/*_spec.rb
|
20
|
+
# @param block [Block] block code to find nodes, match conditions and rewrite code.
|
21
|
+
# @return [Synvert::Core::Rewriter::Instance]
|
22
|
+
def initialize(file_pattern, &block)
|
23
|
+
@actions = []
|
24
|
+
@file_pattern = file_pattern
|
25
|
+
@block = block
|
26
|
+
end
|
27
|
+
|
28
|
+
# Process the instance.
|
29
|
+
# It finds all files, for each file, it executes the block code, gets all rewrite actions,
|
30
|
+
# and rewrite source code back to original file.
|
31
|
+
def process
|
32
|
+
parser = Parser::CurrentRuby.new
|
33
|
+
file_pattern = File.join(Configuration.instance.get(:path), @file_pattern)
|
34
|
+
Dir.glob(file_pattern).each do |file_path|
|
35
|
+
unless Configuration.instance.get(:skip_files).include? file_path
|
36
|
+
begin
|
37
|
+
source = File.read(file_path)
|
38
|
+
buffer = Parser::Source::Buffer.new file_path
|
39
|
+
buffer.source = source
|
40
|
+
|
41
|
+
parser.reset
|
42
|
+
ast = parser.parse buffer
|
43
|
+
|
44
|
+
@current_file = file_path
|
45
|
+
@current_source = source
|
46
|
+
@current_node = ast
|
47
|
+
instance_eval &@block
|
48
|
+
@current_node = ast
|
49
|
+
|
50
|
+
@actions.sort!
|
51
|
+
check_conflict_actions
|
52
|
+
@actions.reverse.each do |action|
|
53
|
+
source[action.begin_pos...action.end_pos] = action.rewritten_code
|
54
|
+
source = remove_code_or_whole_line(source, action.line)
|
55
|
+
end
|
56
|
+
@actions = []
|
57
|
+
|
58
|
+
File.write file_path, source
|
59
|
+
end while !@conflict_actions.empty?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Gets current node, it allows to get current node in block code.
|
65
|
+
#
|
66
|
+
# @return [Parser::AST::Node]
|
67
|
+
def node
|
68
|
+
@current_node
|
69
|
+
end
|
70
|
+
|
71
|
+
#######
|
72
|
+
# DSL #
|
73
|
+
#######
|
74
|
+
|
75
|
+
# Parse within_node dsl, it creates a [Synvert::Core::Rewriter::Scope] to find matching ast nodes,
|
76
|
+
# then continue operating on each matching ast node.
|
77
|
+
#
|
78
|
+
# @param rules [Hash] rules to find mathing ast nodes.
|
79
|
+
# @param block [Block] block code to continue operating on the matching nodes.
|
80
|
+
def within_node(rules, &block)
|
81
|
+
Rewriter::Scope.new(self, rules, &block).process
|
82
|
+
end
|
83
|
+
|
84
|
+
alias with_node within_node
|
85
|
+
|
86
|
+
# Parse if_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfExistCondition] to check
|
87
|
+
# if matching nodes exist in the child nodes, if so, then continue operating on each matching ast node.
|
88
|
+
#
|
89
|
+
# @param rules [Hash] rules to check mathing ast nodes.
|
90
|
+
# @param block [Block] block code to continue operating on the matching nodes.
|
91
|
+
def if_exist_node(rules, &block)
|
92
|
+
Rewriter::IfExistCondition.new(self, rules, &block).process
|
93
|
+
end
|
94
|
+
|
95
|
+
# Parse unless_exist_node dsl, it creates a [Synvert::Core::Rewriter::UnlessExistCondition] to check
|
96
|
+
# if matching nodes doesn't exist in the child nodes, if so, then continue operating on each matching ast node.
|
97
|
+
#
|
98
|
+
# @param rules [Hash] rules to check mathing ast nodes.
|
99
|
+
# @param block [Block] block code to continue operating on the matching nodes.
|
100
|
+
def unless_exist_node(rules, &block)
|
101
|
+
Rewriter::UnlessExistCondition.new(self, rules, &block).process
|
102
|
+
end
|
103
|
+
|
104
|
+
# Parse if_only_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfOnlyExistCondition] to check
|
105
|
+
# if current node has only one child node and the child node matches rules,
|
106
|
+
# if so, then continue operating on each matching ast node.
|
107
|
+
#
|
108
|
+
# @param rules [Hash] rules to check mathing ast nodes.
|
109
|
+
# @param block [Block] block code to continue operating on the matching nodes.
|
110
|
+
def if_only_exist_node(rules, &block)
|
111
|
+
Rewriter::IfOnlyExistCondition.new(self, rules, &block).process
|
112
|
+
end
|
113
|
+
|
114
|
+
# Parse append dsl, it creates a [Synvert::Core::Rewriter::AppendAction] to
|
115
|
+
# append the code to the bottom of current node body.
|
116
|
+
#
|
117
|
+
# @param code [String] code need to be appended.
|
118
|
+
def append(code)
|
119
|
+
@actions << Rewriter::AppendAction.new(self, code)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Parse insert dsl, it creates a [Synvert::Core::Rewriter::InsertAction] to
|
123
|
+
# insert the code to the top of current node body.
|
124
|
+
#
|
125
|
+
# @param code [String] code need to be inserted.
|
126
|
+
def insert(code)
|
127
|
+
@actions << Rewriter::InsertAction.new(self, code)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Parse insert_after dsl, it creates a [Synvert::Core::Rewriter::InsertAfterAction] to
|
131
|
+
# insert the code next to the current node.
|
132
|
+
#
|
133
|
+
# @param code [String] code need to be inserted.
|
134
|
+
def insert_after(node)
|
135
|
+
@actions << Rewriter::InsertAfterAction.new(self, node)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Parse replace_with dsl, it creates a [Synvert::Core::Rewriter::ReplaceWithAction] to
|
139
|
+
# replace current node with code.
|
140
|
+
#
|
141
|
+
# @param code [String] code need to be replaced with.
|
142
|
+
def replace_with(code)
|
143
|
+
@actions << Rewriter::ReplaceWithAction.new(self, code)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Parse remove dsl, it creates a [Synvert::Core::Rewriter::RemoveAction] to current node.
|
147
|
+
def remove
|
148
|
+
@actions << Rewriter::RemoveAction.new(self)
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
# It changes source code from bottom to top, and it can change source code twice at the same time.
|
154
|
+
# So if there is an overlap between two actions, it removes the conflict actions and operate them in the next loop.
|
155
|
+
def check_conflict_actions
|
156
|
+
i = @actions.length - 1
|
157
|
+
@conflict_actions = []
|
158
|
+
while i > 0
|
159
|
+
if @actions[i].begin_pos <= @actions[i - 1].end_pos
|
160
|
+
@conflict_actions << @actions.delete_at(i)
|
161
|
+
end
|
162
|
+
i -= 1
|
163
|
+
end
|
164
|
+
@conflict_actions
|
165
|
+
end
|
166
|
+
|
167
|
+
# It checks if code is removed and that line is empty.
|
168
|
+
#
|
169
|
+
# @param source [String] source code of file
|
170
|
+
# @param line [String] the line number
|
171
|
+
def remove_code_or_whole_line(source, line)
|
172
|
+
newline_at_end_of_line = source[-1] == "\n"
|
173
|
+
source_arr = source.split("\n")
|
174
|
+
if source_arr[line - 1] && source_arr[line - 1].strip.empty?
|
175
|
+
source_arr.delete_at(line - 1)
|
176
|
+
if source_arr[line - 2] && source_arr[line - 2].strip.empty? && source_arr[line - 1] && source_arr[line - 1].strip.empty?
|
177
|
+
source_arr.delete_at(line - 1)
|
178
|
+
end
|
179
|
+
source_arr.join("\n") + (newline_at_end_of_line ? "\n" : '')
|
180
|
+
else
|
181
|
+
source
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Synvert::Core
|
4
|
+
# Scope finds the child nodes which match rules.
|
5
|
+
class Rewriter::Scope
|
6
|
+
# Initialize a scope
|
7
|
+
#
|
8
|
+
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
+
# @param rules [Hash]
|
10
|
+
# @param block [Block]
|
11
|
+
def initialize(instance, rules, &block)
|
12
|
+
@instance = instance
|
13
|
+
@rules = rules
|
14
|
+
@block = block
|
15
|
+
end
|
16
|
+
|
17
|
+
# Find the matching nodes. It checks the current node and iterates all child nodes,
|
18
|
+
# then run the block code for each matching node.
|
19
|
+
def process
|
20
|
+
current_node = @instance.current_node
|
21
|
+
return unless current_node
|
22
|
+
process_with_node current_node do
|
23
|
+
matching_nodes = []
|
24
|
+
matching_nodes << current_node if current_node.match? @instance, @rules
|
25
|
+
current_node.recursive_children do |child_node|
|
26
|
+
matching_nodes << child_node if child_node.match? @instance, @rules
|
27
|
+
end
|
28
|
+
matching_nodes.each do |matching_node|
|
29
|
+
process_with_node matching_node do
|
30
|
+
@instance.instance_eval &@block
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Set instance current node properly and process.
|
39
|
+
# @param node [Parser::AST::Node]
|
40
|
+
def process_with_node(node)
|
41
|
+
@instance.current_node = node
|
42
|
+
yield
|
43
|
+
@instance.current_node = node
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
2
|
+
|
3
|
+
require 'synvert/core'
|
4
|
+
|
5
|
+
require 'coveralls'
|
6
|
+
Coveralls.wear!
|
7
|
+
|
8
|
+
Dir[File.join(File.dirname(__FILE__), 'support', '*')].each do |path|
|
9
|
+
require path
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.include ParserHelper
|
14
|
+
|
15
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
config.filter_run :focus
|
18
|
+
|
19
|
+
config.order = 'random'
|
20
|
+
|
21
|
+
config.before do
|
22
|
+
Synvert::Core::Configuration.instance.set :skip_files, []
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parser::AST::Node do
|
4
|
+
describe '#name' do
|
5
|
+
it 'gets for class node' do
|
6
|
+
node = parse('class Synvert; end')
|
7
|
+
expect(node.name).to eq parse('Synvert')
|
8
|
+
|
9
|
+
node = parse('class Synvert::Core::Rewriter::Instance; end')
|
10
|
+
expect(node.name).to eq parse('Synvert::Core::Rewriter::Instance')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'gets for module node' do
|
14
|
+
node = parse('module Synvert; end')
|
15
|
+
expect(node.name).to eq parse('Synvert')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'gets for def node' do
|
19
|
+
node = parse('def current_node; end')
|
20
|
+
expect(node.name).to eq :current_node
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'gets for defs node' do
|
24
|
+
node = parse('def self.current_node; end')
|
25
|
+
expect(node.name).to eq :current_node
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#receiver' do
|
30
|
+
it 'gets for send node' do
|
31
|
+
node = parse('FactoryGirl.create :post')
|
32
|
+
expect(node.receiver).to eq parse('FactoryGirl')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#message' do
|
37
|
+
it 'gets for send node' do
|
38
|
+
node = parse('FactoryGirl.create :post')
|
39
|
+
expect(node.message).to eq :create
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#arguments' do
|
44
|
+
it 'gets for send node' do
|
45
|
+
node = parse("FactoryGirl.create :post, title: 'post'")
|
46
|
+
expect(node.arguments).to eq parse("[:post, title: 'post']").children
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'gets for block node' do
|
50
|
+
source = 'RSpec.configure do |config|; end'
|
51
|
+
node = parse(source)
|
52
|
+
instance = double(current_source: source)
|
53
|
+
expect(node.arguments.map { |argument| argument.source(instance) }).to eq ['config']
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'gets for defined? node' do
|
57
|
+
node = parse('defined?(Bundler)')
|
58
|
+
expect(node.arguments).to eq [parse('Bundler')]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#caller' do
|
63
|
+
it 'gets for block node' do
|
64
|
+
node = parse('RSpec.configure do |config|; end')
|
65
|
+
expect(node.caller).to eq parse('RSpec.configure')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#body' do
|
70
|
+
it 'gets one line for block node' do
|
71
|
+
node = parse('RSpec.configure do |config|; include EmailSpec::Helpers; end')
|
72
|
+
expect(node.body).to eq [parse('include EmailSpec::Helpers')]
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'gets multiple lines for block node' do
|
76
|
+
node = parse('RSpec.configure do |config|; include EmailSpec::Helpers; include EmailSpec::Matchers; end')
|
77
|
+
expect(node.body).to eq [parse('include EmailSpec::Helpers'), parse('include EmailSpec::Matchers')]
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'gets for begin node' do
|
81
|
+
node = parse('foo; bar')
|
82
|
+
expect(node.body).to eq [parse('foo'), parse('bar')]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#keys" do
|
87
|
+
it 'gets for hash node' do
|
88
|
+
node = parse("{:foo => :bar, 'foo' => 'bar'}")
|
89
|
+
expect(node.keys).to eq [Parser::CurrentRuby.parse(':foo'), Parser::CurrentRuby.parse("'foo'")]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#values" do
|
94
|
+
it 'gets for hash node' do
|
95
|
+
node = parse("{:foo => :bar, 'foo' => 'bar'}")
|
96
|
+
expect(node.values).to eq [Parser::CurrentRuby.parse(':bar'), Parser::CurrentRuby.parse("'bar'")]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#key" do
|
101
|
+
it 'gets for pair node' do
|
102
|
+
node = parse("{:foo => 'bar'}").children[0]
|
103
|
+
expect(node.key).to eq Parser::CurrentRuby.parse(':foo')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#value" do
|
108
|
+
it 'gets for hash node' do
|
109
|
+
node = parse("{:foo => 'bar'}").children[0]
|
110
|
+
expect(node.value).to eq Parser::CurrentRuby.parse("'bar'")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#condition" do
|
115
|
+
it 'gets for if node' do
|
116
|
+
node = parse('if defined?(Bundler); end')
|
117
|
+
expect(node.condition).to eq parse('defined?(Bundler)')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#source' do
|
122
|
+
it 'gets for node' do
|
123
|
+
source = 'params[:user][:email]'
|
124
|
+
instance = double(current_source: source)
|
125
|
+
node = parse(source)
|
126
|
+
expect(node.source(instance)).to eq 'params[:user][:email]'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#indent' do
|
131
|
+
it 'gets column number' do
|
132
|
+
node = parse(' FactoryGirl.create :post')
|
133
|
+
expect(node.indent).to eq 2
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '#recursive_children' do
|
138
|
+
it 'iterates all children recursively' do
|
139
|
+
node = parse('class Synvert; def current_node; @node; end; end')
|
140
|
+
children = []
|
141
|
+
node.recursive_children { |child| children << child.type }
|
142
|
+
expect(children).to be_include :const
|
143
|
+
expect(children).to be_include :def
|
144
|
+
expect(children).to be_include :args
|
145
|
+
expect(children).to be_include :ivar
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe '#match?' do
|
150
|
+
let(:instance) { Synvert::Core::Rewriter::Instance.new('file pattern') }
|
151
|
+
|
152
|
+
it 'matches class name' do
|
153
|
+
source = 'class Synvert; end'
|
154
|
+
instance.current_source = source
|
155
|
+
node = parse(source)
|
156
|
+
expect(node).to be_match(instance, type: 'class', name: 'Synvert')
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'matches message with regexp' do
|
160
|
+
source = 'User.find_by_login(login)'
|
161
|
+
instance.current_source = source
|
162
|
+
node = parse(source)
|
163
|
+
expect(node).to be_match(instance, type: 'send', message: /^find_by_/)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'matches arguments with symbol' do
|
167
|
+
source = 'params[:user]'
|
168
|
+
instance.current_source = source
|
169
|
+
node = parse(source)
|
170
|
+
expect(node).to be_match(instance, type: 'send', receiver: 'params', message: '[]', arguments: [:user])
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'matches assign number' do
|
174
|
+
source = 'at_least(0)'
|
175
|
+
instance.current_source = source
|
176
|
+
node = parse(source)
|
177
|
+
expect(node).to be_match(instance, type: 'send', arguments: [0])
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'matches arguments with string' do
|
181
|
+
source = 'params["user"]'
|
182
|
+
instance.current_source = source
|
183
|
+
node = parse(source)
|
184
|
+
expect(node).to be_match(instance, type: 'send', receiver: 'params', message: '[]', arguments: ['user'])
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'matches arguments any' do
|
188
|
+
source = 'config.middleware.insert_after ActiveRecord::QueryCache, Lifo::Cache, page_cache: false'
|
189
|
+
instance.current_source = source
|
190
|
+
node = parse(source)
|
191
|
+
expect(node).to be_match(instance, type: 'send', arguments: {any: 'Lifo::Cache'})
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'matches not' do
|
195
|
+
source = 'class Synvert; end'
|
196
|
+
instance.current_source = source
|
197
|
+
node = parse(source)
|
198
|
+
expect(node).not_to be_match(instance, type: 'class', name: {not: 'Synvert'})
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|