Skip to content

Commit d8c3561

Browse files
committed
Refactor various files to ensure proper newline at end of file; enhance test cases for optional tuple parameters and lazy callable collections; improve error message assertions in AdvancedEdgeCasesTest.
1 parent 4a0bf91 commit d8c3561

9 files changed

Lines changed: 57 additions & 21 deletions

File tree

src/Internal/Checker/ReturnChecker.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,4 @@ private static function resolveConditionalReturnType(
199199

200200
return $returnTypeNode;
201201
}
202-
}
202+
}

src/Internal/DocblockNormalizer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ function (array $matches): string {
5252
$doc
5353
) ?? $doc;
5454
}
55-
}
55+
}

src/Internal/ErrorFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,4 @@ public static function prepareException(TypeError $e, ?int $line = null): TypeEr
8686

8787
return $e;
8888
}
89-
}
89+
}

src/Wrapper/IterableWrapper.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace TypePHP\Wrapper;
66

7-
use ArrayIterator;
87
use Generator;
98
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
109
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
@@ -144,4 +143,4 @@ private static function wrapGenerator(iterable $iterable, \Closure $typeCheckCal
144143
yield $key => $value;
145144
}
146145
}
147-
}
146+
}

tests/Fixtures/Services/ClassUsingAliasedTraitMethod.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ class ClassUsingAliasedTraitMethod
99
use ShiftedLoggerTrait {
1010
logEvent as recordAuditLog; // Aliases logEvent -> recordAuditLog
1111
}
12-
}
12+
}

tests/Internal/DocblockNormalizerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,4 @@
126126

127127
expect(DocblockNormalizer::normalize($doc))->toBe($expected);
128128
});
129-
});
129+
});

tests/RuntimeChecker/GeneratorCheckerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ function sampleGeneratorFixture(): Generator
5050
->and($result->getMessage())->toContain('Generator sent value (TSend)')
5151
;
5252
});
53-
});
53+
});

tests/TypeChecking/ArraysAndShapes/ArrayAndListTypesTest.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,38 @@ function testReturnKeylessTuple(bool $valid): array
175175
return [[10, 20], 'bundle'];
176176
}
177177

178+
/**
179+
* Positional Tuple with Optional Trailing Element
180+
*
181+
* @param array{0: positive-int, 1?: non-empty-string} $tuple
182+
*/
183+
function testOptionalTupleParam(array $tuple): bool
184+
{
185+
return true;
186+
}
187+
188+
describe('Positional Tuples with Optional Trailing Elements (array{0: T1, 1?: T2})', function () {
189+
test('accepts tuple when optional trailing element is omitted', function () {
190+
expect(testOptionalTupleParam([42]))->toBeTrue();
191+
});
192+
193+
test('accepts tuple when optional trailing element is provided with valid value', function () {
194+
expect(testOptionalTupleParam([42, 'Alice']))->toBeTrue();
195+
});
196+
197+
test('throws TypeError when required first tuple item is invalid', function () {
198+
expect(fn () => testOptionalTupleParam([-5]))
199+
->toThrow(TypeError::class, "['0'] must be of type positive-int")
200+
;
201+
});
202+
203+
test('throws TypeError when optional second tuple item is provided with invalid value', function () {
204+
expect(fn () => testOptionalTupleParam([42, '']))
205+
->toThrow(TypeError::class, "['1'] must be of type non-empty-string")
206+
;
207+
});
208+
});
209+
178210
describe('Class Object Arrays (Dog[])', function () {
179211
test('accepts array of matching class instances', function () {
180212
expect(testDogArrayParam([new Dog(), new Dog()]))->toBe(2);
@@ -433,7 +465,8 @@ function testReturnKeylessTuple(bool $valid): array
433465
];
434466

435467
expect(fn () => testUnsealedTypedShape($payload))
436-
->toThrow(TypeError::class, "['code'] must be of type string, int (999) given");
468+
->toThrow(TypeError::class, "['code'] must be of type string, int (999) given")
469+
;
437470
});
438471
});
439472
});

tests/TypeChecking/Boundaries/AdvancedEdgeCasesTest.php

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,17 @@ function testNestedConditionalReturn(string $format, mixed $value): mixed
9797
/** @var GenericCollection<?positive-int> $collection */
9898
$collection = new GenericCollection();
9999

100-
expect(fn() => $collection->add(-50))
101-
->toThrow(TypeError::class, 'Argument $item (template T = ?positive-int) must be of type positive-int, negative int (-50) given');
100+
expect(fn () => $collection->add(-50))
101+
->toThrow(TypeError::class, 'Argument $item (template T = ?positive-int) must be of type positive-int, negative int (-50) given')
102+
;
102103
});
103104
});
104105

105106
describe('Collections of Lazy Callables', function () {
106107
test('executes and validates a list of lazy callable proxies', function () {
107108
$formatters = [
108-
fn(int $id): string => "id_{$id}",
109-
fn(int $id): string => "user#{$id}",
109+
fn (int $id): string => "id_{$id}",
110+
fn (int $id): string => "user#{$id}",
110111
];
111112

112113
$results = processFormatterList($formatters, 42);
@@ -115,28 +116,31 @@ function testNestedConditionalReturn(string $format, mixed $value): mixed
115116

116117
test('throws TypeError when a callable in the collection returns an invalid type', function () {
117118
$formatters = [
118-
fn(int $id): string => "id_{$id}",
119-
fn(int $id): string => '',
119+
fn (int $id): string => "id_{$id}",
120+
fn (int $id): string => '',
120121
];
121122

122-
expect(fn() => processFormatterList($formatters, 42))
123-
->toThrow(TypeError::class, 'Callback $formatters[1] return value must be of type non-empty-string');
123+
expect(fn () => processFormatterList($formatters, 42))
124+
->toThrow(TypeError::class, 'Callback $formatters[1] return value must be of type non-empty-string')
125+
;
124126
});
125127
});
126128

127129
describe('Multi-Branch Nested Conditional Return Types', function () {
128130
test('throws TypeError when return value violates nested conditional branch', function () {
129-
expect(fn() => testNestedConditionalReturn('float', -5.5))
130-
->toThrow(TypeError::class, 'Return value must be of type positive-float');
131+
expect(fn () => testNestedConditionalReturn('float', -5.5))
132+
->toThrow(TypeError::class, 'Return value must be of type positive-float')
133+
;
131134
});
132135
});
133136

134137
describe('Trait Method Aliasing (use Trait { old as new; })', function () {
135138
test('inherits DocBlock contracts when a Trait method is aliased in a class', function () {
136139
$service = new TypePHP\Tests\Fixtures\Services\ClassUsingAliasedTraitMethod();
137140

138-
expect(fn() => $service->recordAuditLog(-1, 'audit_ok'))
139-
->toThrow(TypeError::class, 'Argument $level must be of type positive-int');
141+
expect(fn () => $service->recordAuditLog(-1, 'audit_ok'))
142+
->toThrow(TypeError::class, 'Argument $level must be of type positive-int')
143+
;
140144
});
141145
});
142146
});

0 commit comments

Comments
 (0)