Class: PDK::Validate::InvokableValidator Abstract

Inherits:
Validator
  • Object
show all
Defined in:
lib/pdk/validate/invokable_validator.rb

Overview

This class is abstract.

A base class for file based validators. This class provides base methods and helpers to help determine the file targets to validate against. Acutal validator implementation should inherit from other child abstract classes e.g. ExternalCommandValdiator

See Also:

Instance Attribute Summary

Attributes inherited from Validator

#context, #options, #prepared

Instance Method Summary collapse

Methods inherited from Validator

#initialize, #invoke, #name, #spinners_enabled?, #start_spinner, #stop_spinner

Constructor Details

This class inherits a constructor from PDK::Validate::Validator

Instance Method Details

#allow_empty_targets?Boolean

This method is abstract.

Controls how the validator behaves if not passed any targets.

true  - PDK will not pass the globbed targets to the validator command
        and it will instead rely on the underlying tool to find its
        own default targets.
false - PDK will pass the globbed targets to the validator command.

Returns:

  • (Boolean)


183
184
185
# File 'lib/pdk/validate/invokable_validator.rb', line 183

def allow_empty_targets?
  false
end

#fnmatch?(pattern, target) ⇒ Boolean

Matches a target against a pattern

Parameters:

  • pattern (String, Array[String])

    The pattern to match against

Returns:

  • (Boolean)


117
118
119
# File 'lib/pdk/validate/invokable_validator.rb', line 117

def fnmatch?(pattern, target)
  Array(pattern).any? { |p| PDK::Util::Filesystem.fnmatch(PDK::Util::Filesystem.expand_path(p), PDK::Util::Filesystem.expand_path(target), File::FNM_DOTMATCH) }
end

#ignore_dotfiles?Boolean

This method is abstract.

Whether the target parsing ignores “dotfiles” (e.g. .gitignore or .pdkignore) which are considered hidden files in POSIX

Returns:

  • (Boolean)


124
125
126
# File 'lib/pdk/validate/invokable_validator.rb', line 124

def ignore_dotfiles?
  true
end

#invoke_styleObject

This method is abstract.

Controls how many times the validator is invoked.

:once -       The validator will be invoked once and passed all the
              targets.
:per_target - The validator will be invoked for each target
              separately.


18
19
20
# File 'lib/pdk/validate/invokable_validator.rb', line 18

def invoke_style
  :once
end

#parse_targetsObject

Parses the target strings provided from the CLI

Parameters:

  • options (Hash)

    A Hash containing the input options from the CLI.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/pdk/validate/invokable_validator.rb', line 60

def parse_targets
  requested_targets = options.fetch(:targets, [])
  # If no targets are specified and empty targets are allowed return with an empty list.
  # It will be up to the validator (and whatever validation tool it uses) to determine the
  # targets. For example, using rubocop with no targets, will allow rubocop to determine the
  # target list using it's .rubocop.yml file
  return [[], [], []] if requested_targets.empty? && allow_empty_targets?

  # If no targets are specified, then we will run validations from the base context directory.
  targets = requested_targets.empty? ? [context.root_path] : requested_targets
  targets.map! { |r| r.gsub(File::ALT_SEPARATOR, File::SEPARATOR) } if File::ALT_SEPARATOR

  # If this validator is not valid in this context then skip all of the targets
  return [[], targets, []] unless valid_in_context?

  skipped = []
  invalid = []
  matched = targets.filter_map do |target|
    if pattern.nil?
      target
    else
      if PDK::Util::Filesystem.directory?(target) # rubocop:disable Style/IfInsideElse
        target_root = context.root_path
        pattern_glob = Array(pattern).map { |p| PDK::Util::Filesystem.glob(File.join(target_root, p), File::FNM_DOTMATCH) }
        target_list = pattern_glob.flatten
                                  .select { |glob| PDK::Util::Filesystem.fnmatch(File.join(PDK::Util::Filesystem.expand_path(PDK::Util.canonical_path(target)), '*'), glob, File::FNM_DOTMATCH) }
                                  .map { |glob| Pathname.new(glob).relative_path_from(Pathname.new(context.root_path)).to_s }

        ignore_list = ignore_pathspec
        target_list = target_list.reject { |file| ignore_list.match(file) }

        if target_list.flatten.empty?
          PDK.logger.info(format('Validator \'%{validator}\' skipped for \'%{target}\'. No files matching \'%{pattern}\' found to validate.', validator: name, target: target, pattern: pattern))

          skipped << target
        end

        target_list
      elsif PDK::Util::Filesystem.file?(target)
        if (Array(pattern).include? target) || fnmatch?(pattern, target)
          target
        else
          skipped << target
          next
        end
      else
        invalid << target
        next
      end
    end
  end.flatten.uniq
  [matched, skipped, invalid]
