Class: Pod::Validator

Inherits:
Object
  • Object
show all
Includes:
Config::Mixin
Defined in:
lib/cocoapods/validator.rb

Overview

Validates a Specification.

Extends the Linter from the Core to add additional which require the LocalPod and the Installer.

In detail it checks that the file patterns defined by the user match actually do match at least a file and that the Pod builds, by installing it without integration and building the project with xcodebuild.

Defined Under Namespace

Classes: Result

Constant Summary collapse

DEFAULT_SWIFT_VERSION =

The default version of Swift to use when linting pods

'4.0'.freeze
VALID_PLATFORMS =

The valid platforms for linting

Platform.all.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Config::Mixin

#config

Constructor Details

#initialize(spec_or_path, source_urls, platforms = []) ⇒ Validator

Initialize a new instance

Parameters:

  • spec_or_path (Specification, Pathname, String)

    the Specification or the path of the `podspec` file to lint.

  • source_urls (Array<String>)

    the Source URLs to use in creating a Podfile.

  • platforms (Array<String>) (defaults to: [])

    the platforms to lint.


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/cocoapods/validator.rb', line 41

def initialize(spec_or_path, source_urls, platforms = [])
  @use_frameworks = true
  @linter = Specification::Linter.new(spec_or_path)
  @source_urls = if @linter.spec && @linter.spec.dependencies.empty? && @linter.spec.recursive_subspecs.all? { |s| s.dependencies.empty? }
                   []
                 else
                   source_urls.map { |url| config.sources_manager.source_with_name_or_url(url) }.map(&:url)
                 end

  @platforms = platforms.map do |platform|
    result =  case platform.to_s.downcase
              # Platform doesn't recognize 'macos' as being the same as 'osx' when initializing
              when 'macos' then Platform.macos
              else Platform.new(platform, nil)
              end
    unless valid_platform?(result)
      raise Informative, "Unrecognized platform `#{platform}`. Valid platforms: #{VALID_PLATFORMS.join(', ')}"
    end
    result
  end
  @use_frameworks = true
end

Instance Attribute Details

#allow_warningsBool

Returns Whether the validator should fail on warnings, or only on errors.

Returns:

  • (Bool)

    Whether the validator should fail on warnings, or only on errors.


230
231
232
# File 'lib/cocoapods/validator.rb', line 230

def allow_warnings
  @allow_warnings
end

#analyzeBool

Returns Whether the validator should run Xcode Static Analysis.

Returns:

  • (Bool)

    Whether the validator should run Xcode Static Analysis.


250
251
252
# File 'lib/cocoapods/validator.rb', line 250

def analyze
  @analyze
end

#configurationObject

Returns the value of attribute configuration


282
283
284
# File 'lib/cocoapods/validator.rb', line 282

def configuration
  @configuration
end

#external_podspecsString

Returns A glob for podspecs to be used during building of the local Podfile via :podspec.

Returns:

  • (String)

    A glob for podspecs to be used during building of the local Podfile via :podspec.


277
278
279
# File 'lib/cocoapods/validator.rb', line 277

def external_podspecs
  @external_podspecs
end

#fail_fastBool

Returns whether the linter should fail as soon as the first build variant causes an error. Helpful for i.e. multi-platforms specs, specs with subspecs.

Returns:

  • (Bool)

    whether the linter should fail as soon as the first build variant causes an error. Helpful for i.e. multi-platforms specs, specs with subspecs.


218
219
220
# File 'lib/cocoapods/validator.rb', line 218

def fail_fast
  @fail_fast
end

#file_accessorSandbox::FileAccessor

Returns the file accessor for the spec.

Returns:


103
104
105
# File 'lib/cocoapods/validator.rb', line 103

def file_accessor
  @file_accessor
end

#ignore_public_only_resultsBoolean

Returns Whether attributes that affect only public sources Bool be skipped.

Returns:

  • (Boolean)

    Whether attributes that affect only public sources Bool be skipped.


267
268
269
# File 'lib/cocoapods/validator.rb', line 267

