inherit_from:
  - .rubocop_todo.yml
  - .rubocop_new.yml

# ----- CONFIGURED -----

AllCops:
  TargetRubyVersion: 3.2

plugins:
  - rubocop-minitest
  - rubocop-rake
  - rubocop-rspec

# We use filenames such as “create-site.rb” that translate to method names.
Naming/FileName:
  Exclude:
    - "nanoc/lib/nanoc/orig_cli/commands/*.rb"
    - "nanoc-cli/lib/nanoc/cli/commands/*.rb"
    - "nanoc-*/lib/nanoc-*.rb"
    - "nanoc-dart-sass/lib/nanoc/dart-sass.rb"
    - "nanoc-org-mode/lib/nanoc/org-mode.rb"
    - "guard-nanoc/lib/guard-nanoc.rb"
    - "*/*.gemspec"

Style/TrailingCommaInArguments:
  EnforcedStyleForMultiline: comma

Style/TrailingCommaInArrayLiteral:
  EnforcedStyleForMultiline: comma

Style/TrailingCommaInHashLiteral:
  EnforcedStyleForMultiline: comma

Layout/FirstArrayElementIndentation:
  EnforcedStyle: consistent

# Having the leading underscore makes it clear that the instance variable is not
# intended to be used directly.
Naming/MemoizedInstanceVariableName:
  EnforcedStyleForLeadingUnderscores: required

Naming/MethodParameterName:
  AllowedNames:
    - "to" # destination
    - "e" # element
    - "fn" # filename
    - "id" # identifier
    - "io" # IO instance
    - "y" # enumerator yielder

# Some specs deal with things that aren’t classes.
RSpec/DescribeClass:
  Exclude:
    - "*/spec/gem_spec.rb"
    - "*/spec/manifest_spec.rb"
    - "*/spec/meta_spec.rb"
    - "nanoc/spec/contributors_spec.rb"
    - "nanoc/spec/nanoc/integration/*_spec.rb"
    - "nanoc/spec/nanoc/regressions/*_spec.rb"
    - "nanoc/spec/regression_filenames_spec.rb"

# ----- CONFIGURED (enabled non-default cops) -----

Layout/ClassStructure:
  Enabled: true
  Include:
    - "nanoc-core/**/*.rb"

Lint/RaiseException:
  Enabled: true

Lint/StructNewOverride:
  Enabled: true

Style/AccessorGrouping:
  Enabled: true
  EnforcedStyle: separated

Style/HashEachMethods:
  Enabled: true

Style/HashTransformKeys:
  Enabled: true

Style/HashTransformValues:
  Enabled: true

# ----- CONFIGURED (exceptions for tests) -----

# This breaks RSpec on occasion, e.g. `expect { subject }.not_to change { foo }`,
# and generally does not provide useful warnings
Lint/AmbiguousBlockAssociation:
  Exclude:
    - "*/spec/**/*.rb"

# `rescue nil` is useful in specs where the exception is not important, but
# the size effects are.
Style/RescueModifier:
  Exclude:
    - "*/spec/**/*.rb"

# A common pattern in tests is to define anonymous classes in which methods are defined, which trips
# up Rubocop’s nested method definition cop.
Lint/NestedMethodDefinition:
  Exclude:
    - "*/test/**/*.rb"
    - "*/spec/**/*.rb"

# This is used in tests, to verify the effect of state-changing functions.
Style/GlobalVars:
  Exclude:
    - "*/test/**/*.rb"
    - "*/spec/**/*.rb"

# This interferes with variables named `focus`.
RSpec/Focus:
  Enabled: false

# ----- TO ENABLE LATER -----

# Valid cops, but fixing the offenses they report is non-trivial.

Style/EmptyElse:
  Enabled: false

Style/Next:
  Enabled: false

Naming/HeredocDelimiterNaming:
  Enabled: false

Style/EvalWithLocation:
  Enabled: false

Layout/LineLength:
  Enabled: false

Lint/MixedRegexpCaptureTypes:
  Enabled: false

RSpec/LeakyLocalVariable:
  Enabled: false

# ----- DISABLED (security) -----

# Nanoc runs offline in a trusted environment, and these security checks are false positives.

Security/YAMLLoad:
  Enabled: false

Security/MarshalLoad:
  Enabled: false

Security/Eval:
  Exclude:
    - "*/test/**/*.rb"
    - "*/spec/**/*.rb"
    - "nanoc/lib/nanoc/filters/erubi.rb"

# ----- DISABLED (opinionated) -----

# Cops for metrics are disabled because they should not cause tests to fail.
Metrics:
  Enabled: false

# We should embrace UTF-8, not avoid it. Since the Encoding cop is enabled,
# there’s no point in enforcing ASCII comments.
Style/AsciiComments:
  Enabled: false

# It does not make sense to enforce everything to have documentation.
Style/Documentation:
  Enabled: false

# Nanoc suppresses exceptions for valid reasons in a few cases.
Lint/SuppressedException:
  Enabled: false

# if/unless at the end of the line makes it too easy to oversee.
Style/IfUnlessModifier:
  Enabled: false

# Personal preference is to have decent constructors for exceptions rather than
# just a class and a message.
Style/RaiseArgs:
  Enabled: false

# Some methods that appear to be accessors (return a single value or set a
# single value) should still not be considered to be accessors. This is a purely
# semantic difference.
Style/TrivialAccessors:
  Enabled: false

# This does not always semantically make sense.
Style/GuardClause:
  Enabled: false

# Used for “undo work, whatever error happens”
Style/RescueStandardError:
  Enabled: false

# For the sake of consistency, it makes the most sense to retain $stderr.puts
# when used in situations where $stderr.flush, $stderr.print, … are also used.
Style/StderrPuts:
  Enabled: false

# This catches too many false positives. A string that contains a % followed by
# a letter is not always a format string.
Style/FormatStringToken:
  Enabled: false

# Both {} and [] are considered empty, but it’s still important to check whether
# something is {} rather than [] or vice versa.
Minitest/AssertEmptyLiteral:
  Enabled: false

# This is not directly replaceable with `it_behaves_like`.
RSpec/IncludeExamples: # new in 3.6
  Enabled: false

# ----- DISABLED (buggy) -----

# This cop attempts to replace Nanoc::VERSION with described_class, which makes
# the spec fail.
RSpec/DescribedClass:
  Exclude:
    - "**/version_spec.rb"

# This turns
#
#     expect(File.directory?('output')).to be_falsy
#
# into
#
#     expect(File).not_to be_directory('output')
#
# … which does not look right.
RSpec/PredicateMatcher:
  Exclude:
    - "nanoc-core/spec/nanoc/core/item_rep_writer_spec.rb"

# This yields false positives; a class that responds to #each does not
# necessarily also respond to #map.
Style/MapIntoArray:
  Enabled: false

# This incorrectly identifies some methods that return true/false as being predicate methods.
Naming/PredicateMethod:
  Enabled: false
