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.
@@ -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