Class: Solargraph::ComplexType

Inherits:
Object
  • Object
show all
Defined in:
lib/solargraph/complex_type.rb,
lib/solargraph/complex_type/unique_type.rb,
lib/solargraph/complex_type/type_methods.rb

Overview

A container for type data based on YARD type tags.

Defined Under Namespace

Modules: TypeMethods Classes: UniqueType

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(types = [UniqueType::UNDEFINED]) ⇒ ComplexType

Returns a new instance of ComplexType.

Parameters:

  • types (Array<UniqueType>) (defaults to: [UniqueType::UNDEFINED])


14
15
16
# File 'lib/solargraph/complex_type.rb', line 14

def initialize types = [UniqueType::UNDEFINED]
  @items = types.uniq(&:to_s)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



83
84
85
86
87
# File 'lib/solargraph/complex_type.rb', line 83

def method_missing name, *args, &block
  return if @items.first.nil?
  return @items.first.send(name, *args, &block) if respond_to_missing?(name)
  super
end

Class Method Details

.parse(*strings, partial: false) ⇒ ComplexType, ...

Note:

The ‘partial` parameter is used to indicate that the method is receiving a string that will be used inside another ComplexType. It returns arrays of ComplexTypes instead of a single cohesive one. Consumers should not need to use this parameter; it should only be used internally.

Parse type strings into a ComplexType.

Examples:

ComplexType.parse 'String', 'Foo', 'nil' #=> [String, Foo, nil]

Parameters:

  • *strings (Array<String>)

    The type definitions to parse

  • partial (Boolean) (defaults to: false)

    True if the string is part of a another type

Returns:



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/solargraph/complex_type.rb', line 175

def parse *strings, partial: false
  @cache ||= {}
  unless partial
    cached = @cache[strings]
    return cached unless cached.nil?
  end
  types = []
  key_types = nil
  strings.each do |type_string|
    point_stack = 0
    curly_stack = 0
    paren_stack = 0
    base = String.new
    subtype_string = String.new
    type_string&.each_char do |char|
      if char == '='
        #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
      elsif char == '<'
        point_stack += 1
      elsif char == '>'
        if subtype_string.end_with?('=') && curly_stack > 0
          subtype_string += char
        elsif base.end_with?('=')
          raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
          # types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
          types.push UniqueType.new(base[0..-2].strip)
          key_types = types
          types = []
          base.clear
          subtype_string.clear
          next
        else
          raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack == 0
          point_stack -= 1
          subtype_string += char
        end
        next
      elsif char == '{'
        curly_stack += 1
      elsif char == '}'
        curly_stack -= 1
        subtype_string += char
        raise ComplexTypeError, "Invalid close in type #{type_string}" if curly_stack < 0
        next
      elsif char == '('
        paren_stack += 1
      elsif char == ')'
        paren_stack -= 1
        subtype_string += char if paren_stack == 0
        raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0
        next
      elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
        # types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
        types.push UniqueType.new(base.strip, subtype_string.strip)
        base.clear
        subtype_string.clear
        next
      end
      if point_stack == 0 && curly_stack == 0 && paren_stack == 0
        base.concat char
      else
        subtype_string.concat char
      end
    end
    raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
    # types.push ComplexType.new([UniqueType.new(base, subtype_string)])
    types.push UniqueType.new(base.strip, subtype_string.strip)
  end
  unless key_types.nil?
    raise ComplexTypeError, "Invalid use of key/value parameters" unless partial
    return key_types if types.empty?
    return [key_types, types]
  end
  result = partial ? types : ComplexType.new(types)
  @cache[strings] = result unless partial
  result
end

.try_parse(*strings) ⇒ ComplexType

Parameters:

  • strings (Array<String>)

Returns:



255
256
257
258
259
260
# File 'lib/solargraph/complex_type.rb', line 255

def try_parse *strings
  parse *strings
rescue ComplexTypeError => e
  Solargraph.logger.info "Error parsing complex type: #{e.message}"
  ComplexType::UNDEFINED
end

Instance Method Details

#[](index) ⇒ Object



64
65
66
# File 'lib/solargraph/complex_type.rb', line 64

def [](index)
  @items[index]
end

#all?(&block) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/solargraph/complex_type.rb', line 97

def all? &block
  @items.all? &block
end

#all_paramsObject



131
132
133
# File 'lib/solargraph/complex_type.rb', line 131

def all_params
  @items.first.all_params || []
end

#any?(&block) ⇒ Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/solargraph/complex_type.rb', line 101

def any? &block
  @items.compact.any? &block
end

#each {|| ... } ⇒ Array

Yield Parameters:

Returns:

  • (Array)


46
47
48
# File 'lib/solargraph/complex_type.rb', line 46

def each &block
  @items.each &block
end

#each_unique_type {|| ... } ⇒ Enumerator<UniqueType>

Yield Parameters:

Returns:



52
53
54
55
56
57
58
# File 'lib/solargraph/complex_type.rb', line 52

def each_unique_type &block
  return enum_for(__method__) unless block_given?

  @items.each do |item|
    item.each_unique_type &block
  end
end

#firstObject



30
31
32
# File 'lib/solargraph/complex_type.rb', line 30

def first
  @items.first
end

#lengthObject



60
61
62
# File 'lib/solargraph/complex_type.rb', line 60

def length
  @items.length
end

#map(&block) ⇒ Object



40
41
42
# File 'lib/solargraph/complex_type.rb', line 40

def map &block
  @items.map &block
end

#namespaceString

Returns:

  • (String)


73
74
75
76
# File 'lib/solargraph/complex_type.rb', line 73

def namespace
  # cache this attr for high frequency call
  @namespace ||= method_missing(:namespace).to_s
end

#namespacesArray<String>

Returns:

  • (Array<String>)


79
80
81
# File 'lib/solargraph/complex_type.rb', line 79

def namespaces
  @items.map(&:namespace)
end

#nullable?Boolean

Returns:

  • (Boolean)


127
128
129
# File 'lib/solargraph/complex_type.rb', line 127

def nullable?
  @items.any?(&:nil_type?)
end

#parameterized?Boolean

Returns:

  • (Boolean)


109
110
111
# File 'lib/solargraph/complex_type.rb', line 109

def parameterized?
  any?(&:parameterized?)
end

#qualify(api_map, context = '') ⇒ ComplexType

Parameters:

  • api_map (ApiMap)
  • context (String) (defaults to: '')

Returns:



21
22
23
24
25
26
27
28
# File 'lib/solargraph/complex_type.rb', line 21

def qualify api_map, context = ''
  red = reduce_object
  types = red.items.map do |t|
    next t if ['Boolean', 'nil', 'void', 'undefined'].include?(t.name)
    t.qualify api_map, context
  end
  ComplexType.new(types).reduce_object
end

#resolve_parameters(definitions, context) ⇒ Object



113
114
115
116
# File 'lib/solargraph/complex_type.rb', line 113

def resolve_parameters definitions, context
  result = @items.map { |i| i.resolve_parameters(definitions, context) }
  ComplexType.parse(*result.map(&:tag))
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
# File 'lib/solargraph/complex_type.rb', line 89

def respond_to_missing?(name, include_private = false)
  TypeMethods.public_instance_methods.include?(name) || super
end

#select(&block) ⇒ Object



68
69
70
# File 'lib/solargraph/complex_type.rb', line 68

def select &block
  @items.select &block
end

#self_to(dst) ⇒ ComplexType

Parameters:

  • dst (String)

Returns:



120
121
122
123
124
125
# File 'lib/solargraph/complex_type.rb', line 120

def self_to dst
  return self unless selfy?
  red = reduce_class(dst)
  result = @items.map { |i| i.self_to red }
  ComplexType.parse(*result.map(&:tag))
end

#selfy?Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/solargraph/complex_type.rb', line 105

def selfy?
  @items.any?(&:selfy?)
end

#to_rbsObject



34
35
36
37
38
# File 'lib/solargraph/complex_type.rb', line 34

def to_rbs
  ((@items.length > 1 ? '(' : '') + @items.map do |item|
    "#{item.namespace}#{item.parameters? ? "[#{item.subtypes.map { |s| s.to_rbs }.join(', ')}]" : ''}"
  end.join(' | ') + (@items.length > 1 ? ')' : '')).gsub(/undefined/, 'untyped')
end

#to_sObject



93
94
95
# File 'lib/solargraph/complex_type.rb', line 93

def to_s
  map(&:tag).join(', ')
end