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



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 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
end

Instance Attribute Details

#allow_warningsBoolean



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

def allow_warnings
  @allow_warnings
end

#analyzeBoolean



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

def analyze
  @analyze
end

#configurationObject

Returns the value of attribute configuration.



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

def configuration
  @configuration
end

#external_podspecsString



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

def external_podspecs
  @external_podspecs
end

#fail_fastBoolean



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

def fail_fast
  @fail_fast
end

#file_accessorSandbox::FileAccessor



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

def file_accessor
  @file_accessor
end

#ignore_public_only_resultsBoolean



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

def ignore_public_only_results
  @ignore_public_only_results
end

#include_podspecsString



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

def include_podspecs
  @include_podspecs
end

#linterSpecification::Linter (readonly)



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

def linter
  @linter
end

#localBoolean 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.



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

def local
  @local
end

#no_cleanBoolean



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

def no_clean
  @no_clean
end

#no_subspecsBoolean



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

def no_subspecs
  @no_subspecs
end

#only_subspecString



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

def only_subspec
  @only_subspec
end

#quickBoolean



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

def quick
  @quick
end

#resultsObject (readonly)

Returns the value of attribute results.



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

def results
  @results
end

#skip_import_validationObject Also known as: skip_import_validation?

Returns the value of attribute skip_import_validation.



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

def skip_import_validation
  @skip_import_validation
end

#skip_testsBoolean



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

def skip_tests
  @skip_tests
end

#swift_versionString

‘–swift-version` parameter during validation.



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

def swift_version
  @swift_version
end

#test_specsArray<String>



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

def test_specs
  @test_specs
end

#use_frameworksBoolean



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

def use_frameworks
  @use_frameworks
end

#use_modular_headersBoolean



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

def use_modular_headers
  @use_modular_headers
end

#use_static_frameworksBoolean



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

def use_static_frameworks
  @use_static_frameworks
end

Instance Method Details

#derived_swift_versionString



352
353
354
355
356
357
358
359
360
361
362
# File 'lib/cocoapods/validator.rb', line 352

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



339
340
341
342
343
344
# File 'lib/cocoapods/validator.rb', line 339

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



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

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



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

def file
  @linter.file
end

#platforms_to_lint(spec) ⇒ Array<Platform>

Returns a list of platforms to lint for a given Specification



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

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.



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

def print_results
  UI.puts results_message
end

#result_colorSymbol



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

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

#result_typeSymbol



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

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



144
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
177
# File 'lib/cocoapods/validator.rb', line 144

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] '
    elsif result.platforms == [:visionos]
      platform_message = '[visionOS] '
    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



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

def spec
  @linter.spec
end

#uses_swift?Boolean



366
367
368
# File 'lib/cocoapods/validator.rb', line 366

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

#validateBoolean

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.



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

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



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

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

#validation_dirPathname



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

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

#validation_dir=(validation_dir) ⇒ Object



328
329
330
# File 'lib/cocoapods/validator.rb', line 328

def validation_dir=(validation_dir)
  @validation_dir = Pathname(validation_dir) unless validation_dir.nil?
end