class TypeStringParserTest extends TestCase (View source)

Boundary tests for the structural type-string grammar.

This is the single implementation used by the serializers, the stub type converter and the validators, and it had no direct test at all — a regression here silently changes every parsed type in the project. The tests below pin each grammar branch and, in particular, the two precedence rules that are easy to break: | is examined before & so DNF strings are not misrouted to intersection parsing, and the nullable shorthand is only applied when the non-null part is not a parenthesised group.

Methods

void
setUp()

No description

testGrammarProducesTheExpectedTypeShape(string $input, string $expectedClass, string $expectedString)

No description

static array
grammarCases()

No description

testDnfUnionKeepsItsIntersectionMembers()

| must be examined before &. If the order were reversed, "int|(A&B)" would be routed to intersection parsing and the union structure would be lost entirely.

testParenthesisedBranchDoesNotSwallowAWholeDnfString()

The parenthesised-intersection branch is guarded by "contains no |". Without that guard, "(A&B)|(C&D)" starts with '(' and ends with ')' and would be mis-parsed as one intersection of the whole inner text.

testNullableIntersectionStaysAUnionRatherThanCollapsing()

A nullable DNF type must stay a UnionType: the nullable shorthand cannot represent an intersection as its basic type, since NullableType only accepts a StandaloneType.

testUnionWithNullAndTwoOthersIsNotCollapsedToNullable()

Three parts including null is a union, not a nullable — nullable is the exactly-two case.

testEveryLeafNamePassesThroughTheResolver(string $input, string $expected)

No description

static array
everyLeafIsResolvedCases()

No description

testNullMatchingInTheNullableCollapseIsCaseSensitive()

'null' in a two-part union is matched literally and case-sensitively, so 'NULL' does not trigger the nullable collapse. Pinned because the surrounding code lowercases elsewhere, making this a plausible thing to "harmonise" and thereby change behaviour.

testIntersectionMembersAreTrimmed()

Intersection members are trimmed, so a spaced source type hint parses the same.

testUnionPartsAreTrimmed()

Union parts are trimmed too, via splitUnionParts().

testDnfGroupSurvivesAlongsidePlainUnionMembers()

A DNF group survives alongside plain members in a three-part union.

testUnionSplittingRespectsParenthesisDepth()

splitUnionParts() tracks parenthesis depth, so a '|' inside a group is not a separator.

testTrailingSeparatorDoesNotProduceAnEmptyMember()

A trailing separator yields no empty trailing member (splitUnionParts drops it).

testRenderedTypesReparseToTheSameShapeAndString(string $input)

toString() renders in a form the parser accepts again, and re-parsing is stable. Note the ?Foo shorthand normalises to Foo|null on the way out, so the round trip is idempotent from the second pass onward rather than character-preserving on the first.

static array
roundTripCases()

No description

Details

protected void setUp()

No description

Return Value

void

testGrammarProducesTheExpectedTypeShape(string $input, string $expectedClass, string $expectedString)

No description

Parameters

string $input
string $expectedClass
string $expectedString

static array grammarCases()

No description

Return Value

array

testDnfUnionKeepsItsIntersectionMembers()

| must be examined before &. If the order were reversed, "int|(A&B)" would be routed to intersection parsing and the union structure would be lost entirely.

testDnfUnionOfTwoIntersectionGroups()

No description

testParenthesisedBranchDoesNotSwallowAWholeDnfString()

The parenthesised-intersection branch is guarded by "contains no |". Without that guard, "(A&B)|(C&D)" starts with '(' and ends with ')' and would be mis-parsed as one intersection of the whole inner text.

testNullableIntersectionStaysAUnionRatherThanCollapsing()

A nullable DNF type must stay a UnionType: the nullable shorthand cannot represent an intersection as its basic type, since NullableType only accepts a StandaloneType.

testUnionWithNullAndTwoOthersIsNotCollapsedToNullable()

Three parts including null is a union, not a nullable — nullable is the exactly-two case.

testEveryLeafNamePassesThroughTheResolver(string $input, string $expected)

No description

Parameters

string $input
string $expected

static array everyLeafIsResolvedCases()

No description

Return Value

array

testNullMatchingInTheNullableCollapseIsCaseSensitive()

'null' in a two-part union is matched literally and case-sensitively, so 'NULL' does not trigger the nullable collapse. Pinned because the surrounding code lowercases elsewhere, making this a plausible thing to "harmonise" and thereby change behaviour.

testIntersectionMembersAreTrimmed()

Intersection members are trimmed, so a spaced source type hint parses the same.

testUnionPartsAreTrimmed()

Union parts are trimmed too, via splitUnionParts().

testDnfGroupSurvivesAlongsidePlainUnionMembers()

A DNF group survives alongside plain members in a three-part union.

testUnionSplittingRespectsParenthesisDepth()

splitUnionParts() tracks parenthesis depth, so a '|' inside a group is not a separator.

No valid PHP type reaches this: DNF forbids a union inside parentheses, and every well-formed input has only '&' inside its groups. So the depth counter can only be pinned with a synthetic string — and it must be pinned structurally, because toString() renders '(A|B)' either way whether the group was kept whole or split into '(A' and 'B)'. Dropping the depth check passes every other test in this class, so without this one the counter is unguarded.

testTrailingSeparatorDoesNotProduceAnEmptyMember()

A trailing separator yields no empty trailing member (splitUnionParts drops it).

testRenderedTypesReparseToTheSameShapeAndString(string $input)

toString() renders in a form the parser accepts again, and re-parsing is stable. Note the ?Foo shorthand normalises to Foo|null on the way out, so the round trip is idempotent from the second pass onward rather than character-preserving on the first.

Parameters

string $input

See also

NullableType::toString

static array roundTripCases()

No description

Return Value

array