method-args 0.0.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/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +35 -0
- data/README.markdown +40 -0
- data/Rakefile +20 -0
- data/lib/method_args.rb +170 -0
- data/lib/method_args/version.rb +3 -0
- data/method_args.gemspec +30 -0
- data/test/fixtures/1.rb +21 -0
- data/test/helper.rb +4 -0
- data/test/test_method_args.rb +37 -0
- metadata +200 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
method_args (0.0.1)
|
5
|
+
ruby2ruby (~> 1.2.4)
|
6
|
+
ruby_parser (~> 2.0)
|
7
|
+
sexp_processor (~> 3.0.4)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
callsite (0.0.4)
|
13
|
+
minitest (2.0.2)
|
14
|
+
phocus (1.1)
|
15
|
+
rake (0.8.7)
|
16
|
+
ruby2ruby (1.2.5)
|
17
|
+
ruby_parser (~> 2.0)
|
18
|
+
sexp_processor (~> 3.0)
|
19
|
+
ruby_parser (2.0.5)
|
20
|
+
sexp_processor (~> 3.0)
|
21
|
+
sexp_processor (3.0.5)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
bundler (~> 1.0.0)
|
28
|
+
callsite (~> 0.0.4)
|
29
|
+
method_args!
|
30
|
+
minitest
|
31
|
+
phocus
|
32
|
+
rake
|
33
|
+
ruby2ruby (~> 1.2.4)
|
34
|
+
ruby_parser (~> 2.0)
|
35
|
+
sexp_processor (~> 3.0.4)
|
data/README.markdown
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# MethodArgs
|
2
|
+
|
3
|
+
## Purpose
|
4
|
+
|
5
|
+
You've got a method, but want to know more about the arguments? `#arity` and `#parameters` (if available) are useful,
|
6
|
+
but not nearly enough. You need something better. Like, the default arguments. *MethodArgs* makes this simple. It operates
|
7
|
+
on a source file to supply the more details argument information by parsing the code itself.
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
Pretend you have a file `your_ruby_file.rb`:
|
12
|
+
|
13
|
+
class MyClass
|
14
|
+
def initialize
|
15
|
+
@default_value = 'hello'
|
16
|
+
end
|
17
|
+
|
18
|
+
def something(one, two = 'two', three = @default_value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
To look at the arguments to something, do the following.
|
23
|
+
|
24
|
+
MethodArgs.load('your_ruby_file') # <-- this also requires the file
|
25
|
+
MyClass.arg_list(:something)
|
26
|
+
|
27
|
+
This will return an `ArgList` object. You can then look at the names & types.
|
28
|
+
|
29
|
+
MyClass.arg_list(:something).names
|
30
|
+
# => [:one, :two, :three]
|
31
|
+
|
32
|
+
MyClass.arg_list(:something).types
|
33
|
+
# => [:required, :optional, :splat]
|
34
|
+
|
35
|
+
If you want to get the value of a default argument, you'll need a context in which to evaluate it, namely,
|
36
|
+
an instance of the class from which the method derives.
|
37
|
+
|
38
|
+
obj = MyClass.new
|
39
|
+
MyClass.arg_list(:something).last.default_value(obj)
|
40
|
+
# => 'hello'
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
desc "Run tests"
|
5
|
+
task :test do
|
6
|
+
$: << 'lib'
|
7
|
+
require 'method_args'
|
8
|
+
require 'test/helper'
|
9
|
+
Dir['test/**/test_*.rb'].each { |test| require test }
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
desc "Generate documentation"
|
14
|
+
Rake::RDocTask.new do |rd|
|
15
|
+
rd.main = "README.rdoc"
|
16
|
+
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
17
|
+
rd.rdoc_dir = 'rdoc'
|
18
|
+
end
|
19
|
+
|
20
|
+
Bundler::GemHelper.install_tasks
|
data/lib/method_args.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'ruby2ruby'
|
2
|
+
require 'ruby_parser'
|
3
|
+
require 'sexp_processor'
|
4
|
+
|
5
|
+
module MethodArgs
|
6
|
+
|
7
|
+
class ArgList < Array
|
8
|
+
class Arg
|
9
|
+
|
10
|
+
attr_reader :name, :type
|
11
|
+
|
12
|
+
def initialize(cls, arg)
|
13
|
+
@cls = cls
|
14
|
+
@name = arg[0]
|
15
|
+
@type = arg[1]
|
16
|
+
@default = arg[2]
|
17
|
+
end
|
18
|
+
|
19
|
+
def required?
|
20
|
+
@type == :required
|
21
|
+
end
|
22
|
+
|
23
|
+
def optional?
|
24
|
+
@type == :optional
|
25
|
+
end
|
26
|
+
|
27
|
+
def splat?
|
28
|
+
@type == :splat
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_value(inst)
|
32
|
+
return nil if @default.nil?
|
33
|
+
raise "You must evaluate defaults in the context of a matching class. #{inst.class.name} is not a #{@cls.name}." unless inst.is_a?(@cls)
|
34
|
+
inst.instance_eval(@default)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def required_size
|
39
|
+
inject(0) {|count, arg| count += arg.required? ? 1 : 0}
|
40
|
+
end
|
41
|
+
alias_method :required_count, :required_size
|
42
|
+
|
43
|
+
def names
|
44
|
+
map(&:name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def types
|
48
|
+
map(&:type)
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(cls, method)
|
52
|
+
@cls, @method = cls, method
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_method
|
56
|
+
@cls.instance_method(@method)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def self.load(file)
|
62
|
+
file = File.expand_path(file)
|
63
|
+
require file
|
64
|
+
parser = RubyParser.new
|
65
|
+
sexp = parser.process(File.read(File.exist?(file) ? file : "#{file}.rb"))
|
66
|
+
method_args = Processor.new
|
67
|
+
method_args.process(sexp)
|
68
|
+
end
|
69
|
+
|
70
|
+
class Processor < SexpProcessor
|
71
|
+
|
72
|
+
attr_reader :method_maps
|
73
|
+
|
74
|
+
def initialize
|
75
|
+
@method_maps = Hash.new{|h,k| h[k] = {}}
|
76
|
+
@current_class = []
|
77
|
+
super()
|
78
|
+
end
|
79
|
+
|
80
|
+
def process_module(exp)
|
81
|
+
exp.shift
|
82
|
+
@current_class << exp.first.to_sym
|
83
|
+
process(exp)
|
84
|
+
@current_class.pop
|
85
|
+
exp.clear
|
86
|
+
exp
|
87
|
+
end
|
88
|
+
|
89
|
+
def process_class(exp)
|
90
|
+
exp.shift
|
91
|
+
current_class_size = @current_class.size
|
92
|
+
case exp.first
|
93
|
+
when Symbol
|
94
|
+
@current_class << exp.first.to_sym
|
95
|
+
process(exp)
|
96
|
+
else
|
97
|
+
if exp.first.first == :colon2
|
98
|
+
exp.first.shift
|
99
|
+
class_exp = exp.shift
|
100
|
+
class_exp[0, class_exp.size - 1].each do |const|
|
101
|
+
@current_class << const.last
|
102
|
+
end
|
103
|
+
@current_class << class_exp.last
|
104
|
+
else
|
105
|
+
raise
|
106
|
+
end
|
107
|
+
exp.shift
|
108
|
+
process(exp.first)
|
109
|
+
end
|
110
|
+
@current_class.slice!(current_class_size, @current_class.size)
|
111
|
+
exp.clear
|
112
|
+
exp
|
113
|
+
end
|
114
|
+
|
115
|
+
def process_defn(exp)
|
116
|
+
exp.shift
|
117
|
+
@current_method = exp.shift
|
118
|
+
@ruby2ruby = Ruby2Ruby.new
|
119
|
+
process_args(exp.shift)
|
120
|
+
scope = exp.shift
|
121
|
+
exp
|
122
|
+
end
|
123
|
+
|
124
|
+
def process_args(exp)
|
125
|
+
exp.shift
|
126
|
+
arg_list = ArgList.new(current_class, @current_method)
|
127
|
+
while !exp.empty?
|
128
|
+
t = exp.shift
|
129
|
+
case t
|
130
|
+
when Symbol
|
131
|
+
arg_list << if t.to_s[0] == ?*
|
132
|
+
ArgList::Arg.new(current_class, [t.to_s[1, t.to_s.size].to_sym, :splat])
|
133
|
+
else
|
134
|
+
ArgList::Arg.new(current_class, [t, :required])
|
135
|
+
end
|
136
|
+
when Sexp
|
137
|
+
case t.shift
|
138
|
+
when :block
|
139
|
+
lasgn = t.shift
|
140
|
+
lasgn.shift
|
141
|
+
name = lasgn.shift
|
142
|
+
new_arg = ArgList::Arg.new(current_class, [name, :optional, @ruby2ruby.process(lasgn.last)])
|
143
|
+
arg_list.each_with_index{|arg, idx| arg_list[idx] = new_arg if arg.name == name}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
@method_maps[current_classname][@current_method] = arg_list
|
148
|
+
add_methods
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_methods
|
152
|
+
unless current_class.const_defined?(:ArgList)
|
153
|
+
current_class.send(:const_set, :ArgList, @method_maps[current_classname])
|
154
|
+
current_class.module_eval "
|
155
|
+
def self.arg_list(method_name)
|
156
|
+
ArgList[method_name]
|
157
|
+
end
|
158
|
+
"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def current_classname
|
163
|
+
@current_class.map{|c| c.to_s}.join('::')
|
164
|
+
end
|
165
|
+
|
166
|
+
def current_class
|
167
|
+
@current_class.inject(Module) {|c, m| c.const_get(m)}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/method_args.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "method_args/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "method-args"
|
7
|
+
s.version = MethodArgs::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Joshua Hull"]
|
10
|
+
s.email = ["joshbuddy@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/joshbuddy/method_args"
|
12
|
+
s.summary = "Get back more detailed information about the arguments for a method"
|
13
|
+
s.description = "Get back more detailed information about the arguments for a method"
|
14
|
+
|
15
|
+
s.rubyforge_project = "method_args2"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency "ruby_parser", "~> 2.0"
|
23
|
+
s.add_dependency "ruby2ruby", "~> 1.2.4"
|
24
|
+
s.add_dependency "sexp_processor", "~> 3.0.4"
|
25
|
+
s.add_development_dependency "callsite", "~> 0.0.4"
|
26
|
+
s.add_development_dependency "bundler", "~> 1.0.0"
|
27
|
+
s.add_development_dependency "rake"
|
28
|
+
s.add_development_dependency "phocus"
|
29
|
+
s.add_development_dependency "minitest"
|
30
|
+
end
|
data/test/fixtures/1.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
class One
|
2
|
+
attr_accessor :two_method
|
3
|
+
|
4
|
+
def no_args
|
5
|
+
end
|
6
|
+
|
7
|
+
def one_args(one)
|
8
|
+
end
|
9
|
+
|
10
|
+
def two_args(one, two)
|
11
|
+
end
|
12
|
+
|
13
|
+
def splat_args(one, two, *three)
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_args(one, two = 'two')
|
17
|
+
end
|
18
|
+
|
19
|
+
def default_args_with_dependant_value(one, two = two_method)
|
20
|
+
end
|
21
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
class TestMethodArgs < MiniTest::Unit::TestCase
|
2
|
+
def setup
|
3
|
+
MethodArgs.load(~'fixtures/1')
|
4
|
+
end
|
5
|
+
|
6
|
+
def test_arg_counts
|
7
|
+
assert_equal 0, One.arg_list(:no_args).count
|
8
|
+
assert_equal 1, One.arg_list(:one_args).count
|
9
|
+
assert_equal 2, One.arg_list(:two_args).count
|
10
|
+
assert_equal 3, One.arg_list(:splat_args).count
|
11
|
+
assert_equal 2, One.arg_list(:splat_args).required_count
|
12
|
+
assert_equal 2, One.arg_list(:default_args).count
|
13
|
+
assert_equal 1, One.arg_list(:default_args).required_count
|
14
|
+
assert_equal 2, One.arg_list(:default_args_with_dependant_value).count
|
15
|
+
assert_equal 1, One.arg_list(:default_args_with_dependant_value).required_count
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_arg_types
|
19
|
+
assert_equal [], One.arg_list(:no_args).types
|
20
|
+
assert_equal [:required], One.arg_list(:one_args).types
|
21
|
+
assert_equal [:required, :required], One.arg_list(:two_args).types
|
22
|
+
assert_equal [:required, :required, :splat], One.arg_list(:splat_args).types
|
23
|
+
assert_equal [:required, :optional], One.arg_list(:default_args).types
|
24
|
+
assert_equal [:required, :optional], One.arg_list(:default_args_with_dependant_value).types
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_arg_method
|
28
|
+
assert_equal One.instance_method(:no_args), One.arg_list(:no_args).to_method
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_default_args
|
32
|
+
one = One.new
|
33
|
+
one.two_method = 'happy times'
|
34
|
+
assert_equal 'happy times', One.arg_list(:default_args_with_dependant_value).last.default_value(one)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: method-args
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Joshua Hull
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-02 00:00:00 -08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: ruby_parser
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 0
|
33
|
+
version: "2.0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: ruby2ruby
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 23
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 2
|
48
|
+
- 4
|
49
|
+
version: 1.2.4
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: sexp_processor
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 15
|
61
|
+
segments:
|
62
|
+
- 3
|
63
|
+
- 0
|
64
|
+
- 4
|
65
|
+
version: 3.0.4
|
66
|
+
type: :runtime
|
67
|
+
version_requirements: *id003
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: callsite
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 23
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
- 0
|
80
|
+
- 4
|
81
|
+
version: 0.0.4
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id004
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: bundler
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ~>
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
hash: 23
|
93
|
+
segments:
|
94
|
+
- 1
|
95
|
+
- 0
|
96
|
+
- 0
|
97
|
+
version: 1.0.0
|
98
|
+
type: :development
|
99
|
+
version_requirements: *id005
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: rake
|
102
|
+
prerelease: false
|
103
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 3
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
version: "0"
|
112
|
+
type: :development
|
113
|
+
version_requirements: *id006
|
114
|
+
- !ruby/object:Gem::Dependency
|
115
|
+
name: phocus
|
116
|
+
prerelease: false
|
117
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
hash: 3
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
version: "0"
|
126
|
+
type: :development
|
127
|
+
version_requirements: *id007
|
128
|
+
- !ruby/object:Gem::Dependency
|
129
|
+
name: minitest
|
130
|
+
prerelease: false
|
131
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
hash: 3
|
137
|
+
segments:
|
138
|
+
- 0
|
139
|
+
version: "0"
|
140
|
+
type: :development
|
141
|
+
version_requirements: *id008
|
142
|
+
description: Get back more detailed information about the arguments for a method
|
143
|
+
email:
|
144
|
+
- joshbuddy@gmail.com
|
145
|
+
executables: []
|
146
|
+
|
147
|
+
extensions: []
|
148
|
+
|
149
|
+
extra_rdoc_files: []
|
150
|
+
|
151
|
+
files:
|
152
|
+
- .gitignore
|
153
|
+
- Gemfile
|
154
|
+
- Gemfile.lock
|
155
|
+
- README.markdown
|
156
|
+
- Rakefile
|
157
|
+
- lib/method_args.rb
|
158
|
+
- lib/method_args/version.rb
|
159
|
+
- method_args.gemspec
|
160
|
+
- test/fixtures/1.rb
|
161
|
+
- test/helper.rb
|
162
|
+
- test/test_method_args.rb
|
163
|
+
has_rdoc: true
|
164
|
+
homepage: https://github.com/joshbuddy/method_args
|
165
|
+
licenses: []
|
166
|
+
|
167
|
+
post_install_message:
|
168
|
+
rdoc_options: []
|
169
|
+
|
170
|
+
require_paths:
|
171
|
+
- lib
|
172
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
none: false
|
174
|
+
requirements:
|
175
|
+
- - ">="
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
hash: 3
|
178
|
+
segments:
|
179
|
+
- 0
|
180
|
+
version: "0"
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
|
+
none: false
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
hash: 3
|
187
|
+
segments:
|
188
|
+
- 0
|
189
|
+
version: "0"
|
190
|
+
requirements: []
|
191
|
+
|
192
|
+
rubyforge_project: method_args2
|
193
|
+
rubygems_version: 1.3.7
|
194
|
+
signing_key:
|
195
|
+
specification_version: 3
|
196
|
+
summary: Get back more detailed information about the arguments for a method
|
197
|
+
test_files:
|
198
|
+
- test/fixtures/1.rb
|
199
|
+
- test/helper.rb
|
200
|
+
- test/test_method_args.rb
|