Author: kclark
Date: Tue Jun 17 18:01:07 2008
New Revision: 668926

URL: http://svn.apache.org/viewvc?rev=668926&view=rev
Log:
deprecate_class! now sets up a proxy class that logs a warning when used

Modified:
    incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb
    incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb

Modified: incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb
URL: 
http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb?rev=668926&r1=668925&r2=668926&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb (original)
+++ incubator/thrift/trunk/lib/rb/lib/thrift/deprecation.rb Tue Jun 17 18:01:07 
2008
@@ -31,6 +31,42 @@
   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 @@
   # 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

Modified: incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb
URL: 
http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb?rev=668926&r1=668925&r2=668926&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb (original)
+++ incubator/thrift/trunk/lib/rb/spec/deprecation_spec.rb Tue Jun 17 18:01:07 
2008
@@ -168,6 +168,12 @@
 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 @@
         end
       end
       deprecate_class! :DeprecationSpecOldClass => klass
+      stub_stderr(klass)
       ::DeprecationSpecOldClass.should eql(klass)
       ::DeprecationSpecOldClass.new.foo.should == "foo"
     ensure
@@ -194,10 +201,32 @@
         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


Reply via email to