class Pod::Specification::Linter::Analyzer
Constants
- DEPRECATED_KEYS
@return [Array<String>] Keys that are valid but have been deprecated.
- INTERNAL_KEYS
@return [Array<String>] Keys that are only used for internal purposes.
Attributes
Public Class Methods
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 7 def initialize(consumer, results) @consumer = consumer @results = results @results.consumer = @consumer end
Public Instance Methods
Analyzes the consumer adding a {Result} for any failed check to the {#results} object.
@return [Results] the results of the analysis.
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 18 def analyze check_attributes validate_file_patterns check_if_spec_is_empty results end
Private Instance Methods
Checks the attributes hash for any unknown key which might be the result of a misspelling in a JSON file.
@note Sub-keys are not checked per-platform as
there is no attribute supporting this combination.
@note The keys of sub-keys are not checked as they are only used by
the `source` attribute and they are subject to change according to the support in the `cocoapods-downloader` gem.
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 50 def check_attributes attributes_keys = Pod::Specification::DSL.attributes.keys.map(&:to_s) platform_keys = Specification::DSL::PLATFORMS.map(&:to_s) valid_keys = attributes_keys + platform_keys + DEPRECATED_KEYS + INTERNAL_KEYS attributes_hash = consumer.spec.attributes_hash keys = attributes_hash.keys Specification::DSL::PLATFORMS.each do |platform| if attributes_hash[platform.to_s] keys += attributes_hash[platform.to_s].keys end end unknown_keys = keys - valid_keys unknown_keys.each do |key| results.add_warning('attributes', "Unrecognized `#{key}` key.") end Pod::Specification::DSL.attributes.each do |_key, attribute| declared_value = consumer.spec.attributes_hash[attribute.name.to_s] validate_attribute_occurrence(attribute, declared_value) validate_attribute_type(attribute, declared_value) if attribute.name != :platforms value = value_for_attribute(attribute) validate_attribute_value(attribute, value) if value end end end
Check empty subspec attributes
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 105 def check_if_spec_is_empty methods = %w( source_files on_demand_resources resources resource_bundles preserve_paths dependencies vendored_libraries vendored_frameworks ) empty_patterns = methods.all? { |m| consumer.send(m).empty? } empty = empty_patterns && consumer.spec.subspecs.empty? if empty results.add_error('File Patterns', "The #{consumer.spec} spec is " \ 'empty (no source files, resources, resource_bundles, ' \ 'preserve paths, vendored_libraries, vendored_frameworks, ' \ 'dependencies, nor subspecs).') end end
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 183 def validate_attribute_array_keys(attribute, value) unknown_keys = value.keys.map(&:to_s) - attribute.keys.map(&:to_s) unknown_keys.each do |unknown_key| results.add_warning('keys', "Unrecognized `#{unknown_key}` key for " \ "`#{attribute.name}` attribute.") end end
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 191 def validate_attribute_hash_keys(attribute, value) unless value.is_a?(Hash) results.add_error(attribute.name, "Unsupported type `#{value.class}`, expected `Hash`") return end major_keys = value.keys & attribute.keys.keys if major_keys.count.zero? results.add_warning('keys', "Missing primary key for `#{attribute.name}` " \ 'attribute. The acceptable ones are: ' \ "`#{attribute.keys.keys.map(&:to_s).sort.join(', ')}`.") elsif major_keys.count == 1 acceptable = attribute.keys[major_keys.first] || [] unknown = value.keys - major_keys - acceptable unless unknown.empty? results.add_warning('keys', "Incompatible `#{unknown.sort.join(', ')}` " \ "key(s) with `#{major_keys.first}` primary key for " \ "`#{attribute.name}` attribute.") end else sorted_keys = major_keys.map(&:to_s).sort results.add_warning('keys', "Incompatible `#{sorted_keys.join(', ')}` " \ "keys for `#{attribute.name}` attribute.") end end
@param [Object] value
The value of the attribute.
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 147 def validate_attribute_occurrence(attribute, value) if attribute.root_only? && !value.nil? && !consumer.spec.root? results.add_error('attributes', "Can't set `#{attribute.name}` attribute for " \ "subspecs (in `#{consumer.spec.name}`).") end if attribute.test_only? && !value.nil? && !consumer.spec.test_specification? results.add_error('attributes', "Attribute `#{attribute.name}` can only be set " \ "within test specs (in `#{consumer.spec.name}`).") end end
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 174 def validate_attribute_type(attribute, value) return unless value types = attribute.supported_types if types.none? { |klass| value.class == klass } results.add_error('attributes', 'Unacceptable type ' \ "`#{value.class}` for `#{attribute.name}`. Allowed values: `#{types.inspect}`.") end end
Validates the given value for the given attribute.
@param [Spec::DSL::Attribute] attribute
The attribute.
@param [Object] value
The value of the attribute.
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 166 def validate_attribute_value(attribute, value) if attribute.keys.is_a?(Array) validate_attribute_array_keys(attribute, value) elsif attribute.keys.is_a?(Hash) validate_attribute_hash_keys(attribute, value) end end
Checks the attributes that represent file patterns.
@todo Check the attributes hash directly.
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 82 def validate_file_patterns attributes = DSL.attributes.values.select(&:file_patterns?) attributes.each do |attrb| patterns = consumer.send(attrb.name) if patterns.is_a?(Hash) patterns = patterns.values.flatten(1) end if patterns.respond_to?(:each) patterns.each do |pattern| pattern = pattern[:paths].join if attrb.name == :on_demand_resources if pattern.respond_to?(:start_with?) && pattern.start_with?('/') results.add_error('File Patterns', 'File patterns must be ' \ "relative and cannot start with a slash (#{attrb.name}).") end end end end end
Returns the own or inherited (if applicable) value of the given attribute.
@param [Spec::DSL::Attribute] attribute
The attribute.
@return [mixed]
# File lib/cocoapods-core/specification/linter/analyzer.rb, line 128 def value_for_attribute(attribute) if attribute.root_only? consumer.spec.send(attribute.name) else consumer.send(attribute.name) if consumer.respond_to?(attribute.name) end rescue => e results.add_error('attributes', "Unable to validate `#{attribute.name}` (#{e}).") nil end