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.
@@ -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.0
1
+ 0.2.1
@@ -1,6 +1,9 @@
1
1
  module RubyCodeAPI
2
2
  module Manipulation
3
3
  module Delete
4
+ class DeleteError < StandardError
5
+ end
6
+
4
7
  def delete
5
8
  # index = parent.find_index(self)
6
9
  parent.get_elements.delete(self)
@@ -1,36 +1,8 @@
1
1
  module RubyCodeAPI
2
2
  module Manipulation
3
3
  module Insert
4
- def append_code(code)
5
- return append_code_simple(code) if !elemental?
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 Error, "Invalid position given: #{position}, must be either :before or :after"
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
- module PositionReplacer
2
- def replace_position_arg(options)
3
- pos = position_arg?(options[:arg])
4
- self.arguments.elements[pos.to_i].replace_pos_argument(options)
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 PositionReplacer
95
- include TokenReplacer
96
- include HashReplacer
97
- include ValueReplacer
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
- return replace_position_arg(options) if position_arg?(options[:arg])
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 Error, "Invalid options: #{options}"
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
@@ -0,0 +1,13 @@
1
+ module RubyCodeAPI
2
+ module Manipulation
3
+ module Update
4
+ module Value
5
+ def replace_value(options)
6
+ if self.class == Ruby::Assignment
7
+ self.right.token = options[:value]
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -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 StandardError, "Must have block argument" if !block_given?
29
+ raise FindError, "Must have block argument" if !block_given?
27
30
  find(type, name, options = {}, &block)
28
31
  end
29
32
 
@@ -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.0"
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",
@@ -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 'ripper', :src => 'blip'
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 => ['ripper'])
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 => 'blip'}} , :with_code => "{:src => 'unknown'}")
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
- - 0
9
- version: 0.2.0
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