Правила подавления (Suppression)¶
Правила этой группы сообщают о конфигурации подавлений самого прогона, а не о коде, который он проанализировал. Значение suppress_paths или suppress_namespaces, не назвавшее ничего, ничего не прячет и не спрячет, тогда как автор считает, что прячет.
Конфигурация подавлений¶
Rule ID: suppression.configuration
Под самим именем suppression.configuration не сообщается ничего — оно существует для того, чтобы у каналов ниже был один владелец, которого можно выключить и настроить целиком. У каждого канала своё имя и свой смысл.
Что измеряется¶
Каждое значение подавления, полученное прогоном, — глобальное или под rules.<имя> — сверяется с тем, что прогон действительно увидел: suppress_paths с проанализированными файлами, suppress_namespaces с объявленными неймспейсами. Значение, не совпавшее ни с чем, сообщается.
Почему это важно¶
Это другой ноль, не тот, что уже показывает --format=suppressed. Список neverMatched в том отчёте строится из удалённых находок и отвечает «этот суппрессор ничего не удалил» — до такого состояния доходит и честное подавление, чей долг выплачен, и правильный ответ на него — порадоваться и удалить запись. Каналы здесь отвечают «этот суппрессор ничего не назвал», и никакой ремонт кода к этому не приводит. Приводит только опечатка, переименование или перенос.
Два вопроса выглядят в отчёте одинаково и ведут к противоположным действиям — поэтому отвечают на них раздельно.
Область и severity¶
Все каналы сообщаются на уровне проекта, severity warning.
Они судятся только на прогоне, чьи пути покрывают всё, что composer.json проекта объявляет production-кодом, — корни psr-4 и psr-0, записи classmap и files наравне. На более узком прогоне значение не привязывается просто потому, что названный им код лежит вне среза, — это выбор вызывающего, а не ошибка автора; на проекте, чей манифест не объявляет production-автозагрузки вовсе (нет composer.json, он не парсится, в нём нет production-секции), знаменателя нет, и каналы молчат.
Дальше каждое значение судится отдельно — по месту, которое оно называет. suppress_paths: [tests/Legacy] указывает в tests/, куда qmx check src/ не заглядывал, поэтому на таком прогоне запись не судится, а suppress_paths: [src/Legacy] на том же прогоне — судится. Значение-неймспейс размещается по карте PSR-4, включая autoload-dev: Acme\Tests\Legacy живёт в tests/ и судится только прогоном, который его проанализировал. Значение, начинающееся с glob-символа (*Legacy.php), не называет одного места и не судится никогда.
В генерируемый baseline они не попадают: baseline:generate измеряет находки другим швом, и предупреждение о собственной конфигурации автора не должно становиться принятым долгом в файле, который автор генерирует одной командой.
Если значение корректно и исправить его нельзя — общий для нескольких репозиториев qmx.yaml, называющий путь, которого в одном из них нет, — есть два выхода, и они не одно и то же:
- Выключить канал там, где живёт эта общая конфигурация:
disabled_rules: ['suppression.unmatched-path']гасит ровно один канал, два других продолжают говорить.--disable-ruleделает то же для одного прогона. - Принять находку в baseline, написанный вручную. Записанная вручную запись под
project:, называющая канал иoccurrenceнаходки, учитывается как любая другая. Поскольку значение входит в этотoccurrence, принятие относится именно к этому значению: замена его другим непривязанным будет показана, а не пройдёт под принятой записью.
Каналы¶
| Канал | Что обнаруживает |
|---|---|
suppression.unmatched-path |
Глобальное значение suppress_paths, не совпавшее ни с одним файлом |
suppression.unmatched-namespace |
Глобальное suppress_namespaces, не совпавшее ни с одним неймспейсом |
suppression.unmatched-rule-ledger |
То же для значения, заданного под rules.<имя>, включая suppress_namespace_channels — оно называется вместе с селектором, под которым написано |
Канал реестра правила отделён потому, что у ошибки, которую он ловит, своя форма: подавление на правило пишется рядом с тем правилом, которому принадлежит, и значение, пережившее свой предмет, ещё долго читается в контексте как осмысленное.
Пример¶
[project] suppression.unmatched-namespace
The suppress_namespaces pattern "App\Legacy\Importer" matched no namespace
declared in this run, so it suppressed nothing and could not have. If the
code it was written for still exists under another spelling, its findings
are being reported.
Опции¶
| Опция | По умолчанию | Описание |
|---|---|---|
enabled |
true |
Включает или выключает правило и все его каналы |