defined 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Sean Huber - shuber@huberry.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,53 @@
1
+ = defined
2
+
3
+ Calls <tt>Module#defined</tt> after a class or module has been defined or redefined
4
+
5
+
6
+ == Installation
7
+
8
+ gem install defined
9
+
10
+
11
+ == Usage
12
+
13
+ class User
14
+ def self.defined(file, line, method)
15
+ puts " defined by #{file}:#{line} with #{method}"
16
+ end
17
+
18
+ puts 'in original class definition'
19
+ end
20
+
21
+ User.class_eval do
22
+ puts 'in class_eval'
23
+ end
24
+
25
+ class User
26
+ puts 'in class definition again'
27
+ end
28
+
29
+ Class.new(User) do
30
+ puts 'in Class.new'
31
+ end
32
+
33
+ === Outputs
34
+
35
+ in original class definition
36
+ defined by /tmp/untitled.rb:1 with class
37
+ in class_eval
38
+ defined by /tmp/untitled.rb:9 with class_eval
39
+ in class definition again
40
+ defined by /tmp/untitled.rb:13 with class
41
+ in Class.new
42
+ defined by /tmp/untitled.rb:17 with initialize
43
+
44
+ ==== Note the <tt>method</tt> in the last example is <tt>initialize</tt> NOT <tt>new</tt>
45
+
46
+
47
+ == Patches and pull requests
48
+
49
+ * Fork the project.
50
+ * Make your feature addition or bug fix.
51
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
52
+ * Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
53
+ * Send me a pull request. Bonus points for topic branches.
@@ -0,0 +1,50 @@
1
+ # Calls <tt>Module#defined(file, line, method)</tt> after a class or module has been defined or redefined
2
+ module Defined
3
+ autoload :Version, 'defined/version'
4
+
5
+ class << self
6
+ def included(mod) # :nodoc:
7
+ set_trace_func method(:trace_function).to_proc
8
+ end
9
+
10
+ # An array of classes and modules that are currently being defined
11
+ def definitions
12
+ @definitions ||= []
13
+ end
14
+
15
+ protected
16
+
17
+ def definition?(event, method, klass, keyword_event, method_event)
18
+ event == keyword_event || (event == method_event && definition_method?(method, klass))
19
+ end
20
+
21
+ # Checks if the event is the end of a class or module definition
22
+ def definition_end?(event, method, klass)
23
+ !definitions.empty? && definition?(event, method, klass, 'end', 'c-return')
24
+ end
25
+
26
+ # Checks if the event is a call to <tt>Module.new</tt>, <tt>Class.new</tt>, or <tt>/(class|instance|module)_(eval|exec)/</tt>
27
+ def definition_method?(method, klass)
28
+ (method == :initialize && klass.is_a?(Module)) || method.to_s =~ /^(class|instance|module)_(eval|exec)$/
29
+ end
30
+
31
+ # Checks if the event is the start of a class or module definition
32
+ def definition_start?(event, method, klass)
33
+ definition?(event, method, klass, 'class', 'c-call')
34
+ end
35
+
36
+ # Checks if the event is the end of a class or module definition, and if so
37
+ # it calls <tt>Module#defined(file, line, method)</tt> if implemented
38
+ def trace_function(event, file, line, method, binding, klass)
39
+ if definition_start?(event, method, klass)
40
+ definitions << binding.eval('self')
41
+ elsif definition_end?(event, method, klass)
42
+ object = definitions.pop
43
+ method ||= object.class.name.downcase.to_sym
44
+ object.defined(file, line, method) if object.respond_to?(:defined)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Module.send(:include, Defined)
@@ -0,0 +1,17 @@
1
+ module Defined
2
+ # Contains information about this gem's version
3
+ module Version
4
+ MAJOR = 0
5
+ MINOR = 0
6
+ PATCH = 0
7
+
8
+ # Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
9
+ #
10
+ # Example
11
+ #
12
+ # Version.string # '1.0.2'
13
+ def self.string
14
+ [MAJOR, MINOR, PATCH].join('.')
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,122 @@
1
+ require 'test_helper'
2
+
3
+ class DefinedTest < Test::Unit::TestCase
4
+ module TestMethods
5
+ attr_reader :file, :line, :method, :called
6
+
7
+ def defined(file, line, method)
8
+ @file, @line, @method, @called = file, line, method, true
9
+ end
10
+ end
11
+
12
+ module Mock
13
+ extend TestMethods
14
+ end
15
+
16
+ class Dummy
17
+ extend TestMethods
18
+ end
19
+
20
+ def test_should_match_definition_start_with_keyword
21
+ assert Defined.send(:definition_start?, 'class', false, false)
22
+ end
23
+
24
+ def test_should_not_match_definition_start_with_wrong_keyword
25
+ assert !Defined.send(:definition_start?, 'wrong_keyword', :class_eval, false)
26
+ end
27
+
28
+ def test_should_match_definition_start_with_method
29
+ assert Defined.send(:definition_start?, 'c-call', :class_eval, false)
30
+ end
31
+
32
+ def test_should_not_match_definition_start_with_normal_method
33
+ assert !Defined.send(:definition_start?, 'c-call', :normal_method, false)
34
+ end
35
+
36
+ def test_should_match_definition_start_with_initialize
37
+ assert Defined.send(:definition_start?, 'c-call', :initialize, Module.new)
38
+ end
39
+
40
+ def test_should_not_match_definition_start_with_initialize_if_not_called_on_module_or_class
41
+ assert Defined.send(:definition_start?, 'c-call', :initialize, Dummy)
42
+ end
43
+
44
+ def test_should_match_definition_end_with_keyword
45
+ with_dummy_definition do
46
+ assert Defined.send(:definition_end?, 'end', false, false)
47
+ end
48
+ end
49
+
50
+ def test_should_not_match_definition_end_with_wrong_keyword
51
+ with_dummy_definition do
52
+ assert !Defined.send(:definition_end?, 'wrong_keyword', :class_eval, false)
53
+ end
54
+ end
55
+
56
+ def test_should_match_definition_end_with_method
57
+ with_dummy_definition do
58
+ assert Defined.send(:definition_end?, 'c-return', :class_eval, false)
59
+ end
60
+ end
61
+
62
+ def test_should_not_match_definition_end_with_normal_method
63
+ with_dummy_definition do
64
+ assert !Defined.send(:definition_end?, 'c-return', :normal_method, false)
65
+ end
66
+ end
67
+
68
+ def test_should_match_definition_end_with_initialize
69
+ with_dummy_definition do
70
+ assert Defined.send(:definition_end?, 'c-return', :initialize, Module.new)
71
+ end
72
+ end
73
+
74
+ def test_should_not_match_definition_end_with_initialize_if_not_called_on_module_or_class
75
+ with_dummy_definition do
76
+ assert Defined.send(:definition_end?, 'c-return', :initialize, Dummy)
77
+ end
78
+ end
79
+
80
+ def test_should_not_match_end_without_start
81
+ assert !Defined.send(:definition_end?, 'end', false, false)
82
+ end
83
+
84
+ def test_method_should_be_class_or_module_when_defined_with_keywords
85
+ assert_equal :module, Mock.method
86
+ assert_equal :class, Dummy.method
87
+ end
88
+
89
+ def test_should_not_call_defined_unless_implemented
90
+ mod = Module.new
91
+ assert !mod.respond_to?(:defined)
92
+ end
93
+
94
+ def test_should_call_defined_when_module_is_defined
95
+ assert Mock.called
96
+ end
97
+
98
+ def test_should_call_defined_when_module_is_defined_with_new
99
+ mod = Module.new { extend TestMethods }
100
+ assert mod.called
101
+ assert_equal :initialize, mod.method
102
+ end
103
+
104
+ %w(class instance module).each do |prefix|
105
+ %w(eval exec).each do |suffix|
106
+ method_name = [prefix, suffix].join('_').to_sym
107
+ define_method "test_should_call_defined_when_module_is_defined_with_#{method_name}" do
108
+ Mock.send(method_name) { @called = false }
109
+ assert Mock.called
110
+ assert_equal method_name, Mock.method
111
+ end
112
+ end
113
+ end
114
+
115
+ protected
116
+
117
+ def with_dummy_definition
118
+ Defined.definitions << Dummy
119
+ yield
120
+ Defined.definitions.pop
121
+ end
122
+ end
@@ -0,0 +1,5 @@
1
+ require 'test/unit'
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ $:.unshift(File.dirname(__FILE__))
5
+ require 'defined'
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: defined
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Sean Huber
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-23 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Calls Module#defined whenever a class or module is defined or redefined
23
+ email: shuber@huberry.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/defined/version.rb
32
+ - lib/defined.rb
33
+ - MIT-LICENSE
34
+ - README.rdoc
35
+ - test/defined_test.rb
36
+ - test/test_helper.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/shuber/defined
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --line-numbers
44
+ - --inline-source
45
+ - --main
46
+ - README.rdoc
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.5.0
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Calls Module#defined whenever a class or module is (re)defined
74
+ test_files:
75
+ - test/defined_test.rb
76
+ - test/test_helper.rb