diff --git a/lib/typeprof/core/ast/const.rb b/lib/typeprof/core/ast/const.rb index 927f05cb..2943a68f 100644 --- a/lib/typeprof/core/ast/const.rb +++ b/lib/typeprof/core/ast/const.rb @@ -112,10 +112,30 @@ def install0(genv) @cpath.install(genv) if @cpath val = @rhs.install(genv) if @static_cpath - @changes.add_edge(genv, val, @static_ret.vtx) + if detect_class_new?(@rhs) + # Create a module entity for the dynamically created class + mod = genv.resolve_cpath(@static_cpath) + + # Create singleton type for the new class + singleton_ty = Type::Singleton.new(genv, mod) + vtx = Source.new(singleton_ty) + @changes.add_edge(genv, vtx, @static_ret.vtx) + else + @changes.add_edge(genv, val, @static_ret.vtx) + end end val end + + private + + def detect_class_new?(node) + node.is_a?(CallBaseNode) && + node.mid == :new && + node.recv.is_a?(ConstantReadNode) && + node.recv.cname == :Class && + node.recv.cbase.nil? + end end end end diff --git a/scenario/control/rescue-assign-with-class-new.rb b/scenario/control/rescue-assign-with-class-new.rb new file mode 100644 index 00000000..ebfc82c7 --- /dev/null +++ b/scenario/control/rescue-assign-with-class-new.rb @@ -0,0 +1,15 @@ +## update: my_error.rb +MyError = Class.new(StandardError) + +## update: test.rb +class C + def foo + rescue MyError => e + raise ArgumentError, e.message + end +end + +## assert: test.rb +class C + def foo: -> nil +end