55namespace TypeLang \Mapper \Type \Builder ;
66
77use Psr \Container \ContainerInterface ;
8+ use TypeLang \Mapper \Exception \Definition \InternalTypeException ;
89use TypeLang \Mapper \Runtime \Parser \TypeParserInterface ;
910use TypeLang \Mapper \Runtime \Repository \TypeRepositoryInterface ;
1011use TypeLang \Mapper \Type \TypeInterface ;
1112use TypeLang \Parser \Node \Stmt \TypeStatement ;
1213
1314/**
15+ * Creates a new type from a PSR-compatible container using service-location.
16+ *
17+ * ```
18+ * // ExamplePlatform.php
19+ * yield new CallableTypeBuilder(
20+ * names: 'custom-string',
21+ * serviceId: CustomString::class,
22+ * container: $psrCompatibleContainer,
23+ * );
24+ * ```
25+ *
26+ * Tip: When using Symfony, make sure the service is not private.
27+ *
1428 * @template-extends NamedTypeBuilder<TypeInterface>
1529 */
1630class PsrContainerTypeBuilder extends NamedTypeBuilder
1731{
1832 /**
1933 * @param non-empty-array<non-empty-string>|non-empty-string $names
20- * @param class-string<TypeInterface> $serviceId
34+ * @param class-string<TypeInterface> $serviceId
2135 */
2236 public function __construct (
2337 array |string $ names ,
@@ -27,15 +41,33 @@ public function __construct(
2741 parent ::__construct ($ names );
2842 }
2943
30- public function build (TypeStatement $ statement , TypeRepositoryInterface $ types , TypeParserInterface $ parser ): TypeInterface
31- {
44+ public function build (
45+ TypeStatement $ statement ,
46+ TypeRepositoryInterface $ types ,
47+ TypeParserInterface $ parser ,
48+ ): TypeInterface {
3249 $ this ->expectNoShapeFields ($ statement );
3350 $ this ->expectNoTemplateArguments ($ statement );
3451
35- $ service = $ this ->container ->get ($ this ->serviceId );
52+ try {
53+ $ service = $ this ->container ->get ($ this ->serviceId );
54+ } catch (\Throwable $ e ) {
55+ throw InternalTypeException::becauseInternalTypeErrorOccurs (
56+ type: $ statement ,
57+ message: 'An error occurred while trying to fetch {{type}} type from service container ' ,
58+ previous: $ e ,
59+ );
60+ }
3661
3762 if (!$ service instanceof TypeInterface) {
38- throw new \RuntimeException ("Type service ' {$ this ->serviceId }' does not implement TypeLang\Mapper\Type\TypeInterface " );
63+ throw InternalTypeException::becauseInternalTypeErrorOccurs (
64+ type: $ statement ,
65+ message: \sprintf (
66+ 'Received service from service container defined as {{type}} must be instanceof %s, but %s given ' ,
67+ TypeInterface::class,
68+ \get_debug_type ($ service ),
69+ ),
70+ );
3971 }
4072
4173 return $ service ;
0 commit comments