run:
  skip-dirs-use-default: false
linters-settings:
  errcheck:
    check-type-assertions: true
  exhaustruct:
    include:
      # No zero values for param structs.
      - 'github\.com/bufbuild/connect-go\..*[pP]arams'
      # No zero values for ClientStream, ServerStream, and friends.
      - 'github\.com/bufbuild/connect-go\.ClientStream.*'
      - 'github\.com/bufbuild/connect-go\.ServerStream.*'
      - 'github\.com/bufbuild/connect-go\.BidiStream.*'
  forbidigo:
    forbid:
      - '^fmt\.Print'
      - '^log\.'
      - '^print$'
      - '^println$'
      - '^panic$'
  godox:
    # TODO, OPT, etc. comments are fine to commit. Use FIXME comments for
    # temporary hacks, and use godox to prevent committing them.
    keywords: [FIXME]
  varnamelen:
    ignore-decls:
      - T any
      - i int
      - wg sync.WaitGroup
linters:
  enable-all: true
  disable:
    - cyclop            # covered by gocyclo
    - deadcode          # abandoned
    - exhaustivestruct  # replaced by exhaustruct
    - funlen            # rely on code review to limit function length
    - gocognit          # dubious "cognitive overhead" quantification
    - gofumpt           # prefer standard gofmt
    - goimports         # rely on gci instead
    - golint            # deprecated by Go team
    - gomnd             # some unnamed constants are okay
    - ifshort           # deprecated by author
    - interfacer        # deprecated by author
    - ireturn           # "accept interfaces, return structs" isn't ironclad
    - lll               # don't want hard limits for line length
    - maintidx          # covered by gocyclo
    - maligned          # readability trumps efficient struct packing
    - nlreturn          # generous whitespace violates house style
    - nosnakecase       # deprecated in https://github.com/golangci/golangci-lint/pull/3065
    - scopelint         # deprecated by author
    - structcheck       # abandoned
    - testpackage       # internal tests are fine
    - varcheck          # abandoned
    - wrapcheck         # don't _always_ need to wrap errors
    - wsl               # generous whitespace violates house style
issues:
  exclude:
    # Don't ban use of fmt.Errorf to create new errors, but the remaining
    # checks from err113 are useful.
    - "err113: do not define dynamic errors.*"

  exclude-rules:
    # If future reflect.Kinds are nil-able, we'll find out when a test fails.
    - linters: [exhaustive]
      path: internal/assert/assert.go
    # We need our duplex HTTP call to have access to the context.
    - linters: [containedctx]
      path: duplex_http_call.go
    # We need to init a global in-mem HTTP server for testable examples.
    - linters: [gochecknoinits, gochecknoglobals]
      path: example_init_test.go
    # We need to initialize a global map from a slice.
    - linters: [gochecknoinits, gochecknoglobals]
      path: protocol_grpc.go
    # We purposefully do an ineffectual assignment for an example.
    - linters: [ineffassign]
      path: client_example_test.go
    # The generated file is effectively a global receiver.
    - linters: [varnamelen]
      path: cmd/protoc-gen-connect-go
      text: "parameter name 'g' is too short"
    # Thorough error logging and timeout config make this example unreadably long.
    - linters: [errcheck, gosec]
      path: error_writer_example_test.go
    # It should be crystal clear that Connect uses plain *http.Clients.
    - linters: [revive, stylecheck]
      path: client_example_test.go
    # Don't complain about timeout management or lack of output assertions in examples.
    - linters: [gosec, testableexamples]
      path: handler_example_test.go
    # No output assertions needed for these examples.
    - linters: [testableexamples]
      path: error_writer_example_test.go
