Перейти к содержанию

Конфигурация

Qualimetrix работает из коробки с разумными настройками по умолчанию. Файл конфигурации позволяет настроить пороговые значения, отключить правила и исключить пути, чтобы адаптировать инструмент под ваш проект.


Файл конфигурации

Создайте файл qmx.yaml в корне проекта. Qualimetrix автоматически ищет этот файл.

Также можно указать файл явно:

vendor/bin/qmx check src/ --config=my-config.yaml

Секции конфигурации

Пути для анализа (paths)

Директории для анализа:

paths:
  - src/

Примечание

Если вы передаёте пути через аргументы командной строки (например, vendor/bin/qmx check src/ lib/), они имеют приоритет над конфигурационным файлом.

Исключения (exclude)

Директории, которые полностью пропускаются. Файлы в этих директориях не анализируются вообще:

exclude:
  - vendor/
  - tests/Fixtures/

Включение сгенерированных файлов (include_generated)

По умолчанию файлы с аннотацией @generated в первых 2 КБ автоматически пропускаются при анализе. Чтобы включить их:

include_generated: true

Эквивалент в CLI: --include-generated

Исключение путей из отчёта (exclude_paths)

Паттерны путей для подавления нарушений. В отличие от exclude, эти файлы всё равно анализируются (их метрики собираются), но нарушения не выводятся в отчёт. Поддерживаются префиксы директорий и glob-паттерны:

