forked from rubygems/rubygems
/
deprecate.rb
123 lines (107 loc) · 3.07 KB
/
deprecate.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
##
# Provides a single method +deprecate+ to be used to declare when
# something is going away.
#
# class Legacy
# def self.klass_method
# # ...
# end
#
# def instance_method
# # ...
# end
#
# extend Deprecate
# deprecate :instance_method, "X.z", 2011, 4
#
# class << self
# extend Deprecate
# deprecate :klass_method, :none, 2011, 4
# end
# end
module Deprecate
SKIP_DEFAULT = false
@skip = nil
def self.skip # :nodoc:
@skip.nil? ? SKIP_DEFAULT : @skip
end
def self.skip= v # :nodoc:
@skip = v
end
def self.saved_warnings # :nodoc:
@saved_warnings ||= []
end
def self.add_warning w # :nodoc:
warn "Warning: #{w.message} (Further warnings suppressed until exit.)\n#{w.loc}" if saved_warnings.empty?
unless saved_warnings.include? w
@saved_warnings << w
end
end
at_exit do
# todo: extract and test
unless Deprecate.saved_warnings.size == 0
warn Deprecate.report
end
end
def self.report
out = ""
out << "Some of your installed gems called deprecated methods. See http://blog.zenspider.com/2011/05/rubygems-18-is-coming.html for background. Use 'gem pristine --all' to fix or 'rubygems update --system 1.7.2' to downgrade.\n"
last_message = nil
warnings = @saved_warnings.sort_by{|w| w.full_name}.each do |w|
out << (last_message = w.message) + "\n" unless last_message == w.message
out << w.loc
out << "\n"
end
out
end
##
# Temporarily turn off warnings. Intended for tests only.
def skip_during(will_skip = true)
Deprecate.skip, original = will_skip, Deprecate.skip
yield
ensure
Deprecate.skip = original
end
require 'ostruct'
class Warning < OpenStruct
def message
[ "#{target}#{method_name} is deprecated",
repl == :none ? " with no replacement" : "; use #{replacement} instead.",
" It will be removed on or after %4d-%02d-01." % [year, month]
].join
end
def loc
" called from #{location.join(":")}"
end
def full_name
"#{target}#{method_name}"
end
end
##
# Simple deprecation method that deprecates +name+ by wrapping it up
# in a dummy method. It warns on each call to the dummy method
# telling the user of +repl+ (unless +repl+ is :none) and the
# year/month that it is planned to go away.
def deprecate name, repl, year, month
class_eval {
old = "_deprecated_#{name}"
alias_method old, name
define_method name do |*args, &block| # TODO: really works on 1.8.7?
unless Deprecate.skip
klass =
warning = Warning.new({
:target => (self.kind_of? Module) ? "#{self}." : "#{self.class}#",
:method_name => name,
:location => Gem.location_of_caller,
:replacement => repl,
:year => year,
:month => month
})
Deprecate.add_warning warning
end
send old, *args, &block
end
}
end
module_function :deprecate, :skip_during
end