Skip to content

Commit a0550d2

Browse files
authored
Merge pull request #47 from xp-framework/feature/implementation
Implement `Package::implementation()` to load implementations of a given type
2 parents fabe0fa + 062f912 commit a0550d2

File tree

5 files changed

+80
-19
lines changed

5 files changed

+80
-19
lines changed

README.md

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,14 @@ if ($parameters->accept($args)) {
164164
}
165165

166166
foreach ($parameters as $name => $parameter) {
167-
$parameter->position(); // 0
168-
$parameter->name(); // 'arg'
169-
$parameter->variadic(); // false
170-
$parameter->optional(); // true
171-
$parameter->default(); // (parameter default value)
172-
$parameter->constraint(); // Constraint
173-
$parameter->annotations(); // Annotations
174-
$parameter->annotation(Inject::class) // Annotation or NULL
167+
$parameter->position(); // 0
168+
$parameter->name(); // 'arg'
169+
$parameter->variadic(); // false
170+
$parameter->optional(); // true
171+
$parameter->default(); // (parameter default value)
172+
$parameter->constraint(); // Constraint
173+
$parameter->annotations(); // Annotations
174+
$parameter->annotation(Inject::class) // Annotation or NULL
175175
}
176176
```
177177

@@ -182,12 +182,13 @@ use lang\Reflection;
182182

183183
$package= Reflection::of('org.example');
184184

185-
$package->name(); // org.example
186-
$package->literal(); // 'org\example'
187-
$package->type('Fixture'); // Type instance
188-
$package->types(); // iterable with Type instances
189-
$package->parent() // Package or NULL
190-
$package->child('impl') // Child package "org.example.impl" or NULL
191-
$package->children(); // iterable with Package instances
192-
$package->classLoaders(); // iterable with lang.ClassLoader instances
185+
$package->name(); // org.example
186+
$package->literal(); // 'org\example'
187+
$package->type('Fixture'); // Type instance
188+
$package->implementation($t, 'Fixture'); // Type instance (subclass of $t)
189+
$package->types(); // iterable with Type instances
190+
$package->parent() // Package or NULL
191+
$package->child('impl') // Child package "org.example.impl" or NULL
192+
$package->children(); // iterable with Package instances
193+
$package->classLoaders(); // iterable with lang.ClassLoader instances
193194
```

src/main/php/lang/reflection/Package.class.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,21 @@ public function type($name) {
122122
throw new IllegalArgumentException('Given type '.$type.' is not in package '.$this->name);
123123
}
124124

125+
/**
126+
* Returns an implementation for a given type
127+
*
128+
* @param string|lang.reflection.Type $type
129+
* @param string $name
130+
* @return lang.reflection.Type
131+
* @throws lang.IllegalArgumentException
132+
*/
133+
public function implementation($type, $name) {
134+
$impl= $this->type($name);
135+
if ($impl->is($type)) return $impl;
136+
137+
throw new IllegalArgumentException('Given type '.$impl->name().' is not an implementation of '.$type);
138+
}
139+
125140
/** @return string */
126141
public function hashCode() { return md5($this->name); }
127142

src/test/php/lang/reflection/unittest/PackageTest.class.php

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
<?php namespace lang\reflection\unittest;
22

3-
use lang\IllegalArgumentException;
43
use lang\reflection\Package;
4+
use lang\reflection\unittest\fixture\{Instruction, CreateInstruction};
5+
use lang\{Reflection, IllegalArgumentException};
56
use test\{Assert, Expect, Test, Values};
67

78
class PackageTest {
9+
const FIXTURES= 'lang.reflection.unittest.fixture';
10+
11+
/** @return iterable */
12+
private function instructions() {
13+
yield [Instruction::class, 'class literal'];
14+
yield ['lang.reflection.unittest.fixture.Instruction', 'class name'];
15+
yield [Reflection::type(Instruction::class), 'type'];
16+
}
817

918
#[Test, Values(['lang.reflection', 'lang\reflection', 'lang.reflection.'])]
1019
public function name($arg) {
@@ -90,16 +99,42 @@ public function types() {
9099

91100
#[Test]
92101
public function type_via_short_name() {
93-
Assert::equals(self::class, (new Package(__NAMESPACE__))->type('PackageTest')->literal());
102+
Assert::equals(Reflection::type(self::class), (new Package(__NAMESPACE__))->type('PackageTest'));
94103
}
95104

96105
#[Test]
97106
public function type_via_full_name() {
98-
Assert::equals(self::class, (new Package(__NAMESPACE__))->type(self::class)->literal());
107+
Assert::equals(Reflection::type(self::class), (new Package(__NAMESPACE__))->type(self::class));
99108
}
100109

101110
#[Test, Expect(class: IllegalArgumentException::class, message: 'Given type util.Date is not in package lang')]
102111
public function type_with_namespace() {
103112
(new Package('lang'))->type('util.Date');
104113
}
114+
115+
#[Test, Values(from: 'instructions')]
116+
public function implementation_by_name($type) {
117+
Assert::equals(
118+
Reflection::type(CreateInstruction::class),
119+
(new Package(self::FIXTURES))->implementation($type, 'CreateInstruction')
120+
);
121+
}
122+
123+
#[Test, Values(from: 'instructions')]
124+
public function implementation_by_class($type) {
125+
Assert::equals(
126+
Reflection::type(CreateInstruction::class),
127+
(new Package(self::FIXTURES))->implementation($type, CreateInstruction::class)
128+
);
129+
}
130+
131+
#[Test, Expect(class: IllegalArgumentException::class, message: '/Given type util.Date is not in package .+/')]
132+
public function implementation_not_in_package() {
133+
(new Package(self::FIXTURES))->implementation(Instruction::class, 'util.Date');
134+
}
135+
136+
#[Test, Expect(class: IllegalArgumentException::class, message: '/Given type .+ is not an implementation of lang.Runnable/')]
137+
public function not_an_implementation() {
138+
(new Package(self::FIXTURES))->implementation('lang.Runnable', 'CreateInstruction');
139+
}
105140
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php namespace lang\reflection\unittest\fixture;
2+
3+
class CreateInstruction implements Instruction {
4+
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php namespace lang\reflection\unittest\fixture;
2+
3+
interface Instruction {
4+
5+
}

0 commit comments

Comments
 (0)