Пакет analysis описывает интерфейс между модульным статическим анализом и программой-драйвером. Модульный анализ смотрит на один пакет, но умеет сохранять факты из низлежащих пакетов, чтобы использовать их при проверке вышестоящих — как раздельная компиляция в toolchain. Например, printf-чекер видит, что log.Fatalf делегирует вызов fmt.Printf, запоминает это и затем проверяет вызовы log.Fatalf в других пакетах.
Главный тип — Analyzer. Разработчик объявляет переменную с именем, докой, флагами и функцией Run. Драйвер (будь то vet, go build, IDE, Bazel, Buck, SourceGraph, godoc или батч-пайплайн) импортирует нужные анализаторы списком. Поле Flags описывает настройки: драйвер сам решает, как их пробрасывать — через -флаг для одиночной команды, -анализатор.флаг в наборе или через графический интерфейс. Флаг RunDespiteErrors разрешает запуск даже при ошибках парсинга или типов. Если анализатор порождает результат для других, он указывает ResultType, а зависимости перечисляет в Requires. Драйвер выполняет их в правильном порядке и складывает результаты в ResultOf.
Одна единица работы — это Pass: запуск конкретного Analyzer на конкретном пакете. Он передаёт в Run синтаксические деревья (ast.File), типовую информацию (types.Info), а также имена не-Go-файлов в OtherFiles и игнорируемых файлов в IgnoredFiles. Основной способ отдать диагностику — метод Report (и его обёртка Reportf). Диагностика — структура Diagnostic с позицией, опциональной категорией и сообщением. Серьёзность не зашита внутрь: подразумевается, что драйвер даст пользователю настроить фильтрацию и приоритеты по имени анализатора и категории.
Модульность построена на Fact. Анализатор заявляет свои типы фактов в FactTypes. Например, printf-чекер экспортирует факт isWrapper для функций-обёрток fmt.Printf. Факты сериализуются через gob, поэтому должны быть детерминированными, иначе сломаются контентно-адресуемые кеши сборочных систем. Экспорт и импорт делаются через ExportObjectFact, ImportObjectFact, ExportPackageFact и ImportPackageFact; импортировать можно факты только из прямых зависимостей. Драйверы на базе Bazel и Blaze сейчас не гоняют анализаторы по стандартной библиотеке, так что авторам чекеров советуют не рассчитывать на факты из неё.
Для тестирования анализаторов есть пакет analysistest. Он прогоняет анализатор по тестовым файлам и сверяет выданные диагностики с // want ...-комментариями в коде. Чтобы быстро собрать отдельную утилиту, используют singlechecker (для одного анализатора) или multichecker (для набора).