exclude_paths:
  - src/Entity                # префикс: все файлы в src/Entity/
  - src/Metrics/*Visitor.php  # glob: только файлы визиторов

Также доступна как CLI-опция: --exclude-path (объединяется с YAML-конфигурацией).

Не действует на правила architecture.*

exclude_paths--exclude-path) никогда не подавляют нарушения architecture.layer-violation и architecture.circular-dependency — по той же причине, что и exclude_namespaces ниже: нарушение архитектурной границы — не метрика, и исключение пути, нацеленное на подавление шумных метрик, не должно незаметно становиться способом выключить контроль архитектуры. Чтобы подавить конкретное архитектурное нарушение, используйте @qmx-ignore, запись в baseline или блок exclude: внутри самой конфигурации архитектурных слоёв. Как и для exclude_namespaces, это исключение действует только для глобального механизма — исключение на уровне правила exclude_paths, описанное ниже, для правил architecture.* по-прежнему работает.

Исключение неймспейсов (exclude_namespaces)

Подавление нарушений для классов из определённых неймспейсов (сопоставление по префиксу). Как и exclude_paths, файлы всё равно анализируются и метрики собираются, но нарушения не выводятся. Применяется ко всем правилам глобально:

exclude_namespaces:
  - App\Tests
  - App\Generated

Это полезно, когда целые поддеревья неймспейсов не должны генерировать нарушения. Для исключений на уровне отдельного правила используйте exclude_namespaces внутри конфигурации правила (см. ниже).

Также доступна как CLI-опция: --exclude-namespace (объединяется с YAML-конфигурацией).

Не действует на правила architecture.*

exclude_namespaces--exclude-namespace) никогда не подавляют нарушения architecture.layer-violation и architecture.circular-dependency. Нарушение архитектурной границы — не метрика: если бы оно тоже подавлялось, исключение шумной метрики незаметно выключало бы контроль архитектуры. Чтобы подавить конкретное архитектурное нарушение, используйте @qmx-ignore, запись в baseline или блок exclude: внутри самой конфигурации архитектурных слоёв.

Это исключение действует только для глобального механизма. Исключение на уровне правила exclude_namespaces / exclude_paths, описанное ниже (rules: {architecture.layer-violation: {exclude_namespaces: [...]}}), для правил architecture.* по-прежнему работает — как и для любого другого правила. См. «Правила» ниже и раздел «Подавление нарушений» архитектурного правила — там объяснено, почему эта асимметрия осознанная: явное указание имени правила — однозначный, проверяемый выбор, а глобальная запись exclude_namespaces — нет.

Правила (rules)

Управление активными правилами и настройка пороговых значений.

Полное отключение правила:

rules:
  code-smell.boolean-argument:
    enabled: false

Переопределение пороговых значений:

Каждое правило определяет уровни серьёзности. Когда метрика превышает порог, фиксируется нарушение соответствующего уровня. Например, правило цикломатической сложности имеет пороги для методов:

rules:
  complexity.cyclomatic:
    method:
      warning: 15
      error: 25

Это означает: выдавать предупреждение (warning), когда цикломатическая сложность метода достигает 15, и ошибку (error), когда достигает 25.

Сокращённая запись threshold:

Если вам нужен простой порог "прошёл/не прошёл" (все нарушения — ошибки), используйте threshold вместо отдельных warning и error:

rules:
  complexity.cyclomatic:
    method:
      threshold: 15    # warning=15 и error=15 → все нарушения становятся ошибками

  size.method-count:
    threshold: 25      # то же самое, что warning: 25, error: 25

Это эквивалентно warning: 15 + error: 15. Полезно в CI, где нужен бинарный результат.

Ограничение

Нельзя смешивать threshold с явными ключами warning/error в пределах одного слоя конфигурации (одного пресета, одного qmx.yaml, одного вызова CLI) для одного и того же уровня правила — это конфигурационная ошибка.

Переопределение режима между слоями: более приоритетный слой (файл конфигурации поверх пресета, CLI поверх файла конфигурации) может свободно переключать режим для уровня правила — например, пресет strict задаёт warning/error, а --rule-opt=size.method-count:threshold=25 в командной строке переключает это правило на единый порог. threshold из CLI перекрывает warning/error из пресета, а не конфликтует с ними:

# qmx.yaml (или пресет)
rules:
  size.method-count:
    warning: 10
    error: 20
# CLI переключает правило в режим простого порога "прошёл/не прошёл" — без ошибки "cannot mix"
bin/qmx check src/ --rule-opt=size.method-count:threshold=25

То же самое работает и в обратную сторону (threshold из нижнего слоя перекрывается парой warning/error из более приоритетного), а также для составных правил — на том уровне вложенности, где заданы ключи (например, method:/class: у complexity.cyclomatic).

coupling.cbo и coupling.instability тоже принимают голый threshold на своём верхнем уровне, но с другим эффектом, чем у complexity.cyclomatic: поскольку их дефолты для class/namespace совпадают, threshold на верхнем уровне применяется РАВНОМЕРНО к ОБОИМ уровням сразу, а не только к более детальному:

rules:
  coupling.cbo:
    threshold: 15   # class И namespace: warning=error=15

Для правила design.type-coverage доступны специализированные варианты: param_threshold, return_threshold, property_threshold.

Вычисляемые метрики (computed metrics) также поддерживают threshold.

Исключение неймспейсов из правила:

Любое правило может исключить конкретные неймспейсы по префиксу. Нарушения из совпадающих неймспейсов подавляются:

rules:
  complexity.cyclomatic:
    exclude_namespaces:
      - App\Tests
      - App\Legacy
    method:
      warning: 15
      error: 25

  coupling.cbo:
    exclude_namespaces:
      - App\Tests
    exclude_paths:
      - src/Infrastructure/DependencyInjection

Это полезно, когда определённые неймспейсы (например, тесты, сгенерированный код, legacy-модули) не должны вызывать нарушения для конкретного правила, но при этом всё равно анализируются для сбора метрик.

Работает для любого правила, включая architecture.*

exclude_namespaces и exclude_paths извлекаются и применяются на уровне фреймворка для любого имени правила, независимо от того, объявляет ли класс Options этого правила такое поле — это намеренно не opt-in для каждого правила по отдельности. Это касается и architecture.layer-violation, и architecture.circular-dependency — они исключены из глобальных exclude_namespaces и exclude_paths выше, но не из этой формы на уровне правила: явное указание имени правила делает подавление однозначным, проверяемым выбором, а не побочным эффектом project-wide исключения. См. раздел «Подавление нарушений» архитектурного правила — там объяснена логика.

Исключение путей из правила:

Любое правило может исключить конкретные файлы по префиксу пути или glob-паттерну. Нарушения из совпадающих файлов подавляются:

rules:
  coupling.cbo:
    exclude_paths:
      - src/Metrics                # префикс: все файлы в src/Metrics/
      - src/Metrics/*Visitor.php   # glob: только файлы визиторов

Работает совместно с exclude_namespaces -- оба фильтра применяются. В отличие от глобального exclude_paths, эта опция на уровне правила влияет только на конкретное правило, а не на все.

Видимость: в отличие от @qmx-ignore, это подавление по умолчанию происходит незаметно — ничто в стандартном выводе не намекает на то, что нарушения были отброшены. Запустите с -v, чтобы увидеть разбивку по правилам — сколько нарушений подавлено таким образом (отдельно для exclude_namespaces и exclude_paths), и добавьте --show-suppressed, чтобы также вывести список каждого подавленного нарушения — вместе с нарушениями, подавленными через @qmx-ignore.

Переопределение порогов для символа через @qmx-threshold:

Помимо общих для проекта порогов в YAML, можно переопределять пороги для отдельных классов или методов с помощью аннотаций @qmx-threshold прямо в исходном коде:

/**
 * @qmx-threshold complexity.cyclomatic method.warning=20 method.error=40
 */
