ruby_traverser 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.
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.markdown +195 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/lib/mutate/api.rb +124 -0
- data/lib/mutate/replacer.rb +129 -0
- data/lib/rails/api_wrapper.rb +23 -0
- data/lib/ruby_traverser.rb +4 -0
- data/lib/traversal/api/finders.rb +41 -0
- data/lib/traversal/api/inside.rb +36 -0
- data/lib/traversal/api/traversal.rb +20 -0
- data/lib/traversal/misc.rb +152 -0
- data/lib/traversal/mixin.rb +50 -0
- data/lib/traversal/module.rb +52 -0
- data/lib/traversal/patch.rb +83 -0
- data/ruby_traverser.gemspec +79 -0
- data/spec/ruby_traverser_spec.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/test/mutate/mutate_class_test.rb +29 -0
- data/test/mutate/mutate_test.rb +90 -0
- data/test/rails_api/gemfile_api.rb +27 -0
- data/test/test_helper.rb +53 -0
- data/test/traversal/gemfile_test.rb +92 -0
- data/test/traversal/ruby_api_traversal_test.rb +128 -0
- metadata +122 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Node
|
3
|
+
module Traversal
|
4
|
+
module Misc
|
5
|
+
def args?(value, with_block = nil)
|
6
|
+
found = 0
|
7
|
+
obj = has_a_block?(with_block) ? self.block : self
|
8
|
+
args_list = get_args_list(obj)
|
9
|
+
return false if !args_list
|
10
|
+
args_list.elements.each do |arg|
|
11
|
+
argument = retrieve_arg(arg)
|
12
|
+
next if !valid_arg?(argument)
|
13
|
+
value.each do |v|
|
14
|
+
v = v[:array] if v.respond_to?(:has_key?) && v[:array]
|
15
|
+
found += 1 if argument == v
|
16
|
+
end
|
17
|
+
end
|
18
|
+
return found == argument_count(value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def argument_count(args)
|
22
|
+
args.reject{|arg| !valid_arg?(arg)}.size
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid_arg?(arg)
|
26
|
+
arg && arg != {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_a_block?(with_block)
|
30
|
+
with_block && self.respond_to?(:block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_args_list(obj)
|
34
|
+
return obj.params if obj.respond_to? :params
|
35
|
+
return obj.arguments if obj.respond_to? :arguments
|
36
|
+
# return obj if obj.class == Ruby::ArgsList
|
37
|
+
end
|
38
|
+
|
39
|
+
def resolve_arg_wrapper(arg_wrapper)
|
40
|
+
return arg_wrapper.arg if arg_wrapper.respond_to? :arg
|
41
|
+
return arg_wrapper.param if arg_wrapper.respond_to? :param
|
42
|
+
return arg_wrapper if arg_wrapper.class == Ruby::Arg
|
43
|
+
arg_wrapper
|
44
|
+
end
|
45
|
+
|
46
|
+
def retrieve_arg(arg_wrapper)
|
47
|
+
arg = resolve_arg_wrapper(arg_wrapper)
|
48
|
+
argument = get_arg(arg)
|
49
|
+
convert_value(argument, arg)
|
50
|
+
end
|
51
|
+
|
52
|
+
def convert_value(value, type = nil)
|
53
|
+
type_val = type || value
|
54
|
+
case type_val
|
55
|
+
when Ruby::Symbol
|
56
|
+
value.to_sym
|
57
|
+
when Ruby::Integer
|
58
|
+
value.to_i
|
59
|
+
when Ruby::Float
|
60
|
+
value.to_f
|
61
|
+
when Ruby::Hash
|
62
|
+
type ? get_hash(type) : value
|
63
|
+
when Ruby::Array
|
64
|
+
type ? get_array(type) : value
|
65
|
+
when Ruby::Assoc
|
66
|
+
return get_assoc(type)
|
67
|
+
else
|
68
|
+
value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_arg(arg)
|
73
|
+
get_symbol(arg) || get_assoc(arg) || get_composite(arg) || get_identifier(arg) || get_token(arg) || resolve_arg_wrapper(arg)
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_symbol(arg)
|
77
|
+
return nil if !(arg.class == Ruby::Symbol)
|
78
|
+
t = get_token(arg)
|
79
|
+
t ? t.to_sym : nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_composite(arg)
|
83
|
+
return nil if !arg.respond_to? :elements
|
84
|
+
e = arg.elements
|
85
|
+
return get_arg(e[0]) if e.size == 1
|
86
|
+
get_hash(e) || get_array(e)
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_array(args)
|
90
|
+
return nil if arg.class != Ruby::Array
|
91
|
+
arr = []
|
92
|
+
args.each do |arg|
|
93
|
+
arr << get_arg(arg)
|
94
|
+
end
|
95
|
+
return arr if !arr.empty?
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_hash(args)
|
100
|
+
return nil if !args.class == Ruby::Hash
|
101
|
+
items = args.respond_to?(:elements) ? args.elements : args
|
102
|
+
hash = {}
|
103
|
+
items.each do |arg|
|
104
|
+
hash_val = get_arg(arg)
|
105
|
+
hash.merge!(hash_val)
|
106
|
+
end
|
107
|
+
return hash if !hash.empty?
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_assoc(arg)
|
112
|
+
return nil if !(arg.class == Ruby::Assoc)
|
113
|
+
get_hash_item(arg)
|
114
|
+
end
|
115
|
+
|
116
|
+
def get_hash_item(arg)
|
117
|
+
return if !arg.respond_to? :key
|
118
|
+
key = get_key(arg.key)
|
119
|
+
value = get_value(arg.value)
|
120
|
+
return {key => value}
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_key(key)
|
124
|
+
if key.respond_to? :identifier
|
125
|
+
id = get_identifier(key)
|
126
|
+
end
|
127
|
+
return id.to_sym if key.class == Ruby::Symbol
|
128
|
+
return get_token(key) if key.class == Ruby::Variable
|
129
|
+
id
|
130
|
+
end
|
131
|
+
|
132
|
+
# Needs rework!
|
133
|
+
def get_value(value)
|
134
|
+
real_value = get_arg(value)
|
135
|
+
convert_value(real_value, value)
|
136
|
+
end
|
137
|
+
|
138
|
+
def get_identifier(arg)
|
139
|
+
get_token(arg.identifier) if arg.respond_to? :identifier
|
140
|
+
end
|
141
|
+
|
142
|
+
def get_string(arg)
|
143
|
+
get_token(arg.elements[0]) if arg.class == Ruby::String
|
144
|
+
end
|
145
|
+
|
146
|
+
def get_token(arg)
|
147
|
+
arg.token if arg.respond_to? :token
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'traversal/module'
|
2
|
+
require 'traversal/misc'
|
3
|
+
require 'traversal/patch'
|
4
|
+
|
5
|
+
module Ruby
|
6
|
+
class Node
|
7
|
+
include Traversal::Module
|
8
|
+
include Traversal::Misc
|
9
|
+
include Traversal::Patch
|
10
|
+
|
11
|
+
def has_const?(value)
|
12
|
+
if respond_to?(:const)
|
13
|
+
if namespace?(value)
|
14
|
+
name = value.split('::').last
|
15
|
+
return self.const.identifier.token == name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_block?
|
22
|
+
respond_to? :block
|
23
|
+
end
|
24
|
+
|
25
|
+
def has_namespace?(value)
|
26
|
+
if respond_to?(:namespace)
|
27
|
+
return self.namespace.identifier.token == value
|
28
|
+
end
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_identifier?(value)
|
33
|
+
if respond_to?(:identifier)
|
34
|
+
id = self.identifier
|
35
|
+
|
36
|
+
if namespace?(value)
|
37
|
+
return id.token.to_s == value.to_s if id.respond_to?(:token)
|
38
|
+
if id.respond_to?(:identifier)
|
39
|
+
name = value.split('::').last
|
40
|
+
return id.identifier.token == name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
else
|
44
|
+
has_const?(value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Node
|
3
|
+
module Traversal
|
4
|
+
module Module
|
5
|
+
def namespace?(full_name)
|
6
|
+
if full_name.split('::').size > 1
|
7
|
+
namespaces = full_name.split('::')[0..-2]
|
8
|
+
namespace = namespaces.join('::')
|
9
|
+
|
10
|
+
if class_or_module?
|
11
|
+
return module_namespace?(namespace)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def class_or_module?
|
18
|
+
[Ruby::Class, Ruby::Module].include?(self.class)
|
19
|
+
end
|
20
|
+
|
21
|
+
def module_namespace?(namespace)
|
22
|
+
namespace == get_full_namespace(get_namespace)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_namespace
|
26
|
+
return self.const.namespace if self.respond_to?(:const)
|
27
|
+
self.identifier.namespace
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_full_namespace(ns)
|
31
|
+
if ns.respond_to?(:namespace)
|
32
|
+
name = ns.identifier.token
|
33
|
+
parent_ns = get_full_namespace(ns.namespace)
|
34
|
+
name += ('::' + parent_ns) if !parent_ns.empty?
|
35
|
+
return name.split('::').reverse.join('::')
|
36
|
+
else
|
37
|
+
return ns.identifier.token if ns.respond_to?(:identifier)
|
38
|
+
""
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def superclass?(value)
|
43
|
+
if class_or_module?
|
44
|
+
ns = get_full_namespace(self.super_class)
|
45
|
+
return ns == value
|
46
|
+
end
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Node
|
3
|
+
module Traversal
|
4
|
+
module Patch
|
5
|
+
def select(*args, &block)
|
6
|
+
result = []
|
7
|
+
result << self if matches?(args.dup, &block)
|
8
|
+
children.flatten.compact.inject(result) do |result, node|
|
9
|
+
if node.class.to_s == 'Symbol'
|
10
|
+
return result
|
11
|
+
end
|
12
|
+
selected = node.select(*args, &block)
|
13
|
+
result + selected
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def children
|
18
|
+
(self.try(:elements).to_a || prolog.try(:elements).to_a || []) + nodes
|
19
|
+
end
|
20
|
+
|
21
|
+
def matches?(args, &block)
|
22
|
+
conditions = args.last.is_a?(::Hash) ? args.pop : {}
|
23
|
+
conditions[:is_a] = args unless args.empty?
|
24
|
+
|
25
|
+
type_condition = conditions[:is_a][0]
|
26
|
+
if type_condition
|
27
|
+
return nil if !has_type?(type_condition)
|
28
|
+
end
|
29
|
+
|
30
|
+
res = conditions.inject(!conditions.empty?) do |result, (type, value)|
|
31
|
+
block_result = (!block_given? || block.call(self))
|
32
|
+
check_res = check_pair(type, value)
|
33
|
+
return false if !check_res
|
34
|
+
result && check_res && block_result
|
35
|
+
end
|
36
|
+
res
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_pair(type, value)
|
40
|
+
res = case type
|
41
|
+
when :is_a
|
42
|
+
has_type?(value)
|
43
|
+
when :class
|
44
|
+
is_instance_of?(value)
|
45
|
+
when :token
|
46
|
+
has_token?(value)
|
47
|
+
when :left_token
|
48
|
+
left.has_token?(value)
|
49
|
+
when :right_token
|
50
|
+
right.has_token?(value)
|
51
|
+
when :value
|
52
|
+
has_value?(value)
|
53
|
+
when :identifier
|
54
|
+
has_identifier?(value)
|
55
|
+
when :const
|
56
|
+
has_const?(value)
|
57
|
+
when :block
|
58
|
+
has_block?
|
59
|
+
when :namespace
|
60
|
+
has_namespace?(value)
|
61
|
+
when :superclass
|
62
|
+
superclass?(value)
|
63
|
+
when :args, :params
|
64
|
+
args?(value)
|
65
|
+
when :block_params
|
66
|
+
args?(value, :withblock)
|
67
|
+
when :pos, :position
|
68
|
+
position?(value)
|
69
|
+
when :right_of
|
70
|
+
right_of?(value)
|
71
|
+
when :left_of
|
72
|
+
left_of?(value)
|
73
|
+
else
|
74
|
+
true
|
75
|
+
end
|
76
|
+
# puts "check pair type:#{type}, value:#{value} => #{res}, self: #{self.inspect}" if self.class == Ruby::Variable
|
77
|
+
res
|
78
|
+
end
|
79
|
+
|
80
|
+
end # Patch
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ruby_traverser}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Kristian Mandrup"]
|
12
|
+
s.date = %q{2010-04-27}
|
13
|
+
s.description = %q{traverse a ruby code model and optionally mutate it along the way using a nice rubyish DSL}
|
14
|
+
s.email = %q{kmandrup@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.markdown",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"lib/mutate/api.rb",
|
26
|
+
"lib/mutate/replacer.rb",
|
27
|
+
"lib/rails/api_wrapper.rb",
|
28
|
+
"lib/ruby_traverser.rb",
|
29
|
+
"lib/traversal/api/finders.rb",
|
30
|
+
"lib/traversal/api/inside.rb",
|
31
|
+
"lib/traversal/api/traversal.rb",
|
32
|
+
"lib/traversal/misc.rb",
|
33
|
+
"lib/traversal/mixin.rb",
|
34
|
+
"lib/traversal/module.rb",
|
35
|
+
"lib/traversal/patch.rb",
|
36
|
+
"ruby_traverser.gemspec",
|
37
|
+
"spec/ruby_traverser_spec.rb",
|
38
|
+
"spec/spec.opts",
|
39
|
+
"spec/spec_helper.rb",
|
40
|
+
"test/mutate/mutate_class_test.rb",
|
41
|
+
"test/mutate/mutate_test.rb",
|
42
|
+
"test/rails_api/gemfile_api.rb",
|
43
|
+
"test/test_helper.rb",
|
44
|
+
"test/traversal/gemfile_test.rb",
|
45
|
+
"test/traversal/ruby_api_traversal_test.rb"
|
46
|
+
]
|
47
|
+
s.homepage = %q{http://github.com/kristianmandrup/ruby_trav}
|
48
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
49
|
+
s.require_paths = ["lib"]
|
50
|
+
s.rubygems_version = %q{1.3.6}
|
51
|
+
s.summary = %q{traverse and mutate ruby code using a nice DSL}
|
52
|
+
s.test_files = [
|
53
|
+
"spec/ruby_traverser_spec.rb",
|
54
|
+
"spec/spec_helper.rb",
|
55
|
+
"test/mutate/mutate_class_test.rb",
|
56
|
+
"test/mutate/mutate_test.rb",
|
57
|
+
"test/rails_api/gemfile_api.rb",
|
58
|
+
"test/test_helper.rb",
|
59
|
+
"test/traversal/gemfile_test.rb",
|
60
|
+
"test/traversal/ruby_api_traversal_test.rb"
|
61
|
+
]
|
62
|
+
|
63
|
+
if s.respond_to? :specification_version then
|
64
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
65
|
+
s.specification_version = 3
|
66
|
+
|
67
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
68
|
+
s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
|
69
|
+
s.add_runtime_dependency(%q<ripper2ruby>, ["> 0.0.2"])
|
70
|
+
else
|
71
|
+
s.add_dependency(%q<rspec>, [">= 2.0.0"])
|
72
|
+
s.add_dependency(%q<ripper2ruby>, ["> 0.0.2"])
|
73
|
+
end
|
74
|
+
else
|
75
|
+
s.add_dependency(%q<rspec>, [">= 2.0.0"])
|
76
|
+
s.add_dependency(%q<ripper2ruby>, ["> 0.0.2"])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class TraversalTest < Test::Unit::TestCase
|
5
|
+
include TestHelper
|
6
|
+
|
7
|
+
define_method :"test select Class that inherits from other Class and insert gem statements and a new method def" do
|
8
|
+
src = %q{ class Monty < Abc::Blip
|
9
|
+
end}
|
10
|
+
|
11
|
+
def_src = %q{
|
12
|
+
def my_fun
|
13
|
+
end}
|
14
|
+
|
15
|
+
def_code = Ripper::RubyBuilder.build(def_src)
|
16
|
+
code = Ripper::RubyBuilder.build(src)
|
17
|
+
code.inside_class('Monty', :superclass => 'Abc::Blip') do |b|
|
18
|
+
assert_equal Ruby::Class, b.class
|
19
|
+
gem_abc = b.append_code("gem 'abc'")
|
20
|
+
blip = b.append_code("blip")
|
21
|
+
gem_123 = gem_abc.append_code("gem '123'")
|
22
|
+
gem_123.append_comment("hello")
|
23
|
+
my_def = b.append_code(def_src)
|
24
|
+
|
25
|
+
b.prepend_code("gem '789'")
|
26
|
+
puts b.to_ruby
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class TraversalTest < Test::Unit::TestCase
|
5
|
+
include TestHelper
|
6
|
+
|
7
|
+
define_method :"test find gem statement inside group using DSL and then insert new gem statement" do
|
8
|
+
src = %q{
|
9
|
+
group :test do
|
10
|
+
gem 'ripper', :src => 'github'
|
11
|
+
gem 'blip'
|
12
|
+
end
|
13
|
+
}
|
14
|
+
|
15
|
+
code = Ripper::RubyBuilder.build(src)
|
16
|
+
|
17
|
+
code.inside_block('group', :args => [:test]) do |b|
|
18
|
+
call_node = b.find_call('gem', :args => ['ripper', {:src => 'github'}])
|
19
|
+
assert_equal Ruby::Call, call_node.class
|
20
|
+
b.append_code("gem 'abc'")
|
21
|
+
puts "mutated block:"
|
22
|
+
puts b.to_ruby
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method :"test find gem statement inside group using DSL and then replace symbol argument with hash argument" do
|
27
|
+
src = %q{
|
28
|
+
group :test do
|
29
|
+
gem 'ripper', :src
|
30
|
+
end
|
31
|
+
}
|
32
|
+
|
33
|
+
code = Ripper::RubyBuilder.build(src)
|
34
|
+
code.inside_block('group', :args => [:test]) do |b|
|
35
|
+
call_node = b.find_call('gem', :args => ['ripper'])
|
36
|
+
assert_equal Ruby::Call, call_node.class
|
37
|
+
call_node.replace(:arg => :src , :replace_code => "{:src => 'unknown'}")
|
38
|
+
puts b.to_ruby
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
define_method :"test find gem statement inside group using DSL and then replace matching hash with new hash" do
|
43
|
+
src = %q{
|
44
|
+
group :test do
|
45
|
+
gem 'ripper', :src => 'blip'
|
46
|
+
end
|
47
|
+
}
|
48
|
+
|
49
|
+
code = Ripper::RubyBuilder.build(src)
|
50
|
+
code.inside_block('group', :args => [:test]) do |b|
|
51
|
+
call_node = b.find_call('gem', :args => ['ripper'])
|
52
|
+
assert_equal Ruby::Call, call_node.class
|
53
|
+
call_node.replace(:arg => {:src => 'blip'} , :replace_code => "{:src => 'unknown'}")
|
54
|
+
puts b.to_ruby
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
define_method :"test find assignment in method definition and replace value of right side" do
|
59
|
+
src = %q{
|
60
|
+
def hello_world(a)
|
61
|
+
my_var = 2
|
62
|
+
end
|
63
|
+
}
|
64
|
+
|
65
|
+
code = Ripper::RubyBuilder.build(src)
|
66
|
+
|
67
|
+
code.inside_def('hello_world', :params => ['a']) do |b|
|
68
|
+
# call_node = b.find_call('gem', :args => ['ripper', {:src => 'github'}], :verbose => true)
|
69
|
+
call_node = b.find_assignment('my_var')
|
70
|
+
assert_equal Ruby::Assignment, call_node.class
|
71
|
+
|
72
|
+
call_node.replace(:value => "3")
|
73
|
+
puts b.to_ruby
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
define_method :"test select Class that inherits from other Class and insert new method def" do
|
78
|
+
src = %q{
|
79
|
+
class Monty < Abc::Blip
|
80
|
+
end
|
81
|
+
}
|
82
|
+
code = Ripper::RubyBuilder.build(src)
|
83
|
+
code.find_class('Monty', :superclass => 'Abc::Blip') do |b|
|
84
|
+
assert_equal Ruby::Class, b.class
|
85
|
+
b.append_code("gem 'abc'")
|
86
|
+
puts b.to_ruby
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
require 'rails/api_wrapper'
|
5
|
+
|
6
|
+
class TraversalTest < Test::Unit::TestCase
|
7
|
+
include TestHelper
|
8
|
+
|
9
|
+
define_method :"test find gem statement inside group using DSL and then insert new gem statement" do
|
10
|
+
src = %q{
|
11
|
+
group :test do
|
12
|
+
gem 'ripper', :src => 'github'
|
13
|
+
gem 'blip'
|
14
|
+
end
|
15
|
+
}
|
16
|
+
|
17
|
+
code = Ripper::RubyBuilder.build(src)
|
18
|
+
|
19
|
+
code.extend(RubyAPI::Rails::Gemfile)
|
20
|
+
code.inside_group :test do |b|
|
21
|
+
b.add_gem 'cucumber' if !b.find_gem 'cucumber'
|
22
|
+
b.replace_gem 'blip', 'blap'
|
23
|
+
end
|
24
|
+
puts code.to_ruby
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'ripper/ruby_builder'
|
4
|
+
require 'ruby_traverser'
|
5
|
+
require 'ripper/event_log'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'pp'
|
8
|
+
require 'highlighters/ansi'
|
9
|
+
|
10
|
+
module TestHelper
|
11
|
+
def build(src, filename = nil)
|
12
|
+
Ripper::RubyBuilder.build(src, filename)
|
13
|
+
end
|
14
|
+
|
15
|
+
def sexp(src)
|
16
|
+
pp Ripper::SexpBuilder.new(src).parse
|
17
|
+
end
|
18
|
+
|
19
|
+
def log(src)
|
20
|
+
Ripper::EventLog.out(src)
|
21
|
+
end
|
22
|
+
|
23
|
+
def assert_build(src)
|
24
|
+
expr = build(src)
|
25
|
+
assert_equal src, expr.to_ruby(true)
|
26
|
+
assert_equal src, expr.src(true)
|
27
|
+
# expr.all_nodes.each { |node| assert_equal Ruby::Program, node.root.class }
|
28
|
+
yield(expr) if block_given?
|
29
|
+
expr
|
30
|
+
end
|
31
|
+
|
32
|
+
def assert_node(node, assertions)
|
33
|
+
node = node.first if node.is_a?(Array)
|
34
|
+
assertions.each do |type, value|
|
35
|
+
case type
|
36
|
+
when :is_a
|
37
|
+
assert node.is_a?(value)
|
38
|
+
when :class
|
39
|
+
assert_equal value, node.class
|
40
|
+
when :pos, :position
|
41
|
+
assert_position(value, node)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def assert_position(position, node)
|
47
|
+
node = node.first if node.is_a?(Array)
|
48
|
+
assert_equal position, node.position.to_a
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
|