Опции CLI¶
Qualimetrix предоставляет команду check для анализа кода и несколько вспомогательных команд для работы с baseline, git-хуками и визуализацией графа зависимостей.
Команда check¶
Аргумент paths¶
Укажите одну или несколько директорий или файлов для анализа:
# Анализ конкретных директорий
bin/qmx check src/ lib/
# Анализ одного файла
bin/qmx check src/Service/UserService.php
Отсутствующий итоговый путь или явно названный существующий обычный файл
с расширением, отличным от .php, отклоняется с кодом 3 до discovery. Это
действует для путей из CLI, YAML и пресетов в check, directives,
graph:export, debug:layer-assignment и четырёх измеряющих командах baseline.
Каталоги обходятся как обычно; дерево без PHP остаётся отдельным отказом анализа.
Путь, который вы называете и который сам является каталогом vendor, node_modules или .git (bin/qmx check lib/vendor), останавливает прогон ошибкой конфигурации: Qualimetrix никогда не заходит в такой каталог, и прогон не проанализировал бы ничего. Назовите файл или каталог внутри него (bin/qmx check vendor/acme/); каталог vendor внутри названного пути по-прежнему пропускается.
Авторские exclude: и --exclude применяются к названным файлам и каталогам
из CLI, YAML и пресетов. exact: убирает только названную запись, subtree: —
её и потомков. Совпавший написанный корень считается исключённым, а не ошибкой
ввода. Если analyzed=0, failed=0 и excluded + generatedExcluded > 0, результат
намеренно пуст: check и directives возвращают 0, graph:export пишет пустой
граф, а baseline:generate — пустой baseline. Объяснение остаётся на stderr
и в поддерживающих его отчётах. Любая неполнота имеет приоритет с кодом 4:
диагностический отчёт сохраняется, baseline и авторитетный граф не записываются.
Действительно пустое дерево без найденных или исключённых записей сохраняет
прежние исходы каждой команды.
. и канонически эквивалентные формы корня допустимы. Каталог или directory alias
должен канонически указывать внутрь захваченного корня; внешнее написание alias
на внутренний каталог допустимо, обратное направление отклоняется с кодом 3.
Для файла проверяется канонический родитель, а последнее имя сохраняется буквально,
включая названную ссылку на внешний файл. --working-dir выбирает корень вызова;
публикация пути не использует outside-root fallback.
Если пути не указаны, Qualimetrix автоматически определит их по всем путям, которые объявляет секция autoload вашего composer.json, — корням psr-4 и psr-0, записям classmap (шаблон * раскрывается в подходящие каталоги) и записям files. По этим же путям Qualimetrix судит, охватил ли прогон весь проект, итоговый охват также учитывает отсутствующие PHP-файлы, авторские и generated-исключения и известность состава кода. Запись, которая сама является каталогом vendor, node_modules или .git или лежит внутри него (Qualimetrix туда никогда не заходит), не входит ни туда, ни туда и называется в предупреждении: сторонний код не анализируется как код вашего проекта. Объявленный путь, которого нет на диске, останавливает прогон ошибкой конфигурации. autoload-dev не включается: тестовый код анализируется, только когда его путь назван явно (bin/qmx check src/ tests/ или paths: в qmx.yaml), или когда вы считаете его частью проекта через --include-autoload-dev.
Опции файлов¶
--config, -c¶
Путь к YAML-файлу конфигурации:
Пустое значение — не то же, что опция не указана. --config= — обычно это
--config=$QMX_CONFIG с незаданной переменной — отклоняется с кодом 3, а не откатывается на
qmx.yaml из рабочего каталога. То же для --baseline=, --output=, --report= и
--preset= (включая пустое имя в списке вроде --preset=strict,): чтобы получить значение по
умолчанию, опцию нужно просто не указывать.
Предупреждения о конфигурации, которую команда приняла, — например, only_rules: [],
снимающий фильтр пресета, — каждая команда, читающая конфигурацию, пишет в stderr строками
Warning:, а check --format=json дополнительно несёт их в configurationDiagnostics. См.
Предупреждения о конфигурации.
--exclude¶
Исключить директории из анализа явным селектором пути. Можно указывать несколько раз:
Привязка проверяется каналом
discovery.unmatched-exclude. Полнота PHP-путей
и известность состава кода допускают проверку ещё не привязанных селекторов;
авторские и generated-исключения сами по себе её не закрывают. Привязанный
селектор остаётся Removed и на узком прогоне. Возможное скрытое поддерево
своего источника даёт ограниченное предупреждение, другого источника —
именованный пропуск с предложением повторить прогон без исключения.
Исключённый написанный корень измеряется, а не отклоняется.
См. аргумент paths.
--include-generated¶
По умолчанию Qualimetrix автоматически пропускает файлы, содержащие аннотацию @generated в первых 2 КБ. Этот флаг переопределяет это поведение и включает сгенерированные файлы в анализ:
Также можно задать в qmx.yaml:
--include-autoload-dev¶
Считает код, объявленный в composer.json в секции autoload-dev, частью проекта. Обе половины прогона следуют этому вместе:
- прогон без путей анализирует все пути, которые объявляет
autoload-devв любой форме автозагрузки, рядом с путямиautoload; - когда Qualimetrix проверяет, охватил ли прогон весь проект,
autoload-devтоже входит в проверку — поэтомуbin/qmx check src/ --include-autoload-devпредупреждает, чтоtests/не проанализирован, а каналы, которые говорят только на прогоне по всему проекту, молчат.
Пути, названные вами явно, не расширяются. По умолчанию выключено:
Можно задать и в qmx.yaml:
--suppress-path¶
Подавить нарушения для файлов, выбранных через exact:, subtree: или regex:. Значение CLI делится по первому двоеточию; regex — фрагмент PCRE без разделителей, автоматически привязанный ко всему пути. Файлы по-прежнему анализируются, опцию можно повторять:
Объединяется с suppress_paths из qmx.yaml — оба источника суммируются.
Объявленные project-scoped каналы остаются видимыми
Циклы architecture.circular-dependency и project-scoped diagnostics не подавляются.
Для architecture.layer-violation опция применяется к источнику нарушения; см.
Подавление путей в отчёте.
--suppress-namespace¶
Подавить нарушения для классов, выбранных явным селектором неймспейса. subtree: следует границам неймспейса, а regex: задаёт полнообъектный фрагмент PCRE. Классы по-прежнему анализируются, опцию можно повторять:
bin/qmx check src/ --suppress-namespace='subtree:App\Entity' --suppress-namespace='regex:App\\DTO(?:\\[^\\]+)*'
Объединяется с suppress_namespaces из qmx.yaml — оба источника суммируются.
Объявленные project-scoped каналы остаются видимыми
Циклы architecture.circular-dependency и project-scoped diagnostics не подавляются.
Для architecture.layer-violation опция применяется к источнику нарушения; см.
Подавление неймспейсов.
Опции пресетов¶
--preset¶
Применить именованный пресет или пользовательский YAML-файл. Можно указывать несколько раз или через запятую:
# Встроенные пресеты
bin/qmx check src/ --preset=strict
bin/qmx check src/ --preset=legacy
# Комбинирование пресетов (объединяются слева направо)
bin/qmx check src/ --preset=strict,ci
bin/qmx check src/ --preset=strict --preset=ci
# Пользовательский файл пресета
bin/qmx check src/ --preset=./my-preset.yaml
Доступные встроенные пресеты: strict, legacy, ci.
Пресеты применяются после автоопределения composer.json, но до qmx.yaml, поэтому ваш файл конфигурации всегда имеет приоритет. Подробности смотрите в разделе Конфигурация > Пресеты.
Встроенный пресет можно также импортировать из файла конфигурации — imports: [strict] — тогда он применяется к каждому запуску, читающему файл, включая pre-commit-хук и GitHub Action, ни один из которых не передаёт --preset. Импортированный пресет стоит в полосе файла конфигурации, выше пресетов из --preset. См. Конфигурация > Встроенные пресеты.
Опции вывода¶
--format, -f¶
Выбор формата вывода. По умолчанию: summary.
Доступные форматы: summary, text, json, metrics, checkstyle, sarif, gitlab, github, health, html, suppressed.
Подробности о каждом формате смотрите в разделе Форматы вывода.
--output, -o¶
Записать отчёт в файл вместо stdout:
Названный обычный файл подготавливается после проверки конфигурации, области анализа, селекторов и входного baseline, до анализа. Результат удерживается во временном соседнем файле; новое конечное имя отсутствует, прежние байты сохраняются до полной записи, сброса буферов и проверки идентичности перед атомарной публикацией. Замена сохраняет права и меняет конечный inode; другие жёсткие ссылки сохраняют прежние байты. Родительский каталог должен существовать и разрешать создание и замену, даже если конечный файл уже существует и доступен для записи. Перенеси цель или разреши запись и поиск в родительском каталоге до запуска qmx.
SIGINT/SIGTERM до публикации удаляют собственный временный файл прогона и дают 128 + номер сигнала, когда доступны pcntl и монопольное владение обработчиками. Иначе обычная атомарная публикация выполняется без замены чужих обработчиков, а при прерывании временный сосед может остаться. Замена обработчиков во время защищённой операции не поддерживается. Гарантия уборки также не охватывает SIGKILL, ошибку удаления и уже опубликованные цели. Профиль, уже опубликованный до позднего сбоя отчёта, не откатывается.
Символическая ссылка принимается, только если другой пользователь не может подложить эту запись каталога. Принятая ссылка сохраняется, запись меняет её разрешённую цель; это относится и к висячей ссылке в существующий каталог. Подменяемая ссылка отклоняется на обычном и thread-safe PHP. Возможность изменить другие части пути сообщается в stderr до анализа. Для гонок подмены компонентов, ACL, происхождения жёстких ссылок и нелокальных файловых систем сохраняются ограничения платформы.
Своя ссылка в каталоге 0775 принимается, если группа каталога доказанно является
личной первичной группой эффективного пользователя: в ней нет других первичных
или дополнительных участников. Проверка поддерживает полное перечисление
отдельных NSS-источников files и systemd. Неизвестные источники, явный
initgroups, ошибка перечисления или неподдерживаемая платформа сохраняют
консервативный отказ.
/dev/stdout, /dev/stderr, /dev/fd/N, /proc/self/fd/N,
/proc/thread-self/fd/N, php://stdout, php://stderr и php://fd/N
обращаются к существующему потоку процесса; написания /proc требуют procfs.
file:///absolute/path задаёт
файловый путь. Остальные URI-схемы отклоняются. Именованный канал открывается
после проверок ввода и требует читателя; /dev/null поддерживается.
Существование дескриптора проверяется до анализа. Linux fdinfo также позволяет рано отклонить дескриптор, открытый только для чтения. На macOS PHP не раскрывает его исходный флаг доступа, поэтому неизвестный режим оставляется до настоящей записи и её отказа среды. Запись в дескрипторы и потоки использует блокирующий режим.
Адресаты отчёта, профиля и лога проверяются вместе. Два адресата одного обычного inode или одного отсутствующего имени отклоняются до анализа, как и адресат, совпадающий с входным baseline. Адресат, совпадающий с файлом, который читает прогон, тоже отклоняется до анализа:
- с файлом конфигурации — найденным
qmx.yaml/qmx.yml(илиqmx.dist.yaml/qmx.dist.yml) или файлом--config, каждым импортированным им файлом, каждым файлом пресета; - с
composer.jsonрабочего каталога, объявляет он пути автозагрузки или нет; - с PHP-файлом, который выбирает прогон, — анализируемым или исключённым как сгенерированный.
Файлы сравниваются по идентичности, поэтому другое написание, символическая
или жёсткая ссылка отклоняются так же. Новый файл среди анализируемых
исходников, например --output=src/report.json, записывается. Тому же
правилу следуют graph:export --output и файл baseline, который пишут
baseline:generate, baseline:update и baseline:cleanup. Если отчёт
check или graph:export идёт в stdout, а оболочка открыла stdout на таком
файле (>>, 1<>), прогон тоже отклоняется раньше любого другого адресата, и
отказ выводится только в stderr; при > оболочка опустошает файл ещё до
запуска qmx. Отказ, возникший раньше, пока читаются опции и конфигурация,
как обычно выводится в stdout в запрошенном формате. Выбор исходников
стоит одного дополнительного обхода анализируемых путей без чтения файлов и
выполняется, только когда адресат или перенаправленный stdout — существующий
обычный файл.
Не проверяются: другие файлы Composer, которые читает прогон (composer.json
выше рабочего каталога или рядом с анализируемым пакетом,
vendor/composer/installed.json, классы из vendor), и stdout команд baseline.
Унаследованное от оболочки 2>&1 не является вторым названным адресатом. Символьные устройства,
например терминал
или /dev/null, могут совпадать. Отсутствующий родитель, каталог вместо файла,
недоступный путь, закрытый дескриптор и ошибка записи дают код 3. Причина
различает неверный ввод и отказ среды. Если stdout недоступен для ответа об
ошибке записи отчёта, отказ поступает в stderr.
--group-by¶
Группировка нарушений в выводе. Значение по умолчанию зависит от форматтера.
Доступные значения: none, file, rule, severity, class, namespace.
--format-opt¶
Передача специфичных для форматтера опций в формате key=value. Можно указывать несколько раз:
Ключ, который не читает ни один форматтер, отвергается с кодом 3. Ключ, который
читает другой форматтер, по-прежнему принимается, поэтому скрипт, прогоняющий
один набор опций по нескольким форматам, продолжает работать. Каждый ключ можно
написать один раз: --format-opt=violations=2 --format-opt=violations=1
отвергается с кодом 3, а не выигрывает последнее значение. Каждая пара
проверяется в том виде, в каком написана, поэтому неразбираемое значение
отвергается, даже если его заменила бы другая пара или --all. Так же
отвергаются два ключа, задающие одно значение: violations рядом с limit или
limit рядом с --all (который пишет violations=all).
Опции формата JSON:
| Опция | По умолчанию | Описание |
|---|---|---|
violations=N\|all |
all | Макс. кол-во нарушений в выводе (0=нет) |
limit=N\|all |
all | То же значение, что violations, но 0 означает «без ограничения»; пишите один из двух |
top=N |
10 | Количество худших нарушителей |
rank-by=score\|density |
score | Упорядочить худших нарушителей по возрастанию health-балла (по умолчанию) или убыванию плотности нарушений |
bin/qmx check src/ --format=json --format-opt=limit=100
bin/qmx check src/ --format=json --format-opt=violations=all
bin/qmx check src/ --format=json --format-opt=rank-by=density
Опции формата summary:
| Опция | По умолчанию | Описание |
|---|---|---|
top=N |
3 | Количество худших нарушителей |
rank-by=score\|density |
score | Упорядочить худших нарушителей по возрастанию health-балла (по умолчанию) или убыванию плотности нарушений |
Отбор худших нарушителей использует полную сохранённую популяцию до ранжирования и top. Селекторы неймспейсов объединяются. Для отдельного заголовка class health выборка --class в JSON/summary требует единственного точного объявления; несколько объявлений логического имени дают отказ с кодом 3 с перечнем точных объявлений. Чтобы сохранить все их точные записи offender, используй --namespace. rank-by=count отвергается с кодом 3; используй score или density. Summary показывает настоящий остаток и советует --format-opt=top=<total>.
Два несвязанных top
--format-opt=top=N (форматы JSON и summary) ограничивает списки худших
пространств имён/классов. Глобальный флаг --top — другая опция:
он ограничивает отдельный список «Top issues by impact». Их можно задавать
независимо друг от друга.
Опции формата health:
| Опция | По умолчанию | Описание |
|---|---|---|
contributors=N |
3 | Сколько худших вкладчиков показывать для каждого измерения |
Опции формата HTML:
| Опция | По умолчанию | Описание |
|---|---|---|
project-name=NAME |
автоопределение | Переопределяет имя проекта в HTML-отчёте |
--fail-on¶
Минимальный уровень нарушения, при котором возвращается ненулевой код выхода. По умолчанию: error.
# Поведение по умолчанию: ошибка только при error, предупреждения допускаются
bin/qmx check src/
# Ошибка и при warning (для строгого контроля качества)
bin/qmx check src/ --fail-on=warning
# Никогда не завершать с ошибкой из-за нарушений
bin/qmx check src/ --fail-on=none
Предупреждения по-прежнему отображаются в выводе, но по умолчанию не приводят к ненулевому коду завершения. Используйте --fail-on=warning, если хотите, чтобы предупреждения также блокировали CI.
Также можно задать в qmx.yaml:
--exclude-health¶
Исключить конкретные измерения здоровья из оценки. Исключённые измерения не отображаются в сводке здоровья и не влияют на общую оценку. Можно указывать несколько раз:
# Исключить типизацию из оценки здоровья
bin/qmx check src/ --exclude-health=typing
# Исключить несколько измерений
bin/qmx check src/ --exclude-health=typing --exclude-health=maintainability
Доступные измерения: complexity, cohesion, coupling, typing, maintainability.
Также можно задать в qmx.yaml:
--detail¶
Добавляет после сводки группированный список нарушений; значение — необязательный потолок его
длины. Опция не указана — списка нет (если не заданы --namespace или --class); указана без
значения — до 200 нарушений; --detail=N — не больше N; --detail=all или --detail=0 —
без потолка. Действует только на формат summary.
# Лимит по умолчанию (200 нарушений)
bin/qmx check src/ --detail
# Показать все нарушения (без лимита)
bin/qmx check src/ --detail=all
# Пользовательский лимит
bin/qmx check src/ --detail=50
Автоматически включается при использовании --namespace или --class.
--top¶
Количество самых значимых по влиянию находок. По умолчанию: 10; 0 отключает секцию.
# По умолчанию: топ-10
bin/qmx check src/
# Показать топ-25
bin/qmx check src/ --top=25
# Отключить секцию
bin/qmx check src/ --top=0
Управляет секцией «Top issues by impact» формата summary и ключом topIssues
формата --format=json — списком находок, ранжированных по влиянию (сочетание
ClassRank, серьёзности и времени на исправление), отдельным от списков худших
пространств имён и худших классов. Больше ни один формат её не показывает.
Это другая опция, чем --format-opt=top=N, которая ограничивает списки худших
нарушителей — см. таблицы опций форматов выше.
--all¶
Показать все нарушения без усечения. Сокращение для --format-opt=violations=all --detail=all.
# Все нарушения в формате JSON
bin/qmx check src/ --format=json --all
# Все нарушения в формате summary
bin/qmx check src/ --all
Не может быть объединён с --format-opt=violations=N (числовой лимит) и с --detail/--detail=N (ограниченный список; --detail без значения — это лимит 200): каждое такое сочетание отклоняется с кодом 3 до анализа, а не решается молчаливой победой одного из двух. Совместное использование --all с --format-opt=violations=all, --detail=all или --detail=0 допустимо (они синонимы).
--namespace¶
Фильтрация вывода явным селектором неймспейса. exact: выбирает один неймспейс, subtree: — его и потомков по границам, regex: — фрагмент PCRE без разделителей. Bare- и пустые значения отвергаются; regex всегда сопоставляется со всем неймспейсом.
bin/qmx check src/ --namespace='subtree:App\Service'
bin/qmx check src/ --namespace='regex:App\\(?:Billing|Sales)\\Order'
Фильтрует нарушения и худших нарушителей по выбранным пространствам имён. Показывает оценки здоровья поддерева. Автоматически включает --detail.
Находки уровня проекта (architecture.coverage-gap и прочие диагностики, судящие о прогоне целиком) не выбираются селектором неймспейса: они не принадлежат ни одному пространству имён.
Находки детекторов с именованным объявлением используют пространство имён этого объявления. Находки с файловым субъектом пока проходят через прежнюю логику выбора по пространству имён: одного пути файла недостаточно, чтобы гарантировать их появление в drill-down соответствующего пространства имён.
То же правило сопоставления действует для drill-down по здоровью и списков худших нарушителей, которые включает эта опция, и для опции include_namespaces правила coupling.distance.
Паттерн, не выбравший ни одного проанализированного пространства имён, отвергается с кодом 3, и отказ называет, сколько пространств имён у прогона было. Паттерн, который что-то выбрал и всё равно ничего не сообщил, печатает обычный пустой результат — именно эти два исхода и важно различать.
Взаимоисключающий с --class. Отклоняется с кодом 3 до анализа под
--format=gitlab или --format=checkstyle, в том числе когда формат выбран
файлом конфигурации: их потребители читают каждую запись как находку, поэтому
ни один из них не может сказать, что отчёт — частичный вид.
--class¶
Фильтрация вывода по конкретному классу с точным совпадением FQCN.
Фильтрует нарушения по указанному классу. Автоматически включает --detail.
FQCN, не совпавший ни с одним проанализированным классом, отвергается с кодом 3
по той же причине, что и --namespace: иначе пустой отчёт читается как чистый
класс.
Взаимоисключающий с --namespace. Под gitlab и checkstyle отклоняется так
же, как --namespace.
Опции кэширования¶
Qualimetrix кэширует разобранные AST-деревья для ускорения повторных запусков. По умолчанию кэш находится в пользовательском каталоге платформы под qmx и общий для проектов и worktree этого пользователя; старые записи .qmx-cache внутри checkout не читаются. Поддерживаемый POSIX-абсолютный XDG_CACHE_HOME имеет приоритет; иначе Linux/BSD используют $HOME/.cache, macOS — $HOME/Library/Caches, а ветка Windows читает LOCALAPPDATA. Пути с буквой диска и UNC текущая грамматика не поддерживает. Непригодное умолчание отключает кэш с одним предупреждением.
--no-cache¶
Полностью отключить кэширование:
--cache-dir¶
Указать каталог кэша, который разрешается в поддерживаемый POSIX-путь вне проекта. Относительный путь разрешается от корня проекта: например, ../external-cache подходит, если оказывается вне проекта. По умолчанию используется пользовательский каталог под qmx. Когда корень проекта — / (например, при запуске cron из /), вложенность не проверяется; остальные проверки расположения продолжают действовать.
Когда кэширование включено или --clear-cache использует каталог, путь проверяется без создания каталогов. --no-cache без очистки не проверяет неиспользуемый корень кэша. Явный путь внутри проекта, корень
другого владельца или с доступом на запись группе либо остальным, как и путь
без доступного для записи и поиска каталога, тогда отклоняется с кодом 3. Проверка
корня не удостоверяет доверие ко всем предкам. Непригодный
неявный каталог по умолчанию выключает кэш и вызывает одно предупреждение.
Пригодный каталог создаётся после остальных проверок ввода.
--clear-cache¶
Очистить кэш перед запуском анализа:
Очистка начинается после проверок ввода и подготовки адресатов. Цель или её временный сосед внутри физического корня кэша отклоняются до очистки и анализа, в том числе через символическую ссылку. Если запись кэша не удаётся удалить, команда выдаёт ошибку среды с кодом 3, каталогом, числом оставшихся записей и причиной. При неполной очистке сообщение «Cache cleared.» не выводится. Очистка удаляет только записи qmx, но всех проектов в этом пользовательском корне. Записи, не читавшиеся 30 дней, удаляются постепенно. При каждом открытии проверяются 16 из 256 сегментов; после 16 успешных шагов целевой объём каждого формата — 2 ГиБ плюс записи, добавленные после последней очистки своего сегмента, и по одной самой новой записи сверх лимита в каждом сегменте. Это не мгновенный жёсткий предел. Временные файлы публикации удаляются по возрасту после 30 дней; свежие сохраняются при квотной очистке, чтобы не лишать активную запись её имени. Их объём добавляется к целевому объёму записей кэша. Старые временные файлы в каталоге метаданных формата тоже удаляются. Если посторонние данные удерживают отделённый каталог, очистка сохраняет их и сообщает отказ вместо «Cache cleared». Следующая очистка повторно обрабатывает оставшиеся отделённые каталоги.
Опции baseline¶
Полный жизненный цикл и формат файла описаны в Baseline.
--baseline=BASELINE¶
Использовать файл baseline, чтобы применить принятые потолки к текущим нарушениям:
--show-resolved¶
Посчитать записи, чья полная идентичность больше не появляется в измеряемом наборе:
Stale требует полного сравнимого отсутствия. Stale/inert публикуют проектный Warning baseline.unused-entry с обычной политикой --fail-on. Группа, которая всё ещё срабатывает с меньшим числом элементов, не считается resolved.
Lifecycle-команды baseline¶
Ниже приведена полная поверхность команд для записи и проверки baseline:
bin/qmx baseline:generate <baseline> [<paths>...] [--mode=MODE] [--force]
bin/qmx baseline:update <baseline> [<paths>...] [--force] [--accept-new=CHANNEL]... [--record-exclusions]
bin/qmx baseline:cleanup <baseline> [<paths>...] [--remove=REMOVE]... [--force]
bin/qmx baseline:explain <symbol> [<paths>...] [--baseline=BASELINE] [--channel=CHANNEL]
bin/qmx baseline:rename-channels <baseline> <map> [--format=FORMAT]
Первые четыре команды принимают --config=CONFIG, --preset=PRESET, --disable-rule=DISABLE-RULE, --only-rule=ONLY-RULE и --rule-opt=RULE-OPT. Все четыре также принимают --include-generated, --include-autoload-dev, --no-cache, --workers/-w и --memory-limit. Ни одна не принимает опции исключения или suppression. baseline:rename-channels не принимает ни одной из них: она не запускает анализ, поэтому измеряемого набора, который они определяли бы, нет.
baseline:generateзахватывает текущие измеряемые нарушения. По умолчанию используется--mode=ratchet;--mode=suppressзаписывает безусловное принятие захваченных идентичностей. Его--forceперезаписывает существующий файл.baseline:updateтолько ужесточает существующие записи. Его--forceснимает проверку покрытия записанной области.baseline:cleanupпо умолчанию выводит кандидатов и удаляет только повторяемые селекторы--remove=REMOVE. Его--forceтакже снимает проверку области.baseline:explainпоказывает порог из конфигурации, принятую величину baseline и override из исходника для канонического символа;--channel=CHANNELсужает ответ.baseline:rename-channelsпереписывает полеchannelзаписей, названных объявленной табличной картой, и больше ничего, не анализируя код. Ошибки содержимого, грамматики и окружения следуют политике отказов команды (код 3); частичная запись не публикуется. См. Перенос baseline на переименованные каналы — учти, что перенос записи меняет её селектор.
Четыре анализирующие команды отказываются классифицировать или записывать baseline при
неполном анализе и завершаются с кодом 4. --force снимает только ограничения
файла/области; он не делает частичный набор измерений допустимым. Существующий
файл остаётся побайтово неизменным, а baseline:generate не создаёт отсутствующий файл.
Загружаемые версии baseline и процедура миграции старого файла описаны в разделе Замена старого baseline.
Удалённые опции --generate-baseline и --baseline-ignore-stale не имеют алиасов. Используй вместо них baseline:generate и явный baseline:cleanup --remove.
--accept-new=CHANNEL и --record-exclusions¶
Несовместимые режимы baseline:update. Повторяй --accept-new с точными выбранными объявленными каналами: добавляются только новые полные сравнимые измеренные identity, старые границы/modes сохраняются. Wildcard, уровни, необъявленные, configuration-error и audit каналы отклоняются с 3 до анализа. --record-exclusions требует точно записанные пути даже с --force, записывает полное определение и перезахватывает только затронутые полные сравнимые группы с modes. Недоступные доказательства запрещают всю запись. Обычный update сохраняет scope/exclusions; равное принятие unchanged, no-op сохраняет байты/generated. Пять читателей выполняют preflight документа один раз до анализа/ переноса: грамматика рано, настроенная семантика позже. Неполный анализ — 4 до записи. Stale требует полного сравнимого отсутствия; stale/inert дают проектный Warning baseline.unused-entry с обычной политикой --fail-on.
Опции подавления¶
--show-suppressed¶
Показать нарушения, подавленные тегами @qmx-ignore, а также нарушения, подавленные записью
suppress_namespaces / suppress_namespace_channels / suppress_paths на уровне правила в qmx.yaml (см.
«Правила»):
Независимо от --show-suppressed, запуск с -v печатает разбивку по правилам — сколько
нарушений подавлено таким образом. Namespace-бакет включает обе опции неймспейсов и выводится
отдельно от suppress_paths; каждый бакет разбит по имени правила. В отличие от @qmx-ignore, в остальном это подавление проходит
незаметно — ничто в стандартном выводе не сигнализирует о том, что оно произошло.
--show-suppressed выводит прозой лишь часть этого.
--format=suppressed публикует полный состав — все восемь механизмов подавления,
а не только эти два, — как машиночитаемый JSON; см.
«Форматы вывода». Для взведения
per-rule-захвата достаточно либо --show-suppressed, либо выбора
--format=suppressed (в том числе format: suppressed в qmx.yaml) — оба
вместе не нужны. В остальном эти две поверхности не эквивалентны — что
показывает каждая, см. в разделе
suppressed.
Suppression composition включает восемь механизмов, включая снятие реально
порождённых находок механизмом selection. Producer, который не исполнялся,
ничего не породил для снятия и описан отдельно в notRun, не в byMechanism.
Threshold-audit effects, усечение форматтером и namespace/class drill-down
сохраняют отдельный смысл; усечение/drill-down меняют представление, а не
identity исходных находок.
--no-suppression-annotations¶
Выводить все нарушения, включая те, которые подавлены тегами @qmx-ignore:
Опция не меняет то, что измеряет baseline
Флаг влияет только на отчёт. Baseline измеряет те нарушения, которые
оставляют конфигурация и аннотации в исходниках, поэтому нарушение,
убранное тегом @qmx-ignore, никогда не попадает в baseline и никогда не
сравнивается с ним — независимо от того, передан ли этот флаг.
Видимое следствие: под этим флагом подавленное аннотацией нарушение
показывается со своей собственной серьёзностью и никогда не повышается
до ошибки, потому что ни одна запись baseline его не покрывает. Флаг может
сузить измеряемое baseline множество (--suppress-path,
--suppress-namespace), но расширить его не может ни один.
Опции области Git¶
Публикация находок относительно изменённых файлов с сохранением объявленной project-scoped диагностики, в том числе циклов архитектуры. Нарушение слоя сохраняется только при изменении source-файла в обоих режимах. Полное руководство смотрите в разделе Интеграция с Git.
--report¶
Ограничивает публикацию по Git, сохраняя выбранные пути анализа. Обычный режим также сохраняет соответствующие namespace/project находки; объявленные project-scoped находки остаются видимыми:
--report-strict¶
Ограничивает file-scoped находки изменёнными файлами без namespace/project расширения. Объявленные project-scoped находки, включая циклы архитектуры, сохраняются и в strict-режиме. Нарушения слоёв фильтруются по source-файлу:
Опции выполнения¶
--workers, -w¶
Управление параллельной обработкой. По умолчанию: автоопределение по количеству CPU.
# Отключить параллельную обработку (один процесс)
bin/qmx check src/ --workers=1
# Отключить параллельную обработку (последовательно)
bin/qmx check src/ --workers=0
# Использовать ровно 4 воркера
bin/qmx check src/ --workers=4
Совет
Используйте --workers=1 для отладки или в однопроцессном окружении. --workers=0 отключает параллелизм (последовательное выполнение); автоопределение действует, когда опция не задана. Транспорт использует процессы, а не потоки или fork. Нужны proc_open и, вне Windows, ext-posix. На подходящем прогоне явное значение больше одного даёт отказ среды с кодом 3, если первый воркер не стартует или не отвечает за 10 секунд; автоматический выбор предупреждает и переходит к последовательной работе. NUMBER_OF_PROCESSORS читается только на Windows и там должен быть положительным десятичным целым.
--memory-limit¶
Установить лимит памяти PHP для анализа. По умолчанию используется значение memory_limit из php.ini.
Лимит действует и в рабочих процессах (см. --workers), где файлы разбираются и измеряются. Рабочий процесс, которому не хватило памяти, проваливает файл, который обрабатывал: прогон сообщает этот файл как необработанный, завершается кодом 4, и сообщение о сбое называет лимит, с которым работали процессы; собственная строка PHP «Allowed memory size … exhausted» появляется в stderr.
# Установить лимит памяти 1ГБ для больших проектов
bin/qmx check src/ --memory-limit=1G
# Без ограничений памяти
bin/qmx check src/ --memory-limit=-1
Допустимые форматы: -1 (без ограничений) или положительное целое с необязательным суффиксом K/M/G (например, 512M, 2G). 0, ведущий ноль (010M, который PHP считал бы восьмеричным) и значение свыше PHP_INT_MAX байт отклоняются с кодом 3. OOM координатора после связывания диагностики и выделения резерва даёт код 4 с лимитом и источником; более ранний чужой shutdown callback может заменить последнюю ошибку PHP до её чтения.
Эквивалент в YAML: memory_limit: 1G
--log-file¶
Записывать лог прогона в файл, по одной JSON-записи на строку:
Файл дописывается; родительский каталог должен существовать. Записи лога, возникшие при проверках ввода, накапливаются в памяти. После этих проверок адресат открывается вместе с адресатами отчёта и профиля, затем накопленные записи дописываются. Прикрепление публикует имя лога: успешный прогон оставляет пустой файл, даже если ни одна запись не прошла минимальный уровень. Неверный ввод оставляет файл лога нетронутым.
Действуют те же правила ссылок, дескрипторов и совпадений адресатов, что для
--output. Недоступный для записи адресат отклоняется с кодом 3. При ошибке
записи во время анализа логгер запоминает первую причину и считает потерянные
записи; команда сообщает ошибку среды до публикации отчёта. Неполная строка
может остаться. Пустое или пробельное значение, в том числе --log-file=$LOG
при незаданной переменной, отклоняется с кодом 3. Чтобы не писать файловый лог,
не указывайте опцию. Опцию принимает только check.
--log-level¶
Установить минимальный уровень строк лога — для файла --log-file и для
консоли:
Доступные уровни: debug, info, warning, error. Значение вне этого набора
отвергается с кодом 3, а не откатывается к значению по умолчанию.
| Задано | Консоль | --log-file |
|---|---|---|
| ничего | warning; с -v — info; с -vv — debug |
info |
уровень, с -v и выше |
этот уровень | этот уровень |
уровень, без -v |
этот уровень, если он строже warning, иначе warning |
этот уровень |
Без -v уровень может только сузить консоль: --log-level=error скрывает
предупреждения, а --log-level=debug --log-file=qmx.log пишет подробный файл и
оставляет терминал таким же тихим, как был. -q глушит консольные логи при любом уровне, но ответы команд и сообщения о завершении остаются; файл продолжает получать строки.
--no-progress¶
Отключить прогресс-бар. Полезно в CI-пайплайнах:
Принимается каждой командой, которая показывает прогресс-бар: check,
directives, debug:layer-assignment, baseline:generate, baseline:update,
baseline:cleanup и baseline:explain. graph:export тоже анализирует дерево,
но бара не рисует, поэтому опции у него нет.
Прогресс-бар пишется в поток ошибок, поэтому отчёт в стандартном выводе остаётся
машиночитаемым даже на терминале — bin/qmx check src/ --format=json >
report.json даёт валидный JSON и без этого флага. Бар рисуется, только если
поток ошибок — терминал; перенаправление потока ошибок гасит его, не трогая
отчёт.
Бар делит поток ошибок с подробным логом (-v, -vv, -vvv) и с
предупреждениями во время прогона. И то и другое рисуется через одного
владельца: строка диагностики сдвигает бар вниз и остаётся на экране, а бар
перерисовывается под ней. Поэтому повышение подробности бар не выключает, а бар
не съедает строки лога.
--silent, -q/--quiet¶
Флаги Symfony Console, подавляющие обычный вывод. Оба принимаются любой командой:
--silent и -q/--quiet подавляют progress и статусные логи, но
сохраняют ответ отвечающей команды и сообщения о завершении.
SHELL_VERBOSITY=-1 или -2 ведёт себя так же. Отказ из-за ввода по-прежнему
пишет причину в stderr для текстовых форматов, а JSON-форматы публикуют JSON-конверт ошибки в stdout; успешный check --format=json выводит полный JSON
в stdout. Если нужен только код, перенаправьте stdout; stderr перенаправляйте,
только если диагностика не нужна.
Опции профилирования¶
--profile¶
Включить внутренний профайлер. Опционально можно указать файл для сохранения профиля:
<!-- llms:skip-end -->
# Показать сводку профилирования на экране
bin/qmx check src/ --profile
# Сохранить профиль в файл
bin/qmx check src/ --profile=profile.json
Цель, в которую нельзя записать, отклоняется с кодом 3 до анализа по
тем же правилам адресата, что и --output. Пустое
--profile= также отклоняется. Отказ до начала анализа, включая неверный
baseline, не публикует профиль. Если анализ начался и команда дошла до своего
завершения, профиль публикуется до отчёта; параллельный прогон включает
collection.workers. Сбой записи профиля проходит через конверт ошибки
прогона вместо успешного отчёта в stdout. OOM координатора до публикации
профиля не создаёт новый файл. Профиль, опубликованный до более позднего OOM
отчёта, остаётся: опубликованные адресаты не откатываются. Неопубликованные
именованные адресаты освобождаются на связанном OOM-пути. Эта гарантия
начинается после связывания диагностики и выделения резерва.
--profile-format¶
Выбор формата экспорта профиля. По умолчанию: json. Любое другое значение отклоняется с
кодом 3 до начала анализа — независимо от того, указан ли файл в --profile.
Доступные форматы: json, chrome-tracing.
Совет
Используйте формат chrome-tracing и откройте файл в Chrome DevTools (chrome://tracing) для визуального анализа производительности.
Опции правил¶
--disable-rule¶
Отключить правило-производитель, целую группу или отдельный канал нарушения. Селектор — это
либо точное имя (правило-производитель или канал), либо X.* строго для потомков X —
сам X в это не входит; группа выбирается только так (complexity.*). Голый префикс без
звёздочки — ошибка. Селектор канала можно сузить до одного уровня дерева агрегации через :level, как и у
--only-rule. Отключение одного канала не останавливает производителя, чтобы остальные его
каналы продолжали попадать в отчёт. Опцию можно указывать несколько раз:
# Отключить одно правило
bin/qmx check src/ --disable-rule=size.class-count
# Отключить все правила сложности
bin/qmx check src/ --disable-rule=complexity.*
# Отключить несколько
bin/qmx check src/ --disable-rule=complexity.* --disable-rule=cohesion.lcom
# Отключить только один канал computed finding
bin/qmx check src/ --disable-rule=health.complexity
Сбой из-за нехватки памяти в Duplication
Если PHP исчерпает память во время duplication.clone, детектор выведет
в stderr короткую диагностику с местом сбоя и текущим memory_limit,
предложит --memory-limit или memory_limit в qmx.yaml и завершится с
кодом 4. Фатальная нехватка памяти может прервать вывод отчёта; валидный
или полный JSON не гарантируется. Поздний отказ чтения также делает прогон
неполным с кодом 4 и очищает частичный результат Duplication. Пустой результат
такого прогона не доказывает отсутствие копий. Чтобы намеренно пропустить
обнаружение, отключи само duplication.clone.
--only-rule¶
Запустить только подходящие правила-производители или каналы нарушений. Селектор — это либо
точное имя (правило-производитель или канал), либо X.* строго для его потомков —
единственный способ выбрать группу; каждое из них можно сузить до одного уровня дерева агрегации через
:level. Селектор с уровнем не останавливает своего производителя: отфильтрованный
производитель никогда не выдал бы запрошенный уровень. Опцию можно указывать несколько раз:
# Запустить только правила сложности
bin/qmx check src/ --only-rule=complexity.*
# Запустить два конкретных правила
bin/qmx check src/ --only-rule=complexity.ccn --only-rule=size.method-count
# Выбрать один канал встроенного измерения здоровья: производитель и канал
# называются одинаково, потому что каждое из шести измерений — сам себе производитель
bin/qmx check src/ --only-rule=health.complexity
Селектор должен точно совпасть с зарегистрированным producer или выводимым каналом,
либо X.* должен разрешиться хотя бы в одного потомка. Неизвестный селектор — включая голый
префикс без звёздочки или X.*, не совпавший ни с чем, — завершается с кодом 3 до записи
report-payload в stdout. Если написание со звёздочкой что-то выбрало бы, отказ его называет:
Rule selector "complexity" does not match any registered producer or channel. Write "complexity.*" to select its descendants.
Единственное голое слово, которое принимается, — computed: это имя производителя, а не группы.
Аналогично, владелец перед : в --rule-opt=RULE:OPTION=VALUE должен быть точным
producer-rule, а не группой или каналом — группа или канал здесь являются ошибкой. То же
правило действует и для ключей секции rules: в YAML.
Роль selection объявлена для каждого канала
annotation.unresolved-directive и annotation.unused-directive выбираются напрямую. Unsupported/invalid thresholds следуют addressed producer. Явный disable annotation.directive останавливает producer. Применимость path/namespace exclusions остаётся отдельным вопросом.
--rule-opt¶
Переопределить опции правил из командной строки. Формат: rule-name:option=value, где
rule-name должен быть точным producer-rule — никогда группой, никогда каналом и никогда
wildcard. То же ограничение точного producer действует для ключей rules:
в YAML. Selection с :level адресует объявленный channel code, а не иначе
названного producer. Опцию можно указывать несколько раз:
bin/qmx check src/ --rule-opt=complexity.ccn:callable.warning=15
bin/qmx check src/ --rule-opt=complexity.ccn:callable.error=30
Все три способа ошибиться отвергаются с кодом 3 там, где раньше пара опций
молча отбрасывалась: значение, записанное без =VALUE; имя правила, которому
не отвечает ни один зарегистрированный producer; и имя опции, которого это
правило не принимает. В последнем случае отказ перечисляет опции, которые
правило принимает.
suppress_namespace_channels настраивается в YAML, а не через --rule-opt: каждому селектору
нужен непустой список паттернов неймспейсов, а channel-keyed dictionaries
не являются объявленными dotted option addresses CLI.
Его ключи — это селекторы каналов, подчиняющиеся тому же правилу «точное имя или X.*», что
и @qmx-ignore: голый префикс вроде health теперь ошибка, а не сокращение для health.*.
Ключ может добавить :namespace и никакой другой уровень: опции достаются только агрегаты по
неймспейсам, поэтому любой другой уровень назвал бы фильтр, который не сработает никогда.
Быстрые флаги для правил¶
Для многих правил доступны специальные CLI-флаги для быстрой настройки опций:
| Флаг | Правило | Опция |
|---|---|---|
--cyclomatic-warning=N |
complexity.ccn | callable.warning |
--cyclomatic-error=N |
complexity.ccn | callable.error |
--cyclomatic-class-warning=N |
complexity.ccn | class.max_warning |
--cyclomatic-class-error=N |
complexity.ccn | class.max_error |
--cognitive-warning=N |
complexity.cognitive | callable.warning |
--cognitive-error=N |
complexity.cognitive | callable.error |
--cognitive-class-warning=N |
complexity.cognitive | class.max_warning |
--cognitive-class-error=N |
complexity.cognitive | class.max_error |
--npath-warning=N |
complexity.npath | callable.warning |
--npath-error=N |
complexity.npath | callable.error |
--npath-class-warning=N |
complexity.npath | class.max_warning |
--npath-class-error=N |
complexity.npath | class.max_error |
--wmc-warning=N |
complexity.wmc | warning |
--wmc-error=N |
complexity.wmc | error |
--wmc-exclude-data-classes |
complexity.wmc | excludeDataClasses |
| Флаг | Правило | Опция |
|---|---|---|
--cbo-warning=N |
coupling.cbo | class.warning |
--cbo-error=N |
coupling.cbo | class.error |
--cbo-ns-warning=N |
coupling.cbo | namespace.warning |
--cbo-ns-error=N |
coupling.cbo | namespace.error |
--distance-warning=N |
coupling.distance | max_distance_warning |
--distance-error=N |
coupling.distance | max_distance_error |
--instability-class-warning=N |
coupling.instability | class.max_warning |
--instability-class-error=N |
coupling.instability | class.max_error |
--instability-ns-warning=N |
coupling.instability | namespace.max_warning |
--instability-ns-error=N |
coupling.instability | namespace.max_error |
--class-rank-warning=N |
coupling.class-rank | warning |
--class-rank-error=N |
coupling.class-rank | error |
| Флаг | Правило | Опция |
|---|---|---|
--class-count-warning=N |
size.class-count | warning |
--class-count-error=N |
size.class-count | error |
--method-count-warning=N |
size.method-count | warning |
--method-count-error=N |
size.method-count | error |
--property-count-warning=N |
size.property-count | warning |
--property-count-error=N |
size.property-count | error |
| Флаг | Правило | Опция |
|---|---|---|
--dit-warning=N |
design.dit | warning |
--dit-error=N |
design.dit | error |
--lcom-warning=N |
cohesion.lcom | warning |
--lcom-error=N |
cohesion.lcom | error |
--lcom-min-methods=N |
cohesion.lcom | minMethods |
--lcom-exclude-readonly |
cohesion.lcom | excludeReadonly |
--lcom-exclude-methods='[NAME]' |
cohesion.lcom | excludeMethods |
--noc-warning=N |
design.noc | warning |
--noc-error=N |
design.noc | error |
--param-type-coverage-warning=N |
design.type-coverage.param | warning |
--param-type-coverage-error=N |
design.type-coverage.param | error |
--return-type-coverage-warning=N |
design.type-coverage.return | warning |
--return-type-coverage-error=N |
design.type-coverage.return | error |
--property-type-coverage-warning=N |
design.type-coverage.property | warning |
--property-type-coverage-error=N |
design.type-coverage.property | error |
--property-exclude-readonly |
size.property-count | excludeReadonly |
--property-exclude-promoted-only |
size.property-count | excludePromotedOnly |
| Флаг | Правило | Опция |
|---|---|---|
--mi-warning=N |
maintainability.mi | warning |
--mi-error=N |
maintainability.mi | error |
--mi-min-statements=N |
maintainability.mi | minStatements |
--mi-exclude-tests |
maintainability.mi | excludeTests |
| Флаг | Правило | Опция |
|---|---|---|
--constructor-overinjection-warning=N |
code-smell.constructor-overinjection | warning |
--constructor-overinjection-error=N |
code-smell.constructor-overinjection | error |
--data-class-woc-threshold=N |
design.data-class | wocThreshold |
--data-class-wmc-threshold=N |
design.data-class | wmcThreshold |
--data-class-min-members=N |
design.data-class | minMembers |
--data-class-exclude-readonly |
design.data-class | excludeReadonly |
--data-class-exclude-promoted-only |
design.data-class | excludePromotedOnly |
--data-class-exclude-exceptions |
design.data-class | excludeExceptions |
--god-class-wmc-threshold=N |
design.god-class | wmcThreshold |
--god-class-lcom-threshold=N |
design.god-class | lcomThreshold |
--god-class-tcc-threshold=N |
design.god-class | tccThreshold |
--god-class-class-loc-threshold=N |
design.god-class | classLocThreshold |
--god-class-min-criteria=N |
design.god-class | minCriteria |
--god-class-min-methods=N |
design.god-class | minMethods |
--god-class-exclude-readonly |
design.god-class | excludeReadonly |
--long-parameter-list-warning=N |
code-smell.long-parameter-list | warning |
--long-parameter-list-error=N |
code-smell.long-parameter-list | error |
--long-parameter-list-vo-warning=N |
code-smell.long-parameter-list | vo-warning |
--long-parameter-list-vo-error=N |
code-smell.long-parameter-list | vo-error |
--unreachable-code-warning=N |
code-smell.unreachable-code | warning |
--unreachable-code-error=N |
code-smell.unreachable-code | error |
| Флаг | Правило | Опция |
|---|---|---|
--circular-deps |
architecture.circular-dependency | enabled |
--max-cycle-size=N |
architecture.circular-dependency | maxCycleSize |
--layer-violation |
architecture.layer-violation | enabled |
--layer-violation-severity=SEVERITY |
architecture.layer-violation | severity |
--unassigned-class-mode=MODE |
architecture.unassigned-class | mode |
Другие команды¶
baseline:cleanup¶
Проверить stale-кандидатов в baseline. Без --remove команда только выводит их и никогда не меняет файл; удалить явно проверенный selector можно так, как описано в Baseline:
bin/qmx baseline:cleanup baseline.json src/
bin/qmx baseline:cleanup baseline.json src/ --remove=<selector>
debug:layer-assignment¶
bin/qmx debug:layer-assignment 'App\Service\Foo' --format=json
bin/qmx debug:layer-assignment 'app\service\foo' --config qmx.yaml
| Опция | Значение |
|---|---|
-c, --config=FILE |
Файл конфигурации; по умолчанию qmx.yaml. |
--preset=PRESET |
Именованный или файловый preset; можно повторять. |
--format=FORMAT |
text (по умолчанию) или json. |
Команда выполняет обычные Discovery/Collection и ищет имя среди наблюдённых
объявлений и graph ends; install-only классы не добавляются. ASCII-регистр
разрешается в наблюдённое написание, high-byte имена parser принимаются.
Только пустое нормализованное имя отвергается до анализа; прочий неизвестный
ввод даёт exit 3 после lookup, даже при выключенной политике. Информационный
ответ даёт exit 0. Настройте выключение трёх layer-policy producers в YAML;
--disable-rule команды check здесь не добавлен.
JSON содержит meta, канонический fqn, assigned, contendingMatches,
shadowed, shadowedBy, undecided, contenders, chainStopsAt, hasLayers,
policyDisabled, edgeEndOnly. Shadow verdict публикует точное exemption
при наличии; при disabled policy нет reported/exemption или diagnostic/docs
hint. Полная семантика и нативный пример — в Architecture.
Ошибки JSON заменяют ответ стандартным error/exit_code envelope.
directives¶
Показать, что на самом деле делает каждая инлайновая директива @qmx-ignore и @qmx-threshold в анализируемом дереве. Подавление оценивается по тому, что оно погасило; пороговая директива — снятием и повторным исполнением правил поверх измерений того же прогона, по умолчанию только того правила, которое она адресует, — одно исполнение на директиву.
bin/qmx directives src/
# Переисполнить все включённые правила, а не только адресуемое — контроль, которым проверяется узкий проход по умолчанию
bin/qmx directives src/ --sweep=full
# Машиночитаемый вывод — для агентов, скриптов и CI
bin/qmx directives src/ --format=json
| Опция | Описание |
|---|---|
-c, --config=FILE |
Путь к qmx.yaml (по умолчанию qmx.yaml в текущем каталоге) |
--format=FORMAT |
text (по умолчанию) или json |
--sweep=SCOPE |
Сколько правил переисполняет каждая контрфактическая проверка: narrow (по умолчанию) или full |
--preset=PRESET |
Применить именованный пресет (можно повторять) |
--only-rule=RULE |
Судить по прогону, в котором работали только эти правила (можно повторять) |
--disable-rule=RULE |
Судить по прогону с выключенными правилами (можно повторять) |
--rule-opt=RULE:OPT=VAL |
Судить по прогону с этой опцией правила (можно повторять) |
--no-cache |
Не читать и не писать кэш AST |
--cache-dir=DIR |
Каталог кэша AST, проверяется как у check |
-w, --workers=N |
Параллельные воркеры (0 — последовательно) |
--memory-limit=LIMIT |
Лимит памяти PHP, например 512M или -1 |
Четыре опции селекции нужны потому, что вердикт относителен прогону: указывайте те же правила и границы, с которыми проверяет ваш CI, иначе ответ будет про другой прогон.
@qmx-threshold называет ровно одно правило, поэтому при --sweep=narrow контрфактическая проверка переисполняет только его. --sweep=full переисполняет все включённые правила ради тех же вердиктов, но заметно дороже — это не медленный запасной вариант, а контроль, которым измеряется, а не предполагается, что снятие директивы одного правила не может сдвинуть находки другого: оба охвата прогоняются по одному дереву и сравниваются вердикт к вердикту. На собственном src/ этого проекта узкий охват в несколько раз дешевле, и оба охвата совпадают по каждому вердикту. И текстовый отчёт, и --format=json указывают, каким охватом получены вердикты.
Опции исполнения значат то же, что у check (--no-cache, --cache-dir, --workers, --memory-limit), поэтому аудит можно запускать изолированно от общего кэша: bin/qmx directives src/ --no-cache --workers=0.
Коды возврата: 0 — нет публикуемого отказа или наблюдаемой inert-директивы,
включая полный намеренно пустой исключённый набор; 2 — есть публикуемый
отказ или inert с наблюдаемой границей; 3 — ошибка ввода/конфигурации,
включая действительно пустое дерево; 4 — неполный прогон; 5 —
непредвиденный внутренний сбой команды. Неполнота имеет приоритет. Text и JSON сохраняют
все места, включая отказы, каналы которых итоговая селекция не публикует.
Измеренная пометка охвата есть в тексте и JSON scope.note. JSON также публикует
измеренный охват проекта в scope.project_scope: состояние, неизмеренные каналы
и причины источников.
Вердиктов пять:
| Вердикт | Что он утверждает |
|---|---|
| effective | Подавлена произведённая находка или снятие меняет результат threshold. |
| applied-boundary-only | Директива применилась; изменилась лишь граница в находке (JSON: overrun). |
| inert | Ничего не подавлено или снятие ничего не меняет; код 2 только при наблюдаемой границе. |
| unmeasured | Producer не исполнялся, субъект не покрыт либо threshold перекрыт другой директивой. |
| refused | Директива недопустима или неприменима, с непустым списком причин отказа. |
Каждый прочитанный тег имеет одно место независимо от числа привязок.
Иначе неиспользуемое подавление остаётся unmeasured, если прогон не может судить
о субъекте производителя. Узкий прогон не доказывает неиспользуемость объявления
зависимого от запуска канала; проанализированный локальный участник по-прежнему
может быть измерен.
Позиции подавления/диагностики различают одинаковые комментарии на строке;
JSON по-прежнему публикует file, line, form и target, а не
внутреннюю позицию. Для next-line line — строка тега, а не цель после
комментария. Места отказа несут обязательный
refusals: [{channel, message}]; прочие исходы — пустой список.
reason описывает только Unmeasured, при необходимости с masked_by.
Ни JSON отказа, ни JSON места не публикуют внутренний addressed producer.
Вердикт относителен анализируемому охвату
Порог на метрике, вычисляемой по проанализированному подграфу, — прежде всего связность — бывает живым по всему проекту и мёртвым по одному его каталогу, и оба ответа верны. Указывайте команде то, что проект действительно анализирует. Отчёт печатает охват, в котором он измерял, а прогон, не разобравший часть дерева, возвращает 4 вместо того, чтобы называть что-либо мёртвым.
Судим по произведённому правилами, а не по отчёту
suppress_paths, suppress_namespaces и suppress_namespace_channels подавляют публикацию, а не измерение. Директива, сдвинувшая находку внутри исключённого неймспейса, всё равно что-то сделала, поэтому аудит задаёт вопрос по всем находкам, произведённым правилами, а не по отчёту. Единственный канал вне этого универсума — annotation.unused-directive, который прогон собирает уже после исполнения правил: адресовать его директива не может, поэтому и судить по нему нечего.
Подавлению не засчитывается гашение ошибки конфигурации
(annotation.unresolved-directive и два его собрата). Эти каналы
выведены из-под аннотационного подавления по построению; допуск и
достижимость могут отказать директиве до оценки её эффекта.
Явный селектор annotation.unused-directive или duplication.clone
получает refused после проверки достижимости/уровня. Аудит несёт те же
причины отказа, что и check. Общий * и голый file оцениваются как
effective/inert по другим находкам и не глушат запрещённые каналы.
Вердикт applied-boundary-only намеренно ничего не утверждает о направлении. У слоя правил нет понятия «строже»: у coupling.instability хуже больше, у cohesion.tcc меньше, — поэтому директива, ужесточающая границу, и директива, поднявшая границу, которую величина уже прошла, дают одно и то же наблюдение. В --format=json этот вердикт сохраняет стабильный ключ overrun.
Если правило не публикует границу вместе с находкой, вердикт inert сопровождается пометкой об этом и не роняет сборку: граница, которую величина уже прошла, выглядела бы точно так же, и требовать удаления директивы значило бы выдать незаданный вопрос за доказанный долг. В --format=json это поле "boundary_observable": false.
При ошибке --format=json печатает в stdout {"error": "...", "exit_code": N, "position": ..., "source": ...} вместо человекочитаемой строки <error>.
graph:export¶
Команда читает общий документ конфигурации. Без аргументов путей использует
настроенные или Composer defaults; применяет exclude и фильтр @generated.
Принимает --config, --preset, --exclude, --include-generated,
--include-autoload-dev, --no-cache, --workers/-w и --memory-limit.
--format/-f выбирает только dot или json независимо от format анализа
в документе. У --direction нет короткого алиаса; глобальный -d меняет
рабочий каталог.
Экспортировать граф зависимостей для визуализации:
# Экспорт в формате DOT (по умолчанию)
bin/qmx graph:export src/ -o graph.dot
# Экспорт в формате JSON (агрегированный список смежности с метаданными)
bin/qmx graph:export src/ --format=json -o graph.json
# Фильтрация по пространству имён
bin/qmx graph:export src/ --namespace='subtree:App\Service' --namespace='subtree:App\Repository'
# Исключение пространств имён
bin/qmx graph:export src/ --exclude-namespace='subtree:App\Generated'
# Изменение направления графа
bin/qmx graph:export src/ --direction=TB
# Отключение группировки по пространствам имён
bin/qmx graph:export src/ --no-clusters
| Опция | Описание |
|---|---|
-o, --output=FILE |
Выходной файл (по умолчанию: stdout) |
-f, --format=FORMAT |
dot (по умолчанию) или json |
--direction=DIR |
Направление графа: LR, TB, RL, BT (по умолчанию: LR) |
--no-clusters |
Не группировать узлы по пространствам имён |
--namespace=SELECTOR |
Включить неймспейсы через exact:, subtree: или regex: (можно повторять) |
--exclude-namespace=SELECTOR |
Исключить неймспейсы теми же явными формами (можно повторять) |
Любой --namespace или --exclude-namespace должен связаться с исходным graph vertex до фильтрации. Непривязанное значение даёт exit 3; case-only near match советует точное написание графа, но не принимает ошибочный регистр.
Цель --output судится и пишется так же, как check обходится со своим
--output: каталог или имя, оканчивающееся на /, недоступный
для записи существующий файл и новое имя в каталоге, которого нет или в котором
нельзя создать файл, отклоняются с кодом 3 до чтения первого файла. Обычная
названная цель подготавливается во временном файле и публикуется атомарно;
доверенная символическая ссылка сохраняет свою запись и публикует referent.
/dev/stdout и именованные каналы сохраняют потоковую запись. Действует та же
граница доступности обработки SIGINT/SIGTERM.
Любой --namespace или --exclude-namespace, не связанный ни с одним исходным graph vertex, отвергается с exit 3 до фильтрации. Обе двери используют одинаковую проверку; case-only near match советует точное написание графа, но не принимает ошибочный регистр.
Если хотя бы один обнаруженный файл не удалось разобрать или обработать,
graph:export завершается с кодом 4 и не выводит частичный граф. Команда не создаёт
отсутствующий output-файл и побайтово сохраняет существующий.
hook:install¶
Установить git-хук pre-commit:
hook:status¶
Показать текущий статус хука pre-commit:
hook:uninstall¶
Удалить хук pre-commit:
bin/qmx hook:uninstall
# Восстановить оригинальный хук из резервной копии
bin/qmx hook:uninstall --restore-backup
rules¶
Принимает --config=FILE и повторяемый --preset=PRESET, проверяет весь
документ и включает именованные computed metrics. Отмечает правила,
отключённые текущей итоговой селекцией only_rules/disabled_rules.
Не запрашивает пути анализа: каталог без PHP не мешает показать правила.
Ошибочный документ отклоняется с кодом 3. Отдельного CLI-парсера rules: false
или enabled: false для этой отметки нет; эти переключатели принадлежат
разрешению опций правил.
Вывести список всех доступных правил с описаниями и опциями CLI:
Пример вывода (для --group=complexity):
4 rules available
Complexity
complexity.ccn Checks cyclomatic complexity at method and class levels
complexity.ccn judges complexity.ccn, complexity.ccn.max
options: enabled, threshold
options at callable: enabled, error, threshold, warning
options at class: enabled, max-error, max-warning, threshold
--cyclomatic-warning (--rule-opt=complexity.ccn:callable.warning=...)
--cyclomatic-error (--rule-opt=complexity.ccn:callable.error=...)
--cyclomatic-class-warning (--rule-opt=complexity.ccn:class.max-warning=...)
--cyclomatic-class-error (--rule-opt=complexity.ccn:class.max-error=...)
...
Every rule also takes: suppress-namespace-channels, suppress-namespaces, suppress-paths
Usage: bin/qmx check --disable-rule=<name> | --only-rule=<name>
bin/qmx check --rule-opt=<name>:<option>=<value>
Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt
Правила сгруппированы по категориям. Строка options: называет то, что
правило принимает в своём блоке, а строка options at <уровень>: — то, что
принимает слот уровня; это полный набор, независимо от того, есть ли у опции
CLI-алиас. Три ключа в подвале допустимы под любым правилом. enabled
печатается у каждого правила, включая architecture.unassigned-class: false выключает его даже в reportable mode;
явное true с mode: ignore отказывает, потому что producer оставался бы неактивным.
Каждый CLI-алиас показан вместе с длинной формой --rule-opt, в которую он
разворачивается. Значения порогов по умолчанию в этот вывод не входят — см.
Пороги по умолчанию.
Typed values правил и итоговый selection¶
--rule-opt и dedicated aliases разбирают одну объявленную YAML-форму значения.
Например, --lcom-exclude-methods='[getName, getDescription]' пишет sequence;
CSV или scalar не заменяют список. Null не превращается в текст. Две записи
одной canonical option через aliases или --rule-opt в одном invocation отказывают.
Точка в option address проходит только объявленный level slot, а не произвольный
channel-keyed dictionary. suppress_namespace_channels maps пиши в YAML.
Голое имя выбирает точный producer или channel, X.* — строгих потомков.
Пара channel-name:level требует, чтобы именно объявленный channel code публиковался
на этом уровне. Совпадающие producer/channel names работают как имя канала;
отдельного alias producer:level для иначе названных channels нет. Для namespace-channel
exclusion тот же свидетель обязан принадлежать указанному producer/множеству.
Сначала сравниваются слои, затем specificity; в одном слое exact producer enable
сильнее group disable. Поздний exact enable может снять нижний disable.
Exact enable и disable одного producer в одном слое отказывают даже при позднем
перекрытии. only_rules задаёт filter и не включает неактивный producer.
Пустой итоговый selection, dead exact selector, enable вне своего/нижнего итогового
filter и explicit enable при muted option activity отказывают. Высокий disable
может намеренно сузить ранний filter. Пустой only_rules убирает нижний filter,
но пустые maps никогда не сбрасывают options.
Обычно канал выбирается напрямую. Объявленные роли допускают filter-exempt channels или diagnostics, следующие за выбранным addressed producer. Это не дополнительные включения: explicit disable их producer по-прежнему останавливает его. annotation.unresolved-directive и annotation.unused-directive выбираются напрямую; unsupported/invalid threshold errors следуют за addressed producer. Исправь входное значение вместо сокрытия configuration error посторонним only filter.
bin/qmx rules печатает accepted root/level options отдельно от CLI aliases,
затем итоговый only filter и все tied decisive disabled texts. Строка
Selection source: ... (...; layer N) берёт реальный origin и layer index.
Один writer, повторённый в cells, выводится один раз; одинаковый текст разных слоёв
не смешивается. Listing проверяет документ и stated selection, но не effective-band
build/conclude и не runtime state. Directive text/JSON сохраняют все decisive disabling
texts и исключают снятые поздним enable; JSON selection.disabled остаётся списком
строк. Формы значений и слоёв см. в конфигурации.
Окружение прозы¶
QMX_ASCII проверяется до запуска любой команды. Без учёта регистра
1/true/yes/on включают ASCII; 0/false/no/off, пустое и отсутствующее
значение оставляют Unicode. Иное значение даёт отказ с кодом 3 и допустимыми
значениями в причине. Структурированный отказ указывает
source.kind: environment и source.name: QMX_ASCII.
Режим действует на четыре прозаических формата анализа и всю диагностику
ErrorStream, включая прогресс, отчёты в stdout и файлы --output.
Заменяется закрытая таблица глифов продукта; другой Unicode, например Café,
не меняется. Глиф таблицы внутри имени тоже заменяется: K✓ становится K+.
Для сохранения такого имени используй Unicode. Структурированные идентичности
не меняются. Stdout других команд — rules, directive text, отдельный debug
output и DOT — находится вне этого режима.
Селектор неймспейса использует объявленный неймспейс находки. Для файлового
агрегата (annotation.*, duplication.clone) подходит любой неймспейс,
открытый в файле или принадлежащий его декларациям. Если нет ни того ни другого,
используется глобальный неймспейс.
--class не выбирает файловый агрегат. suppress_namespaces намеренно не
делает этот файловый шаг: используй suppress_paths. Перекрывающиеся
namespace exclusions сохраняют кредит первому совпадению.
suppressed --namespace/--class отказывает с кодом 3: документ composition
описывает весь прогон. --show-suppressed допустим; заголовок списка в stderr
говорит, что он относится ко всему прогону и селектор к нему не применён.
Анализ и итоговый код выхода всегда относятся ко всему прогону.