ryan 0.1.0 → 1.0.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.
- checksums.yaml +4 -4
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/README.md +98 -1
- data/Rakefile +10 -1
- data/bin/console +1 -0
- data/lib/ryan.rb +24 -3
- data/lib/ryan/assignment.rb +23 -0
- data/lib/ryan/class_func.rb +13 -0
- data/lib/ryan/condition.rb +111 -0
- data/lib/ryan/const.rb +97 -0
- data/lib/ryan/func.rb +41 -0
- data/lib/ryan/instance_func.rb +13 -0
- data/lib/ryan/sexp_decorator.rb +22 -0
- data/lib/ryan/version.rb +2 -2
- data/ryan.gemspec +6 -2
- metadata +68 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 291fea61132de8ec31f0e70fda31c930a41fc86a
|
4
|
+
data.tar.gz: 9ec06895b0fbd8e8f24cb4333ef443d1e88ffdac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df0bd56e2f47a7887c2dc5d84c5076665c5343a34cd3971a15efac6be4f323802e2dd6f7b55756d74a27d4ae41784805730d86e66336e967c5d374dc014d68bd
|
7
|
+
data.tar.gz: 309d0f95cf4f7e952d6af7054300402cfb0b8282580179126fddbd8d74beb9df188062526396ccf0dc8ac7f6fb1b003970799716d3397d1c8f4fd234143f15c9
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ryan
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.2.2
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,100 @@
|
|
1
1
|
# Ryan
|
2
2
|
|
3
|
-
|
3
|
+
A wrapper around the awesome [RubyParser](https://github.com/seattlerb/ruby_parser) gem that provides an OO interface for
|
4
|
+
reading Ruby code.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'ryan'
|
10
|
+
```
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Give Ryan a Ruby file to play with. Test it out in an IRB session with `bin/console`
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
ryan = Ryan.new FIXTURE_ROOT.join('report.rb')
|
18
|
+
ryan.name
|
19
|
+
#=> "Report"
|
20
|
+
ryan.class?
|
21
|
+
#=> true
|
22
|
+
ryan.module?
|
23
|
+
#=> false
|
24
|
+
ryan.initialization_args
|
25
|
+
#=> [:message]
|
26
|
+
ryan.funcs.length
|
27
|
+
#=> 12
|
28
|
+
ryan.funcs.reject(&:private?).length
|
29
|
+
#=> 10
|
30
|
+
ryan.funcs.first.name
|
31
|
+
#=> :enqueue
|
32
|
+
```
|
33
|
+
|
34
|
+
### Assignments
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
func = ryan.func_by_name(:call)
|
38
|
+
#=> #<Ryan::InstanceFunc:0x007fd49c10d8d0 @sexp=...>
|
39
|
+
func.assignments.length
|
40
|
+
#=> 1
|
41
|
+
func.assignments.first.name
|
42
|
+
#=> :@duder
|
43
|
+
```
|
44
|
+
|
45
|
+
### Conditions
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
#=> "assigns @duder"
|
49
|
+
func.conditions.length
|
50
|
+
#=> 3
|
51
|
+
condition = func.conditions.last
|
52
|
+
#=> #<Ryan::Condition:0x007fd49c10d8d0 @sexp=...>
|
53
|
+
condition.statement
|
54
|
+
#=> "report.save"
|
55
|
+
condition.full_statement
|
56
|
+
#=> "if report.save then\n UserMailer.spam(user).deliver_now if user.wants_mail?\n report.perform\nelse\n ..."
|
57
|
+
condition.if_sexp
|
58
|
+
#=> s(:call, s(:call, nil, :report), :perform)
|
59
|
+
condition.if_text
|
60
|
+
#=> "returns report.perform"
|
61
|
+
condition.else_text
|
62
|
+
#=> ""
|
63
|
+
```
|
64
|
+
|
65
|
+
### Condition Parts
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# Get the parts of the current condition, which will be the any elsif's
|
69
|
+
condition.parts.length
|
70
|
+
#=> 1
|
71
|
+
part = condition.parts.first
|
72
|
+
#=> #<Ryan::Condition:0x007fd49ca5a028 @sexp=...>
|
73
|
+
part.if_text
|
74
|
+
#=> "returns report.force_perform"
|
75
|
+
part.else_text
|
76
|
+
#=> "returns report.failure"
|
77
|
+
```
|
78
|
+
|
79
|
+
### Nested Conditions
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
# Find conditions nested inside this condition
|
83
|
+
condition.nested_conditions.length
|
84
|
+
#=> 1
|
85
|
+
nested_condition = condition.nested_conditions.last
|
86
|
+
#=> #<Ryan::Condition:0x007fd49ca8bbf0 @sexp=...>
|
87
|
+
nested_condition.if_sexp
|
88
|
+
#=> s(:call, s(:call, s(:const, :UserMailer), :spam, s(:call, nil, :user)), :deliver_now)
|
89
|
+
nested_condition.if_text
|
90
|
+
#=> "returns UserMailer.spam(user).deliver_now"
|
91
|
+
```
|
92
|
+
|
93
|
+
## Development
|
94
|
+
|
95
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake` to run the tests.
|
96
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
97
|
+
|
98
|
+
## Contributing
|
99
|
+
|
100
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ridiculous/ryan.
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
data/lib/ryan.rb
CHANGED
@@ -1,5 +1,26 @@
|
|
1
|
-
require '
|
1
|
+
require 'ruby_parser'
|
2
|
+
require 'forwardable'
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
class Ryan
|
5
|
+
autoload :Version, 'ryan/version'
|
6
|
+
autoload :Const, 'ryan/const'
|
7
|
+
autoload :Condition, 'ryan/condition'
|
8
|
+
autoload :Func, 'ryan/func'
|
9
|
+
autoload :ClassFunc, 'ryan/class_func'
|
10
|
+
autoload :InstanceFunc, 'ryan/instance_func'
|
11
|
+
autoload :Assignment, 'ryan/assignment'
|
12
|
+
autoload :SexpDecorator, 'ryan/sexp_decorator'
|
13
|
+
|
14
|
+
attr_reader :sexp, :const
|
15
|
+
|
16
|
+
extend Forwardable
|
17
|
+
|
18
|
+
def_delegators :const,
|
19
|
+
:name, :funcs, :type, :initialization_args, :func_by_name, :class?, :module?
|
20
|
+
|
21
|
+
# @param [Pathname, String] file
|
22
|
+
def initialize(file)
|
23
|
+
@sexp = RubyParser.new.parse File.read(file)
|
24
|
+
@const = Const.new(sexp)
|
25
|
+
end
|
5
26
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Ryan
|
2
|
+
class Assignment
|
3
|
+
attr_reader :sexp
|
4
|
+
|
5
|
+
def initialize(sexp)
|
6
|
+
@sexp = sexp
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
"assigns #{name}"
|
11
|
+
end
|
12
|
+
|
13
|
+
# @example s(:iasgn, :@duder, s(:if, ...)
|
14
|
+
# @example s(:op_asgn_or, s(:ivar, :@report), ...)
|
15
|
+
def name
|
16
|
+
if sexp.first == :iasgn
|
17
|
+
sexp[1]
|
18
|
+
elsif sexp.first == :op_asgn_or
|
19
|
+
sexp[1][1]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'ruby2ruby'
|
3
|
+
|
4
|
+
class Ryan::Condition
|
5
|
+
|
6
|
+
attr_reader :nested_conditions, :sexp, :parts
|
7
|
+
|
8
|
+
def initialize(sexp)
|
9
|
+
@sexp = sexp
|
10
|
+
@nested_conditions = create_nested_conditions
|
11
|
+
@parts = load_parts
|
12
|
+
end
|
13
|
+
|
14
|
+
def full_statement
|
15
|
+
@full_statement ||= Ruby2Ruby.new.process(sexp.deep_clone)
|
16
|
+
end
|
17
|
+
|
18
|
+
def statement
|
19
|
+
edit_statement Ruby2Ruby.new.process(sexp[1].deep_clone)
|
20
|
+
end
|
21
|
+
|
22
|
+
def if_text
|
23
|
+
edit_return_text Ruby2Ruby.new.process(if_sexp.deep_clone)
|
24
|
+
end
|
25
|
+
|
26
|
+
def else_text
|
27
|
+
edit_return_text Ruby2Ruby.new.process(else_sexp.deep_clone)
|
28
|
+
end
|
29
|
+
|
30
|
+
def if_sexp
|
31
|
+
if sexp[2].nil?
|
32
|
+
sexp.last
|
33
|
+
elsif sexp[2].first == :if
|
34
|
+
nil
|
35
|
+
elsif sexp[2].first == :block
|
36
|
+
sexp[2].last
|
37
|
+
elsif sexp[2].first == :rescue
|
38
|
+
sexp[2][1].last
|
39
|
+
else
|
40
|
+
sexp[2]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def else_sexp
|
45
|
+
if sexp.compact[3].nil?
|
46
|
+
nil
|
47
|
+
elsif sexp[3].first == :block
|
48
|
+
sexp[3].last
|
49
|
+
elsif sexp[3].first == :if
|
50
|
+
nil
|
51
|
+
else
|
52
|
+
sexp[3]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Private
|
58
|
+
#
|
59
|
+
|
60
|
+
def edit_return_text(txt)
|
61
|
+
txt = txt.to_s
|
62
|
+
txt.sub! /^return\b/, 'returns'
|
63
|
+
txt.sub! /^returns\s*$/, 'returns nil'
|
64
|
+
if txt.include?(' = ')
|
65
|
+
txt = "assigns #{txt}"
|
66
|
+
elsif !txt.empty? and txt !~ /^return/
|
67
|
+
txt = "returns #{txt.strip}"
|
68
|
+
end
|
69
|
+
txt.strip
|
70
|
+
end
|
71
|
+
|
72
|
+
def edit_statement(txt)
|
73
|
+
txt = txt[/(.+)\n?/, 1] # take first line
|
74
|
+
txt.prepend 'unless ' if sexp[2].nil? # this is an unless statement
|
75
|
+
txt
|
76
|
+
end
|
77
|
+
|
78
|
+
# @description handles elsif
|
79
|
+
def load_parts
|
80
|
+
condition_parts = Set.new
|
81
|
+
sexp.each_sexp do |s|
|
82
|
+
if s.first == :if
|
83
|
+
condition_parts << self.class.new(s)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
condition_parts.to_a
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_nested_conditions
|
90
|
+
nc = Set.new
|
91
|
+
s = sexp.drop(1)
|
92
|
+
s.flatten.include?(:if) && s.deep_each do |exp|
|
93
|
+
Ryan::SexpDecorator.new(exp).each_sexp_condition do |node|
|
94
|
+
nc << self.class.new(node)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
nc.to_a
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Set comparison operators
|
102
|
+
#
|
103
|
+
|
104
|
+
def eql?(other)
|
105
|
+
hash == other.hash
|
106
|
+
end
|
107
|
+
|
108
|
+
def hash
|
109
|
+
sexp.object_id
|
110
|
+
end
|
111
|
+
end
|
data/lib/ryan/const.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
class Ryan::Const
|
2
|
+
CLASS_MOD_DEFS = { class: :class, module: :module }
|
3
|
+
CONSTANT_DEFS = { cdecl: :class }.merge CLASS_MOD_DEFS
|
4
|
+
PRIVATE_DEFS = [:private, :protected]
|
5
|
+
|
6
|
+
attr_reader :sexp
|
7
|
+
|
8
|
+
# @param [Sexp] sexp
|
9
|
+
def initialize(sexp)
|
10
|
+
sexp = sexp[2] if sexp[0] == :block
|
11
|
+
@sexp = sexp
|
12
|
+
end
|
13
|
+
|
14
|
+
# @description Extracts the class/mod definition from a Sexp object. Handles stuff that looks like:
|
15
|
+
# - s(:module, :Admin, s(:class, :Super, nil, s(:class, :UsersController, s(:colon3, :ApplicationController), s(:defn, :name, s(:args)
|
16
|
+
# - s(:class, :Report, nil, s(:cdecl, :DEFAULT_TZ, s(:str, "UTC")), s(:defs, s(:self), :enqueue,
|
17
|
+
# - s(:module, s(:colon2, s(:const, :Mixins), :Models))
|
18
|
+
# - s(:module, :Mixins, s(:module, :Helpers, s(:cdecl, :CSS, s(:str, "height:0"))))
|
19
|
+
# - s(:module, :Admin, s(:class, :Super, nil, s(:class, :UsersController, s(:colon3, :ApplicationController), s(:defn, :name, s(:args), ...))))
|
20
|
+
def name(sexp = @sexp, list = [])
|
21
|
+
if sexp[1].is_a?(Sexp) && sexp[1][0] == :colon2
|
22
|
+
parts = sexp[1].to_a.flatten
|
23
|
+
list.concat parts.drop(parts.size / 2)
|
24
|
+
elsif CONSTANT_DEFS.key?(sexp[0])
|
25
|
+
list << sexp[1].to_s
|
26
|
+
# skip when the second element is nil; it's just there sometimes and usually indicates the end of the definition
|
27
|
+
if !sexp[2].nil? || (sexp[3].is_a?(Sexp) and CLASS_MOD_DEFS.key?(sexp[3].first))
|
28
|
+
compact_sexp = sexp.compact[2]
|
29
|
+
if CLASS_MOD_DEFS.key?(compact_sexp.first)
|
30
|
+
name(compact_sexp, list)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
list.join('::')
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialization_args
|
38
|
+
funcs.find(-> { OpenStruct.new }) { |func| func.name == :initialize }.args.to_a.reject { |a| a.to_s.sub(/^\*/, '').empty? }
|
39
|
+
end
|
40
|
+
|
41
|
+
def func_by_name(name_as_symbol)
|
42
|
+
funcs.find { |x| x.name == name_as_symbol }
|
43
|
+
end
|
44
|
+
|
45
|
+
def funcs
|
46
|
+
@funcs ||= load_funcs.flatten
|
47
|
+
end
|
48
|
+
|
49
|
+
def class?
|
50
|
+
type == :class
|
51
|
+
end
|
52
|
+
|
53
|
+
def module?
|
54
|
+
type == :module
|
55
|
+
end
|
56
|
+
|
57
|
+
def type(sexp = @sexp, val = nil)
|
58
|
+
sexp = Array(sexp)
|
59
|
+
if sexp[1].is_a?(Sexp) && sexp[1][0] == :colon2
|
60
|
+
val = sexp[0]
|
61
|
+
elsif CONSTANT_DEFS.key?(sexp[0])
|
62
|
+
val = type(sexp.compact[2], sexp[0])
|
63
|
+
end
|
64
|
+
CONSTANT_DEFS[val]
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def load_funcs(sexp_list = sexp)
|
70
|
+
marked_private = false
|
71
|
+
sexp_list.map { |node|
|
72
|
+
next unless node.is_a?(Sexp)
|
73
|
+
case node.first
|
74
|
+
when :defn
|
75
|
+
Ryan::InstanceFunc.new(node, marked_private)
|
76
|
+
when :defs
|
77
|
+
Ryan::ClassFunc.new(node, marked_private)
|
78
|
+
when :call
|
79
|
+
marked_private ||= PRIVATE_DEFS.include?(node[2])
|
80
|
+
nil
|
81
|
+
when ->(name) { CONSTANT_DEFS.key?(name) }
|
82
|
+
# @note handle diz kind stuff:
|
83
|
+
# s(:class, :VerificationCode, nil, s(:defs, s(:self), :find, s(:args, :*)))
|
84
|
+
# and
|
85
|
+
# s(:module, :ConditionParsers, s(:class, :ReturnValue, ...))
|
86
|
+
# and
|
87
|
+
# s(:class, :NotificationPresenter, nil, s(:call, nil, :extend, s(:const, :Forwardable)), s(:call, nil, :attr_reader, ...))
|
88
|
+
load_funcs(node.compact.drop(2))
|
89
|
+
else
|
90
|
+
# @todo uncomment with logger at debug level
|
91
|
+
# puts "got #{__method__} with #{node.first} and don't know how to handle it"
|
92
|
+
# @note :const seems to indicate module inclusion/extension
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
}.compact
|
96
|
+
end
|
97
|
+
end
|
data/lib/ryan/func.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
class Ryan::Func
|
2
|
+
attr_accessor :sexp, :_private
|
3
|
+
|
4
|
+
alias private? _private
|
5
|
+
|
6
|
+
def initialize(sexp, _private)
|
7
|
+
@sexp, @_private = sexp, _private
|
8
|
+
end
|
9
|
+
|
10
|
+
def conditions
|
11
|
+
@conditions ||= Ryan::SexpDecorator.new(sexp).each_sexp_condition.map &Ryan::Condition.method(:new)
|
12
|
+
end
|
13
|
+
|
14
|
+
def assignments
|
15
|
+
nodes = find_assignments(sexp)
|
16
|
+
sexp.find_nodes(:rescue).each do |node|
|
17
|
+
node = node[1] if node[1].first == :block
|
18
|
+
nodes.concat find_assignments(node)
|
19
|
+
end
|
20
|
+
nodes.map &Ryan::Assignment.method(:new)
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_assignments(s_expression)
|
24
|
+
s_expression.find_nodes(:op_asgn_or) + s_expression.find_nodes(:iasgn)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @note we drop(1) to get rid of :args (which should be the first item in the sexp)
|
28
|
+
# @note called from subclasses
|
29
|
+
def map_args(_sexp = sexp, list = [])
|
30
|
+
val = _sexp.first
|
31
|
+
return list.drop(1) unless val
|
32
|
+
case val
|
33
|
+
when Symbol
|
34
|
+
map_args(_sexp.drop(1), list << val)
|
35
|
+
when Sexp
|
36
|
+
map_args(_sexp.drop(1), list << val[1])
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
class Ryan::SexpDecorator < DelegateClass(Sexp)
|
4
|
+
def each_sexp_condition
|
5
|
+
return enum_for(__method__) unless block_given?
|
6
|
+
yielded = []
|
7
|
+
each_sexp do |exp|
|
8
|
+
if exp.first == :if
|
9
|
+
yield exp
|
10
|
+
yielded << exp
|
11
|
+
else
|
12
|
+
nested_sexp = exp.enum_for(:deep_each).select { |s| s.first == :if }
|
13
|
+
nested_sexp.each do |sexp|
|
14
|
+
if yielded.find { |x| x.object_id == sexp.object_id or x.enum_for(:deep_each).find { |xx| xx.object_id == sexp.object_id } }.nil?
|
15
|
+
yield sexp
|
16
|
+
yielded << sexp
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/ryan/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '
|
1
|
+
class Ryan
|
2
|
+
VERSION = '1.0.0'.freeze
|
3
3
|
end
|
data/ryan.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Ryan Buckley"]
|
10
10
|
spec.email = ["arebuckley@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.description = %q{
|
12
|
+
spec.summary = %q{Ryan meet Ruby}
|
13
|
+
spec.description = %q{A wrapper around the RubyParser gem}
|
14
14
|
spec.homepage = "https://github.com/ridiculous/ryan"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -20,4 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.10"
|
22
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", ">= 3.2", "< 4"
|
24
|
+
|
25
|
+
spec.add_dependency 'ruby_parser', '>= 3.7.0', '< 4.0.0'
|
26
|
+
spec.add_dependency 'ruby2ruby', '~> 2.2'
|
23
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ryan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Buckley
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,7 +38,61 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.2'
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '4'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '3.2'
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '4'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: ruby_parser
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 3.7.0
|
68
|
+
- - "<"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 4.0.0
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 3.7.0
|
78
|
+
- - "<"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 4.0.0
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: ruby2ruby
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '2.2'
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '2.2'
|
95
|
+
description: A wrapper around the RubyParser gem
|
42
96
|
email:
|
43
97
|
- arebuckley@gmail.com
|
44
98
|
executables: []
|
@@ -46,6 +100,8 @@ extensions: []
|
|
46
100
|
extra_rdoc_files: []
|
47
101
|
files:
|
48
102
|
- ".gitignore"
|
103
|
+
- ".ruby-gemset"
|
104
|
+
- ".ruby-version"
|
49
105
|
- ".travis.yml"
|
50
106
|
- Gemfile
|
51
107
|
- README.md
|
@@ -53,6 +109,13 @@ files:
|
|
53
109
|
- bin/console
|
54
110
|
- bin/setup
|
55
111
|
- lib/ryan.rb
|
112
|
+
- lib/ryan/assignment.rb
|
113
|
+
- lib/ryan/class_func.rb
|
114
|
+
- lib/ryan/condition.rb
|
115
|
+
- lib/ryan/const.rb
|
116
|
+
- lib/ryan/func.rb
|
117
|
+
- lib/ryan/instance_func.rb
|
118
|
+
- lib/ryan/sexp_decorator.rb
|
56
119
|
- lib/ryan/version.rb
|
57
120
|
- ryan.gemspec
|
58
121
|
homepage: https://github.com/ridiculous/ryan
|
@@ -74,8 +137,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
137
|
version: '0'
|
75
138
|
requirements: []
|
76
139
|
rubyforge_project:
|
77
|
-
rubygems_version: 2.4.
|
140
|
+
rubygems_version: 2.4.8
|
78
141
|
signing_key:
|
79
142
|
specification_version: 4
|
80
|
-
summary:
|
143
|
+
summary: Ryan meet Ruby
|
81
144
|
test_files: []
|