Skip to main content

Coding standards

lint checks the codebase with every linter you kept in the installer, and lint-fix runs the ones that can fix what they find. Both stop at the first tool that fails. This page lists the tools, where they run and how to fix what they report.

To check and fix the codebase, run the following commands:

make lint # Check coding standards
make lint-fix # Fix what the tools can fix

ahoy lint running the linters on the extension in a terminal

The tools​

Locally, lint runs the tools in the order of the following table, while CI runs CSpell first (see In CI). The configuration files live in your project root, and CI reads the same files. So 1 edit changes a rule on your machine and in CI. The PHP and JavaScript tools read copies that assemble makes, as Where they run explains.

ToolWhat it checksConfigurationFixes
PHPCSPHP against the Drupal, DrupalPractice, DrevOps and PHPCompatibility standards for PHP 8.3, and declare(strict_types=1) in every file.phpcs.xmlYes
PHPStanPHP with static analysis, with PHPStan Drupal.phpstan.neonNo
Drupal RectorPHP for deprecated Drupal code. Rector also applies the PHP 8.3 upgrade sets and strict types, plus its dead code, code quality, coding style, type declaration, privatization and naming sets.rector.phpYes
Twig CS FixerTwig templates..twig-cs-fixer.phpYes
ESLintJavaScript, with Prettier formatting..eslintrc.json, .eslintignore, .prettierrc.json, .prettierignoreYes
StylelintCSS..stylelintrc.jsYes
CSpellSpelling across the codebase..cspell.jsonNo

Where they run​

The PHP and JavaScript tools run from the build directory, where the assembled site holds Drupal core and your dependencies. So run assemble, or build the site, before you lint. ESLint and Stylelint check the extension through its directory in the site. They run only when the build installed the frontend dependencies. Otherwise lint and lint-fix skip them without a warning (see Frontend dependencies).

assemble copies the configuration files of the PHP and JavaScript tools into build, so an edit to one applies after the next assemble. Edit the files in your project root, since the next assemble replaces the copies in build.

CSpell runs from the project root and reads .cspell.json in place. It installs the root package.json dependencies first when node_modules is missing. It checks every text file that git doesn't ignore. It skips hidden files and directories, such as .github. It also skips the paths in the ignorePaths of .cspell.json.

Fix what the linters report​

lint-fix runs Rector, PHPCBF, Twig CS Fixer, ESLint and Stylelint with their fix options. PHPCBF is the fixer that comes with PHPCS. To fix what these tools can fix, run the following command:

make lint-fix

Review the changes before you commit them. When an automatic fix is wrong, adjust the tool's configuration to suppress the issue or change the fix.

Spelling​

CSpell checks prose, code and inline code in Markdown, and skips fenced code blocks. An unknown word fails the check. To make CSpell accept a word:

  • Add a word the whole project uses to the words of .cspell.json.
  • Add a word only 1 file uses to that file, in a comment such as cspell:ignore laminas written in the file's own comment syntax. 1 comment can list several words, separated by spaces.

In CI​

CI runs the same tools in its lint jobs, 1 per Drupal major you test. Each tool runs in a step of its own, apart from ESLint and Stylelint, which share 1. CSpell runs first, then the others in the order of the table. A step that fails stops the job, so the steps after it don't run.

To let a step fail without failing the job while you work through its findings, set the step's ignore-failure variable. It's a repository variable, so it covers that step in every lint job. The steps after it then still run.