synvert 0.0.17 → 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 +4 -4
- data/.travis.yml +0 -1
- data/CHANGELOG.md +4 -0
- data/README.md +7 -26
- data/bin/synvert +0 -1
- data/lib/synvert/cli.rb +26 -14
- data/lib/synvert/snippet.rb +17 -0
- data/lib/synvert/version.rb +1 -1
- data/lib/synvert.rb +3 -11
- data/synvert.gemspec +2 -3
- metadata +6 -85
- data/lib/synvert/configuration.rb +0 -25
- data/lib/synvert/exceptions.rb +0 -13
- data/lib/synvert/node_ext.rb +0 -319
- data/lib/synvert/rewriter/action.rb +0 -224
- data/lib/synvert/rewriter/condition.rb +0 -56
- data/lib/synvert/rewriter/gem_spec.rb +0 -42
- data/lib/synvert/rewriter/instance.rb +0 -185
- data/lib/synvert/rewriter/scope.rb +0 -46
- data/lib/synvert/rewriter.rb +0 -200
- data/lib/synvert/snippets/check_syntax.rb +0 -5
- data/lib/synvert/snippets/factory_girl/syntax_methods.rb +0 -98
- data/lib/synvert/snippets/rails/convert_dynamic_finders.rb +0 -93
- data/lib/synvert/snippets/rails/strong_parameters.rb +0 -93
- data/lib/synvert/snippets/rails/upgrade_3_0_to_3_1.rb +0 -135
- data/lib/synvert/snippets/rails/upgrade_3_1_to_3_2.rb +0 -42
- data/lib/synvert/snippets/rails/upgrade_3_2_to_4_0.rb +0 -230
- data/lib/synvert/snippets/rspec/be_close_to_be_within.rb +0 -18
- data/lib/synvert/snippets/rspec/block_to_expect.rb +0 -22
- data/lib/synvert/snippets/rspec/boolean_matcher.rb +0 -20
- data/lib/synvert/snippets/rspec/collection_matcher.rb +0 -34
- data/lib/synvert/snippets/rspec/its_to_it.rb +0 -89
- data/lib/synvert/snippets/rspec/message_expectation.rb +0 -41
- data/lib/synvert/snippets/rspec/method_stub.rb +0 -84
- data/lib/synvert/snippets/rspec/negative_error_expectation.rb +0 -21
- data/lib/synvert/snippets/rspec/new_syntax.rb +0 -18
- data/lib/synvert/snippets/rspec/one_liner_expectation.rb +0 -71
- data/lib/synvert/snippets/rspec/should_to_expect.rb +0 -50
- data/lib/synvert/snippets/rspec/stub_and_mock_to_double.rb +0 -22
- data/lib/synvert/snippets/ruby/new_hash_syntax.rb +0 -21
- data/lib/synvert/snippets/ruby/new_lambda_syntax.rb +0 -20
- data/spec/spec_helper.rb +0 -26
- data/spec/support/parser_helper.rb +0 -5
- data/spec/synvert/node_ext_spec.rb +0 -201
- data/spec/synvert/rewriter/action_spec.rb +0 -225
- data/spec/synvert/rewriter/condition_spec.rb +0 -106
- data/spec/synvert/rewriter/gem_spec_spec.rb +0 -52
- data/spec/synvert/rewriter/instance_spec.rb +0 -163
- data/spec/synvert/rewriter/scope_spec.rb +0 -42
- data/spec/synvert/rewriter_spec.rb +0 -153
- data/spec/synvert/snippets/factory_girl/syntax_methods_spec.rb +0 -154
- data/spec/synvert/snippets/rails/convert_dynamic_finders_spec.rb +0 -83
- data/spec/synvert/snippets/rails/strong_parameters_spec.rb +0 -132
- data/spec/synvert/snippets/rails/upgrade_3_0_to_3_1_spec.rb +0 -88
- data/spec/synvert/snippets/rails/upgrade_3_1_to_3_2_spec.rb +0 -41
- data/spec/synvert/snippets/rails/upgrade_3_2_to_4_0_spec.rb +0 -299
- data/spec/synvert/snippets/rspec/new_syntax_spec.rb +0 -183
- data/spec/synvert/snippets/ruby/new_hash_syntax_spec.rb +0 -27
- data/spec/synvert/snippets/ruby/new_lambda_syntax_spec.rb +0 -27
@@ -1,185 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Synvert
|
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::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::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::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::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::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::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::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::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::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::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::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
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Synvert
|
4
|
-
# Scope finds the child nodes which match rules.
|
5
|
-
class Rewriter::Scope
|
6
|
-
# Initialize a scope
|
7
|
-
#
|
8
|
-
# @param instance [Synvert::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/lib/synvert/rewriter.rb
DELETED
@@ -1,200 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Synvert
|
4
|
-
# Rewriter is the top level namespace in a snippet.
|
5
|
-
#
|
6
|
-
# One Rewriter can contain one or many [Synvert::Rewriter::Instance],
|
7
|
-
# which define the behavior what files and what codes to detect and rewrite to what code.
|
8
|
-
#
|
9
|
-
# Synvert::Rewriter.new 'factory_girl_short_syntax', 'use FactoryGirl short syntax' do
|
10
|
-
# if_gem 'factory_girl', {gte: '2.0.0'}
|
11
|
-
#
|
12
|
-
# within_files 'spec/**/*.rb' do
|
13
|
-
# with_node type: 'send', receiver: 'FactoryGirl', message: 'create' do
|
14
|
-
# replace_with "create({{arguments}})"
|
15
|
-
# end
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
class Rewriter
|
19
|
-
autoload :Action, 'synvert/rewriter/action'
|
20
|
-
autoload :AppendAction, 'synvert/rewriter/action'
|
21
|
-
autoload :InsertAction, 'synvert/rewriter/action'
|
22
|
-
autoload :InsertAfterAction, 'synvert/rewriter/action'
|
23
|
-
autoload :ReplaceWithAction, 'synvert/rewriter/action'
|
24
|
-
autoload :RemoveAction, 'synvert/rewriter/action'
|
25
|
-
|
26
|
-
autoload :Instance, 'synvert/rewriter/instance'
|
27
|
-
|
28
|
-
autoload :Scope, 'synvert/rewriter/scope'
|
29
|
-
|
30
|
-
autoload :Condition, 'synvert/rewriter/condition'
|
31
|
-
autoload :IfExistCondition, 'synvert/rewriter/condition'
|
32
|
-
autoload :UnlessExistCondition, 'synvert/rewriter/condition'
|
33
|
-
autoload :IfOnlyExistCondition, 'synvert/rewriter/condition'
|
34
|
-
|
35
|
-
autoload :GemSpec, 'synvert/rewriter/gem_spec'
|
36
|
-
|
37
|
-
class <<self
|
38
|
-
# Register a rewriter with its name.
|
39
|
-
#
|
40
|
-
# @param name [String] the unique rewriter name.
|
41
|
-
# @param rewriter [Synvert::Rewriter] the rewriter to register.
|
42
|
-
def register(name, rewriter)
|
43
|
-
@rewriters ||= {}
|
44
|
-
@rewriters[name] = rewriter
|
45
|
-
end
|
46
|
-
|
47
|
-
# Fetch a rewriter by name.
|
48
|
-
#
|
49
|
-
# @param name [String] rewrtier name.
|
50
|
-
# @return [Synvert::Rewriter] the matching rewriter.
|
51
|
-
def fetch(name)
|
52
|
-
@rewriters[name]
|
53
|
-
end
|
54
|
-
|
55
|
-
# Get a registered rewriter by name and process that rewriter.
|
56
|
-
#
|
57
|
-
# @param name [String] the rewriter name.
|
58
|
-
# @return [Synvert::Rewriter] the registered rewriter.
|
59
|
-
# @raise [Synvert::RewriterNotFound] if the registered rewriter is not found.
|
60
|
-
def call(name)
|
61
|
-
if (rewriter = @rewriters[name])
|
62
|
-
rewriter.process
|
63
|
-
rewriter
|
64
|
-
else
|
65
|
-
raise RewriterNotFound.new "Rewriter #{name} not found"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Get all available rewriters
|
70
|
-
#
|
71
|
-
# @return [Array<Synvert::Rewriter>]
|
72
|
-
def availables
|
73
|
-
@rewriters.values
|
74
|
-
end
|
75
|
-
|
76
|
-
# Clear all registered rewriters.
|
77
|
-
def clear
|
78
|
-
@rewriters.clear
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# @!attribute [r] name
|
83
|
-
# @return [String] the unique name of rewriter
|
84
|
-
# @!attribute [r] sub_snippets
|
85
|
-
# @return [Array<Synvert::Rewriter>] all rewriters this rewiter calls.
|
86
|
-
attr_reader :name, :sub_snippets
|
87
|
-
|
88
|
-
# Initialize a rewriter.
|
89
|
-
# When a rewriter is initialized, it is also registered.
|
90
|
-
#
|
91
|
-
# @param name [String] name of the rewriter.
|
92
|
-
# @param block [Block] a block defines the behaviors of the rewriter, block code won't be called when initialization.
|
93
|
-
# @return [Synvert::Rewriter]
|
94
|
-
def initialize(name, &block)
|
95
|
-
@name = name.to_s
|
96
|
-
@block = block
|
97
|
-
@helpers = []
|
98
|
-
@sub_snippets = []
|
99
|
-
self.class.register(@name, self)
|
100
|
-
end
|
101
|
-
|
102
|
-
# Process the rewriter.
|
103
|
-
# It will call the block.
|
104
|
-
def process
|
105
|
-
self.instance_eval &@block
|
106
|
-
end
|
107
|
-
|
108
|
-
# Process rewriter with sandbox mode.
|
109
|
-
# It will call the block but doesn't change any file.
|
110
|
-
def process_with_sandbox
|
111
|
-
@sandbox = true
|
112
|
-
self.process
|
113
|
-
@sandbox = false
|
114
|
-
end
|
115
|
-
|
116
|
-
#######
|
117
|
-
# DSL #
|
118
|
-
#######
|
119
|
-
|
120
|
-
# Parse description dsl, it sets description of the rewrite.
|
121
|
-
# Or get description.
|
122
|
-
#
|
123
|
-
# @param description [String] rewriter description.
|
124
|
-
# @return rewriter description.
|
125
|
-
def description(description=nil)
|
126
|
-
if description
|
127
|
-
@description = description
|
128
|
-
else
|
129
|
-
@description
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# Parse if_gem dsl, it compares version of the specified gem.
|
134
|
-
#
|
135
|
-
# @param name [String] gem name.
|
136
|
-
# @param comparator [Hash] equal, less than or greater than specified version, e.g. {gte: '2.0.0'},
|
137
|
-
# key can be eq, lt, gt, lte, gte or ne.
|
138
|
-
def if_gem(name, comparator)
|
139
|
-
@gem_spec = Rewriter::GemSpec.new(name, comparator)
|
140
|
-
end
|
141
|
-
|
142
|
-
# Parse within_files dsl, it finds specified files.
|
143
|
-
# It creates a [Synvert::Rewriter::Instance] to rewrite code.
|
144
|
-
#
|
145
|
-
# @param file_pattern [String] pattern to find files, e.g. spec/**/*_spec.rb
|
146
|
-
# @param block [Block] the block to rewrite code in the matching files.
|
147
|
-
def within_files(file_pattern, &block)
|
148
|
-
return if @sandbox
|
149
|
-
|
150
|
-
if !@gem_spec || @gem_spec.match?
|
151
|
-
instance = Rewriter::Instance.new(file_pattern, &block)
|
152
|
-
@helpers.each { |helper| instance.singleton_class.send(:define_method, helper[:name], &helper[:block]) }
|
153
|
-
instance.process
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
# Parse within_file dsl, it finds a specifiled file.
|
158
|
-
alias within_file within_files
|
159
|
-
|
160
|
-
# Parses add_file dsl, it adds a new file.
|
161
|
-
#
|
162
|
-
# @param filename [String] file name of newly created file.
|
163
|
-
# @param content [String] file body of newly created file.
|
164
|
-
def add_file(filename, content)
|
165
|
-
return if @sandbox
|
166
|
-
|
167
|
-
File.open filename, 'w' do |file|
|
168
|
-
file.write content
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# Parse add_snippet dsl, it calls anther rewriter.
|
173
|
-
#
|
174
|
-
# @param name [String] name of another rewriter.
|
175
|
-
def add_snippet(name)
|
176
|
-
@sub_snippets << self.class.call(name.to_s)
|
177
|
-
end
|
178
|
-
|
179
|
-
# Parse helper_method dsl, it defines helper method for [Synvert::Rewriter::Instance].
|
180
|
-
#
|
181
|
-
# @param name [String] helper method name.
|
182
|
-
# @param block [Block] helper method block.
|
183
|
-
def helper_method(name, &block)
|
184
|
-
@helpers << {name: name, block: block}
|
185
|
-
end
|
186
|
-
|
187
|
-
# Parse todo dsl, it sets todo of the rewriter.
|
188
|
-
# Or get todo.
|
189
|
-
#
|
190
|
-
# @param todo_list [String] rewriter todo.
|
191
|
-
# @return [String] rewriter todo.
|
192
|
-
def todo(todo=nil)
|
193
|
-
if todo
|
194
|
-
@todo = todo
|
195
|
-
else
|
196
|
-
@todo
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
Synvert::Rewriter.new "factory_girl_short_syntax" do
|
2
|
-
description <<-EOF
|
3
|
-
Uses FactoryGirl short syntax.
|
4
|
-
|
5
|
-
1. it adds FactoryGirl::Syntax::methods module to RSpec, Test::Unit, Cucumber, Spainach, MiniTest, MiniTest::Spec, minitest-rails.
|
6
|
-
|
7
|
-
# rspec
|
8
|
-
RSpec.configure do |config|
|
9
|
-
config.include FactoryGirl::Syntax::Methods
|
10
|
-
end
|
11
|
-
|
12
|
-
# Test::Unit
|
13
|
-
class Test::Unit::TestCase
|
14
|
-
include FactoryGirl::Syntax::Methods
|
15
|
-
end
|
16
|
-
|
17
|
-
# Cucumber
|
18
|
-
World(FactoryGirl::Syntax::Methods)
|
19
|
-
|
20
|
-
# Spinach
|
21
|
-
class Spinach::FeatureSteps
|
22
|
-
include FactoryGirl::Syntax::Methods
|
23
|
-
end
|
24
|
-
|
25
|
-
# MiniTest
|
26
|
-
class MiniTest::Unit::TestCase
|
27
|
-
include FactoryGirl::Syntax::Methods
|
28
|
-
end
|
29
|
-
|
30
|
-
# MiniTest::Spec
|
31
|
-
class MiniTest::Spec
|
32
|
-
include FactoryGirl::Syntax::Methods
|
33
|
-
end
|
34
|
-
|
35
|
-
# minitest-rails
|
36
|
-
class MiniTest::Rails::ActiveSupport::TestCase
|
37
|
-
include FactoryGirl::Syntax::Methods
|
38
|
-
end
|
39
|
-
|
40
|
-
2. it converts to short syntax.
|
41
|
-
|
42
|
-
FactoryGirl.create(...) => create(...)
|
43
|
-
FactoryGirl.build(...) => build(...)
|
44
|
-
FactoryGirl.attributes_for(...) => attributes_for(...)
|
45
|
-
FactoryGirl.build_stubbed(...) => build_stubbed(...)
|
46
|
-
FactoryGirl.create_list(...) => create_list(...)
|
47
|
-
FactoryGirl.build_list(...) => build_list(...)
|
48
|
-
FactoryGirl.create_pair(...) => create_pair(...)
|
49
|
-
FactoryGirl.build_pair(...) => build_pair(...)
|
50
|
-
EOF
|
51
|
-
|
52
|
-
if_gem 'factory_girl', {gte: '2.0.0'}
|
53
|
-
|
54
|
-
# insert include FactoryGirl::Syntax::Methods
|
55
|
-
within_file 'spec/spec_helper.rb' do
|
56
|
-
within_node type: 'block', caller: {receiver: 'RSpec', message: 'configure'} do
|
57
|
-
unless_exist_node type: 'send', message: 'include', arguments: ['FactoryGirl::Syntax::Methods'] do
|
58
|
-
insert "{{arguments.first}}.include FactoryGirl::Syntax::Methods"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# insert include FactoryGirl::Syntax::Methods
|
64
|
-
within_file 'test/test_helper.rb' do
|
65
|
-
%w(Test::Unit::TestCase ActiveSupport::TestCase MiniTest::Unit::TestCase MiniTest::Spec MiniTest::Rails::ActiveSupport::TestCase).each do |class_name|
|
66
|
-
within_node type: 'class', name: class_name do
|
67
|
-
unless_exist_node type: 'send', message: 'include', arguments: ['FactoryGirl::Syntax::Methods'] do
|
68
|
-
insert "include FactoryGirl::Syntax::Methods"
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# insert World(FactoryGirl::Syntax::Methods)
|
75
|
-
within_file 'features/support/env.rb' do
|
76
|
-
unless_exist_node type: 'send', message: 'World', arguments: ['FactoryGirl::Syntax::Methods'] do
|
77
|
-
insert "World(FactoryGirl::Syntax::Methods)"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# FactoryGirl.create(...) => create(...)
|
82
|
-
# FactoryGirl.build(...) => build(...)
|
83
|
-
# FactoryGirl.attributes_for(...) => attributes_for(...)
|
84
|
-
# FactoryGirl.build_stubbed(...) => build_stubbed(...)
|
85
|
-
# FactoryGirl.create_list(...) => create_list(...)
|
86
|
-
# FactoryGirl.build_list(...) => build_list(...)
|
87
|
-
# FactoryGirl.create_pair(...) => create_pair(...)
|
88
|
-
# FactoryGirl.build_pair(...) => build_pair(...)
|
89
|
-
%w(test/**/*.rb spec/**/*.rb features/**/*.rb).each do |file_pattern|
|
90
|
-
within_files file_pattern do
|
91
|
-
%w(create build attributes_for build_stubbed create_list build_list create_pair build_pair).each do |message|
|
92
|
-
with_node type: 'send', receiver: 'FactoryGirl', message: message do
|
93
|
-
replace_with "#{message}({{arguments}})"
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
Synvert::Rewriter.new "convert_rails_dynamic_finders" do
|
2
|
-
description <<-EOF
|
3
|
-
It converts rails dynamic finders to arel syntax.
|
4
|
-
|
5
|
-
find_all_by_... => where(...)
|
6
|
-
find_by_... => where(...).first
|
7
|
-
find_last_by_... => where(...).last
|
8
|
-
scoped_by_... => where(...)
|
9
|
-
find_or_initialize_by_... => find_or_initialize_by(...)
|
10
|
-
find_or_create_by_... => find_or_create_by(...)
|
11
|
-
EOF
|
12
|
-
|
13
|
-
helper_method 'dynamic_finder_to_hash' do |prefix|
|
14
|
-
fields = node.message.to_s[prefix.length..-1].split("_and_")
|
15
|
-
if fields.length == node.arguments.length && :hash != node.arguments.first.type
|
16
|
-
fields.length.times.map { |i|
|
17
|
-
fields[i] + ": " + node.arguments[i].source(self)
|
18
|
-
}.join(", ")
|
19
|
-
else
|
20
|
-
"{{arguments}}"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
within_files '**/*.rb' do
|
25
|
-
# find_all_by_... => where(...)
|
26
|
-
with_node type: 'send', message: /^find_all_by_/ do
|
27
|
-
hash_params = dynamic_finder_to_hash("find_all_by_")
|
28
|
-
if node.receiver
|
29
|
-
replace_with "{{receiver}}.where(#{hash_params})"
|
30
|
-
else
|
31
|
-
replace_with "where(#{hash_params})"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# find_by_... => where(...).first
|
36
|
-
with_node type: 'send', message: /^find_by_/ do
|
37
|
-
if :find_by_id == node.message
|
38
|
-
if node.receiver
|
39
|
-
replace_with "{{receiver}}.find({{arguments}})"
|
40
|
-
else
|
41
|
-
replace_with "find({{arguments}}"
|
42
|
-
end
|
43
|
-
elsif :find_by_sql != node.message
|
44
|
-
hash_params = dynamic_finder_to_hash("find_by_")
|
45
|
-
if node.receiver
|
46
|
-
replace_with "{{receiver}}.where(#{hash_params}).first"
|
47
|
-
else
|
48
|
-
replace_with "where(#{hash_params}).first"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# find_last_by_... => where(...).last
|
54
|
-
with_node type: 'send', message: /^find_last_by_/ do
|
55
|
-
hash_params = dynamic_finder_to_hash("find_last_by_")
|
56
|
-
if node.receiver
|
57
|
-
replace_with "{{receiver}}.where(#{hash_params}).last"
|
58
|
-
else
|
59
|
-
replace_with "where(#{hash_params}).last"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# scoped_by_... => where(...)
|
64
|
-
with_node type: 'send', message: /^scoped_by_/ do
|
65
|
-
hash_params = dynamic_finder_to_hash("scoped_by_")
|
66
|
-
if node.receiver
|
67
|
-
replace_with "{{receiver}}.where(#{hash_params})"
|
68
|
-
else
|
69
|
-
replace_with "where(#{hash_params})"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# find_or_initialize_by_... => find_or_initialize_by(...)
|
74
|
-
with_node type: 'send', message: /^find_or_initialize_by_/ do
|
75
|
-
hash_params = dynamic_finder_to_hash("find_or_initialize_by_")
|
76
|
-
if node.receiver
|
77
|
-
replace_with "{{receiver}}.find_or_initialize_by(#{hash_params})"
|
78
|
-
else
|
79
|
-
replace_with "find_or_initialize_by(#{hash_params})"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# find_or_create_by_... => find_or_create_by(...)
|
84
|
-
with_node type: 'send', message: /^find_or_create_by_/ do
|
85
|
-
hash_params = dynamic_finder_to_hash("find_or_create_by_")
|
86
|
-
if node.receiver
|
87
|
-
replace_with "{{receiver}}.find_or_create_by(#{hash_params})"
|
88
|
-
else
|
89
|
-
replace_with "find_or_create_by(#{hash_params})"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|