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.
@@ -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
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Synvert
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
  end
@@ -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,5 @@
1
+ module ParserHelper
2
+ def parse(code)
3
+ Parser::CurrentRuby.parse code
4
+ end
5
+ end
@@ -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