Class: Fastlane::SwiftFunction

Inherits:
Object
  • Object
show all
Defined in:
fastlane/lib/fastlane/swift_fastlane_function.rb

Direct Known Subclasses

ToolSwiftFunction

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(action_name: nil, action_description: nil, action_details: nil, keys: nil, key_descriptions: nil, key_default_values: nil, key_optionality_values: nil, key_type_overrides: nil, key_is_strings: nil, return_type: nil, return_value: nil, sample_return_value: nil) ⇒ SwiftFunction

Returns a new instance of SwiftFunction.


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 18

def initialize(action_name: nil, action_description: nil, action_details: nil, keys: nil, key_descriptions: nil, key_default_values: nil, key_optionality_values: nil, key_type_overrides: nil, key_is_strings: nil, return_type: nil, return_value: nil, sample_return_value: nil)
  @function_name = action_name
  @function_description = action_description
  @function_details = action_details
  @param_names = keys
  @param_descriptions = key_descriptions
  @param_default_values = key_default_values
  @param_optionality_values = key_optionality_values
  @param_is_strings = key_is_strings
  @return_type = return_type
  @return_value = non_empty(string: return_value)
  @sample_return_value = non_empty(string: sample_return_value)
  @param_type_overrides = key_type_overrides

  # rubocop:disable LineLength
  # class instance?
  @reserved_words = %w[associativity break case catch class continue convenience default deinit didSet do else enum extension fallthrough false final for func get guard if in infix init inout internal lazy let mutating nil operator override postfix precedence prefix private public repeat required return self set static struct subscript super switch throws true try var weak where while willSet].to_set
  # rubocop:enable LineLength
end

Instance Attribute Details

#default_values_to_ignoreObject

Returns the value of attribute default_values_to_ignore


16
17
18
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 16

def default_values_to_ignore
  @default_values_to_ignore
end

#function_descriptionObject

Returns the value of attribute function_description


4
5
6
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 4

def function_description
  @function_description
end

#function_detailsObject

Returns the value of attribute function_details


5
6
7
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 5

def function_details
  @function_details
end

#function_nameObject

Returns the value of attribute function_name


3
4
5
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 3

def function_name
  @function_name
end

#param_default_valuesObject

Returns the value of attribute param_default_values


11
12
13
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 11

def param_default_values
  @param_default_values
end

#param_descriptionsObject

Returns the value of attribute param_descriptions


10
11
12
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 10

def param_descriptions
  @param_descriptions
end

#param_is_stringsObject

Returns the value of attribute param_is_strings


14
15
16
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 14

def param_is_strings
  @param_is_strings
end

#param_namesObject

Returns the value of attribute param_names


9
10
11
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 9

def param_names
  @param_names
end

#param_optionality_valuesObject

Returns the value of attribute param_optionality_values


12
13
14
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 12

def param_optionality_values
  @param_optionality_values
end

#param_type_overridesObject

Returns the value of attribute param_type_overrides


13
14
15
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 13

def param_type_overrides
  @param_type_overrides
end

#reserved_wordsObject

Returns the value of attribute reserved_words


15
16
17
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 15

def reserved_words
  @reserved_words
end

#return_typeObject

Returns the value of attribute return_type


6
7
8
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 6

def return_type
  @return_type
end

#return_valueObject

Returns the value of attribute return_value


7
8
9
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 7

def return_value
  @return_value
end

#sample_return_valueObject

Returns the value of attribute sample_return_value


8
9
10
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 8

def sample_return_value
  @sample_return_value
end

Instance Method Details

#build_argument_listObject


261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 261

def build_argument_list
  unless @param_names
    return "[]" # return empty list for argument
  end

  argument_object_strings = @param_names.zip(param_type_overrides).map do |name, type_override|
    sanitized_name = camel_case_lower(string: name)
    sanitized_name = sanitize_reserved_word(word: sanitized_name)
    type_string = type_override == :string_callback ? ", type: .stringClosure" : nil

    "RubyCommand.Argument(name: \"#{name}\", value: #{sanitized_name}#{type_string})"
  end
  return argument_object_strings
end

#camel_case_lower(string: nil) ⇒ Object


85
86
87
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 85

def camel_case_lower(string: nil)
  string.split('_').inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
end

#determine_type_from_override(type_override: nil, default_type: nil) ⇒ Object


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 89