def ignore_public_only_results
  @ignore_public_only_results
end

#include_podspecsString

Returns A glob for podspecs to be used during building of the local Podfile via :path.

Returns:

  • (String)

    A glob for podspecs to be used during building of the local Podfile via :path.


272
273
274
# File 'lib/cocoapods/validator.rb', line 272

def include_podspecs
  @include_podspecs
end

#linterSpecification::Linter (readonly)

Returns the linter instance from CocoaPods Core.

Returns:

  • (Specification::Linter)

    the linter instance from CocoaPods Core.


28
29
30
# File 'lib/cocoapods/validator.rb', line 28

def linter
  @linter
end

#localBool Also known as: local?

Note:

Uses the `:path` option of the Podfile.

Returns whether the validation should be performed against the root of the podspec instead to its original source.

Returns:

  • (Bool)

    whether the validation should be performed against the root of the podspec instead to its original source.


225
226
227
# File 'lib/cocoapods/validator.rb', line 225

def local
  @local
end

#no_cleanBool

Returns whether the linter should not clean up temporary files for inspection.

Returns:

  • (Bool)

    whether the linter should not clean up temporary files for inspection.


212
213
214
# File 'lib/cocoapods/validator.rb', line 212

def no_clean
  @no_clean
end

#no_subspecsBool

Returns Whether the validator should validate all subspecs.

Returns:

  • (Bool)

    Whether the validator should validate all subspecs.


238
239
240
# File 'lib/cocoapods/validator.rb', line 238

def no_subspecs
  @no_subspecs
end

#only_subspecString

Returns name of the subspec to check, if nil all subspecs are checked.

Returns:

  • (String)

    name of the subspec to check, if nil all subspecs are checked.


234
235
236
# File 'lib/cocoapods/validator.rb', line 234

def only_subspec
  @only_subspec
end

#quickBool

Returns whether the validation should skip the checks that requires the download of the library.

Returns:

  • (Bool)

    whether the validation should skip the checks that requires the download of the library.


207
208
209
# File 'lib/cocoapods/validator.rb', line 207

def quick
  @quick
end

#resultsObject (readonly)

Returns the value of attribute results


290
291
292
# File 'lib/cocoapods/validator.rb', line 290

def results
  @results
end

#skip_import_validationObject Also known as: skip_import_validation?

Returns the value of attribute skip_import_validation


279
280
281
# File 'lib/cocoapods/validator.rb', line 279

def skip_import_validation
  @skip_import_validation
end

#skip_testsBool

Returns Whether the validator should skip building and running tests.

Returns:

  • (Bool)

    Whether the validator should skip building and running tests.


242
243
244
# File 'lib/cocoapods/validator.rb', line 242

def skip_tests
  @skip_tests
end

#swift_versionString

`–swift-version` parameter during validation.

Returns:

  • (String)

    The SWIFT_VERSION that should be used to validate the pod. This is set by passing the


330
331
332
# File 'lib/cocoapods/validator.rb', line 330

def swift_version
  @swift_version
end

#test_specsArray<String>

Returns List of test_specs to run. If nil, all tests are run (unless skip_tests is specified).

Returns:

  • (Array<String>)

    List of test_specs to run. If nil, all tests are run (unless skip_tests is specified).


246
247
248
# File 'lib/cocoapods/validator.rb', line 246

def test_specs
  @test_specs
end

#use_frameworksBool

Returns Whether frameworks should be used for the installation.

Returns:

  • (Bool)

    Whether frameworks should be used for the installation.


254
255
256
# File 'lib/cocoapods/validator.rb', line 254

def use_frameworks
  @use_frameworks
end

#use_modular_headersBoolean

Returns Whether modular headers should be used for the installation.

Returns:

  • (Boolean)

    Whether modular headers should be used for the installation.


258
259
260
# File 'lib/cocoapods/validator.rb', line 258

def use_modular_headers
  @use_modular_headers
end

#use_static_frameworksBoolean

Returns Whether static frameworks should be used for the installation.

Returns:

  • (Boolean)

    Whether static frameworks should be used for the installation.


