File: token_resolver_spec.rb

package info (click to toggle)
yard 0.9.38-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,736 kB
  • sloc: ruby: 31,680; javascript: 7,658; makefile: 21
file content (165 lines) | stat: -rw-r--r-- 4,147 bytes parent folder | download | duplicates (6)
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# frozen_string_literal: true

RSpec.describe YARD::Parser::Ruby::TokenResolver do
  before(:all) do
    YARD.parse_string <<-eof
      module A
        def nomatch; end

        module B
          class C
            def initialize; end

            # @return [A::B::C]
            def self.foo; end

            # @return [self]
            def self.foo2; end

            def bar; end

            # @return [nil, D<String>]
            def baz; end

            # @return [nil]
            # @return [D<String>]
            def baz2; end

            # @overload qux(a)
            #   @return [nil]
            # @overload qux(b)
            #   @return [D<String>]
            def qux; end
          end

          class SubC < C
          end
        end
      end

      module D
        def baz; end
      end

      class Q
        def method; end

        # @return [Q]
        def self.q; end
      end
    eof
  end

  def tokens_match
    expect(@resolved.map {|t| t.first.last }.join).to eq @src
  end

  def objs_match(*objects)
    other_objs = @resolved.reject {|_, o| !o }.map {|_, o| o.path }
    expect(other_objs).to eq objects.flatten
    tokens_match
  end

  def tokenize(src, object = nil)
    @src = src
    @resolver = YARD::Parser::Ruby::TokenResolver.new(src, object)
    @resolved = @resolver.map {|t, o| [t[0, 2], o] }
  end

  it "returns regular tokens" do
    str = "def foo; Z::X::Y end"
    tokenize(str)
    tokens_match
  end

  it "resolves objects in compound constant paths" do
    tokenize "A::B::C"
    objs_match "A", "A::B", "A::B::C"
  end

  it "ignores full constant path if it breaks at beginning" do
    tokenize "E::A::B::C"
    objs_match []
  end

  it "ignores rest of constant path if sub-objects don't match" do
    tokenize "D::A::B::C"
    objs_match "D"
  end

  it "resets parsing at non-op tokens" do
    tokenize "A::B::C < Q"
    objs_match "A", "A::B", "A::B::C", "Q"
  end

  it "does not restart constant path" do
    tokenize "A::B::D::A"
    objs_match "A", "A::B"
  end

  it "resolves objects from base namespace" do
    tokenize "A::B::C C", Registry.at("A::B")
    objs_match "A", "A::B", "A::B::C", "A::B::C"
  end

  it "resolves methods" do
    tokenize "A::B::C.foo"
    objs_match "A", "A::B", "A::B::C", "A::B::C.foo"
  end

  it "supports 'new' constructor method" do
    tokenize "A::B::C.new"
    objs_match "A", "A::B", "A::B::C", "A::B::C#initialize"
  end

  it "skips constructor method if not found but continues resolving" do
    tokenize "Q.new.method"
    objs_match "Q", "Q#method"
  end

  it "resolves methods in inheritance tree" do
    tokenize "A::B::SubC.new"
    objs_match "A", "A::B", "A::B::SubC", "A::B::C#initialize"
  end

  it "parses compound method call chains based on return type" do
    tokenize "A::B::C.foo.baz"
    objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz"
  end

  it "stops resolving if return types not found" do
    tokenize "A::B::C.foo.bar.baz.baz"
    objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#bar"
  end

  it "handles multiple return types (returns first valid type match)" do
    tokenize "A::B::C.foo.baz.baz"
    objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz", "D#baz"
  end

  it "doesn't perform lexical matching on methods" do
    tokenize "A::B::C.nomatch"
    objs_match "A", "A::B", "A::B::C"
  end

  it "handles multiple return tags (returns first valid type match)" do
    tokenize "A::B::C.foo.baz2.baz"
    objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz2", "D#baz"
  end

  it "handles self as return type" do
    tokenize "A::B::C.foo2.baz"
    objs_match "A", "A::B", "A::B::C", "A::B::C.foo2", "A::B::C#baz"
  end

  it "handles multiple return tags inside overload tags" do
    tokenize "A::B::C.foo.qux.baz"
    objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#qux", "D#baz"
  end

  it "resolves method calls with arguments" do
    tokenize "Q.q(A::B, A::B::C.foo().bar).q.q"
    objs_match "Q", "Q.q", "A", "A::B", "A", "A::B", "A::B::C",
               "A::B::C.foo", "A::B::C#bar", "Q.q", "Q.q"
  end
end if HAVE_RIPPER