def determine_type_from_override(type_override: nil, default_type: nil)
  if type_override == Array
    return "[String]"
  elsif type_override == Hash
    return "[String : Any]"
  elsif type_override == Integer
    return "Int"
  elsif type_override == Boolean
    return "Bool"
  elsif type_override == Float
    return "Float"
  elsif type_override == :string_callback
    return "((String) -> Void)"
  else
    return default_type
  end
end

#fix_documentation_indentation(string: nil) ⇒ Object


256
257
258
259
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 256

def fix_documentation_indentation(string: nil)
  indent = ' '
  string.gsub("\n", "\n#{indent}")
end

#get_type(param: nil, default_value: nil, optional: nil, param_type_override: nil, is_string: true) ⇒ Object


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
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 114

def get_type(param: nil, default_value: nil, optional: nil, param_type_override: nil, is_string: true)
  unless param_type_override.nil?
    type = determine_type_from_override(type_override: param_type_override)
  end

  # defaulting type to Any if is_string is false so users are allowed to input all allowed types
  type ||= is_string ? "String" : "Any"

  optional_specifier = ""
  # if we are optional and don't have a default value, we'll need to use ?
  optional_specifier = "?" if (optional && default_value.nil?) && type != "((String) -> Void)"

  # If we have a default value of true or false, we can infer it is a Bool
  if default_value.class == FalseClass
    type = "Bool"
  elsif default_value.class == TrueClass
    type = "Bool"
  elsif default_value.kind_of?(Array)
    type = "[String]"
  elsif default_value.kind_of?(Hash)
    type = "[String : Any]"
  # Altough we can have a default value of Integer type, if param_type_override overridden that value, respect it.
  elsif default_value.kind_of?(Integer)
    if type == "Double" || type == "Float"
      begin
        # If we're not able to instantiate
        _ = BigDecimal(default_value)
      rescue
        # We set it as a Int
        type = "Int"
      end
    else
      type = "Int"
    end
  end
  return "#{type}#{optional_specifier}"
end

#implementationObject


300
301
302
303
304
305
306
307
308
309
310
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 300

def implementation
  args = build_argument_list

  implm = "  let command = RubyCommand(commandID: \"\", methodName: \"#{@function_name}\", className: nil, args: ["
  # Get the indent of the first argument in the list to give each
  # subsequent argument it's own line with proper indenting
  indent = ' ' * implm.length
  implm += args.join(",\n#{indent}")
  implm += "])\n"
  return implm + "  #{return_statement}"
end

#non_empty(string: nil) ⇒ Object


45
46
47
48
49
50
51
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 45

def non_empty(string: nil)
  if string.nil? || string.to_s.empty?
    return nil
  else
    return string
  end
end

#override_default_value_if_not_correct_type(param_name: nil, param_type: nil, default_value: nil) ⇒ Object


107
108
109
110
111
112
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 107

def override_default_value_if_not_correct_type(param_name: nil, param_type: nil, default_value: nil)
  return "[]" if param_type == "[String]" && default_value == ""
  return "{_ in }" if param_type == "((String) -> Void)"

  return default_value
end

#parametersObject


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 152

def parameters
  unless @param_names
    return ""
  end

  param_names_and_types = @param_names.zip(param_default_values, param_optionality_values, param_type_overrides, param_is_strings).map do |param, default_value, optional, param_type_override, is_string|
    type = get_type(param: param, default_value: default_value, optional: optional, param_type_override: param_type_override, is_string: is_string)

    unless default_value.nil?
      if type == "[String : Any]"
        # we can't handle default values for Hashes, yet
        # see method swift_default_implementations for similar behavior
        default_value = "[:]"
      elsif type != "Bool" && type != "[String]" && type != "Int" && type != "((String) -> Void)" && type != "Float" && type != "Double"
        default_value = "\"#{default_value}\""
      end
    end

    # if we don't have a default value, but the param is optional, set a default value in Swift to be nil
    if optional && default_value.nil?
      default_value = "nil"
    end

    # sometimes we get to the point where we have a default value but its type is wrong
    # so we need to correct that because [String] = "" is not valid swift
    default_value = override_default_value_if_not_correct_type(param_type: type, param_name: param, default_value: default_value)

    param = camel_case_lower(string: param)
    param = sanitize_reserved_word(word: param)

    if default_value.nil?
      "#{param}: #{type}"
    else
      "#{param}: #{type} = #{default_value}"
    end
  end

  return param_names_and_types
