overrides 0.1.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +6 -0
- data/README.md +83 -0
- data/Rakefile +7 -0
- data/lib/overrides.rb +32 -11
- data/lib/overrides/for_all.rb +2 -0
- data/lib/overrides/version.rb +1 -1
- data/overrides.gemspec +4 -1
- data/test/overrides_test.rb +178 -0
- metadata +29 -6
data/.travis.yml
ADDED
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Overrides
|
2
|
+
|
3
|
+
An #overrides annotation for your (Ruby) methods.
|
4
|
+
|
5
|
+
Inspired by Java's [@Override][1].
|
6
|
+
|
7
|
+
|
8
|
+
## Install
|
9
|
+
|
10
|
+
$ gem install overrides
|
11
|
+
|
12
|
+
or add this line to your application's *Gemfile* (and `bundle`) :
|
13
|
+
|
14
|
+
gem 'overrides'
|
15
|
+
|
16
|
+
optionally add `:require => 'overrides/for_all'` to have `overrides` available
|
17
|
+
in all classes/modules as a built-in (singleton) method.
|
18
|
+
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
Let's have a base class with `Overrides` pulled in :
|
23
|
+
|
24
|
+
class Message
|
25
|
+
extend Overrides
|
26
|
+
|
27
|
+
def self.deliver(msg); end
|
28
|
+
|
29
|
+
def do_send; end
|
30
|
+
def sent_at; end
|
31
|
+
def reply?; end
|
32
|
+
end
|
33
|
+
|
34
|
+
a notice would be a message sub-type, note how `overrides` gets used :
|
35
|
+
|
36
|
+
class Notice < Message
|
37
|
+
overrides
|
38
|
+
def do_send; super; end
|
39
|
+
|
40
|
+
def reply?; nil; end
|
41
|
+
def sent_at; nil; end
|
42
|
+
|
43
|
+
overrides :reply?, :sent_at
|
44
|
+
end
|
45
|
+
|
46
|
+
without args (before method) works with singleton methods as well :
|
47
|
+
|
48
|
+
class Notice < Message
|
49
|
+
overrides
|
50
|
+
def self.deliver(msg); end
|
51
|
+
end
|
52
|
+
|
53
|
+
**NOTE:** there's no global name-space pollution by default, thus you'll need
|
54
|
+
to hook up the `Overrides` module (or extend `Object` to pull it in for all).
|
55
|
+
|
56
|
+
### "Java"
|
57
|
+
|
58
|
+
Here's how you use it with JRuby to "annotate" method overrides :
|
59
|
+
|
60
|
+
require 'overrides/for_all'
|
61
|
+
|
62
|
+
class NonEmptyList < java.util.ArrayList
|
63
|
+
|
64
|
+
def initialize
|
65
|
+
super(); add nil
|
66
|
+
end
|
67
|
+
|
68
|
+
overrides
|
69
|
+
def clear; super; add nil; end
|
70
|
+
|
71
|
+
def isEmpty; false; end
|
72
|
+
overrides :isEmpty
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
## Copyright
|
78
|
+
|
79
|
+
Copyright (c) 2013 [Karol Bucek](http://kares.org).
|
80
|
+
See LICENSE.txt (http://en.wikipedia.org/wiki/MIT_License) for details.
|
81
|
+
|
82
|
+
[0]: https://github.com/kares/overrides
|
83
|
+
[1]: http://docs.oracle.com/javase/7/docs/api/java/lang/Override.html
|
data/Rakefile
CHANGED
data/lib/overrides.rb
CHANGED
@@ -2,10 +2,11 @@ require 'overrides/version'
|
|
2
2
|
|
3
3
|
# Allows for an #overrides annotation for your methods.
|
4
4
|
#
|
5
|
-
#
|
6
|
-
# expected to
|
5
|
+
# This might help during refactoring (method renaming) to assure methods
|
6
|
+
# expected to be overriding another (and calling super) fail early during
|
7
|
+
# definition time instead of when called.
|
7
8
|
#
|
8
|
-
#
|
9
|
+
# Usage :
|
9
10
|
#
|
10
11
|
# class Message
|
11
12
|
# extend Overrides
|
@@ -26,7 +27,7 @@ require 'overrides/version'
|
|
26
27
|
# end
|
27
28
|
#
|
28
29
|
#
|
29
|
-
# Without arguments works with singleton methods as well :
|
30
|
+
# Without arguments (before method) works with singleton methods as well :
|
30
31
|
#
|
31
32
|
# class Message
|
32
33
|
# extend Overrides
|
@@ -47,13 +48,19 @@ require 'overrides/version'
|
|
47
48
|
#
|
48
49
|
module Overrides
|
49
50
|
|
50
|
-
|
51
|
+
# Custom (missing method error) raised from {#overrides}.
|
52
|
+
class Error < NoMethodError; end
|
51
53
|
|
52
54
|
def overrides(*names)
|
53
|
-
if names.empty? # next method
|
55
|
+
if names.empty? # next method def - singleton or instance
|
54
56
|
@_override = true
|
55
57
|
else
|
56
|
-
names.each do |name|
|
58
|
+
names.each do |name| # only for instance methods
|
59
|
+
unless Overrides.includes_method? self.instance_methods(false), name
|
60
|
+
msg = "(instance) method #{name.inspect} not found in "
|
61
|
+
raise NoMethodError,
|
62
|
+
msg << ( self.is_a?(Class) ? 'class ' : 'module ' ) << self.inspect
|
63
|
+
end
|
57
64
|
unless Overrides.overriden?(self, name)
|
58
65
|
raise Error, "previous (instance) method #{name.inspect} not found"
|
59
66
|
end
|
@@ -61,6 +68,7 @@ module Overrides
|
|
61
68
|
end
|
62
69
|
end
|
63
70
|
|
71
|
+
# @private
|
64
72
|
def method_added(name)
|
65
73
|
return super unless (@_override ||= nil); @_override = false
|
66
74
|
unless Overrides.overriden?(self, name, true)
|
@@ -69,6 +77,7 @@ module Overrides
|
|
69
77
|
super
|
70
78
|
end
|
71
79
|
|
80
|
+
# @private
|
72
81
|
def singleton_method_added(name)
|
73
82
|
return super unless (@_override ||= nil); @_override = false
|
74
83
|
unless Overrides.overriden?(self, name, false)
|
@@ -77,20 +86,32 @@ module Overrides
|
|
77
86
|
super
|
78
87
|
end
|
79
88
|
|
89
|
+
# Checks if a method was previously available in the given module's method
|
90
|
+
# resolution chain. Assumes instance methods by default.
|
80
91
|
def self.overriden?(klass, method, instance = true)
|
81
92
|
if instance
|
82
93
|
klass.included_modules.each do |mod|
|
83
|
-
return true if mod.instance_methods(true)
|
94
|
+
return true if includes_method? mod.instance_methods(true), method
|
84
95
|
end
|
85
96
|
return false unless klass.is_a?(Class) # "only" a Module ...
|
86
|
-
return klass.superclass.instance_methods(true)
|
97
|
+
return includes_method? klass.superclass.instance_methods(true), method
|
87
98
|
else
|
88
99
|
(class << klass; self; end).included_modules.each do |mod|
|
89
|
-
return true if mod.instance_methods(true)
|
100
|
+
return true if includes_method? mod.instance_methods(true), method
|
90
101
|
end
|
91
102
|
return false unless klass.is_a?(Class) # "only" a Module ...
|
92
|
-
return klass.superclass.methods(true)
|
103
|
+
return includes_method? klass.superclass.methods(true), method
|
93
104
|
end
|
94
105
|
end
|
95
106
|
|
107
|
+
# @private
|
108
|
+
def self.includes_method?(methods, name)
|
109
|
+
methods.include? name
|
110
|
+
end
|
111
|
+
|
112
|
+
# @private
|
113
|
+
def self.includes_method?(methods, name)
|
114
|
+
methods.include? name.to_s
|
115
|
+
end if RUBY_VERSION < '1.9'
|
116
|
+
|
96
117
|
end
|
data/lib/overrides/version.rb
CHANGED
data/overrides.gemspec
CHANGED
@@ -9,7 +9,9 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.authors = ["Karol Bucek"]
|
10
10
|
gem.email = ["self@kares.org"]
|
11
11
|
gem.summary = %q{an #overrides annotation for your methods}
|
12
|
-
gem.description = %q{
|
12
|
+
gem.description = %q{Helps during refactoring (method renaming) to assure
|
13
|
+
methods expected to be overriding another (and calling super) fail early during
|
14
|
+
definition time instead of when called.}
|
13
15
|
gem.homepage = "http://github.com/kares/overrides"
|
14
16
|
gem.license = "MIT"
|
15
17
|
|
@@ -18,6 +20,7 @@ Gem::Specification.new do |gem|
|
|
18
20
|
gem.test_files = gem.files.grep(%r{^(test)/})
|
19
21
|
gem.require_paths = ["lib"]
|
20
22
|
|
23
|
+
gem.add_development_dependency "minitest", "~> 3.0"
|
21
24
|
gem.add_development_dependency "bundler", "~> 1.3"
|
22
25
|
gem.add_development_dependency "rake", "~> 10.1"
|
23
26
|
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'bundler/setup' # if RUBY_VERSION < '1.9'
|
2
|
+
|
3
|
+
require 'overrides'
|
4
|
+
|
5
|
+
require 'minitest/autorun'
|
6
|
+
|
7
|
+
class OverridesTest < MiniTest::Unit::TestCase; end
|
8
|
+
|
9
|
+
# ========================================
|
10
|
+
|
11
|
+
class Ferko
|
12
|
+
|
13
|
+
extend Overrides
|
14
|
+
|
15
|
+
def kuk; 'ferko-kuk'; end
|
16
|
+
def muk; 'ferko-muk'; end
|
17
|
+
|
18
|
+
overrides
|
19
|
+
def to_s
|
20
|
+
'ferko' + super.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.hoja; 'hoja-ferko'; end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
OverridesTest.class_eval do
|
28
|
+
|
29
|
+
def test_overrides_builtin_method
|
30
|
+
assert Ferko.new.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_methods_stay_the_same
|
34
|
+
assert_equal 'ferko-kuk', Ferko.new.kuk
|
35
|
+
assert_equal 'hoja-ferko', Ferko.hoja
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
# ========================================
|
41
|
+
|
42
|
+
class Jozko < Ferko
|
43
|
+
|
44
|
+
overrides
|
45
|
+
def kuk; super; 'jozko-kuk'; end
|
46
|
+
|
47
|
+
def muk; 'jozko-muk'; end
|
48
|
+
def tuk; 'jozko-tuk'; end
|
49
|
+
|
50
|
+
overrides :muk
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
OverridesTest.class_eval do
|
55
|
+
|
56
|
+
def test_overrides_inherited_methods
|
57
|
+
assert_equal 'jozko-kuk', Jozko.new.kuk
|
58
|
+
assert_equal 'jozko-muk', Jozko.new.muk
|
59
|
+
assert_equal 'jozko-tuk', Jozko.new.tuk
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# ========================================
|
65
|
+
|
66
|
+
class Jozko
|
67
|
+
|
68
|
+
overrides
|
69
|
+
def self.hoja; super; 'hoja-jozko'; end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
OverridesTest.class_eval do
|
74
|
+
|
75
|
+
def test_overrides_singleton_method
|
76
|
+
assert_equal 'hoja-jozko', Jozko.hoja
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
# ========================================
|
82
|
+
|
83
|
+
class Janko < Ferko
|
84
|
+
|
85
|
+
def kuk; super; 'janko-kuk'; end
|
86
|
+
def muk; super; 'janko-muk'; end
|
87
|
+
|
88
|
+
overrides :muk, :kuk
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
OverridesTest.class_eval do
|
93
|
+
|
94
|
+
def test_overrides_multiple_at_once
|
95
|
+
assert_equal 'janko-kuk', Janko.new.kuk
|
96
|
+
assert_equal 'janko-muk', Janko.new.muk
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
# ========================================
|
102
|
+
|
103
|
+
class Jozko
|
104
|
+
|
105
|
+
def jak; 'jozko-jak'; end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
OverridesTest.class_eval do
|
110
|
+
|
111
|
+
def test_uses_no_method_error
|
112
|
+
assert_kind_of NoMethodError, Overrides::Error.new
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_fails_when_override_not_met
|
116
|
+
assert_raises Overrides::Error do
|
117
|
+
Jozko.class_eval do
|
118
|
+
overrides :jak
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
assert_raises Overrides::Error do
|
123
|
+
Jozko.class_eval do
|
124
|
+
overrides
|
125
|
+
def tak; end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
assert_raises Overrides::Error do
|
130
|
+
Jozko.class_eval do
|
131
|
+
overrides
|
132
|
+
def self.kuk; end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
# ========================================
|
140
|
+
|
141
|
+
class Ferko
|
142
|
+
def sak; end
|
143
|
+
end
|
144
|
+
|
145
|
+
class Petko < Ferko
|
146
|
+
end
|
147
|
+
|
148
|
+
OverridesTest.class_eval do
|
149
|
+
|
150
|
+
def test_fails_when_method_not_defined
|
151
|
+
assert_raises NoMethodError do
|
152
|
+
Petko.class_eval do
|
153
|
+
overrides :sak
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
# ========================================
|
161
|
+
|
162
|
+
class Otakar
|
163
|
+
def coje; 'tha-nic'; end
|
164
|
+
end
|
165
|
+
|
166
|
+
class Bohuslav < Otakar; end
|
167
|
+
|
168
|
+
OverridesTest.class_eval do
|
169
|
+
|
170
|
+
def test_works_for_all_when_required
|
171
|
+
require 'overrides/for_all'
|
172
|
+
Bohuslav.class_eval do
|
173
|
+
overrides
|
174
|
+
def coje; 'ta-daco'; end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: overrides
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-11-
|
12
|
+
date: 2013-11-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: bundler
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -43,7 +59,9 @@ dependencies:
|
|
43
59
|
- - ~>
|
44
60
|
- !ruby/object:Gem::Version
|
45
61
|
version: '10.1'
|
46
|
-
description: !
|
62
|
+
description: ! "Helps during refactoring (method renaming) to assure\n methods expected
|
63
|
+
to be overriding another (and calling super) fail early during\n definition time
|
64
|
+
instead of when called."
|
47
65
|
email:
|
48
66
|
- self@kares.org
|
49
67
|
executables: []
|
@@ -51,12 +69,16 @@ extensions: []
|
|
51
69
|
extra_rdoc_files: []
|
52
70
|
files:
|
53
71
|
- .gitignore
|
72
|
+
- .travis.yml
|
54
73
|
- Gemfile
|
55
74
|
- LICENSE.txt
|
75
|
+
- README.md
|
56
76
|
- Rakefile
|
57
77
|
- lib/overrides.rb
|
78
|
+
- lib/overrides/for_all.rb
|
58
79
|
- lib/overrides/version.rb
|
59
80
|
- overrides.gemspec
|
81
|
+
- test/overrides_test.rb
|
60
82
|
homepage: http://github.com/kares/overrides
|
61
83
|
licenses:
|
62
84
|
- MIT
|
@@ -72,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
94
|
version: '0'
|
73
95
|
segments:
|
74
96
|
- 0
|
75
|
-
hash:
|
97
|
+
hash: 3588119150367271522
|
76
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
99
|
none: false
|
78
100
|
requirements:
|
@@ -81,11 +103,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
103
|
version: '0'
|
82
104
|
segments:
|
83
105
|
- 0
|
84
|
-
hash:
|
106
|
+
hash: 3588119150367271522
|
85
107
|
requirements: []
|
86
108
|
rubyforge_project:
|
87
109
|
rubygems_version: 1.8.25
|
88
110
|
signing_key:
|
89
111
|
specification_version: 3
|
90
112
|
summary: ! 'an #overrides annotation for your methods'
|
91
|
-
test_files:
|
113
|
+
test_files:
|
114
|
+
- test/overrides_test.rb
|