ruby_traverser 0.2.0 → 0.2.1
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/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
|