class ComplexStateMachine
{
    // Методы этого класса используют повышенные пороги сложности
}

Полный синтаксис и примеры смотрите в разделе Baseline > @qmx-threshold.

Отключение правил (disabled_rules)

Отключение конкретных правил или целых групп:

disabled_rules:
  - code-smell.boolean-argument
  - duplication

Эквивалент в CLI: --disable-rule=code-smell.boolean-argument --disable-rule=duplication

Только указанные правила (only_rules)

Запустить только указанные правила (все остальные отключаются):

only_rules:
  - complexity.cyclomatic
  - complexity.cognitive

Эквивалент в CLI: --only-rule=complexity.cyclomatic --only-rule=complexity.cognitive

Условие завершения с ошибкой (fail_on)

Управление тем, какие уровни серьёзности приводят к ненулевому коду завершения:

fail_on: error    # Завершение с ошибкой только при error (по умолчанию)
# fail_on: warning  # Завершение с ошибкой и при warning
# fail_on: info     # Завершение с ошибкой при любом нарушении, включая Info
# fail_on: none     # Никогда не завершаться с ошибкой из-за нарушений

Примечание

По умолчанию fail_on установлен в error. Предупреждения и Info-диагностики по-прежнему отображаются в выводе, но не приводят к ненулевому коду завершения. Используйте fail_on: warning, чтобы блокировать сборку и предупреждениями, или fail_on: info, чтобы дополнительно учитывать Info-диагностики (например, architecture.unreachable-layer и architecture.potential-shadow).

Исключение измерений здоровья (exclude_health)

Исключить конкретные измерения здоровья из оценки. Исключённые измерения не отображаются в сводке здоровья и не влияют на общую оценку:

exclude_health:
  - typing
  - maintainability

Эквивалент в CLI: --exclude-health=typing --exclude-health=maintainability

Лимит памяти (memory_limit)

Лимит памяти PHP для анализа. По умолчанию используется значение memory_limit из php.ini.

memory_limit: 1G    # 1 гигабайт
# memory_limit: -1  # Без ограничений

Эквивалент в CLI: --memory-limit=1G

Формат вывода (format)

Формат отчёта по умолчанию:

format: summary   # По умолчанию
# format: json
# format: html

Кэширование (cache)

Управление кэшированием AST для ускорения повторных запусков:

cache:
  enabled: true         # По умолчанию: true
  dir: .qmx-cache       # По умолчанию: .qmx-cache

Эквивалент в CLI: --no-cache для отключения, --cache-dir=DIR для изменения директории.

Параллельная обработка (parallel)

Количество параллельных воркеров для анализа файлов:

parallel:
  workers: 4     # Фиксированное количество воркеров
  # workers: 0   # Отключить параллелизм (однопоточный режим)

По умолчанию Qualimetrix автоматически определяет оптимальное количество воркеров по числу ядер CPU. Эквивалент в CLI: --workers=4

Совет

Используйте workers: 0 для отладки или в окружениях без ext-parallel.

Определение неймспейсов (namespace)

Стратегия определения соответствия неймспейсов и директорий:

namespace:
  strategy: chain          # По умолчанию: chain (сначала psr4, затем tokenizer)
  # strategy: psr4         # Только PSR-4 (требует composer.json)
  # strategy: tokenizer    # Парсинг неймспейса из PHP-токенов
  composer_json: composer.json   # Путь к composer.json для PSR-4

Связанность (coupling)

Настройка префиксов неймспейсов фреймворка для метрики CBO (Coupling Between Objects). Зависимости от неймспейсов фреймворка отслеживаются отдельно как cbo_app и ce_framework:

coupling:
  framework-namespaces:
    - Symfony
    - Doctrine
    - Psr
    - Illuminate

Если framework-namespaces не указаны, cbo_app равен cbo (без эффекта).

Агрегация (aggregation)

Управление группировкой неймспейсов для агрегированных метрик:

aggregation:
  prefixes:
    - App\Domain
    - App\Infrastructure
  auto_depth: 2    # Автоопределение глубины группировки

Архитектура (architecture)

Правила слоёв и allow-list для правила architecture.layer-violation живут под верхнеуровневым ключом architecture:. Полная схема описана в правилах архитектуры; ключи, наиболее релевантные для общей конфигурации:

architecture:
  layers:
    - name: 'domain-{module}'                         # шаблонный слой с переменной захвата
      patterns: ['App\Module\{module}\Domain\**']
    - name: shared-kernel
      patterns: ['App\Shared\**']

  allow:
    'domain-{m}':
      - shared-kernel
      - target: 'domain-{m}'
        relations: [implements, extends]              # whitelist видов зависимостей

  coverage: ignore                                    # ignore | warn | error
  max_expanded_layers: 500                            # кумулятивный лимит на раскрытие шаблонов

