Class: Reviewer::Arguments::Keywords

Inherits:
Object
  • Object
show all
Defined in:
lib/reviewer/arguments/keywords.rb

Overview

Handles interpreting all 'leftover' arguments and translating them to file-related, tag-related, or tool-related arguments

Constant Summary collapse

FOR_FILES =

Keywords that resolve to a list of files. Arguments::Files implements one method per entry, so a keyword here without a matching method silently contributes nothing.

%w[staged unstaged modified untracked].freeze
FOR_TOOLS =

Keywords that select tools rather than files. failed reads last_status from history via Tools#failed_from_history; the per-tool file scope comes from Command#stored_failed_files.

%w[failed].freeze
RESERVED =
(FOR_FILES + FOR_TOOLS).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*provided, tools: nil) ⇒ self

Generates an instance of parsed keywords from the provided arguments



35
36
37
38
# File 'lib/reviewer/arguments/keywords.rb', line 35

def initialize(*provided, tools: nil)
  @provided = Array(provided.flatten)
  @tools = tools
end

Instance Attribute Details

#providedArray<String> Also known as: raw



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
113
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
# File 'lib/reviewer/arguments/keywords.rb', line 10

class Keywords
  # Keywords that resolve to a list of files. `Arguments::Files` implements one method per
  # entry, so a keyword here without a matching method silently contributes nothing.
  FOR_FILES = %w[staged unstaged modified untracked].freeze

  # Keywords that select tools rather than files. `failed` reads `last_status` from history via
  # `Tools#failed_from_history`; the per-tool file scope comes from `Command#stored_failed_files`.
  FOR_TOOLS = %w[failed].freeze

  RESERVED = (FOR_FILES + FOR_TOOLS).freeze

  attr_reader :provided

  # Sets the tools collection after initialization when tools become available
  # @param value [Tools] the configured tools collection
  # @return [Tools] the tools collection
  attr_writer :tools

  alias raw provided

  # Generates an instance of parsed keywords from the provided arguments
  # @param provided [Array<String>] the leftover (non-flag) arguments from the command line
  # @param tools [Tools] the collection of configured tools for keyword recognition
  #
  # @return [self]
  def initialize(*provided, tools: nil)
    @provided = Array(provided.flatten)
    @tools = tools
  end

  # Provides the full list of raw keyword arguments explicitly passed via command-line as an array
  #
  # @return [Array<String>] full collection of the provided keyword arguments
  def to_a = provided

  # Provides the full list of raw keyword arguments explicitly passed via command-line as a
  #   comma-separated string
  #
  # @return [String] comma-separated list of the keyword arguments as a string
  def to_s = to_a.join(',')

  # Summary of the state of keyword arguments based on how Reviewer parsed them
  #
  # @return [Hash] represents the summary of the keyword values parsed from the command-line and
  #   grouped based on how they were parsed
  def to_h
    {
      provided: provided,
      recognized: recognized,
      unrecognized: unrecognized,
      reserved: reserved,
      for_tags: for_tags,
      for_tool_names: for_tool_names
    }
  end
  alias inspect to_h

  # Whether the `failed` keyword was provided
  #
  # @return [Boolean] true if the `failed` keyword is present
  def failed? = provided.include?('failed')

  # Extracts reserved keywords from the provided arguments
  #
  # @return [Array<String>] intersection of provided arguments and reserved keywords
  def reserved = intersection_with(RESERVED)

  # Extracts only the reserved keywords that resolve to files. Passing the full reserved set to
  # `Arguments::Files` made `failed` look like a file keyword that matched nothing, which reads
  # as "you scoped to files and there are none" and skips the run entirely.
  #
  # @return [Array<String>] intersection of provided arguments and file-resolving keywords
  def for_files = intersection_with(FOR_FILES)

  # Extracts keywords that match configured tags for enabled tools
  #
  # @return [Array<String>] intersection of provided arguments and configured tags for tools
  def for_tags = intersection_with(configured_tags)

  # Extracts keywords that match configured tool keys
  #
  # @return [Array<String>] intersection of provided arguments and configured tool names
  def for_tool_names = intersection_with(configured_tool_names)

  # Extracts keywords that match any possible recognized keyword values
  #
  # @return [Array<String>] intersection of provided arguments and recognizable keywords
  def recognized = intersection_with(possible)

  # Extracts keywords that don't match any possible recognized keyword values
  #
  # @return [Array<String>] leftover keywords that weren't recognized
  def unrecognized = (provided - recognized).uniq.sort

  # Provides the complete list of all recognized keywords based on configuration
  #
  # @return [Array<String>] all keywords that Reviewer can recognize
  def possible = (RESERVED + configured_tags + configured_tool_names).uniq.sort

  # Provides the complete list of all configured tags, including tags carried only by
  # tools excluded from the batch -- naming one explicitly is a valid way to select it
  #
  # @return [Array<String>] all unique configured tags
  def configured_tags
    return [] unless tools

    tools.all.map(&:tags).flatten.uniq.sort
  end

  # Provides the complete list of all configured tool names for enabled tools
  #
  # @return [Array<String>] all unique configured tools
  def configured_tool_names
    return [] unless tools

    # We explicitly don't sort the tool names list because Reviewer uses the configuration order
    # to determine the execution order. So not sorting maintains the predicted order it will run
    # in and leaves the option to sort to the consuming code if needed
    tools.all.map { |tool| tool.key.to_s }
  end

  private

  attr_reader :tools

  # Syntactic sugar for finding intersections with valid keywords
  # @param values [Array<String>] the collection to use for finding intersecting values
  #
  # @return [Array<String>] the list of intersecting values
  def intersection_with(values) = (values & provided).uniq.sort
