NilAway Documentation

repository·main·Indexed 26 days ago

https://github.com/uber-go/nilaway

NilAway is a static analysis tool for Go designed to detect potential nil pointer panics. It can be used as a standalone checker, integrated into golangci-lint as a module plugin, or used within Bazel/nogo. The tool features a multi-analyzer architecture including an inference engine and facts mechanism to track nil flows across packages.

Tokens
3.3K
Snippets
11
Records
20
Agent score
86%

What's inside NilAway

  1. NilAway Architecture Overview

    main

    NilAway is composed of multiple sub-analyzers that implement the analysis.Analyzer interface. These analyzers are connected via dependencies (using the Requires field).

    Core Components:

    • Triggers: Flow conditions that may cause nil panics.
    • Annotations: Metadata about nilability of types and functions.
    • Inference Engine: Matches triggers with annotations to detect nil flows.
    • Facts Mechanism: Caches analysis results across packages for performance.

    Analyzer Hierarchy:

    • nilaway.Analyzer: The top-level analyzer that reports errors.
      • accumulation.Analyzer: Collects triggers and runs inference.
        • annotation.Analyzer: Reads annotations.
        • function.Analyzer: Analyzes functions and creates triggers.
        • affiliation.Analyzer: Creates interface-struct affiliation triggers.
        • global.Analyzer: Creates global variable triggers

    All analyzers depend on config.Analyzer to retrieve configurations.

  2. Integrate NilAway with Bazel/nogo

    main

    Configuring NilAway for Bazel/nogo requires configuring two separate analyzers in your nogo config.json file:

    1. nilaway_config: Use this to pass NilAway's functional flags (like include-pkgs or exclude-pkgs) via the analyzer_flags key.
    2. nilaway: Use this to handle error suppressions (like exclude_files or only_files).

    This distinction exists because NilAway uses a multi-analyzer architecture where flags must be captured by a configuration analyzer before being used by sub-analyzers.

    {
      "nilaway_config": {
        "analyzer_flags": {
          "include-pkgs": "go.uber.org",
          "exclude-pkgs": "vendor/",
          "exclude-file-docstrings": "@generated,Code generated by,Autogenerated by"
        }
      },
      "nilaway": {
        "exclude_files": {
          "bazel-out": "this prevents nilaway from outputting diagnostics on intermediate test files"
        },
        "only_files": {
          "my/code/path": "This is the comment for why we want to enable NilAway on this code path"
        }
      }
    }
  3. Run NilAway linting

    main

    To check code quality and formatting, use the following commands. If you need to apply auto-fixes, pass the FIX=true environment variable.

    • make lint: Runs all linting (format check, mod tidy, golangci-lint, and nilaway self-check).
    • make lint-fix: Runs all linting with autofix and auto-formatting applied.

    Individual components:

    • make format-lint: Checks Go file formatting.
    • make tidy-lint: Checks go.mod tidiness.
    • make golangci-lint: Runs golangci-lint only.
    • make nilaway-lint: Runs NilAway on itself.
    make lint                    # Run all linting (format check, mod tidy, golangci-lint, nilaway self-check)
    make lint-fix                # Run all linting with autofix (and auto-formats) applied
  4. Integrate NilAway with golangci-lint

    main

    To use NilAway within golangci-lint, add it to the linters-settings.custom section of your .golangci.yaml file.

    Important: Settings must be provided as a "map from string to string" to mimic command line flags. The keys are the flag names and the values are the flag values.

    linters-settings:
      custom:
        nilaway:
          type: "module"
          description: Static analysis tool to detect potential nil panics in Go code.
          settings:
            # Settings must be a "map from string to string"
            include-pkgs: "<YOUR_PACKAGE_PREFIXES>"
  5. Run NilAway golden tests

    main

    Golden tests run NilAway on a base branch (usually main) and a test branch (usually HEAD) on the standard library, comparing the differences in NilAway violations. This is primarily used in CI to detect unexpected breakages.

    Arguments are passed via the ARGS environment variable.

    # The arguments are passed as an environment variable `ARGS`.
    # Use `make golden-test ARGS="-h" to see the available arguments.
    make golden-test ARGS="-base-branch main -test-branch HEAD -result-file /tmp/result.txt"
  6. Run NilAway tests

    main

    Use the following commands to run different types of tests for the NilAway project:

    • Unit tests: Run unit tests for all modules.
    • Coverage: Run tests with coverage reports.
    • Integration tests: Run integration tests using real drivers.
    make test                     # Run unit tests for all modules
    make cover                    # Run tests with coverage reports
    make integration-test         # Run integration tests (using real drivers)
  7. Integrate NilAway as a golangci-lint module plugin

    main

    NilAway can be used as a private linter within golangci-lint by implementing the module plugin interface. The gclplugin package provides the necessary implementation to register NilAway as a plugin named nilaway.

    To use this plugin, ensure your configuration settings are provided as a map[string]any where all values are strings, mimicking command-line flags. The plugin will then map these settings to NilAway's internal configuration flags.

  8. Use NilAway with golangci-lint

    main

    You can use a custom build of golangci-lint that includes the NilAway plugin. First, build the custom binary, then run it against your code.

    golangci-lint custom         # Build custom binary with NilAway plugin
    ./custom-gcl run ./...       # Run custom golangci-lint with NilAway