Переменные захвата в именах слоёв и паттернах используют синтаксис {name} (один сегмент namespace) или {name:**} (cross-segment). Одно и то же имя переменной в пределах одной записи слоя привязывается к одному значению (co-binding); переменные в разных записях независимы. Полную грамматику см. в секции про шаблонные слои.

max_expanded_layers ограничивает общее количество конкретных слоёв, производимых раскрытием шаблонов по всем шаблонам (по умолчанию 500). Лимит защищает от патологически широких шаблонов, чьи binding tuples взорвали бы число слоёв. Поднимайте предел явно, когда монорепо легитимно содержит больше bounded contexts, чем дефолт; превышение отклоняется на стадии раскрытия с понятной ошибкой.


Пресеты

Пресеты — это именованные наборы конфигурации, которые применяют предопределённые настройки: пороговые значения, отключённые правила, поведение при ошибках — одним флагом. Вместо ручной настройки десятков параметров выберите пресет, соответствующий зрелости вашего проекта.

Пресет Описание
strict Строгие пороговые значения для новых проектов. Устанавливает fail_on: warning
legacy Ослабленные пороговые значения для легаси-кодовых баз. Отключает шумные правила
ci Явный режим CI. Устанавливает fail_on: error
# Использовать один пресет
vendor/bin/qmx check src/ --preset=strict

# Комбинировать несколько пресетов
vendor/bin/qmx check src/ --preset=strict,ci

# Использовать пользовательский файл пресета
vendor/bin/qmx check src/ --preset=./my-preset.yaml

Порядок приоритетов: Пресеты применяются после обнаружения composer.json, но до qmx.yaml. Ваш файл конфигурации всегда переопределяет значения из пресетов.

Несколько пресетов: При комбинировании пресетов они объединяются слева направо — последующие пресеты переопределяют предыдущие, за исключением списковых ключей вроде disabled_rules, которые накапливаются. Например, --preset=legacy,ci даёт ослабленные пороговые значения с поведением CI при ошибках.

Внимание

only_rules не накапливается между пресетами — значение из последнего пресета полностью заменяет предыдущие. Это сделано намеренно: only_rules — это ограничивающий фильтр, и объединение расширяло бы область действия.

Пользовательские пресеты: Любой YAML-файл со структурой qmx.yaml можно использовать как пресет. Передайте путь к файлу вместо имени встроенного пресета.


Полный пример

# Или начните с пресета и настройте:
# vendor/bin/qmx check src/ --preset=strict

paths:
  - src/

exclude:
  - vendor/
  - tests/Fixtures/

exclude_paths:
  - src/Entity
  - src/DTO

exclude_namespaces:
  - App\Tests

include_generated: false

format: summary
fail_on: error

cache:
  enabled: true
  dir: .qmx-cache

parallel:
  workers: 4

coupling:
  framework-namespaces:
    - Symfony
    - Doctrine

exclude_health:
  - typing

disabled_rules:
  - code-smell.boolean-argument
  - duplication

rules:
  complexity.cyclomatic:
    exclude_namespaces:
      - App\Tests
    exclude_paths:
      - src/Generated
    method:
      warning: 15
      error: 25

  size.method-count:
    warning: 25
    error: 40

Параметры CLI имеют приоритет

Параметры командной строки всегда имеют приоритет над значениями из конфигурационного файла. Например:

# В конфиге указано paths: [src/], но CLI переопределяет
vendor/bin/qmx check lib/

# Добавить дополнительные исключения поверх конфига
vendor/bin/qmx check src/ --exclude-path='src/Generated/*'

Это позволяет экспериментировать без редактирования файла конфигурации.


Валидация конфигурации

Qualimetrix валидирует конфигурационный файл и сообщает о типичных ошибках понятными сообщениями.

Неизвестные ключи

Любой нераспознанный ключ — на верхнем уровне или внутри секции — вызывает ошибку с подсказкой:

Invalid configuration in qmx.yaml:
  Unknown key "workes" in "parallel" section. Did you mean "workers"?

Ошибки типов

Если значение имеет неверный тип, вы получите понятное сообщение вместо молчаливого отката на значение по умолчанию:

Invalid value for "cache.enabled": expected boolean, got string

Неизвестные имена правил

Опечатки в именах правил в секции rules: отклоняются:

Unknown rule "complexty.cyclomatic" in qmx.yaml. Did you mean "complexity.cyclomatic"?

Tip

Установите значение ~ (YAML null) или оставьте пустым, чтобы явно использовать значение по умолчанию — это всегда допустимо.


Что дальше?

Смотрите справочник параметров CLI для полного списка параметров командной строки.