ruby_traverser 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +15 -0
- data/VERSION +1 -1
- data/lib/manipulation/delete/api.rb +3 -0
- data/lib/manipulation/insert/api.rb +37 -31
- data/lib/manipulation/update/api.rb +18 -95
- data/lib/manipulation/update/hash.rb +58 -0
- data/lib/manipulation/update/position.rb +29 -0
- data/lib/manipulation/update/token.rb +15 -0
- data/lib/manipulation/update/value.rb +13 -0
- data/lib/query/find.rb +4 -1
- data/ruby_traverser.gemspec +5 -1
- data/test/mutate/mutate_test.rb +4 -6
- metadata +6 -2
data/README.markdown
CHANGED
@@ -40,6 +40,21 @@ The insert and update API support blocks and always returns the updated or inser
|
|
40
40
|
* update(:select, :with_code, &block)
|
41
41
|
* update(:value, &block)
|
42
42
|
|
43
|
+
Supports updating
|
44
|
+
* arguments (for method calls, block and method definitions)
|
45
|
+
* assignment values (for assignments)
|
46
|
+
|
47
|
+
Argument find for update
|
48
|
+
* by position (fx :arg => '#1')
|
49
|
+
* by key name (fx :arg => :src)
|
50
|
+
* by value (fx :arg => 'blip')
|
51
|
+
|
52
|
+
Note:
|
53
|
+
Update needs some polishing and is still a little buggy!
|
54
|
+
|
55
|
+
TODO:
|
56
|
+
update identifier of module, class, method call and method definition.
|
57
|
+
|
43
58
|
### Delete ##
|
44
59
|
* delete
|
45
60
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.1
|
@@ -1,36 +1,8 @@
|
|
1
1
|
module RubyCodeAPI
|
2
2
|
module Manipulation
|
3
3
|
module Insert
|
4
|
-
|
5
|
-
|
6
|
-
obj = object
|
7
|
-
indentation = obj.last_indent
|
8
|
-
code = "\n#{code}\n".indent(' ', indentation)
|
9
|
-
ruby_code = Ripper::RubyBuilder.build(code)
|
10
|
-
inject_code = ruby_code.elements[0]
|
11
|
-
obj.get_elements << inject_code
|
12
|
-
inject_code
|
13
|
-
end
|
14
|
-
|
15
|
-
def append_code_simple(code)
|
16
|
-
indentation = position.col
|
17
|
-
code = "\n#{code}\n".indent(' ', indentation)
|
18
|
-
ruby_code = Ripper::RubyBuilder.build(code)
|
19
|
-
inject_code = ruby_code.elements[0]
|
20
|
-
index = parent.find_index(self)
|
21
|
-
parent.get_elements.insert(index+1, inject_code)
|
22
|
-
inject_code
|
23
|
-
end
|
24
|
-
|
25
|
-
def prepend_code(code)
|
26
|
-
obj = object
|
27
|
-
indentation = obj.first_indent
|
28
|
-
code = "\n#{code}\n".indent(' ', indentation)
|
29
|
-
ruby_code = Ripper::RubyBuilder.build(code)
|
30
|
-
inject_code = ruby_code.elements[0]
|
31
|
-
obj.get_elements.insert(0, inject_code)
|
32
|
-
obj
|
33
|
-
end
|
4
|
+
class InsertError < StandardError
|
5
|
+
end
|
34
6
|
|
35
7
|
def insert_comment(position, text, &block)
|
36
8
|
insert(position, "# #{text}", &block)
|
@@ -43,7 +15,7 @@ module RubyCodeAPI
|
|
43
15
|
when :before
|
44
16
|
s = prepend_code(code)
|
45
17
|
else
|
46
|
-
raise
|
18
|
+
raise InsertError, "Invalid position given: #{position}, must be either :before or :after"
|
47
19
|
end
|
48
20
|
|
49
21
|
if block_given?
|
@@ -52,6 +24,40 @@ module RubyCodeAPI
|
|
52
24
|
s
|
53
25
|
end
|
54
26
|
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def append_code(code)
|
31
|
+
return append_code_simple(code) if !elemental?
|
32
|
+
obj = object
|
33
|
+
indentation = obj.last_indent
|
34
|
+
code = "\n#{code}\n".indent(' ', indentation)
|
35
|
+
ruby_code = Ripper::RubyBuilder.build(code)
|
36
|
+
inject_code = ruby_code.elements[0]
|
37
|
+
obj.get_elements << inject_code
|
38
|
+
inject_code
|
39
|
+
end
|
40
|
+
|
41
|
+
def append_code_simple(code)
|
42
|
+
indentation = position.col
|
43
|
+
code = "\n#{code}\n".indent(' ', indentation)
|
44
|
+
ruby_code = Ripper::RubyBuilder.build(code)
|
45
|
+
inject_code = ruby_code.elements[0]
|
46
|
+
index = parent.find_index(self)
|
47
|
+
parent.get_elements.insert(index+1, inject_code)
|
48
|
+
inject_code
|
49
|
+
end
|
50
|
+
|
51
|
+
def prepend_code(code)
|
52
|
+
obj = object
|
53
|
+
indentation = obj.first_indent
|
54
|
+
code = "\n#{code}\n".indent(' ', indentation)
|
55
|
+
ruby_code = Ripper::RubyBuilder.build(code)
|
56
|
+
inject_code = ruby_code.elements[0]
|
57
|
+
obj.get_elements.insert(0, inject_code)
|
58
|
+
obj
|
59
|
+
end
|
60
|
+
|
55
61
|
end
|
56
62
|
end
|
57
63
|
end
|
@@ -1,100 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
def replace_pos_argument(options)
|
8
|
-
case self.arg
|
9
|
-
when Ruby::String
|
10
|
-
replace_arg_token(options[:with])
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def position_arg?(arg)
|
15
|
-
return arg[1] if arg && arg[0] == '#'
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
module TokenReplacer
|
21
|
-
def replace_arg_token(replacement)
|
22
|
-
self.arg.elements[0].token = replacement
|
23
|
-
end
|
24
|
-
|
25
|
-
def matching_string_arg?(txt)
|
26
|
-
self.arg.elements[0].token == txt
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
module HashReplacer
|
31
|
-
def hash_arg?(arg)
|
32
|
-
case arg
|
33
|
-
when Hash
|
34
|
-
matching_hash_arg?(arg)
|
35
|
-
when Symbol
|
36
|
-
matching_symbol_arg?(arg)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def replace_hash_arg(options)
|
41
|
-
src = options[:replace_code]
|
42
|
-
code = Ripper::RubyBuilder.build(src)
|
43
|
-
code.set_ldelim(self.arg)
|
44
|
-
self.arg = code
|
45
|
-
end
|
46
|
-
|
47
|
-
def set_ldelim(arg)
|
48
|
-
if arg.respond_to? :elements
|
49
|
-
self.ldelim = arg.elements[0].key.ldelim
|
50
|
-
self.ldelim.token = ''
|
51
|
-
else
|
52
|
-
self.ldelim = arg.ldelim
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def matching_hash_arg?(arg)
|
57
|
-
if self.arg.respond_to? :elements
|
58
|
-
if self.arg.elements[0].class == Ruby::Assoc
|
59
|
-
key = self.arg.elements[0].key
|
60
|
-
value = self.arg.elements[0].value
|
61
|
-
arg_key = arg.first[0]
|
62
|
-
arg_value = arg.first[1]
|
63
|
-
return key.identifier.token.to_sym == arg_key && value.elements[0].token == arg_value
|
64
|
-
end
|
65
|
-
end
|
66
|
-
false
|
67
|
-
end
|
68
|
-
|
69
|
-
def matching_symbol_arg?(arg)
|
70
|
-
if self.arg.respond_to? :elements
|
71
|
-
if self.arg.elements[0].class == Ruby::Assoc
|
72
|
-
return self.arg.elements[0].key.identifier.token.to_sym == arg
|
73
|
-
end
|
74
|
-
else
|
75
|
-
# remove ':' token from symbol
|
76
|
-
self.arg.ldelim.token = ''
|
77
|
-
return self.arg.identifier.token.to_sym == arg
|
78
|
-
end
|
79
|
-
false
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
module ValueReplacer
|
84
|
-
def replace_value(options)
|
85
|
-
if self.class == Ruby::Assignment
|
86
|
-
self.right.token = options[:value]
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
1
|
+
require 'manipulation/update/value'
|
2
|
+
require 'manipulation/update/position'
|
3
|
+
require 'manipulation/update/hash'
|
4
|
+
require 'manipulation/update/token'
|
90
5
|
|
91
6
|
module RubyCodeAPI
|
92
7
|
module Manipulation
|
93
8
|
module Update
|
94
|
-
include
|
95
|
-
include
|
96
|
-
include
|
97
|
-
include
|
9
|
+
include Position
|
10
|
+
include Token
|
11
|
+
include Hash
|
12
|
+
include Value
|
13
|
+
|
14
|
+
class UpdateError < StandardError
|
15
|
+
end
|
98
16
|
|
99
17
|
# update :select => {...}, :with => {...}
|
100
18
|
# update :select => {...}, :with_code => 'code'
|
@@ -111,9 +29,12 @@ module RubyCodeAPI
|
|
111
29
|
# :arg => 'ripper', :replace_arg => 'rapper'
|
112
30
|
def replace(options)
|
113
31
|
return replace_value(options) if options[:value]
|
114
|
-
|
32
|
+
if position_arg?(options[:arg])
|
33
|
+
puts "POSITION ARG"
|
34
|
+
return replace_position_arg(options)
|
35
|
+
end
|
115
36
|
return replace_arg(options) if options[:arg]
|
116
|
-
raise
|
37
|
+
raise UpdateError, "Invalid replace options: #{options}"
|
117
38
|
end
|
118
39
|
|
119
40
|
def replace_arg(options)
|
@@ -132,6 +53,8 @@ module RubyCodeAPI
|
|
132
53
|
case self.arg
|
133
54
|
when Ruby::String
|
134
55
|
replace_arg_token(options[:with]) if matching_string_arg?(options[:arg])
|
56
|
+
else
|
57
|
+
raise UpdateError, "Invalid replace_argument options: #{options}"
|
135
58
|
end
|
136
59
|
end
|
137
60
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RubyCodeAPI
|
2
|
+
module Manipulation
|
3
|
+
module Update
|
4
|
+
module Hash
|
5
|
+
def hash_arg?(arg)
|
6
|
+
case arg
|
7
|
+
when Hash
|
8
|
+
matching_hash_arg?(arg)
|
9
|
+
when Symbol
|
10
|
+
matching_symbol_arg?(arg)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def replace_hash_arg(options)
|
15
|
+
src = options[:replace_code]
|
16
|
+
code = Ripper::RubyBuilder.build(src)
|
17
|
+
code.set_ldelim(self.arg)
|
18
|
+
self.arg = code
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_ldelim(arg)
|
22
|
+
if arg.respond_to? :elements
|
23
|
+
self.ldelim = arg.elements[0].key.ldelim
|
24
|
+
self.ldelim.token = ''
|
25
|
+
else
|
26
|
+
self.ldelim = arg.ldelim
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def matching_hash_arg?(arg)
|
31
|
+
if self.arg.respond_to? :elements
|
32
|
+
if self.arg.elements[0].class == Ruby::Assoc
|
33
|
+
key = self.arg.elements[0].key
|
34
|
+
value = self.arg.elements[0].value
|
35
|
+
arg_key = arg.first[0]
|
36
|
+
arg_value = arg.first[1]
|
37
|
+
return key.identifier.token.to_sym == arg_key && value.elements[0].token == arg_value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def matching_symbol_arg?(arg)
|
44
|
+
if self.arg.respond_to? :elements
|
45
|
+
if self.arg.elements[0].class == Ruby::Assoc
|
46
|
+
return self.arg.elements[0].key.identifier.token.to_sym == arg
|
47
|
+
end
|
48
|
+
else
|
49
|
+
# remove ':' token from symbol
|
50
|
+
self.arg.ldelim.token = ''
|
51
|
+
return self.arg.identifier.token.to_sym == arg
|
52
|
+
end
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RubyCodeAPI
|
2
|
+
module Manipulation
|
3
|
+
module Update
|
4
|
+
module Position
|
5
|
+
class UpdatePositionError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
def replace_position_arg(options)
|
9
|
+
pos = position_arg?(options[:arg])
|
10
|
+
self.arguments.elements[pos.to_i].replace_pos_argument(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def replace_pos_argument(options)
|
14
|
+
case self.arg
|
15
|
+
when Ruby::String
|
16
|
+
replace_arg_token(options[:with])
|
17
|
+
else
|
18
|
+
raise UpdatePositionError, "Unknown type for replacing positional argument: #{self.arg.class}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def position_arg?(arg)
|
23
|
+
return arg[1] if arg && arg[0] == '#'
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RubyCodeAPI
|
2
|
+
module Manipulation
|
3
|
+
module Update
|
4
|
+
module Token
|
5
|
+
def replace_arg_token(replacement)
|
6
|
+
self.arg.elements[0].token = replacement
|
7
|
+
end
|
8
|
+
|
9
|
+
def matching_string_arg?(txt)
|
10
|
+
self.arg.elements[0].token == txt
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/query/find.rb
CHANGED
@@ -11,6 +11,9 @@ module RubyCodeAPI
|
|
11
11
|
:call => Ruby::Call,
|
12
12
|
:def => Ruby::Method
|
13
13
|
}
|
14
|
+
|
15
|
+
class FindError < StandardError
|
16
|
+
end
|
14
17
|
|
15
18
|
def find(type, name, options = {}, &block)
|
16
19
|
s = send :"find_#{type.to_s}", name, options
|
@@ -23,7 +26,7 @@ module RubyCodeAPI
|
|
23
26
|
end
|
24
27
|
|
25
28
|
def inside(type, name, options = {}, &block)
|
26
|
-
raise
|
29
|
+
raise FindError, "Must have block argument" if !block_given?
|
27
30
|
find(type, name, options = {}, &block)
|
28
31
|
end
|
29
32
|
|
data/ruby_traverser.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ruby_traverser}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kristian Mandrup"]
|
@@ -35,6 +35,10 @@ Gem::Specification.new do |s|
|
|
35
35
|
"lib/manipulation/insert/api.rb",
|
36
36
|
"lib/manipulation/position.rb",
|
37
37
|
"lib/manipulation/update/api.rb",
|
38
|
+
"lib/manipulation/update/hash.rb",
|
39
|
+
"lib/manipulation/update/position.rb",
|
40
|
+
"lib/manipulation/update/token.rb",
|
41
|
+
"lib/manipulation/update/value.rb",
|
38
42
|
"lib/query/api.rb",
|
39
43
|
"lib/query/find.rb",
|
40
44
|
"lib/rails/api.rb",
|
data/test/mutate/mutate_test.rb
CHANGED
@@ -15,7 +15,6 @@ end
|
|
15
15
|
code = Ripper::RubyBuilder.build(src)
|
16
16
|
|
17
17
|
code.find(:block, 'group', :args => [:test]) do |b|
|
18
|
-
puts "BLOCK"
|
19
18
|
call_node = b.find(:call, 'gem', :args => ['ripper', {:src => 'github'}])
|
20
19
|
assert_equal Ruby::Call, call_node.class
|
21
20
|
b.insert(:after, "gem 'abc'")
|
@@ -42,15 +41,16 @@ end
|
|
42
41
|
define_method :"test find gem statement inside group using DSL and then replace matching hash with new hash" do
|
43
42
|
src = %q{
|
44
43
|
group :test do
|
45
|
-
gem '
|
44
|
+
gem 'kris', 2, :src => 'goody',
|
46
45
|
end
|
47
46
|
}
|
48
47
|
|
49
48
|
code = Ripper::RubyBuilder.build(src)
|
50
49
|
code.inside(:block, 'group', :args => [:test]) do |b|
|
51
|
-
call_node = b.find(:call, 'gem', :args => ['
|
50
|
+
call_node = b.find(:call, 'gem', :args => ['kris'])
|
52
51
|
assert_equal Ruby::Call, call_node.class
|
53
|
-
call_node.update(:select => {:arg => {:src => '
|
52
|
+
# call_node.update(:select => {:arg => {:src => 'goody'}} , :with_code => "{:src => 'unknown'}")
|
53
|
+
# call_node.replace(:arg => '#1' , :with_code => "{:src => 'known'}")
|
54
54
|
puts b.to_ruby
|
55
55
|
end
|
56
56
|
end
|
@@ -65,8 +65,6 @@ end
|
|
65
65
|
code = Ripper::RubyBuilder.build(src)
|
66
66
|
|
67
67
|
code.find(:def, 'hello_world', :params => ['a']) do |b|
|
68
|
-
puts "HELLO"
|
69
|
-
# call_node = b.find_call('gem', :args => ['ripper', {:src => 'github'}], :verbose => true)
|
70
68
|
ass_node = b.find(:assignment, 'my_var')
|
71
69
|
assert_equal Ruby::Assignment, ass_node.class
|
72
70
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 1
|
9
|
+
version: 0.2.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Kristian Mandrup
|
@@ -73,6 +73,10 @@ files:
|
|
73
73
|
- lib/manipulation/insert/api.rb
|
74
74
|
- lib/manipulation/position.rb
|
75
75
|
- lib/manipulation/update/api.rb
|
76
|
+
- lib/manipulation/update/hash.rb
|
77
|
+
- lib/manipulation/update/position.rb
|
78
|
+
- lib/manipulation/update/token.rb
|
79
|
+
- lib/manipulation/update/value.rb
|
76
80
|
- lib/query/api.rb
|
77
81
|
- lib/query/find.rb
|
78
82
|
- lib/rails/api.rb
|