synvert 0.0.1 → 0.0.2
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 +9 -0
- data/README.md +9 -2
- data/lib/synvert.rb +3 -4
- data/lib/synvert/cli.rb +13 -12
- data/lib/synvert/configuration.rb +16 -0
- data/lib/synvert/factory_girl/syntax_methods.rb +37 -0
- data/lib/synvert/node_ext.rb +134 -0
- data/lib/synvert/rewriter.rb +56 -0
- data/lib/synvert/rewriter/action.rb +48 -0
- data/lib/synvert/rewriter/conditions.rb +39 -0
- data/lib/synvert/rewriter/instances.rb +67 -0
- data/lib/synvert/rewriter/scopes.rb +39 -0
- data/lib/synvert/version.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/parser_helper.rb +5 -0
- data/spec/synvert/node_ext_spec.rb +88 -0
- data/spec/synvert/rewriter/action_spec.rb +51 -0
- data/spec/synvert/rewriter/conditions_spec.rb +31 -0
- data/spec/synvert/rewriter/instances_spec.rb +113 -0
- data/spec/synvert/rewriter/scopes_spec.rb +79 -0
- data/spec/synvert/rewriter_spec.rb +31 -0
- data/synvert.gemspec +0 -1
- metadata +25 -28
- data/lib/synvert/base_converter.rb +0 -36
- data/lib/synvert/checking_visitor.rb +0 -37
- data/lib/synvert/factory_girl/syntax_methods_converter.rb +0 -49
- data/lib/synvert/sexp_helper.rb +0 -51
- data/spec/support/shared_context.rb +0 -41
- data/spec/synvert/base_converter_spec.rb +0 -0
- data/spec/synvert/checking_visitor_spec.rb +0 -42
- data/spec/synvert/factory_girl/syntax_methods_converter_spec.rb +0 -148
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Synvert
|
4
|
+
class Rewriter::Scopes
|
5
|
+
def initialize
|
6
|
+
@scopes = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(options)
|
10
|
+
@scopes << Rewriter::Scope.new(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def matching_nodes(node)
|
14
|
+
nodes = [node]
|
15
|
+
@scopes.each do |scope|
|
16
|
+
break if nodes.empty?
|
17
|
+
nodes = scope.matching_nodes(nodes)
|
18
|
+
end
|
19
|
+
nodes
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Rewriter::Scope
|
24
|
+
def initialize(options)
|
25
|
+
@options = options
|
26
|
+
end
|
27
|
+
|
28
|
+
def matching_nodes(nodes)
|
29
|
+
matching_nodes = []
|
30
|
+
while node = nodes.shift
|
31
|
+
matching_nodes << node if node.match?(@options)
|
32
|
+
node.recursive_children do |child_node|
|
33
|
+
matching_nodes << child_node if child_node.match?(@options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
matching_nodes
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/synvert/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -6,9 +6,9 @@ Dir[File.join(File.dirname(__FILE__), 'support', '*')].each do |path|
|
|
6
6
|
require path
|
7
7
|
end
|
8
8
|
|
9
|
-
require 'mocha/api'
|
10
|
-
|
11
9
|
RSpec.configure do |config|
|
10
|
+
config.include ParserHelper
|
11
|
+
|
12
12
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
13
13
|
config.run_all_when_everything_filtered = true
|
14
14
|
config.filter_run :focus
|
@@ -0,0 +1,88 @@
|
|
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::Rewriter::Instance; end')
|
10
|
+
expect(node.name).to eq parse('Synvert::Rewriter::Instance')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#receiver' do
|
15
|
+
it 'gets for send node' do
|
16
|
+
node = parse('FactoryGirl.create :post')
|
17
|
+
expect(node.receiver).to eq parse('FactoryGirl')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#message' do
|
22
|
+
it 'gets for send node' do
|
23
|
+
node = parse('FactoryGirl.create :post')
|
24
|
+
expect(node.message).to eq :create
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#arguments' do
|
29
|
+
it 'gets for send node' do
|
30
|
+
node = parse("FactoryGirl.create :post, title: 'post'")
|
31
|
+
expect(node.arguments).to eq parse("[:post, title: 'post']").children
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'gets for block node' do
|
35
|
+
node = parse('RSpec.configure do |config|; end')
|
36
|
+
expect(node.arguments.map(&:to_s)).to eq ['config']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#caller' do
|
41
|
+
it 'gets for block node' do
|
42
|
+
node = parse('RSpec.configure do |config|; end')
|
43
|
+
expect(node.caller).to eq parse('RSpec.configure')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#to_s' do
|
48
|
+
it 'gets for const node' do
|
49
|
+
node = parse('Synvert')
|
50
|
+
expect(node.to_s).to eq 'Synvert'
|
51
|
+
|
52
|
+
node = parse('Synvert::Rewriter::Instance')
|
53
|
+
expect(node.to_s).to eq 'Synvert::Rewriter::Instance'
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'gets for sym node' do
|
57
|
+
node = parse(':synvert')
|
58
|
+
expect(node.to_s).to eq ':synvert'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'gets for str node' do
|
62
|
+
node = parse("'synvert'")
|
63
|
+
expect(node.to_s).to eq 'synvert'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'gets for lvar node' do
|
67
|
+
node = parse("user = User.find 1; user.valid?").grep_node(type: 'lvar')
|
68
|
+
expect(node.to_s).to eq 'user'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'gets for ivar node' do
|
72
|
+
node = parse('@user')
|
73
|
+
expect(node.to_s).to eq '@user'
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'gets for arg node' do
|
77
|
+
node = parse("RSpec.configure do |config|; end").grep_node(type: 'arg')
|
78
|
+
expect(node.to_s).to eq 'config'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#indent' do
|
83
|
+
it 'gets column number' do
|
84
|
+
node = parse(' FactoryGirl.create :post')
|
85
|
+
expect(node.indent).to eq 2
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Synvert
|
4
|
+
describe Rewriter::ReplaceWithAction do
|
5
|
+
describe '#rewrite' do
|
6
|
+
it 'replaces code' do
|
7
|
+
action = Rewriter::ReplaceWithAction.new('create_list {{node.arguments}}')
|
8
|
+
source = "post = FactoryGirl.create_list :post, 2"
|
9
|
+
send_node = Parser::CurrentRuby.parse(source).children[1]
|
10
|
+
output = action.rewrite(source, send_node)
|
11
|
+
expect(output).to eq "post = create_list :post, 2"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Rewriter::InsertAction do
|
17
|
+
describe '#rewrite' do
|
18
|
+
it 'insert code to block node' do
|
19
|
+
action = Rewriter::InsertAction.new('{{node.arguments.first}}.include FactoryGirl::Syntax::Methods')
|
20
|
+
source = "RSpec.configure do |config|\nend"
|
21
|
+
block_node = Parser::CurrentRuby.parse(source)
|
22
|
+
output = action.rewrite(source, block_node)
|
23
|
+
expect(output).to eq "RSpec.configure do |config|\n config.include FactoryGirl::Syntax::Methods\nend"
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'insert code to class node' do
|
27
|
+
action = Rewriter::InsertAction.new('include FactoryGirl::Syntax::Methods')
|
28
|
+
source = "class Test::Unit::TestCase\nend"
|
29
|
+
block_node = Parser::CurrentRuby.parse(source)
|
30
|
+
output = action.rewrite(source, block_node)
|
31
|
+
expect(output).to eq "class Test::Unit::TestCase\n include FactoryGirl::Syntax::Methods\nend"
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'insert code to begin node' do
|
35
|
+
action = Rewriter::InsertAction.new('World(FactoryGirl::Syntax::Methods)')
|
36
|
+
source = "require 'cucumber/rails'\nActionController::Base.allow_rescue = false"
|
37
|
+
block_node = Parser::CurrentRuby.parse(source)
|
38
|
+
output = action.rewrite(source, block_node)
|
39
|
+
expect(output).to eq "require 'cucumber/rails'\nActionController::Base.allow_rescue = false\nWorld(FactoryGirl::Syntax::Methods)"
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'insert code to other node' do
|
43
|
+
action = Rewriter::InsertAction.new('World(FactoryGirl::Syntax::Methods)')
|
44
|
+
source = "require 'cucumber/rails'"
|
45
|
+
block_node = Parser::CurrentRuby.parse(source)
|
46
|
+
output = action.rewrite(source, block_node)
|
47
|
+
expect(output).to eq "require 'cucumber/rails'\nWorld(FactoryGirl::Syntax::Methods)"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Synvert
|
4
|
+
describe Rewriter::Conditions do
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Rewriter::UnlessExistCondition do
|
9
|
+
let(:source) {
|
10
|
+
"""
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.include EmailSpec::Helpers
|
13
|
+
config.include EmailSpec::Methods
|
14
|
+
end
|
15
|
+
"""
|
16
|
+
}
|
17
|
+
let(:node) { Parser::CurrentRuby.parse(source) }
|
18
|
+
|
19
|
+
describe '#matching_nodes' do
|
20
|
+
it 'gets empty array if does not matchi anything' do
|
21
|
+
condition = Rewriter::UnlessExistCondition.new type: 'send', message: 'include', arguments: {first: {to_s: 'FactoryGirl::Syntax::Methods'} }
|
22
|
+
expect(condition.matching_nodes([node]).size).to eq 1
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'gets matching nodes' do
|
26
|
+
condition = Rewriter::UnlessExistCondition.new type: 'send', message: 'include', arguments: {first: {to_s: 'EmailSpec::Helpers'} }
|
27
|
+
expect(condition.matching_nodes([node])).to eq []
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Synvert
|
4
|
+
describe Rewriter::Instances do
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Rewriter::Instance do
|
9
|
+
let(:instance) { Rewriter::Instance.new('file pattern') }
|
10
|
+
|
11
|
+
describe '#within_node' do
|
12
|
+
it 'adds a scope'do
|
13
|
+
expect_any_instance_of(Rewriter::Scopes).to receive(:add).with(type: 'block', caller: {receiver: 'RSpec', message: 'configure'})
|
14
|
+
instance.within_node type: 'block', caller: {receiver: 'RSpec', message: 'configure'} do; end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#with_node' do
|
19
|
+
it 'adds a scope' do
|
20
|
+
expect_any_instance_of(Rewriter::Scopes).to receive(:add).with(type: 'send', receiver: 'FactoryGirl', message: 'create')
|
21
|
+
instance.with_node type: 'send', receiver: 'FactoryGirl', message: 'create' do; end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#insert' do
|
26
|
+
it 'sets an action' do
|
27
|
+
expect(Rewriter::InsertAction).to receive(:new).with('{{node.arguments.first}}.include FactoryGirl::Syntax::Methods')
|
28
|
+
instance.insert "{{node.arguments.first}}.include FactoryGirl::Syntax::Methods"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#replace_with' do
|
33
|
+
it 'sets an action' do
|
34
|
+
expect(Rewriter::ReplaceWithAction).to receive(:new).with('create {{node.arguments}}')
|
35
|
+
instance.replace_with 'create {{node.arguments}}'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#process' do
|
40
|
+
before { Configuration.instance.set :path, '.' }
|
41
|
+
|
42
|
+
it 'FactoryGirl uses short syntax' do
|
43
|
+
instance = Rewriter::Instance.new('spec/**/*_spec.rb')
|
44
|
+
instance.with_node type: 'send', receiver: 'FactoryGirl', message: 'create' do
|
45
|
+
replace_with 'create {{node.arguments}}'
|
46
|
+
end
|
47
|
+
input = """
|
48
|
+
it 'uses factory_girl' do
|
49
|
+
user = FactoryGirl.create :user
|
50
|
+
post = FactoryGirl.create :post, user: user
|
51
|
+
assert post.valid?
|
52
|
+
end
|
53
|
+
"""
|
54
|
+
output = """
|
55
|
+
it 'uses factory_girl' do
|
56
|
+
user = create :user
|
57
|
+
post = create :post, user: user
|
58
|
+
assert post.valid?
|
59
|
+
end
|
60
|
+
"""
|
61
|
+
expect(Dir).to receive(:glob).with('./spec/**/*_spec.rb').and_return(['spec/models/post_spec.rb'])
|
62
|
+
expect(File).to receive(:read).with('spec/models/post_spec.rb').and_return(input)
|
63
|
+
expect(File).to receive(:write).with('spec/models/post_spec.rb', output)
|
64
|
+
instance.process
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'includes FactoryGirl::Syntax::Methods' do
|
68
|
+
instance = Rewriter::Instance.new('spec/spec_helper.rb')
|
69
|
+
instance.with_node type: 'block', caller: {receiver: 'RSpec', message: 'configure'} do
|
70
|
+
unless_exist_node type: 'send', message: 'include', arguments: {first: {to_s: 'FactoryGirl::Syntax::Methods'}} do
|
71
|
+
insert "{{node.arguments.first}}.include FactoryGirl::Syntax::Methods"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
input = """
|
75
|
+
RSpec.configure do |config|
|
76
|
+
end
|
77
|
+
"""
|
78
|
+
output = """
|
79
|
+
RSpec.configure do |config|
|
80
|
+
config.include FactoryGirl::Syntax::Methods
|
81
|
+
end
|
82
|
+
"""
|
83
|
+
expect(Dir).to receive(:glob).with('./spec/spec_helper.rb').and_return(['spec/spec_helper.rb'])
|
84
|
+
expect(File).to receive(:read).with('spec/spec_helper.rb').and_return(input)
|
85
|
+
expect(File).to receive(:write).with('spec/spec_helper.rb', output)
|
86
|
+
instance.process
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'does not include FactoryGirl::Syntax::Methods' do
|
90
|
+
instance = Rewriter::Instance.new('spec/spec_helper.rb')
|
91
|
+
instance.with_node type: 'block', caller: {receiver: 'RSpec', message: 'configure'} do
|
92
|
+
unless_exist_node type: 'send', message: 'include', arguments: {first: {to_s: 'FactoryGirl::Syntax::Methods'}} do
|
93
|
+
insert "{{node.arguments.first}}.include FactoryGirl::Syntax::Methods"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
input = """
|
97
|
+
RSpec.configure do |config|
|
98
|
+
config.include FactoryGirl::Syntax::Methods
|
99
|
+
end
|
100
|
+
"""
|
101
|
+
output = """
|
102
|
+
RSpec.configure do |config|
|
103
|
+
config.include FactoryGirl::Syntax::Methods
|
104
|
+
end
|
105
|
+
"""
|
106
|
+
expect(Dir).to receive(:glob).with('./spec/spec_helper.rb').and_return(['spec/spec_helper.rb'])
|
107
|
+
expect(File).to receive(:read).with('spec/spec_helper.rb').and_return(input)
|
108
|
+
expect(File).to receive(:write).with('spec/spec_helper.rb', output)
|
109
|
+
instance.process
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Synvert
|
4
|
+
describe Rewriter::Scopes do
|
5
|
+
let(:source) {
|
6
|
+
"""
|
7
|
+
describe Post do
|
8
|
+
before :each do
|
9
|
+
@user = FactoryGirl.create :user
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'gets posts' do
|
13
|
+
post1 = FactoryGirl.create :post
|
14
|
+
post2 = FactoryGirl.create :post
|
15
|
+
end
|
16
|
+
end
|
17
|
+
"""
|
18
|
+
}
|
19
|
+
let(:node) { Parser::CurrentRuby.parse(source) }
|
20
|
+
|
21
|
+
before(:each) { @scopes = Rewriter::Scopes.new }
|
22
|
+
|
23
|
+
describe '#matching_nodes' do
|
24
|
+
it 'gets original node if scopes are empty' do
|
25
|
+
scoped_nodes = @scopes.matching_nodes(node)
|
26
|
+
expect(scoped_nodes).to eq [node]
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'gets all matching nodes with one scope' do
|
30
|
+
@scopes.add type: 'send', receiver: 'FactoryGirl', message: 'create'
|
31
|
+
scoped_nodes = @scopes.matching_nodes(node)
|
32
|
+
expect(scoped_nodes.size).to eq 3
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'gets all matching nodes with multi scopes' do
|
36
|
+
@scopes.add type: 'block', caller: {message: 'describe', arguments: ['Post']}
|
37
|
+
@scopes.add type: 'block', caller: {message: 'before', arguments: [':each']}
|
38
|
+
@scopes.add type: 'send', receiver: 'FactoryGirl', message: 'create'
|
39
|
+
scoped_nodes = @scopes.matching_nodes(node)
|
40
|
+
expect(scoped_nodes.size).to eq 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe Rewriter::Scope do
|
46
|
+
let(:source) {
|
47
|
+
"""
|
48
|
+
describe Post do
|
49
|
+
before :each do
|
50
|
+
@user = FactoryGirl.create :user
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'gets posts' do
|
54
|
+
post1 = FactoryGirl.create :post
|
55
|
+
post2 = FactoryGirl.create :post
|
56
|
+
end
|
57
|
+
end
|
58
|
+
"""
|
59
|
+
}
|
60
|
+
let(:node) { Parser::CurrentRuby.parse(source) }
|
61
|
+
|
62
|
+
describe '#matching_nodes' do
|
63
|
+
it 'gets empty array if does not match anything' do
|
64
|
+
scope = Rewriter::Scope.new type: 'send', message: 'missing'
|
65
|
+
expect(scope.matching_nodes([node])).to eq []
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'gets matching nodes' do
|
69
|
+
scope = Rewriter::Scope.new type: 'send', receiver: 'FactoryGirl', message: 'create', arguments: [':post']
|
70
|
+
expect(scope.matching_nodes([node]).size).to eq 2
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'gets matching nodes witch block caller' do
|
74
|
+
scope = Rewriter::Scope.new type: 'block', caller: {message: 'it', arguments: ['gets posts']}
|
75
|
+
expect(scope.matching_nodes([node]).size).to eq 1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Synvert
|
4
|
+
describe Rewriter do
|
5
|
+
it 'sets description' do
|
6
|
+
rewriter = Rewriter.new 'this is description' do; end
|
7
|
+
expect(rewriter.description).to eq 'this is description'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'parses from_version' do
|
11
|
+
rewriter = Rewriter.new 'description' do
|
12
|
+
from_version '1.0.0'
|
13
|
+
end
|
14
|
+
expect(rewriter.version.to_s).to eq '1.0.0'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'parses within_file' do
|
18
|
+
expect_any_instance_of(Rewriter::Instances).to receive(:add).with('spec/spec_helper.rb')
|
19
|
+
Rewriter.new 'description' do
|
20
|
+
within_file 'spec/spec_helper.rb' do; end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'parses within_files' do
|
25
|
+
expect_any_instance_of(Rewriter::Instances).to receive(:add).with('spec/**/*_spec.rb')
|
26
|
+
Rewriter.new 'description' do
|
27
|
+
within_files 'spec/**/*_spec.rb' do; end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|