From 2a8a7312032c38cb59125d232f67bfede2c11742 Mon Sep 17 00:00:00 2001 From: Kevin Clark Date: Wed, 18 Jun 2008 01:01:07 +0000 Subject: [PATCH] deprecate_class! now sets up a proxy class that logs a warning when used git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@668926 13f79535-47bb-0310-9956-ffa450edef68 --- lib/rb/lib/thrift/deprecation.rb | 41 ++++++++++++++++++++++++++++---- lib/rb/spec/deprecation_spec.rb | 29 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/lib/rb/lib/thrift/deprecation.rb b/lib/rb/lib/thrift/deprecation.rb index e170f57f..d237ee49 100644 --- a/lib/rb/lib/thrift/deprecation.rb +++ b/lib/rb/lib/thrift/deprecation.rb @@ -31,6 +31,42 @@ class Module end end +module Thrift::DeprecationProxy + def self.new(obj) + Class.new(obj) do + klass = self + @@self = klass + @@obj = obj + instance_methods.sort.reject { |x| [:__id__,:__send__].include? x.to_sym }.each do |sym| + undef_method sym + end + def method_missing(sym, *args, &block) + @@obj.instance_method(sym).bind(self).call(*args, &block) + end + (class << self;self;end).class_eval do + @@self = klass + @@obj = obj + @@warned = false + instance_methods.sort.reject { |x| [:__id__,:__send__].include? x.to_sym }.each do |sym| + undef_method sym + end + def method_missing(sym, *args, &block) + unless @@warned + STDERR.puts "Warning: class #{@@obj.inspect} is deprecated" + STDERR.puts " from #{caller.first}" + @@warned = true + end + if @@self.__id__ == self.__id__ + @@obj.send sym, *args, &block + else + @@obj.method(sym).unbind.bind(self).call(*args, &block) + end + end + end + end + end +end + module Kernel # Provides an alternate name for the class for deprecation purposes # Example: @@ -39,13 +75,10 @@ module Kernel # at the moment this only works for creating top-level constants # if necessary, this can be extended to take something like :'Thrift::TBinaryProtocol' # alternately, Module can be extended with a similar method - # - # another idea is to not make the old name a pointer to the new, but rather - # a pointer to a proxy class that logs deprecation warnings and forwards methods def deprecate_class!(klasses) return unless Thrift::DEPRECATION klasses.each_pair do |old, new| - Object.const_set old, new + Object.const_set old, Thrift::DeprecationProxy.new(new) end end end diff --git a/lib/rb/spec/deprecation_spec.rb b/lib/rb/spec/deprecation_spec.rb index cb462b45..ff10177c 100644 --- a/lib/rb/spec/deprecation_spec.rb +++ b/lib/rb/spec/deprecation_spec.rb @@ -168,6 +168,12 @@ end describe "deprecate_class!" do it_should_behave_like "deprecation" + def stub_stderr(callstr, offset=1) + STDERR.should_receive(:puts).with("Warning: class #{callstr} is deprecated") + line = caller.first[/\d+$/].to_i + offset + STDERR.should_receive(:puts).with(" from #{__FILE__}:#{line}") + end + it "should create a new global constant that points to the old one" do begin klass = Class.new do @@ -176,6 +182,7 @@ describe "deprecate_class!" do end end deprecate_class! :DeprecationSpecOldClass => klass + stub_stderr(klass) ::DeprecationSpecOldClass.should eql(klass) ::DeprecationSpecOldClass.new.foo.should == "foo" ensure @@ -194,10 +201,32 @@ describe "deprecate_class!" do end deprecate_class! :DeprecationSpecOldClass => klass end + stub_stderr(klass) ::DeprecationSpecOldClass.should eql(klass) ::DeprecationSpecOldClass.new.foo.should == "foo" ensure Object.send :remove_const, :DeprecationSpecOldClass if Object.const_defined? :DeprecationSpecOldClass end end + + it "should not prevent the deprecated class from being a superclass" do + begin + klass = Class.new do + def foo + "foo" + end + end + deprecate_class! :DeprecationSpecOldClass => klass + subklass = Class.new(::DeprecationSpecOldClass) do + def foo + "subclass #{super}" + end + end + stub_stderr(klass) + subklass.superclass.should eql(klass) + subklass.new.foo.should == "subclass foo" + ensure + Object.send :remove_const, :DeprecationSpecOldClass if Object.const_defined? :DeprecationSpecOldClass + end + end end -- 2.17.1