262
263
264
# File 'lib/cocoapods/validator.rb', line 262

def use_static_frameworks
  @use_static_frameworks
end

Instance Method Details

#derived_swift_versionString

Returns The derived Swift version to use for validation. The order of precedence is as follows:

  • The `–swift-version` parameter is always checked first and honored if passed.

  • The `swift_versions` DSL attribute within the podspec, in which case the latest version is always chosen.

  • The Swift version within the `.swift-version` file if present.

  • If none of the above are set then the `#DEFAULT_SWIFT_VERSION` is used.

Returns:

  • (String)

    The derived Swift version to use for validation. The order of precedence is as follows:

    • The `–swift-version` parameter is always checked first and honored if passed.

    • The `swift_versions` DSL attribute within the podspec, in which case the latest version is always chosen.

    • The Swift version within the `.swift-version` file if present.

    • If none of the above are set then the `#DEFAULT_SWIFT_VERSION` is used.


347
348
349
350
351
352
353
354
355
356
357
# File 'lib/cocoapods/validator.rb', line 347

def derived_swift_version
  @derived_swift_version ||= begin
    if !swift_version.nil?
      swift_version
    elsif version = spec.swift_versions.max || dot_swift_version
      version.to_s
    else
      DEFAULT_SWIFT_VERSION
    end
  end
end

#dot_swift_versionString

Returns the SWIFT_VERSION within the .swift-version file or nil.

Returns:

  • (String)

    the SWIFT_VERSION within the .swift-version file or nil.


334
335
336
337
338
339
# File 'lib/cocoapods/validator.rb', line 334

def dot_swift_version
  return unless file
  swift_version_path = file.dirname + '.swift-version'
  return unless swift_version_path.exist?
  swift_version_path.read.strip
end

#failure_reasonObject


178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/cocoapods/validator.rb', line 178

def failure_reason
  results_by_type = results.group_by(&:type)
  results_by_type.default = []
  return nil if validated?
  reasons = []
  if (size = results_by_type[:error].size) && size > 0
    reasons << "#{size} #{'error'.pluralize(size)}"
  end
  if !allow_warnings && (size = results_by_type[:warning].size) && size > 0
    reason = "#{size} #{'warning'.pluralize(size)}"
    pronoun = size == 1 ? 'it' : 'them'
    reason << " (but you can use `--allow-warnings` to ignore #{pronoun})" if reasons.empty?
    reasons << reason
  end
  if results.all?(&:public_only)
    reasons << 'all results apply only to public specs, but you can use ' \
               '`--private` to ignore them if linting the specification for a private pod'
  end

  reasons.to_sentence
end

#filePathname

Returns the path of the `podspec` file where #spec is defined.

Returns:

  • (Pathname)

    the path of the `podspec` file where #spec is defined.


75
76
77
# File 'lib/cocoapods/validator.rb', line 75

def file
  @linter.file
end

#platforms_to_lint(spec) ⇒ Array<Platform>

Returns a list of platforms to lint for a given Specification

Parameters:

Returns:

  • (Array<Platform>)

    platforms to lint for the given specification


86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/cocoapods/validator.rb', line 86

def platforms_to_lint(spec)
  return spec.available_platforms if @platforms.empty?

  # Validate that the platforms specified are actually supported by the spec
  results = @platforms.map do |platform|
    matching_platform = spec.available_platforms.find { |p| p.name == platform.name }
    unless matching_platform
      raise Informative, "Platform `#{platform}` is not supported by specification `#{spec}`."
    end
    matching_platform
  end.uniq

  results
end

This method returns an undefined value.

Prints the result of the validation to the user.


141
142
143
# File 'lib/cocoapods/validator.rb', line 141

def print_results
  UI.puts results_message
end

#result_colorSymbol

Returns The color, which should been used to display the result. One of: `:green`, `:yellow`, `:red`.

Returns:

  • (Symbol)

    The color, which should been used to display the result. One of: `:green`, `:yellow`, `:red`.


