Skip to content

#143 - Improve PHPStan level from 6 to 7 - #252

Merged
njoubert-cleverage merged 1 commit into
mainfrom
143-level-8
Oct 9, 2026
Merged

njoubert-cleverage merged 1 commit into
mainfrom
143-level-8

Conversation

@njoubert-cleverage

Copy link
Copy Markdown
Member

Description

Refs #143 (step 2: level 7, plus the level 8 errors that can be fixed without breaking backward compatibility; the issue stays open).

phpstan.neon goes from level 6 to level 7 (no ignore), with the level 7 errors fixed:

  • ProcessHelpCommand: branches typed as array<int, string|null>, the remaining task list kept as a list, task code explicitly cast to string;
  • CsvResource::tell() throws a \RuntimeException when ftell() fails (instead of a TypeError);
  • SubprocessInstance throws a \RuntimeException when the PHP executable cannot be found;
  • CsvWriterTask: headers taken from the keys of a list input are cast to strings (same CSV output);
  • typing only: FolderBrowserTask (iterator accessed through a private helper), ProcessLauncherTask process_options normalizer, CachedTransformer::generateCacheKey() returning string|false.

Level 8 errors that do not require a signature change are fixed as well (they used to fail with a TypeError or an Error):

  • CsvResource rejects a blank header line (headers used to be ['']);
  • XpathEvaluatorTransformer throws an explicit \UnexpectedValueException on an invalid query (with the libxml messages, instead of a PHP warning), on a namespace node to unwrap and on a node without document;
  • SlugifyTransformer throws an \UnexpectedValueException on a value that cannot be transliterated (e.g. invalid UTF-8);
  • ProcessState::getContext() returns [] until the context is defined, and a ContextualOptionResolver is used by default when none is set; ConditionTrait defaults to a property accessor;
  • GenericTransformer and TransformerTrait throw an explicit \LogicException when not initialized;
  • IterableBatchTask can be flushed and JsonStreamReaderTask iterated before their first execution;
  • RegistryCompilerPass checks its configuration; null guards in AdvancedStatCounterTask and AbstractIterableOutputTask.

Tests: new CsvResourceTest and RegistryCompilerPassTest, new cases in 7 existing tests; TransformerTraitTest uses a named TransformerTraitHolder instead of an anonymous class (whose methods PHPStan could not see), the test loggers of LoggerTaskTest / ValidatorTaskTest build typed records.

On main, the 12 new regression tests fail. PHPStan (level 7, no ignore), PHPUnit (817 tests), PHP-CS-Fixer and Rector pass.

Left for v6.0 (16 level 8 errors)

They all come from native nullable types that are never null in practice: AbstractConfigurableTask::getOptions(): ?array, ProcessState::getContextualizedOptions(): ?array, CsvResource::$lineNumber, ProcessHistory::$startDate. PHPStan keeps the null of the native type even with a stricter PHPDoc, and narrowing the native types is a BC break (e.g. archive-process-bundle UnzipTask / ZipTask override getOptions(): ?array).

Requirements

  • Documentation updates
    • Reference
    • Cookbooks
    • Changelog
  • Unit tests

Breaking changes

None: no native signature is changed. Edge cases that used to fail with a TypeError / Error now throw explicit exceptions, or work (ProcessState::getContext(), IterableBatchTask, JsonStreamReaderTask). A CSV file whose first line is blank is now rejected when headers are read from the file.

🤖 Generated with Claude Code

…el 8 errors not requiring a signature change: explicit exceptions instead of TypeError / Error on edge cases (CsvResource, XpathEvaluatorTransformer, SlugifyTransformer, GenericTransformer, TransformerTrait, RegistryCompilerPass, SubprocessInstance), safe defaults in ProcessState, ConditionTrait, IterableBatchTask and JsonStreamReaderTask

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@njoubert-cleverage
njoubert-cleverage merged commit 81a28b7 into main Oct 9, 2026
17 checks passed
@njoubert-cleverage
njoubert-cleverage deleted the 143-level-8 branch October 9, 2026 09:14
@njoubert-cleverage njoubert-cleverage mentioned this pull request Oct 9, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant