method-args 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg
2
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in optitron.gemspec
4
+ gemspec
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
@@ -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
@@ -0,0 +1,3 @@
1
+ module MethodArgs
2
+ VERSION = '0.0.1'
3
+ end
@@ -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
@@ -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,4 @@
1
+ require 'minitest/autorun'
2
+ require 'phocus'
3
+ require 'callsite'
4
+ Callsite.activate_string_methods
@@ -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