314
315
316
317
318
319
# File 'lib/cocoapods/validator.rb', line 314

def result_color
  case result_type
  when :error   then :red
  when :warning then :yellow
  else :green end
end

#result_typeSymbol

Returns The type, which should been used to display the result. One of: `:error`, `:warning`, `:note`.

Returns:

  • (Symbol)

    The type, which should been used to display the result. One of: `:error`, `:warning`, `:note`.


301
302
303
304
305
306
307
308
309
# File 'lib/cocoapods/validator.rb', line 301

def result_type
  applicable_results = results
  applicable_results = applicable_results.reject(&:public_only?) if ignore_public_only_results
  types              = applicable_results.map(&:type).uniq
  if    types.include?(:error)   then :error
  elsif types.include?(:warning) then :warning
  else  :note
  end
end

#results_messageObject


145
146
147
148
149
150
151
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
# File 'lib/cocoapods/validator.rb', line 145

def results_message
  message = ''
  results.each do |result|
    if result.platforms == [:ios]
      platform_message = '[iOS] '
    elsif result.platforms == [:osx]
      platform_message = '[OSX] '
    elsif result.platforms == [:watchos]
      platform_message = '[watchOS] '
    elsif result.platforms == [:tvos]
      platform_message = '[tvOS] '
    end

    subspecs_message = ''
    if result.is_a?(Result)
      subspecs = result.subspecs.uniq
      if subspecs.count > 2
        subspecs_message = '[' + subspecs[0..2].join(', ') + ', and more...] '
      elsif subspecs.count > 0
        subspecs_message = '[' + subspecs.join(',') + '] '
      end
    end

    case result.type
    when :error   then type = 'ERROR'
    when :warning then type = 'WARN'
    when :note    then type = 'NOTE'
    else raise "#{result.type}" end
    message << "    - #{type.ljust(5)} | #{platform_message}#{subspecs_message}#{result.attribute_name}: #{result.message}\n"
  end
  message << "\n"
end

#specSpecification

Returns the specification to lint.

Returns:


68
69
70
# File 'lib/cocoapods/validator.rb', line 68

def spec
  @linter.spec
end

#uses_swift?Boolean

Returns Whether any of the pod targets part of this validator use Swift or not.

Returns:

  • (Boolean)

    Whether any of the pod targets part of this validator use Swift or not.


361
362
363
# File 'lib/cocoapods/validator.rb', line 361

def uses_swift?
  @installer.pod_targets.any?(&:uses_swift?)
end

#validateBool

Note:

This method shows immediately which pod is being processed and overrides the printed line once the result is known.

Lints the specification adding a Result for any failed check to the #results list.

Returns:

  • (Bool)

    whether the specification passed validation.


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/cocoapods/validator.rb', line 115

def validate
  @results = []

  # Replace default spec with a subspec if asked for
  a_spec = spec
  if spec && @only_subspec
    subspec_name = @only_subspec.start_with?(spec.root.name) ? @only_subspec : "#{spec.root.name}/#{@only_subspec}"
    a_spec = spec.subspec_by_name(subspec_name, true, true)
    @subspec_name = a_spec.name
  end

  UI.print " -> #{a_spec ? a_spec.name : file.basename}\r" unless config.silent?
  $stdout.flush

  perform_linting
  perform_extensive_analysis(a_spec) if a_spec && !quick

  UI.puts ' -> '.send(result_color) << (a_spec ? a_spec.to_s : file.basename.to_s)
  print_results
  validated?
end

#validated?Boolean

Returns:

  • (Boolean)

294
295
296
# File 'lib/cocoapods/validator.rb', line 294

def validated?
  result_type != :error && (result_type != :warning || allow_warnings)
end

#validation_dirPathname

Returns the temporary directory used by the linter.

Returns:

  • (Pathname)

    the temporary directory used by the linter.


323
324
325
# File 'lib/cocoapods/validator.rb', line 323

def validation_dir
  @validation_dir ||= Pathname(Dir.mktmpdir(['CocoaPods-Lint-', "-#{spec.name}"]))
end