Class: Steep::Interface::Params

Inherits:
Object
  • Object
show all
Defined in:
lib/steep/interface/method_type.rb

Constant Summary collapse

NONE =
Object.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(required:, optional:, rest:, required_keywords:, optional_keywords:, rest_keywords:) ⇒ Params

Returns a new instance of Params.



11
12
13
14
15
16
17
18
# File 'lib/steep/interface/method_type.rb', line 11

def initialize(required:, optional:, rest:, required_keywords:, optional_keywords:, rest_keywords:)
  @required = required
  @optional = optional
  @rest = rest
  @required_keywords = required_keywords
  @optional_keywords = optional_keywords
  @rest_keywords = rest_keywords
end

Instance Attribute Details

#optionalObject (readonly)

Returns the value of attribute optional.



5
6
7
# File 'lib/steep/interface/method_type.rb', line 5

def optional
  @optional
end

#optional_keywordsObject (readonly)

Returns the value of attribute optional_keywords.



8
9
10
# File 'lib/steep/interface/method_type.rb', line 8

def optional_keywords
  @optional_keywords
end

#requiredObject (readonly)

Returns the value of attribute required.



4
5
6
# File 'lib/steep/interface/method_type.rb', line 4

def required
  @required
end

#required_keywordsObject (readonly)

Returns the value of attribute required_keywords.



7
8
9
# File 'lib/steep/interface/method_type.rb', line 7

def required_keywords
  @required_keywords
end

#restObject (readonly)

Returns the value of attribute rest.



6
7
8
# File 'lib/steep/interface/method_type.rb', line 6

def rest
  @rest
end

#rest_keywordsObject (readonly)

Returns the value of attribute rest_keywords.



9
10
11
# File 'lib/steep/interface/method_type.rb', line 9

def rest_keywords
  @rest_keywords
end

Class Method Details

.emptyObject



32
33
34
35
36
37
38
39
40
41
# File 'lib/steep/interface/method_type.rb', line 32

def self.empty
  self.new(
    required: [],
    optional: [],
    rest: nil,
    required_keywords: {},
    optional_keywords: {},
    rest_keywords: nil
  )
end

Instance Method Details

#==(other) ⇒ Object



43
44
45
46
47
48
49
50
51
# File 'lib/steep/interface/method_type.rb', line 43

def ==(other)
  other.is_a?(self.class) &&
    other.required == required &&
    other.optional == optional &&
    other.rest == rest &&
    other.required_keywords == required_keywords &&
    other.optional_keywords == optional_keywords &&
    other.rest_keywords == rest_keywords
end

#closed?Boolean

Returns:

  • (Boolean)


188
189
190
# File 'lib/steep/interface/method_type.rb', line 188

def closed?
  required.all?(&:closed?) && optional.all?(&:closed?) && (!rest || rest.closed?) && required_keywords.values.all?(&:closed?) && optional_keywords.values.all?(&:closed?) && (!rest_keywords || rest_keywords.closed?)
end

#drop_firstObject



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/steep/interface/method_type.rb', line 76

def drop_first
  case
  when required.any? || optional.any? || rest
    self.class.new(
      required: required.any? ? required.drop(1) : [],
      optional: required.empty? && optional.any? ? optional.drop(1) : optional,
      rest: required.empty? && optional.empty? ? nil : rest,
      required_keywords: required_keywords,
      optional_keywords: optional_keywords,
      rest_keywords: rest_keywords
    )
  when has_keywords?
    without_keywords
  else
    raise "Cannot drop from empty params"
  end
end

#each_extra_argument(args) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/steep/interface/method_type.rb', line 102

def each_extra_argument(args)
  return if rest

  if has_keywords?
    args = args.take(args.count - 1) if args.count > 0
  end

  args.size.times do |index|
    if index >= required.count + optional.count
      yield index
    end
  end
end

#each_extra_keyword(args) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/steep/interface/method_type.rb', line 128

def each_extra_keyword(args)
  return unless has_keywords?
  return if rest_keywords

  keywords, rest = extract_keywords(args)

  return unless rest.empty?

  all_keywords = flat_keywords
  keywords.each do |keyword, _|
    yield keyword unless all_keywords.key?(keyword)
  end
end

#each_missing_argument(args) ⇒ Object



94
95
96
97
98
99
100
# File 'lib/steep/interface/method_type.rb', line 94

def each_missing_argument(args)
  required.size.times do |index|
    if index >= args.size
      yield index
    end
  end
end

#each_missing_keyword(args) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/steep/interface/method_type.rb', line 116

def each_missing_keyword(args)
  return unless has_keywords?

  keywords, rest = extract_keywords(args)

  return unless rest.empty?

  required_keywords.each do |keyword, _|
    yield keyword unless keywords.key?(keyword)
  end
end

#each_typeObject



165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/steep/interface/method_type.rb', line 165

