Strikte typering, overal
Spec: ISO 32000-2, §7.5.5 ISO 32000-2 §7.5.5 Evidence: Code-backed PHPStan: Level 10, no src baseline
In een oogopslag
Sectie met titel “In een oogopslag”NextPDF draait PHPStan op Level 10 over de engine-broncode zonder enige onderdrukkingsbaseline. Deze pagina legt uit waarom “geen baseline” een ontwerpbeslissing is en geen tooldetail, en wat die striktheid daadwerkelijk oplevert voor een pijplijn die gegevens niet stilzwijgend verkeerd mag verwerken.
Waarom dit ertoe doet
Sectie met titel “Waarom dit ertoe doet”In de meeste toepassingen is strikte typering vooral hygiëne. In een PDF-engine ligt het dichter bij een correctheidsmechanisme. Het formaat is meedogenloos. Van een lezer wordt verwacht dat die inhoud vindt door het bestand vanaf het einde te lezen, via de trailer en de cross-reference table; daardoor moeten de byte-offsets aan de schrijverskant exact zijn. Denk aan een type dat stilzwijgend verbreedt naar mixed, een int die stilzwijgend een string wordt, of een nullable waarde die ongecontroleerd wordt gedereferentieerd. Elk van die gevallen kan een bestand opleveren dat in de ene viewer probleemloos opent en in een andere niet door de validatie komt, weken later, zonder stack trace die naar de oorzaak verwijst.
De duurste fouten in dit domein zijn de stilzwijgende. Strikte typering plus een strikte analyzer is de manier waarop de engine een categorie stilzwijgende runtimefouten omzet in zichtbare fouten tijdens de build.
De korte versie
Sectie met titel “De korte versie”- De engine-broncode wordt geanalyseerd op PHPStan Level 10 — het strengste niveau — geverifieerd in
phpstan.neon.dist. - Er is geen onderdrukkingsbaseline voor de broncode. De configuratie vergrendelt de broncode-analyse op nul fouten. Een regressie laat de build mislukken in plaats van in een groeiend negeerbestand te belanden.
- De paar
ignoreErrors-vermeldingen die bestaan zijn nauw afgebakend op identifier en pad, en afzonderlijk gemotiveerd in de configuratie (grenzen voor zachte afhankelijkheden tussen packages en reflection-target-testnaden) — geen bulk-baseline. - Een apart strikt profiel draait
level: maxen verbiedt elke nieuwe negeervermelding, zodat nieuwe code aan een nog strengere norm wordt gehouden. - Het beoogde effect is ontwerpdruk: code die niet type-eerlijk kan worden uitgedrukt, komt niet door en wordt daarom opnieuw ontworpen in plaats van onderdrukt.
Hoe NextPDF dit aanpakt
Sectie met titel “Hoe NextPDF dit aanpakt”Het verschil tussen “we gebruiken een strikte analyzer” en “we gebruiken een strikte analyzer zonder baseline” is precies waar het om draait, dus het is de moeite waard om nauwkeurig te zijn.
Een baseline legt elke bestaande overtreding vast en draagt de analyzer op om precies die te negeren. Het is een pragmatische manier om statische analyse in te voeren op een legacy-codebase, maar het heeft een prijs. De baseline wordt een stil schuldgrootboek waar het typesysteem niet meer naar kijkt. Nieuwe overtredingen van dezelfde soort kunnen ongemerkt naast bestaande binnensluipen. De belofte van de analyzer verzwakt van “deze code is type-schoon” naar “deze code is niet slechter dan die was.”
NextPDF maakt die afweging niet voor de engine-broncode. De configuratie vergrendelt de broncode-analyse op nul fouten en schakelt reportUnmatchedIgnoredErrors in, zodat zelfs een verouderde onderdrukking — een die nergens meer op aansluit — de build laat mislukken. De beperkte negeervermeldingen die overblijven zijn afgebakend tot een specifieke fout-identifier en een specifiek bestand. Elk ervan bevat een inline-toelichting waarom de grens opzettelijk is (bijvoorbeeld de core die programmeert tegen een Pro/Enterprise-interface waarvan ze bewust niet concreet afhankelijk wil zijn). Een reviewer kan ze stuk voor stuk lezen en beoordelen. Er is geen ondoorzichtige lijst waardoor je het overzicht kwijtraakt.
De flow die dit eerlijk houdt:
- Change proposed New or modified engine code.
- Level 10 analysis Strictest PHPStan level over src/, treatPhpDocTypesAsCertain on.
- Zero-error gate No source baseline; unmatched ignores also fail.
- Strict profile level: max; no new ignore entries permitted.
- Redesign, not suppress If it cannot be expressed honestly, the design changes.
treatPhpDocTypesAsCertain maakt hier deel van uit. PHPDoc-annotaties worden behandeld als bron van waarheid, dus een @param list<T> of @return non-empty-string is geen commentaar dat de analyzer beleefd negeert. Het is een gecontroleerde belofte. Annotatie en runtimetype moeten overeenkomen.
Wat het bewijs zegt
Sectie met titel “Wat het bewijs zegt”Deze pagina is Evidence: Code-backed . De configuratie is het bewijs:
phpstan.neon.diststeltlevel: 10enphpVersion: 80400in, analyseertsrcen bevat geenbaseline:-sleutel — er is geenphpstan-baseline.neonvoor de broncode-analyse.- Hetzelfde bestand stelt
treatPhpDocTypesAsCertain: trueenreportUnmatchedIgnoredErrors: truein, met een inline-opmerking dat de L10-broncode-analyse op nul fouten is vergrendeld en dat elke regressie CI moet laten mislukken. - De overige
ignoreErrorszijn elk afgebakend peridentifieren vaak perpath, met commentaar dat de motivatie voor de zachte afhankelijkheidsgrens en het reflection-target toelicht — het is geen in bulk gegenereerde baseline. phpstan-strict.neon.disterft die configuratie, verhoogt het niveau naarmaxen bevriest de negeerlijst zodat onder het strikte profiel geen nieuwe vermelding mag worden toegevoegd.
Vanuit de standaarden is de koppeling direct. De engine moet bestanden produceren waarin een lezer vanaf de trailer en de cross-reference table kan navigeren volgens Spec: ISO 32000-2, §7.5.5 ISO 32000-2 §7.5.5 . Exacte byte-offsets zijn een typeprobleem voordat ze een serialisatieprobleem zijn. Een offset is een integer die nooit stilzwijgend iets anders mag worden. Een pijplijn die op Level 10 type-schoon is, heeft al de meeste manieren weggenomen waarop rekenwerk stilletjes mis kan gaan.
Praktisch voorbeeld
Sectie met titel “Praktisch voorbeeld”Strikte typering is het meest zichtbaar waar een domeinregel als type wordt gecodeerd in plaats van als runtimecontrole. De conformiteitsdiscriminator beantwoordt vragen op specificatieniveau met een uitputtende match, zodat een niet-afgehandeld geval een typefout is en geen verkeerde PDF:
declare(strict_types=1);
enum ConformanceMode: string{ case Plain = 'plain'; case PdfUa2 = 'pdfua2'; case PdfA4 = 'pdfa4';
/** @return 2|3|4|null */ public function pdfaPart(): ?int { return match ($this) { self::PdfA4 => 4, default => null, }; }}De @return 2|3|4|null is geen documentatie. Onder
treatPhpDocTypesAsCertain wordt deze gecontroleerd. Een aanroeper die aanneemt dat het resultaat altijd een int is, krijgt dat tijdens de analyse te horen, nog voordat ook maar één byte van een niet-conform PDF/A-onderdeelnummer wordt geschreven.
Veelvoorkomend misverstand
Sectie met titel “Veelvoorkomend misverstand”De valkuil is om “geen baseline” te lezen als “de code heeft toevallig geen overtredingen.” Dat is omgekeerd. De afwezigheid van een baseline is de oorzaak, geen toevallige uitkomst. Omdat er nergens een overtreding kan worden geparkeerd, moet code die er een zou veroorzaken anders worden geschreven. Level 10 zonder source-baseline is een beperking die het ontwerp vormgeeft, geen rapport achteraf dat het beschrijft.
Een tweede misverstand: dat de handvol ignoreErrors-vermeldingen een baseline onder een andere naam zijn. Dat zijn ze niet. Een baseline wordt in bulk gegenereerd en is ondoorzichtig. Deze vermeldingen zijn afzonderlijk geschreven, op identifier afgebakend, toegelicht en beschermd door reportUnmatchedIgnoredErrors, zodat ze niet ongemerkt kunnen verouderen.
Grenzen en beperkingen
Sectie met titel “Grenzen en beperkingen”Deze pagina gaat over de analyse van de engine-broncode. De testsuite wordt geanalyseerd binnen een afzonderlijke, bewust gescheiden scope en configuratie; “geen baseline” is hier een uitspraak over src/, geen bewering dat elke aanvullende analyse in de repository baseline-vrij is. PHPStan bewijst typecorrectheid, geen gedragscorrectheid. Het vervangt de testpiramide niet, maar verwijdert alleen een categorie fouten die tests anders zouden moeten opsporen. Het exacte niveau, de flags en de negeerset kloppen op de reviewdatum van deze pagina. De gezaghebbende bron is altijd phpstan.neon.dist en phpstan-strict.neon.dist in de core-repository.
De editie verandert deze discipline niet. Elke editie wordt gebouwd vanuit dezelfde Level 10-broncode:
| Edition | Availability |
|---|---|
| Core | De Core-broncode wordt geanalyseerd op Level 10 zonder source-baseline. |
| Pro | Pro volgt dezelfde Level 10-discipline voor de broncode. |
| Enterprise | Enterprise volgt dezelfde Level 10-discipline voor de broncode. |
Gerelateerde documentatie
Sectie met titel “Gerelateerde documentatie”- De PHP 8.4-fundamenten — de taalfuncties waarop het typesysteem steunt.
- Fouten als functie — wat er gebeurt met de fouten die strikte typering aan het licht brengt.
- Het pijplijnmodel — de architectuur die deze discipline beschermt.
Verklarende woordenlijst
Sectie met titel “Verklarende woordenlijst”- PHPStan Level 10 — het strengste analyseniveau, dat niet-getypeerde en losjes getypeerde waarden als fouten behandelt in plaats van als waarschuwingen.
- Baseline — een gegenereerd register van bestaande overtredingen die de analyzer opdracht krijgt te negeren. NextPDF gebruikt er geen voor de engine-broncode.
treatPhpDocTypesAsCertain— een PHPStan-instelling die PHPDoc-type-annotaties behandelt als gecontroleerde feiten, niet als adviserend commentaar.reportUnmatchedIgnoredErrors— een instelling die de build laat mislukken wanneer een negeervermelding nergens meer op aansluit, waardoor verouderde onderdrukkingen worden voorkomen.- Ontwerpdruk — het effect van een beperking die afdwingt dat code op een bepaalde manier wordt geschreven, in plaats van een controle die dat alleen meet.