end

#patternArray[String], String

This method is abstract.

An array, or a string, of glob patterns to use to find targets

Returns:

  • (Array[String], String)


31
# File 'lib/pdk/validate/invokable_validator.rb', line 31

def pattern; end

#pattern_ignoreArray[String], ...

This method is abstract.

An array, or a string, of glob patterns to use to ignore targets

Returns:

  • (Array[String], String, Nil)


36
# File 'lib/pdk/validate/invokable_validator.rb', line 36

def pattern_ignore; end

#prepare_invoke!Object

See Also:

  • Validator.prepare_invoke!


39
40
41
42
43
44
45
46
47
# File 'lib/pdk/validate/invokable_validator.rb', line 39

def prepare_invoke!
  return if @prepared

  super

  # Register the spinner
  spinner
  nil
end

#process_invalid(report, invalid = []) ⇒ Object

Process any targets that were invalid by the validator and add the events to the validation report

Parameters:

  • report (PDK::Report)

    The report to add the events to

  • invalid (Array[String]) (defaults to: [])

    The list of invalid targets



163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/pdk/validate/invokable_validator.rb', line 163

def process_invalid(report, invalid = [])
  invalid.each do |invalid_target|
    PDK.logger.debug(format('%{validator}: Skipped \'%{target}\'. Target file not found.', validator: name, target: invalid_target))
    report.add_event(
      file: invalid_target,
      source: name,
      message: 'File does not exist.',
      severity: :error,
      state: :error
    )
  end
end

#process_skipped(report, skipped = []) ⇒ Object

Process any targets that were skipped by the validator and add the events to the validation report

Parameters:

  • report (PDK::Report)

    The report to add the events to

  • skipped (Array[String]) (defaults to: [])

    The list of skipped targets



147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/pdk/validate/invokable_validator.rb', line 147

def process_skipped(report, skipped = [])
  skipped.each do |skipped_target|
    PDK.logger.debug(format('%{validator}: Skipped \'%{target}\'. Target does not contain any files to validate (%{pattern}).', validator: name, target: skipped_target, pattern: pattern))
    report.add_event(
      file: skipped_target,
      source: name,
      message: format('Target does not contain any files to validate (%{pattern}).', pattern: pattern),
      severity: :info,
      state: :skipped
    )
  end
end

#spinnerObject

See Also:

  • Validator.spinner


135
136
137
138
139
140
141
142
# File 'lib/pdk/validate/invokable_validator.rb', line 135

def spinner
  return nil unless spinners_enabled?
  return @spinner unless @spinner.nil?

  require 'pdk/cli/util/spinner'

  @spinner = TTY::Spinner.new("[:spinner] #{spinner_text}", PDK::CLI::Util.spinner_opts_for_platform)
end

#spinner_textObject

This method is abstract.

See Also:

  • Validator.spinner_text


130
131
132
# File 'lib/pdk/validate/invokable_validator.rb', line 130

def spinner_text
  format('Running %{name} validator ...', name: name)
end

#valid_in_context?Boolean

Whether this Validator can be invoked in this context. By default any InvokableValidator can work in any Context, except ::None

Returns:

  • (Boolean)

See Also:



24
25
26
# File 'lib/pdk/validate/invokable_validator.rb', line 24

def valid_in_context?
  !context.is_a?(PDK::Context::None)
end