def each_type()
  if block_given?
    flat_unnamed_params.each do |(_, type)|
      yield type
    end
    flat_keywords.each do |_, type|
      yield type
    end
    rest and yield rest
    rest_keywords and yield rest_keywords
  else
    enum_for :each_type
  end
end

#empty?Boolean

Returns:

  • (Boolean)


228
229
230
# File 'lib/steep/interface/method_type.rb', line 228

def empty?
  required.empty? && optional.empty? && !rest && !has_keywords?
end

#extract_keywords(args) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/steep/interface/method_type.rb', line 142

def extract_keywords(args)
  last_arg = args.last

  keywords = {}
  rest = []

  if last_arg&.type == :hash
    last_arg.children.each do |element|
      case element.type
      when :pair
        if element.children[0].type == :sym
          name = element.children[0].children[0]
          keywords[name] = element.children[1]
        end
      when :kwsplat
        rest << element.children[0]
      end
    end
  end

  [keywords, rest]
end

#flat_keywordsObject



57
58
59
# File 'lib/steep/interface/method_type.rb', line 57

def flat_keywords
  required_keywords.merge optional_keywords
end

#flat_unnamed_paramsObject



53
54
55
# File 'lib/steep/interface/method_type.rb', line 53

def flat_unnamed_params
  required.map {|p| [:required, p] } + optional.map {|p| [:optional, p] }
end

#free_variablesObject



180
181
182
183
184
185
186
# File 'lib/steep/interface/method_type.rb', line 180

def free_variables
  Set.new.tap do |fvs|
    each_type do |type|
      fvs.merge type.free_variables
    end
  end
end

#has_keywords?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/steep/interface/method_type.rb', line 61

def has_keywords?
  !required_keywords.empty? || !optional_keywords.empty? || rest_keywords
end

#map_type(&block) ⇒ Object



217
218
219
220
221
222
223
224
225
226
# File 'lib/steep/interface/method_type.rb', line 217

def map_type(&block)
  self.class.new(
    required: required.map(&block),
    optional: optional.map(&block),
    rest: rest && yield(rest),
    required_keywords: required_keywords.transform_values(&block),
    optional_keywords: optional_keywords.transform_values(&block),
    rest_keywords: rest_keywords && yield(rest_keywords)
  )
end

#sizeObject



203
204
205
# File 'lib/steep/interface/method_type.rb', line 203

def size
  required.size + optional.size + (rest ? 1 : 0) + required_keywords.size + optional_keywords.size + (rest_keywords ? 1 : 0)
end

#subst(s) ⇒ Object



192
193
194
195
196
197
198
199
200
201
# File 'lib/steep/interface/method_type.rb', line 192

def subst(s)
  self.class.new(
    required: required.map {|t| t.subst(s) },
    optional: optional.map {|t| t.subst(s) },
    rest: rest&.subst(s),
    required_keywords: required_keywords.transform_values {|t| t.subst(s) },
    optional_keywords: optional_keywords.transform_values {|t| t.subst(s) },
    rest_keywords: rest_keywords&.subst(s)
  )
end

#to_sObject



207
208
209
210
211
212
213
214
215
# File 'lib/steep/interface/method_type.rb', line 207

def to_s
  required = self.required.map {|ty| ty.to_s }
  optional = self.optional.map {|ty| "?#{ty}" }
  rest = self.rest ? ["*#{self.rest}"] : []
  required_keywords = self.required_keywords.map {|name, type| "#{name}: #{type}" }
  optional_keywords = self.optional_keywords.map {|name, type| "?#{name}: #{type}"}
  rest_keywords = self.rest_keywords ? ["**#{self.rest_keywords}"] : []
  "(#{(required + optional + rest + required_keywords + optional_keywords + rest_keywords).join(", ")})"
end

#update(required: NONE, optional: NONE, rest: NONE, required_keywords: NONE, optional_keywords: NONE, rest_keywords: NONE) ⇒ Object



21
22
23
24
25
26
27
28
29
30
# File 'lib/steep/interface/method_type.rb', line 21

def update(required: NONE, optional: NONE, rest: NONE, required_keywords: NONE, optional_keywords: NONE, rest_keywords: NONE)
  self.class.new(
    required: required.equal?(NONE) ? self.required : required,
    optional: optional.equal?(NONE) ? self.optional : optional,
    rest: rest.equal?(NONE) ? self.rest : rest,
    required_keywords: required_keywords.equal?(NONE) ? self.required_keywords : required_keywords,
    optional_keywords: optional_keywords.equal?(NONE) ? self.optional_keywords : optional_keywords,
    rest_keywords: rest_keywords.equal?(NONE) ? self.rest_keywords : rest_keywords
  )
end

#without_keywordsObject



65
66
67
68
69
70
71
72
73
74
# File 'lib/steep/interface/method_type.rb', line 65

def without_keywords
  self.class.new(
    required: required,
    optional: optional,
    rest: rest,
    required_keywords: {},
    optional_keywords: {},
    rest_keywords: nil
  )
end