end

#tools=(value) ⇒ Tools

Sets the tools collection after initialization when tools become available



26
27
28
# File 'lib/reviewer/arguments/keywords.rb', line 26

def tools=(value)
  @tools = value
end

Instance Method Details

#configured_tagsArray<String>

Provides the complete list of all configured tags, including tags carried only by tools excluded from the batch -- naming one explicitly is a valid way to select it



113
114
115
116
117
# File 'lib/reviewer/arguments/keywords.rb', line 113

def configured_tags
  return [] unless tools

  tools.all.map(&:tags).flatten.uniq.sort
end

#configured_tool_namesArray<String>

Provides the complete list of all configured tool names for enabled tools



122
123
124
125
126
127
128
129
# File 'lib/reviewer/arguments/keywords.rb', line 122

def configured_tool_names
  return [] unless tools

  # We explicitly don't sort the tool names list because Reviewer uses the configuration order
  # to determine the execution order. So not sorting maintains the predicted order it will run
  # in and leaves the option to sort to the consuming code if needed
  tools.all.map { |tool| tool.key.to_s }
end

#failed?Boolean

Whether the failed keyword was provided



70
# File 'lib/reviewer/arguments/keywords.rb', line 70

def failed? = provided.include?('failed')

#for_filesArray<String>

Extracts only the reserved keywords that resolve to files. Passing the full reserved set to Arguments::Files made failed look like a file keyword that matched nothing, which reads as "you scoped to files and there are none" and skips the run entirely.



82
# File 'lib/reviewer/arguments/keywords.rb', line 82

def for_files = intersection_with(FOR_FILES)

#for_tagsArray<String>

Extracts keywords that match configured tags for enabled tools



87
# File 'lib/reviewer/arguments/keywords.rb', line 87

def for_tags = intersection_with(configured_tags)

#for_tool_namesArray<String>

Extracts keywords that match configured tool keys



92
# File 'lib/reviewer/arguments/keywords.rb', line 92

def for_tool_names = intersection_with(configured_tool_names)

#possibleArray<String>

Provides the complete list of all recognized keywords based on configuration



107
# File 'lib/reviewer/arguments/keywords.rb', line 107

def possible = (RESERVED + configured_tags + configured_tool_names).uniq.sort

#recognizedArray<String>

Extracts keywords that match any possible recognized keyword values



97
# File 'lib/reviewer/arguments/keywords.rb', line 97

def recognized = intersection_with(possible)

#reservedArray<String>

Extracts reserved keywords from the provided arguments



75
# File 'lib/reviewer/arguments/keywords.rb', line 75

def reserved = intersection_with(RESERVED)

#to_aArray<String>

Provides the full list of raw keyword arguments explicitly passed via command-line as an array



43
# File 'lib/reviewer/arguments/keywords.rb', line 43

def to_a = provided

#to_hHash Also known as: inspect

Summary of the state of keyword arguments based on how Reviewer parsed them



55
56
57
58
59
60
61
62
63
64
# File 'lib/reviewer/arguments/keywords.rb', line 55

def to_h
  {
    provided: provided,
    recognized: recognized,
    unrecognized: unrecognized,
    reserved: reserved,
    for_tags: for_tags,
    for_tool_names: for_tool_names
  }
end

#to_sString

Provides the full list of raw keyword arguments explicitly passed via command-line as a comma-separated string



49
# File 'lib/reviewer/arguments/keywords.rb', line 49

def to_s = to_a.join(',')

#unrecognizedArray<String>

Extracts keywords that don't match any possible recognized keyword values



102
# File 'lib/reviewer/arguments/keywords.rb', line 102

def unrecognized = (provided - recognized).uniq.sort