end

#return_declarationObject


53
54
55
56
57
58
59
60
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 53

def return_declaration
  expected_type = swift_type_for_return_type
  unless expected_type.to_s.length > 0
    return ""
  end

  return " -> #{expected_type}"
end

#return_statementObject


276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 276

def return_statement
  returned_object = "runner.executeCommand(command)"
  case @return_type
  when :array_of_strings
    returned_object = "parseArray(fromString: #{returned_object})"
  when :hash_of_strings
    returned_object = "parseDictionary(fromString: #{returned_object})"
  when :hash
    returned_object = "parseDictionary(fromString: #{returned_object})"
  when :bool
    returned_object = "parseBool(fromString: #{returned_object})"
  when :int
    returned_object = "parseInt(fromString: #{returned_object})"
  end

  expected_type = swift_type_for_return_type

  return_string = "_ = "
  if expected_type.length > 0
    return_string = "return "
  end
  return "#{return_string}#{returned_object}"
end

#sanitize_reserved_word(word: nil) ⇒ Object


38
39
40
41
42
43
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 38

def sanitize_reserved_word(word: nil)
  unless @reserved_words.include?(word)
    return word
  end
  return "`#{word}`"
end

#swift_codeObject

rubocop:enable Metrics/PerceivedComplexity


193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 193

def swift_code
  function_name = camel_case_lower(string: self.function_name)
  function_return_declaration = self.return_declaration
  discardable_result = function_return_declaration.length > 0 ? "@discardableResult " : ''

  # Calculate the necessary indent to line up parameter names on new lines
  # with the first parameter after the opening paren following the function name.
  # i.e.: @discardableResult func someFunctionName(firstParameter: T
  #                                                secondParameter: T)
  # This just creates a string with as many spaces are necessary given whether or not
  # the function has a 'discardableResult' annotation, the 'func' keyword, function name
  # and the opening paren.
  function_keyword_definition = 'func '
  open_paren = '('
  closed_paren = ')'
  indent = ' ' * (discardable_result.length + function_name.length + function_keyword_definition.length + open_paren.length)
  params = self.parameters.join(",\n#{indent}")

  return "#{swift_documentation}#{discardable_result}#{function_keyword_definition}#{function_name}#{open_paren}#{params}#{closed_paren}#{function_return_declaration} {\n#{self.implementation}\n}\n"
end

#swift_documentationObject


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 214

def swift_documentation
  has_parameters = @param_names && @param_names.length > 0
  unless @function_description || @function_details || has_parameters
    return ''
  end

  description = " #{fix_documentation_indentation(string: @function_description)}" if @function_description
  details = " #{fix_documentation_indentation(string: @function_details)}" if @function_details
  separator = ''
  documentation_elements = [description, swift_parameter_documentation, swift_return_value_documentation, details].compact
  # Adds newlines between each documentation element.
  documentation = documentation_elements.flat_map { |element| [element, separator] }.tap(&:pop).join("\n")

  return "/**\n#{documentation}\n*/\n"
end

#swift_parameter_documentationObject


230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 230

def swift_parameter_documentation
  unless @param_names && @param_names.length > 0
    return nil
  end

  names_and_descriptions = @param_names.zip(@param_descriptions)

  if @param_names.length == 1
    detail_strings = names_and_descriptions.map { |name, description| " - parameter #{camel_case_lower(string: name)}: #{description}" }
    return detail_strings.first
  else
    detail_strings = names_and_descriptions.map { |name, description| "   - #{camel_case_lower(string: name)}: #{description}" }
    return " - parameters:\n#{detail_strings.join("\n")}"
  end
end

#swift_return_value_documentationObject


246
247
248
249
250
251
252
253
254
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 246

def swift_return_value_documentation
  unless @return_value
    return nil
  end

  sample = ". Example: #{@sample_return_value}" if @sample_return_value

  return " - returns: #{return_value}#{sample}"
end

#swift_type_for_return_typeObject


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'fastlane/lib/fastlane/swift_fastlane_function.rb', line 62

def swift_type_for_return_type
  unless @return_type
    return ""
  end

  case @return_type
  when :string
    return "String"
  when :array_of_strings
    return "[String]"
  when :hash_of_strings
    return "[String : String]"
  when :hash
    return "[String : Any]"
  when :bool
    return "Bool"
  when :int
    return "Int"
  else
    return ""
  end
end