# frozen_string_literal: true require File.dirname(__FILE__) + '/spec_helper' RSpec.describe YARD::CodeObjects::Proxy do before { Registry.clear } it "does not allow constants to be used as a namespace if they do not resolve to a valid namespace" do a = ConstantObject.new(:root, :A) a.value = "$$INVALID$$" expect { P("A::MyClass") }.to raise_error(Parser::UndocumentableError) end it "returns the object if it's in the Registry" do ModuleObject.new(:root, :YARD) proxyobj = P(:root, :YARD) expect(proxyobj.type).to eq :module expect(Proxy === proxyobj).to be false end it "handles complex string namespaces" do ModuleObject.new(:root, :A) ModuleObject.new(P(nil, :A), :B) expect(P(:root, "A::B")).to be_instance_of(ModuleObject) end it "does not return true to Proxy === obj if obj is a Proxy class holding a resolved object" do expect(Proxy === P(:root, 'a')).to be true expect(Proxy === P(:root)).to be false MethodObject.new(:root, 'a') expect(Proxy === P(:root, 'a')).to be false x = Proxy.new(:root, 'a') expect(Proxy === x).to be false end it "returns the object if it's an included Module" do yardobj = ModuleObject.new(:root, :YARD) pathobj = ClassObject.new(:root, :TestClass) pathobj.instance_mixins << yardobj expect(P(P(nil, :TestClass), :YARD)).to be_instance_of(ModuleObject) end it "responds to respond_to?" do ClassObject.new(:root, :Object) ModuleObject.new(:root, :YARD) expect(P(:YARD).respond_to?(:children)).to be true expect(P(:NOTYARD).respond_to?(:children)).to be false expect(P(:YARD).respond_to?(:initialize)).to be false expect(P(:YARD).respond_to?(:initialize, true)).to be true expect(P(:NOTYARD).respond_to?(:initialize)).to be false expect(P(:NOTYARD).respond_to?(:initialize, true)).to be true end it "makes itself obvious that it's a proxy" do pathobj = P(:root, :YARD) expect(pathobj.class).to eq Proxy expect(Proxy === pathobj).to be true end it "pretends it's the object's type if it can resolve" do ModuleObject.new(:root, :YARD) proxyobj = P(:root, :YARD) expect(proxyobj).to be_instance_of(ModuleObject) end it "handles instance method names" do obj = P(nil, '#test') expect(obj.name).to eq :test expect(obj.path).to eq "#test" expect(obj.namespace).to eq Registry.root end it "handles instance method names under a namespace" do pathobj = ModuleObject.new(:root, :YARD) obj = P(pathobj, "A::B#test") expect(obj.name).to eq :test expect(obj.path).to eq "A::B#test" end it "allows type to be changed" do obj = P("InvalidClass") expect(obj.type).to eq :proxy expect(Proxy === obj).to be true obj.type = :class expect(obj.type).to eq :class end it "does NOT retain a type change between Proxy objects" do P("InvalidClass").type = :class expect(P("InvalidClass").type).to eq :proxy end it "uses type to ensure resolved object is of intended type" do YARD.parse_string <<-eof module Foo class Bar; end def self.Bar; end end eof proxy = Proxy.new(P('Foo'), 'Bar') proxy.type = :method expect(proxy.path).to eq 'Foo.Bar' end it "allows type in initializer" do expect(Proxy.new(Registry.root, 'Foo', :method).type).to eq :method expect(P(Registry.root, 'Foo', :method).type).to eq :method end it "never equals Registry.root" do expect(P("MYPROXY")).not_to eq Registry.root expect(P("X::A")).not_to eq Registry.root end it "resets namespace and name when object is resolved" do obj1 = ModuleObject.new(:root, :YARD) obj2 = ModuleObject.new(:root, :NOTYARD) resolved = Proxy.new(obj2, :YARD) expect(resolved).to eq obj1 expect(resolved.namespace).to eq Registry.root expect(resolved.name).to eq :YARD end it "ensures that the correct object was resolved" do foo = ModuleObject.new(:root, :Foo) foobar = ModuleObject.new(foo, :Bar) ClassObject.new(foo, :Baz) # Remember, we're looking for Qux::Bar, not just 'Bar' proxy = Proxy.new(foobar, 'Foo::Qux::Bar') expect(proxy.type).to eq :proxy qux = ModuleObject.new(foo, :Qux) ModuleObject.new(qux, :Bar) # Now it should resolve expect(proxy.type).to eq :module end it "handles constant names in namespaces" do YARD.parse_string <<-eof module A; end; B = A module B::C; def foo; end end eof expect(Proxy.new(:root, 'B::C')).to eq Registry.at('A::C') end end