# See https://golangci-lint.run/usage/configuration/
# Over time we should try tightening some of these.

linters-settings:
  dupl:
    # goal: 100
    threshold: 412

  exhaustruct:
    include:
      # Gradually extend to cover more of the codebase.
      - 'httpmw\.\w+'
  gocognit:
    min-complexity: 300

  goconst:
    min-len: 4 # Min length of string consts (def 3).
    min-occurrences: 3 # Min number of const occurrences (def 3).

  gocritic:
    enabled-checks:
      # - appendAssign
      # - appendCombine
      - argOrder
      # - assignOp
      # - badCall
      - badCond
      - badLock
      - badRegexp
      - boolExprSimplify
      # - builtinShadow
      - builtinShadowDecl
      - captLocal
      - caseOrder
      - codegenComment
      # - commentedOutCode
      - commentedOutImport
      - commentFormatting
      - defaultCaseOrder
      - deferUnlambda
      # - deprecatedComment
      # - docStub
      - dupArg
      - dupBranchBody
      - dupCase
      - dupImport
      - dupSubExpr
      # - elseif
      - emptyFallthrough
      # - emptyStringTest
      # - equalFold
      # - evalOrder
      # - exitAfterDefer
      # - exposedSyncMutex
      # - filepathJoin
      - flagDeref
      - flagName
      - hexLiteral
      # - httpNoBody
      # - hugeParam
      # - ifElseChain
      # - importShadow
      - indexAlloc
      - initClause
      - mapKey
      - methodExprCall
      # - nestingReduce
      - newDeref
      - nilValReturn
      # - octalLiteral
      - offBy1
      # - paramTypeCombine
      # - preferStringWriter
      # - preferWriteByte
      # - ptrToRefParam
      # - rangeExprCopy
      # - rangeValCopy
      - regexpMust
      - regexpPattern
      # - regexpSimplify
      - ruleguard
      - singleCaseSwitch
      - sloppyLen
      # - sloppyReassign
      - sloppyTypeAssert
      - sortSlice
      - sprintfQuotedString
      - sqlQuery
      # - stringConcatSimplify
      # - stringXbytes
      # - suspiciousSorting
      - switchTrue
      - truncateCmp
      - typeAssertChain
      # - typeDefFirst
      - typeSwitchVar
      # - typeUnparen
      - underef
      # - unlabelStmt
      # - unlambda
      # - unnamedResult
      # - unnecessaryBlock
      # - unnecessaryDefer
      # - unslice
      - valSwap
      - weakCond
      # - whyNoLint
      # - wrapperFunc
      # - yodaStyleExpr
    settings:
      ruleguard:
        failOn: all
        rules: "${configDir}/scripts/rules.go"

  staticcheck:
    # https://staticcheck.io/docs/options#checks
    # We disable SA1019 because it gets angry about our usage of xerrors. We
    # intentionally xerrors because stack frame support didn't make it into the
    # stdlib port.
    checks: ["all", "-SA1019"]

  goimports:
    local-prefixes: coder.com,cdr.dev,go.coder.com,github.com/cdr,github.com/coder

  importas:
    no-unaliased: true

  misspell:
    locale: US
    ignore-words:
      - trialer

  nestif:
    min-complexity: 4 # Min complexity of if statements (def 5, goal 4)

  revive:
    # see https://github.com/mgechev/revive#available-rules for details.
    ignore-generated-header: true
    severity: warning
    rules:
      - name: atomic
      - name: bare-return
      - name: blank-imports
      - name: bool-literal-in-expr
      - name: call-to-gc
      - name: confusing-naming
      - name: confusing-results
      - name: constant-logical-expr
      - name: context-as-argument
      - name: context-keys-type
      - name: deep-exit
      - name: defer
      - name: dot-imports
      - name: duplicated-imports
      - name: early-return
      - name: empty-block
      - name: empty-lines
      - name: error-naming
      - name: error-return
      - name: error-strings
      - name: errorf
      - name: exported
      - name: flag-parameter
      - name: get-return
      - name: identical-branches
      - name: if-return
      - name: import-shadowing
      - name: increment-decrement
      - name: indent-error-flow
      # - name: modifies-parameter
      - name: modifies-value-receiver
      - name: package-comments
      - name: range
      - name: range-val-address
      - name: range-val-in-closure
      - name: receiver-naming
      - name: redefines-builtin-id
      - name: string-of-int
      - name: struct-tag
      - name: superfluous-else
      - name: time-naming
      - name: unconditional-recursion
      - name: unexported-naming
      - name: unexported-return
      - name: unhandled-error
      - name: unnecessary-stmt
      - name: unreachable-code
      - name: unused-parameter
      - name: unused-receiver
      - name: var-declaration
      - name: var-naming
      - name: waitgroup-by-value

issues:
  # Rules listed here: https://github.com/securego/gosec#available-rules
  exclude-rules:
    - path: _test\.go
      linters:
        # We use assertions rather than explicitly checking errors in tests
        - errcheck
        - forcetypeassert
        - exhaustruct # This is unhelpful in tests.
    - path: scripts/*
      linters:
        - exhaustruct

  fix: true
  max-issues-per-linter: 0
  max-same-issues: 0

run:
  skip-dirs:
    - node_modules
    - .git
  skip-files:
    - scripts/rules.go
  timeout: 10m

# Over time, add more and more linters from
# https://golangci-lint.run/usage/linters/ as the code improves.
linters:
  disable-all: true
  enable:
    - asciicheck
    - bidichk
    - bodyclose
    - dogsled
    - errcheck
    - errname
    - errorlint
    - exhaustruct
    - exportloopref
    - forcetypeassert
    - gocritic
    # gocyclo is may be useful in the future when we start caring
    # about testing complexity, but for the time being we should
    # create a good culture around cognitive complexity.
    # - gocyclo
    - gocognit
    - goimports
    - gomodguard
    - gosec
    - gosimple
    - govet
    - importas
    - ineffassign
    - makezero
    - misspell
    - nilnil
    - noctx
    - paralleltest
    - revive

    # These don't work until the following issue is solved.
    # https://github.com/golangci/golangci-lint/issues/2649
    # - rowserrcheck
    # - sqlclosecheck
    # - structcheck
    # - wastedassign

    - staticcheck
    - tenv
    # In Go, it's possible for a package to test it's internal functionality
    # without testing any exported functions. This is enabled to promote
    # decomposing a package before testing it's internals. A function caller
    # should be able to test most of the functionality from exported functions.
    #
    # There are edge-cases to this rule, but they should be carefully considered
    # to avoid structural inconsistency.
    - testpackage
    - tparallel
    - typecheck
    - unconvert
    - unused
    - dupl
