Skip to content

Commit 5dd5e0c

Browse files
committed
fix: fix Rubocop Metrics/PerceivedComplexity offense
1 parent 1da8c28 commit 5dd5e0c

File tree

4 files changed

+499
-299
lines changed

4 files changed

+499
-299
lines changed

.rubocop_todo.yml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,22 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2025-07-05 15:13:23 UTC using RuboCop version 1.77.0.
3+
# on 2025-07-06 05:52:16 UTC using RuboCop version 1.77.0.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
77
# versions of RuboCop, may require this file to be generated again.
88

9-
# Offense count: 56
9+
# Offense count: 50
1010
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
1111
Metrics/AbcSize:
1212
Max: 109
1313

1414
# Offense count: 21
1515
# Configuration parameters: CountComments, CountAsOne.
1616
Metrics/ClassLength:
17-
Max: 976
17+
Max: 1032
1818

19-
# Offense count: 9
19+
# Offense count: 2
2020
# Configuration parameters: AllowedMethods, AllowedPatterns.
2121
Metrics/CyclomaticComplexity:
22-
Max: 14
23-
24-
# Offense count: 7
25-
# Configuration parameters: AllowedMethods, AllowedPatterns.
26-
Metrics/PerceivedComplexity:
27-
Max: 14
22+
Max: 8

lib/git/args_builder.rb

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# frozen_string_literal: true
2+
3+
module Git
4+
# Takes a hash of user options and a declarative map and produces
5+
# an array of command-line arguments. Also validates that only
6+
# supported options are provided based on the map.
7+
#
8+
# @api private
9+
class ArgsBuilder
10+
# This hash maps an option type to a lambda that knows how to build the
11+
# corresponding command-line argument. This is a scalable dispatch table.
12+
ARG_BUILDERS = {
13+
boolean: ->(config, value) { value ? config[:flag] : [] },
14+
15+
valued_equals: ->(config, value) { "#{config[:flag]}=#{value}" if value },
16+
17+
valued_space: ->(config, value) { [config[:flag], value.to_s] if value },
18+
19+
repeatable_valued_space: lambda do |config, value|
20+
Array(value).flat_map { |v| [config[:flag], v.to_s] }
21+
end,
22+
23+
custom: ->(config, value) { config[:builder].call(value) },
24+
25+
validate_only: ->(_config, _value) { [] } # Does not build any args
26+
}.freeze
27+
28+
# Main entrypoint to validate options and build arguments
29+
def self.build(opts, option_map)
30+
validate!(opts, option_map)
31+
new(opts, option_map).build
32+
end
33+
34+
# Public validation method that can be called independently
35+
def self.validate!(opts, option_map)
36+
validate_unsupported_keys!(opts, option_map)
37+
validate_configured_options!(opts, option_map)
38+
end
39+
40+
def initialize(opts, option_map)
41+
@opts = opts
42+
@option_map = option_map
43+
end
44+
45+
def build
46+
@option_map.flat_map do |config|
47+
type = config[:type]
48+
next config[:flag] if type == :static
49+
50+
key = config[:keys].find { |k| @opts.key?(k) }
51+
next [] unless key
52+
53+
build_arg_for_option(config, @opts[key])
54+
end.compact
55+
end
56+
57+
private
58+
59+
def build_arg_for_option(config, value)
60+
builder = ARG_BUILDERS[config[:type]]
61+
builder&.call(config, value) || []
62+
end
63+
64+
private_class_method def self.validate_unsupported_keys!(opts, option_map)
65+
all_valid_keys = option_map.flat_map { |config| config[:keys] }.compact
66+
unsupported_keys = opts.keys - all_valid_keys
67+
68+
return if unsupported_keys.empty?
69+
70+
raise ArgumentError, "Unsupported options: #{unsupported_keys.map(&:inspect).join(', ')}"
71+
end
72+
73+
private_class_method def self.validate_configured_options!(opts, option_map)
74+
option_map.each do |config|
75+
next unless config[:keys] # Skip static flags
76+
77+
check_for_missing_required_option!(opts, config)
78+
validate_option_value!(opts, config)
79+
end
80+
end
81+
82+
private_class_method def self.check_for_missing_required_option!(opts, config)
83+
return unless config[:required]
84+
85+
key_provided = config[:keys].any? { |k| opts.key?(k) }
86+
return if key_provided
87+
88+
raise ArgumentError, "Missing required option: #{config[:keys].first}"
89+
end
90+
91+
private_class_method def self.validate_option_value!(opts, config)
92+
validator = config[:validator]
93+
return unless validator
94+
95+
user_key = config[:keys].find { |k| opts.key?(k) }
96+
return unless user_key # Don't validate if the user didn't provide the option
97+
98+
return if validator.call(opts[user_key])
99+
100+
raise ArgumentError, "Invalid value for option: #{user_key}"
101+
end
102+
end
103+
end

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy