├── LICENSE.md ├── README.md ├── composer.json ├── qa ├── PHPStan │ ├── Extension │ │ ├── ApiAndInternalAnnotationCheck.php │ │ ├── ArgumentsMapperPHPStanExtension.php │ │ └── TreeMapperPHPStanExtension.php │ └── valinor-phpstan-configuration.php └── Psalm │ ├── Plugin │ ├── ArgumentsMapperPsalmPlugin.php │ └── TreeMapperPsalmPlugin.php │ └── ValinorPsalmPlugin.php └── src ├── Cache ├── ChainCache.php ├── Exception │ ├── CacheDirectoryNotWritable.php │ ├── CompiledPhpCacheFileNotWritten.php │ ├── CorruptedCompiledPhpCacheFile.php │ └── InvalidSignatureToWarmup.php ├── FileSystemCache.php ├── FileWatchingCache.php ├── KeySanitizerCache.php ├── RuntimeCache.php ├── Warmup │ └── RecursiveCacheWarmupService.php └── WarmupCache.php ├── Compiler ├── Compiler.php ├── Library │ ├── NewAttributeNode.php │ └── TypeAcceptNode.php ├── Native │ ├── AnonymousClassNode.php │ ├── ArrayKeyAccessNode.php │ ├── ArrayNode.php │ ├── AssignNode.php │ ├── CallNode.php │ ├── CastNode.php │ ├── ClassNode.php │ ├── CloneNode.php │ ├── ClosureNode.php │ ├── ComplianceNode.php │ ├── DifferentNode.php │ ├── EqualsNode.php │ ├── ExpressionNode.php │ ├── ForEachNode.php │ ├── FunctionCallNode.php │ ├── FunctionNameNode.php │ ├── GreaterOrEqualsToNode.php │ ├── GreaterThanNode.php │ ├── IfNode.php │ ├── InstanceOfNode.php │ ├── LessOrEqualsToNode.php │ ├── LessThanNode.php │ ├── LogicalAndNode.php │ ├── LogicalOrNode.php │ ├── MatchNode.php │ ├── MethodCallNode.php │ ├── MethodNode.php │ ├── NegateNode.php │ ├── NewClassNode.php │ ├── ParameterDeclarationNode.php │ ├── PhpFileNode.php │ ├── PropertyDeclarationNode.php │ ├── PropertyNode.php │ ├── ReturnNode.php │ ├── ShortClosureNode.php │ ├── StaticAccessNode.php │ ├── StaticMethodCallNode.php │ ├── TernaryNode.php │ ├── ThrowNode.php │ ├── ValueNode.php │ ├── VariableAccessNode.php │ ├── VariableNode.php │ ├── WrapNode.php │ └── YieldNode.php └── Node.php ├── Definition ├── AttributeDefinition.php ├── Attributes.php ├── ClassDefinition.php ├── Exception │ ├── ClassTypeAliasesDuplication.php │ ├── ExtendTagTypeError.php │ ├── InvalidExtendTagClassName.php │ ├── InvalidExtendTagType.php │ ├── InvalidTypeAliasImportClass.php │ ├── InvalidTypeAliasImportClassType.php │ ├── SeveralExtendTagsFound.php │ └── UnknownTypeAliasImport.php ├── FunctionDefinition.php ├── FunctionObject.php ├── FunctionsContainer.php ├── MethodDefinition.php ├── Methods.php ├── ParameterDefinition.php ├── Parameters.php ├── Properties.php ├── PropertyDefinition.php └── Repository │ ├── AttributesRepository.php │ ├── Cache │ ├── CacheClassDefinitionRepository.php │ ├── CacheFunctionDefinitionRepository.php │ └── Compiler │ │ ├── AttributesCompiler.php │ │ ├── ClassDefinitionCompiler.php │ │ ├── Exception │ │ └── TypeCannotBeCompiled.php │ │ ├── FunctionDefinitionCompiler.php │ │ ├── MethodDefinitionCompiler.php │ │ ├── ParameterDefinitionCompiler.php │ │ ├── PropertyDefinitionCompiler.php │ │ └── TypeCompiler.php │ ├── ClassDefinitionRepository.php │ ├── FunctionDefinitionRepository.php │ └── Reflection │ ├── ReflectionAttributesRepository.php │ ├── ReflectionClassDefinitionRepository.php │ ├── ReflectionFunctionDefinitionRepository.php │ ├── ReflectionMethodDefinitionBuilder.php │ ├── ReflectionParameterDefinitionBuilder.php │ ├── ReflectionPropertyDefinitionBuilder.php │ └── TypeResolver │ ├── ClassImportedTypeAliasResolver.php │ ├── ClassLocalTypeAliasResolver.php │ ├── ClassParentTypeResolver.php │ ├── ClassTemplatesResolver.php │ ├── FunctionReturnTypeResolver.php │ ├── ParameterTypeResolver.php │ ├── PropertyTypeResolver.php │ └── ReflectionTypeResolver.php ├── Library ├── Container.php └── Settings.php ├── Mapper ├── ArgumentsMapper.php ├── ArgumentsMapperError.php ├── Exception │ ├── InvalidMappingTypeSignature.php │ ├── TypeErrorDuringArgumentsMapping.php │ └── TypeErrorDuringMapping.php ├── MappingError.php ├── Object │ ├── Argument.php │ ├── Arguments.php │ ├── ArgumentsValues.php │ ├── Constructor.php │ ├── DateTimeFormatConstructor.php │ ├── DynamicConstructor.php │ ├── Exception │ │ ├── CannotFindObjectBuilder.php │ │ ├── CannotInstantiateObject.php │ │ ├── CannotParseToDateTime.php │ │ ├── InvalidConstructorClassTypeParameter.php │ │ ├── InvalidConstructorMethodWithAttributeReturnType.php │ │ ├── InvalidConstructorReturnType.php │ │ ├── InvalidSource.php │ │ ├── MissingConstructorClassTypeParameter.php │ │ ├── ObjectBuildersCollision.php │ │ └── PermissiveTypeNotAllowed.php │ ├── Factory │ │ ├── CacheObjectBuilderFactory.php │ │ ├── ConstructorObjectBuilderFactory.php │ │ ├── DateTimeObjectBuilderFactory.php │ │ ├── DateTimeZoneObjectBuilderFactory.php │ │ ├── ObjectBuilderFactory.php │ │ ├── ReflectionObjectBuilderFactory.php │ │ ├── SortingObjectBuilderFactory.php │ │ └── StrictTypesObjectBuilderFactory.php │ ├── FunctionObjectBuilder.php │ ├── MethodArguments.php │ ├── MethodObjectBuilder.php │ ├── NativeConstructorObjectBuilder.php │ ├── NativeEnumObjectBuilder.php │ ├── ObjectBuilder.php │ └── ReflectionObjectBuilder.php ├── Source │ ├── Exception │ │ ├── FileExtensionNotHandled.php │ │ ├── InvalidJson.php │ │ ├── InvalidSource.php │ │ ├── InvalidYaml.php │ │ ├── SourceNotIterable.php │ │ ├── UnableToReadFile.php │ │ └── YamlExtensionNotEnabled.php │ ├── FileSource.php │ ├── IdentifiableSource.php │ ├── JsonSource.php │ ├── Modifier │ │ ├── CamelCaseKeys.php │ │ ├── Mapping.php │ │ └── PathMapping.php │ ├── Source.php │ └── YamlSource.php ├── Tree │ ├── Builder │ │ ├── ArrayNodeBuilder.php │ │ ├── InterfaceNodeBuilder.php │ │ ├── ListNodeBuilder.php │ │ ├── MixedNodeBuilder.php │ │ ├── NodeBuilder.php │ │ ├── NullNodeBuilder.php │ │ ├── ObjectImplementations.php │ │ ├── ObjectNodeBuilder.php │ │ ├── RootNodeBuilder.php │ │ ├── ScalarNodeBuilder.php │ │ ├── ShapedArrayNodeBuilder.php │ │ ├── TreeNode.php │ │ ├── TypeNodeBuilder.php │ │ ├── UndefinedObjectNodeBuilder.php │ │ ├── UnionNodeBuilder.php │ │ └── ValueAlteringNodeBuilder.php │ ├── Exception │ │ ├── CannotInferFinalClass.php │ │ ├── CannotMapToPermissiveType.php │ │ ├── CannotResolveObjectType.php │ │ ├── CannotResolveTypeFromUnion.php │ │ ├── CircularDependencyDetected.php │ │ ├── InterfaceHasBothConstructorAndInfer.php │ │ ├── InvalidAbstractObjectName.php │ │ ├── InvalidIterableKeyType.php │ │ ├── InvalidListKey.php │ │ ├── InvalidNodeHasNoMappedValue.php │ │ ├── InvalidNodeValue.php │ │ ├── InvalidResolvedImplementationValue.php │ │ ├── InvalidTraversableKey.php │ │ ├── MissingNodeValue.php │ │ ├── MissingObjectImplementationRegistration.php │ │ ├── ObjectImplementationCallbackError.php │ │ ├── ObjectImplementationNotRegistered.php │ │ ├── ResolvedImplementationIsNotAccepted.php │ │ ├── SourceIsNotNull.php │ │ ├── SourceMustBeIterable.php │ │ ├── SourceValueWasNotFilled.php │ │ ├── TooManyResolvedTypesFromUnion.php │ │ ├── UnexpectedKeysInSource.php │ │ └── UnresolvableShellType.php │ ├── Message │ │ ├── DefaultMessage.php │ │ ├── ErrorMessage.php │ │ ├── Formatter │ │ │ ├── AggregateMessageFormatter.php │ │ │ ├── CallbackMessageFormatter.php │ │ │ ├── LocaleMessageFormatter.php │ │ │ ├── MessageFormatter.php │ │ │ ├── MessageMapFormatter.php │ │ │ └── TranslationMessageFormatter.php │ │ ├── HasCode.php │ │ ├── HasParameters.php │ │ ├── Message.php │ │ ├── MessageBuilder.php │ │ ├── Messages.php │ │ ├── NodeMessage.php │ │ └── UserlandError.php │ ├── Node.php │ ├── NodeTraverser.php │ └── Shell.php ├── TreeMapper.php ├── TypeArgumentsMapper.php ├── TypeTreeMapper.php └── TypeTreeMapperError.php ├── MapperBuilder.php ├── Normalizer ├── ArrayNormalizer.php ├── AsTransformer.php ├── Exception │ ├── CircularReferenceFoundDuringNormalization.php │ ├── KeyTransformerHasTooManyParameters.php │ ├── KeyTransformerParameterInvalidType.php │ ├── TransformerHasInvalidCallableParameter.php │ ├── TransformerHasNoParameter.php │ ├── TransformerHasTooManyParameters.php │ └── TypeUnhandledByNormalizer.php ├── Format.php ├── Formatter │ ├── Exception │ │ └── CannotFormatInvalidTypeToJson.php │ └── JsonFormatter.php ├── JsonNormalizer.php ├── Normalizer.php ├── StreamNormalizer.php └── Transformer │ ├── CacheTransformer.php │ ├── Compiler │ ├── TransformerDefinition.php │ ├── TransformerDefinitionBuilder.php │ ├── TransformerRootNode.php │ └── TypeFormatter │ │ ├── ClassFormatter.php │ │ ├── DateTimeFormatter.php │ │ ├── DateTimeZoneFormatter.php │ │ ├── EnumFormatter.php │ │ ├── InterfaceFormatter.php │ │ ├── MixedFormatter.php │ │ ├── NullFormatter.php │ │ ├── RegisteredTransformersFormatter.php │ │ ├── ScalarFormatter.php │ │ ├── ShapedArrayFormatter.php │ │ ├── StdClassFormatter.php │ │ ├── TraversableFormatter.php │ │ ├── TypeFormatter.php │ │ ├── UnionFormatter.php │ │ ├── UnitEnumFormatter.php │ │ └── UnsureTypeFormatter.php │ ├── EmptyObject.php │ ├── EvaluatedTransformer.php │ ├── RecursiveTransformer.php │ ├── Transformer.php │ └── TransformerContainer.php ├── Type ├── BooleanType.php ├── ClassType.php ├── CombiningType.php ├── CompositeTraversableType.php ├── CompositeType.php ├── FixedType.php ├── FloatType.php ├── GenericType.php ├── IntegerType.php ├── ObjectType.php ├── Parser │ ├── CachedParser.php │ ├── Exception │ │ ├── Constant │ │ │ ├── ClassConstantCaseNotFound.php │ │ │ └── MissingClassConstantCase.php │ │ ├── Enum │ │ │ ├── EnumCaseNotFound.php │ │ │ ├── MissingEnumCase.php │ │ │ └── MissingSpecificEnumCase.php │ │ ├── Generic │ │ │ ├── AssignedGenericNotFound.php │ │ │ ├── CannotAssignGeneric.php │ │ │ ├── GenericClosingBracketMissing.php │ │ │ ├── GenericCommaMissing.php │ │ │ ├── InvalidAssignedGeneric.php │ │ │ └── MissingGenerics.php │ │ ├── InvalidIntersectionType.php │ │ ├── InvalidType.php │ │ ├── Iterable │ │ │ ├── ArrayClosingBracketMissing.php │ │ │ ├── ArrayCommaMissing.php │ │ │ ├── InvalidArrayKey.php │ │ │ ├── InvalidIterableKey.php │ │ │ ├── IterableClosingBracketMissing.php │ │ │ ├── IterableCommaMissing.php │ │ │ ├── ListClosingBracketMissing.php │ │ │ ├── ShapedArrayClosingBracketMissing.php │ │ │ ├── ShapedArrayColonTokenMissing.php │ │ │ ├── ShapedArrayCommaMissing.php │ │ │ ├── ShapedArrayElementDuplicatedKey.php │ │ │ ├── ShapedArrayElementTypeMissing.php │ │ │ ├── ShapedArrayEmptyElements.php │ │ │ ├── ShapedArrayInvalidUnsealedType.php │ │ │ ├── ShapedArrayUnexpectedTokenAfterSealedType.php │ │ │ ├── ShapedArrayWithoutElementsWithSealedType.php │ │ │ └── SimpleArrayClosingBracketMissing.php │ │ ├── Magic │ │ │ ├── ValueOfClosingBracketMissing.php │ │ │ ├── ValueOfIncorrectSubType.php │ │ │ └── ValueOfOpeningBracketMissing.php │ │ ├── MissingClosingQuoteChar.php │ │ ├── RightIntersectionTypeMissing.php │ │ ├── RightUnionTypeMissing.php │ │ ├── Scalar │ │ │ ├── ClassStringClosingBracketMissing.php │ │ │ ├── IntegerRangeInvalidMaxValue.php │ │ │ ├── IntegerRangeInvalidMinValue.php │ │ │ ├── IntegerRangeMissingClosingBracket.php │ │ │ ├── IntegerRangeMissingComma.php │ │ │ ├── IntegerRangeMissingMaxValue.php │ │ │ ├── IntegerRangeMissingMinValue.php │ │ │ ├── InvalidClassStringSubType.php │ │ │ ├── ReversedValuesForIntegerRange.php │ │ │ └── SameValueForIntegerRange.php │ │ ├── Template │ │ │ ├── DuplicatedTemplateName.php │ │ │ └── InvalidClassTemplate.php │ │ └── UnknownSymbol.php │ ├── Factory │ │ ├── LexingTypeParserFactory.php │ │ ├── Specifications │ │ │ ├── AliasSpecification.php │ │ │ ├── ClassContextSpecification.php │ │ │ ├── TypeAliasAssignerSpecification.php │ │ │ └── TypeParserSpecification.php │ │ └── TypeParserFactory.php │ ├── GenericCheckerParser.php │ ├── Lexer │ │ ├── Annotations.php │ │ ├── NativeLexer.php │ │ ├── SpecificationsLexer.php │ │ ├── Token │ │ │ ├── ArrayToken.php │ │ │ ├── CallableToken.php │ │ │ ├── CaseFinder.php │ │ │ ├── ClassNameToken.php │ │ │ ├── ClassStringToken.php │ │ │ ├── ClosingBracketToken.php │ │ │ ├── ClosingCurlyBracketToken.php │ │ │ ├── ClosingSquareBracketToken.php │ │ │ ├── ColonToken.php │ │ │ ├── CommaToken.php │ │ │ ├── DoubleColonToken.php │ │ │ ├── EnumNameToken.php │ │ │ ├── FloatValueToken.php │ │ │ ├── IntegerToken.php │ │ │ ├── IntegerValueToken.php │ │ │ ├── IntersectionToken.php │ │ │ ├── IterableToken.php │ │ │ ├── LeftTraversingToken.php │ │ │ ├── ListToken.php │ │ │ ├── NullableToken.php │ │ │ ├── ObjectToken.php │ │ │ ├── OpeningBracketToken.php │ │ │ ├── OpeningCurlyBracketToken.php │ │ │ ├── OpeningSquareBracketToken.php │ │ │ ├── StringValueToken.php │ │ │ ├── Token.php │ │ │ ├── TraversingToken.php │ │ │ ├── TripleDotsToken.php │ │ │ ├── TypeToken.php │ │ │ ├── UnionToken.php │ │ │ ├── VacantToken.php │ │ │ └── ValueOfToken.php │ │ ├── TokenStream.php │ │ ├── TokenizedAnnotation.php │ │ ├── TokensExtractor.php │ │ └── TypeLexer.php │ ├── LexingParser.php │ └── TypeParser.php ├── ScalarType.php ├── StringType.php ├── Type.php └── Types │ ├── ArrayKeyType.php │ ├── ArrayType.php │ ├── BooleanValueType.php │ ├── CallableType.php │ ├── ClassStringType.php │ ├── EnumType.php │ ├── Exception │ ├── ForbiddenMixedType.php │ └── InvalidUnionOfClassString.php │ ├── Factory │ ├── CannotBuildTypeFromValue.php │ └── ValueTypeFactory.php │ ├── FloatValueType.php │ ├── IntegerRangeType.php │ ├── IntegerValueType.php │ ├── InterfaceType.php │ ├── IntersectionType.php │ ├── IterableType.php │ ├── ListType.php │ ├── MixedType.php │ ├── NativeBooleanType.php │ ├── NativeClassType.php │ ├── NativeFloatType.php │ ├── NativeIntegerType.php │ ├── NativeStringType.php │ ├── NegativeIntegerType.php │ ├── NonEmptyArrayType.php │ ├── NonEmptyListType.php │ ├── NonEmptyStringType.php │ ├── NonNegativeIntegerType.php │ ├── NonPositiveIntegerType.php │ ├── NullType.php │ ├── NumericStringType.php │ ├── PositiveIntegerType.php │ ├── ScalarConcreteType.php │ ├── ShapedArrayElement.php │ ├── ShapedArrayType.php │ ├── StringValueType.php │ ├── UndefinedObjectType.php │ ├── UnionType.php │ └── UnresolvableType.php └── Utility ├── IsSingleton.php ├── Package.php ├── Polyfill.php ├── Priority ├── HasPriority.php └── PrioritizedList.php ├── Reflection ├── NamespaceFinder.php ├── PhpParser.php ├── Reflection.php └── TokenParser.php ├── String ├── StringCutter.php ├── StringFormatter.php └── StringFormatterError.php ├── TypeHelper.php └── ValueDumper.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Romain Canon 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /qa/PHPStan/valinor-phpstan-configuration.php: -------------------------------------------------------------------------------- 1 | [ 11 | [ 12 | 'class' => TreeMapperPHPStanExtension::class, 13 | 'tags' => ['phpstan.broker.dynamicMethodReturnTypeExtension'] 14 | ], [ 15 | 'class' => ArgumentsMapperPHPStanExtension::class, 16 | 'tags' => ['phpstan.broker.dynamicMethodReturnTypeExtension'] 17 | ], 18 | ], 19 | ]; 20 | -------------------------------------------------------------------------------- /qa/Psalm/ValinorPsalmPlugin.php: -------------------------------------------------------------------------------- 1 | registerHooksFromClass(TreeMapperPsalmPlugin::class); 19 | $api->registerHooksFromClass(ArgumentsMapperPsalmPlugin::class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Cache/Exception/CacheDirectoryNotWritable.php: -------------------------------------------------------------------------------- 1 | getMessage()}", 17 | 1653330261, 18 | $exception 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Cache/WarmupCache.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | interface WarmupCache extends CacheInterface 14 | { 15 | public function warmup(): void; 16 | } 17 | -------------------------------------------------------------------------------- /src/Compiler/Compiler.php: -------------------------------------------------------------------------------- 1 | compile($compiler); 24 | 25 | if ($nodes !== []) { 26 | $compiler = $compiler->write("\n"); 27 | } 28 | } 29 | 30 | return $compiler; 31 | } 32 | 33 | public function sub(): self 34 | { 35 | return new self(); 36 | } 37 | 38 | public function write(string $code): self 39 | { 40 | $self = clone $this; 41 | $self->code .= $code; 42 | 43 | return $self; 44 | } 45 | 46 | public function indent(): self 47 | { 48 | $self = clone $this; 49 | $self->indentation++; 50 | 51 | return $self; 52 | } 53 | 54 | public function code(): string 55 | { 56 | $indent = str_repeat(' ', $this->indentation); 57 | 58 | return $indent . str_replace("\n", "\n" . $indent, $this->code); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Compiler/Library/TypeAcceptNode.php: -------------------------------------------------------------------------------- 1 | compile($this->type->compiledAccept($this->node)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Compiler/Native/ArrayKeyAccessNode.php: -------------------------------------------------------------------------------- 1 | sub()->compile($this->key)->code(); 21 | 22 | return $compiler 23 | ->compile($this->node) 24 | ->write('[' . $key . ']'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Compiler/Native/ArrayNode.php: -------------------------------------------------------------------------------- 1 | */ 17 | private array $assignments 18 | ) {} 19 | 20 | public function compile(Compiler $compiler): Compiler 21 | { 22 | if ($this->assignments === []) { 23 | return $compiler->write('[]'); 24 | } 25 | 26 | $sub = []; 27 | 28 | foreach ($this->assignments as $key => $assignment) { 29 | $sub[] = ' ' . var_export($key, true) . ' => ' . $compiler->sub()->compile($assignment)->code() . ","; 30 | } 31 | 32 | $sub = implode("\n", $sub); 33 | 34 | return $compiler->write("[\n$sub\n]"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Compiler/Native/AssignNode.php: -------------------------------------------------------------------------------- 1 | compile($this->node) 22 | ->write(' = ') 23 | ->compile($this->value); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/CallNode.php: -------------------------------------------------------------------------------- 1 | */ 19 | private array $arguments = [], 20 | ) {} 21 | 22 | public function compile(Compiler $compiler): Compiler 23 | { 24 | $compiler = $compiler 25 | ->compile($this->node) 26 | ->write('('); 27 | 28 | if ($this->arguments !== []) { 29 | $arguments = array_map( 30 | fn (Node $argument) => $compiler->sub()->compile($argument)->code(), 31 | $this->arguments, 32 | ); 33 | 34 | $compiler = $compiler->write(implode(', ', $arguments)); 35 | } 36 | 37 | return $compiler->write(')'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Compiler/Native/CastNode.php: -------------------------------------------------------------------------------- 1 | write('(' . $this->type . ')') 27 | ->compile($this->node); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Compiler/Native/ClassNode.php: -------------------------------------------------------------------------------- 1 | $arguments 21 | */ 22 | public function callStaticMethod( 23 | string $method, 24 | array $arguments = [], 25 | ): Node { 26 | return new StaticMethodCallNode($this, $method, $arguments); 27 | } 28 | 29 | public function compile(Compiler $compiler): Compiler 30 | { 31 | return $compiler->write($this->name); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Compiler/Native/CloneNode.php: -------------------------------------------------------------------------------- 1 | write('clone ') 21 | ->compile($this->node); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Compiler/Native/ClosureNode.php: -------------------------------------------------------------------------------- 1 | */ 17 | private array $use = []; 18 | 19 | /** @var array */ 20 | private array $nodes; 21 | 22 | public function __construct(Node ...$nodes) 23 | { 24 | $this->nodes = $nodes; 25 | } 26 | 27 | /** 28 | * @no-named-arguments 29 | * @param non-empty-string ...$names 30 | */ 31 | public function uses(string ...$names): self 32 | { 33 | $self = clone $this; 34 | $self->use = array_map(fn (string $name) => '$' . $name, $names); 35 | 36 | return $self; 37 | } 38 | 39 | public function compile(Compiler $compiler): Compiler 40 | { 41 | $use = $this->use !== [] ? ' use (' . implode(', ', $this->use) . ')' : ''; 42 | 43 | $body = $compiler->sub()->indent()->compile(...$this->nodes)->code(); 44 | 45 | $code = <<write($code); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Compiler/Native/DifferentNode.php: -------------------------------------------------------------------------------- 1 | compile($this->left) 22 | ->write(' !== ') 23 | ->compile($this->right); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/EqualsNode.php: -------------------------------------------------------------------------------- 1 | compile($this->left) 22 | ->write(' === ') 23 | ->compile($this->right); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/ExpressionNode.php: -------------------------------------------------------------------------------- 1 | write($compiler->sub()->compile($this->node)->code() . ';'); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Compiler/Native/ForEachNode.php: -------------------------------------------------------------------------------- 1 | sub()->compile($this->value)->code(); 25 | $body = $compiler->sub()->indent()->compile($this->body)->code(); 26 | 27 | return $compiler->write( 28 | <<key => $$this->item) { 30 | $body 31 | } 32 | PHP 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Compiler/Native/FunctionCallNode.php: -------------------------------------------------------------------------------- 1 | */ 17 | private array $arguments = [], 18 | ) {} 19 | 20 | public function compile(Compiler $compiler): Compiler 21 | { 22 | return $compiler 23 | ->compile(new CallNode(new FunctionNameNode($this->name), $this->arguments)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/FunctionNameNode.php: -------------------------------------------------------------------------------- 1 | name, self::RESERVED_FUNCTIONS, true) 27 | ? $this->name 28 | : '\\' . $this->name; 29 | 30 | return $compiler->write($function); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Compiler/Native/GreaterOrEqualsToNode.php: -------------------------------------------------------------------------------- 1 | compile($this->left) 22 | ->write(' >= ') 23 | ->compile($this->right); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/GreaterThanNode.php: -------------------------------------------------------------------------------- 1 | compile($this->left) 22 | ->write(' > ') 23 | ->compile($this->right); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/IfNode.php: -------------------------------------------------------------------------------- 1 | sub()->compile($this->condition)->code(); 21 | $body = $compiler->sub()->indent()->compile($this->body)->code(); 22 | 23 | return $compiler->write( 24 | <<className; 22 | 23 | return $compiler 24 | ->compile($this->node) 25 | ->write(' instanceof ') 26 | ->write($className); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Compiler/Native/LessOrEqualsToNode.php: -------------------------------------------------------------------------------- 1 | compile($this->left) 22 | ->write(' <= ') 23 | ->compile($this->right); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/LessThanNode.php: -------------------------------------------------------------------------------- 1 | compile($this->left) 22 | ->write(' < ') 23 | ->compile($this->right); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/LogicalAndNode.php: -------------------------------------------------------------------------------- 1 | */ 14 | private array $nodes; 15 | 16 | /** 17 | * @no-named-arguments 18 | */ 19 | public function __construct(Node ...$nodes) 20 | { 21 | $this->nodes = $nodes; 22 | } 23 | 24 | public function compile(Compiler $compiler): Compiler 25 | { 26 | $nodes = $this->nodes; 27 | 28 | while ($node = array_shift($nodes)) { 29 | $compiler = $compiler->compile($node); 30 | 31 | if ($nodes !== []) { 32 | $compiler = $compiler->write(' && '); 33 | } 34 | } 35 | 36 | return $compiler; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Compiler/Native/LogicalOrNode.php: -------------------------------------------------------------------------------- 1 | */ 14 | private array $nodes; 15 | 16 | /** 17 | * @no-named-arguments 18 | */ 19 | public function __construct(Node ...$nodes) 20 | { 21 | $this->nodes = $nodes; 22 | } 23 | 24 | public function compile(Compiler $compiler): Compiler 25 | { 26 | $nodes = $this->nodes; 27 | 28 | while ($node = array_shift($nodes)) { 29 | $compiler = $compiler->compile($node); 30 | 31 | if ($nodes !== []) { 32 | $compiler = $compiler->write(' || '); 33 | } 34 | } 35 | 36 | return $compiler; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Compiler/Native/MethodCallNode.php: -------------------------------------------------------------------------------- 1 | */ 18 | private array $arguments = [], 19 | ) {} 20 | 21 | public function compile(Compiler $compiler): Compiler 22 | { 23 | return $compiler->compile( 24 | new CallNode(new VariableAccessNode($this->node, $this->method), $this->arguments) 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Compiler/Native/NegateNode.php: -------------------------------------------------------------------------------- 1 | write('! ')->compile($this->node); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Compiler/Native/NewClassNode.php: -------------------------------------------------------------------------------- 1 | */ 19 | private array $arguments; 20 | 21 | /** 22 | * @param class-string $className 23 | */ 24 | public function __construct(string $className, Node ...$arguments) 25 | { 26 | $this->className = $className; 27 | $this->arguments = $arguments; 28 | } 29 | 30 | public function compile(Compiler $compiler): Compiler 31 | { 32 | $arguments = array_map( 33 | fn (Node $argument) => $compiler->sub()->compile($argument)->code(), 34 | $this->arguments, 35 | ); 36 | $arguments = implode(', ', $arguments); 37 | 38 | return $compiler->write("new {$this->className}($arguments)"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Compiler/Native/ParameterDeclarationNode.php: -------------------------------------------------------------------------------- 1 | write($this->type . ' $' . $this->name); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Compiler/Native/PhpFileNode.php: -------------------------------------------------------------------------------- 1 | */ 14 | private array $nodes; 15 | 16 | public function __construct(Node ...$nodes) 17 | { 18 | $this->nodes = $nodes; 19 | } 20 | 21 | public function compile(Compiler $compiler): Compiler 22 | { 23 | return $compiler 24 | ->write("compile(...$this->nodes); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Compiler/Native/PropertyDeclarationNode.php: -------------------------------------------------------------------------------- 1 | write('private ' . $this->type . ' $' . $this->name . ';'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Compiler/Native/PropertyNode.php: -------------------------------------------------------------------------------- 1 | write('$this->' . $this->name); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Compiler/Native/ReturnNode.php: -------------------------------------------------------------------------------- 1 | node ? ' ' . $compiler->sub()->compile($this->node)->code() : ''; 18 | 19 | return $compiler->write("return$code;"); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/Compiler/Native/ShortClosureNode.php: -------------------------------------------------------------------------------- 1 | */ 16 | private array $parameters = []; 17 | 18 | public function __construct(Node $returnNode) 19 | { 20 | $this->returnNode = $returnNode; 21 | } 22 | 23 | public function witParameters(ParameterDeclarationNode ...$parameters): self 24 | { 25 | $self = clone $this; 26 | $self->parameters = $parameters; 27 | 28 | return $self; 29 | } 30 | 31 | public function compile(Compiler $compiler): Compiler 32 | { 33 | $parameters = implode(', ', array_map( 34 | fn (ParameterDeclarationNode $parameter) => $compiler->sub()->compile($parameter)->code(), 35 | $this->parameters, 36 | )); 37 | 38 | $return = $compiler->sub()->compile($this->returnNode)->code(); 39 | 40 | return $compiler->write( 41 | << $return 43 | PHP, 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Compiler/Native/StaticAccessNode.php: -------------------------------------------------------------------------------- 1 | compile($this->left) 23 | ->write("::$this->name"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/StaticMethodCallNode.php: -------------------------------------------------------------------------------- 1 | */ 18 | private array $arguments = [], 19 | ) {} 20 | 21 | public function compile(Compiler $compiler): Compiler 22 | { 23 | return $compiler->compile( 24 | new CallNode(new StaticAccessNode($this->node, $this->method), $this->arguments) 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Compiler/Native/TernaryNode.php: -------------------------------------------------------------------------------- 1 | compile($this->condition) 23 | ->write(' ? ') 24 | ->compile($this->ifTrue) 25 | ->write(' : ') 26 | ->compile($this->ifFalse); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Compiler/Native/ThrowNode.php: -------------------------------------------------------------------------------- 1 | write('throw ') 21 | ->compile($this->node); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Compiler/Native/VariableAccessNode.php: -------------------------------------------------------------------------------- 1 | compile($this->node) 23 | ->write('->' . $this->value); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Compiler/Native/VariableNode.php: -------------------------------------------------------------------------------- 1 | write('$' . $this->name); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Compiler/Native/WrapNode.php: -------------------------------------------------------------------------------- 1 | write('(') 19 | ->compile($this->node) 20 | ->write(')'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Compiler/Native/YieldNode.php: -------------------------------------------------------------------------------- 1 | write('yield ') 22 | ->compile($this->key) 23 | ->write(' => ') 24 | ->compile($this->value); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Definition/AttributeDefinition.php: -------------------------------------------------------------------------------- 1 | */ 13 | public readonly array $arguments, 14 | ) {} 15 | 16 | public function instantiate(): object 17 | { 18 | return new ($this->class->type->className())(...$this->arguments); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Definition/ClassDefinition.php: -------------------------------------------------------------------------------- 1 | $reflection 16 | */ 17 | public function __construct(ReflectionClass $reflection, InvalidType $previous) 18 | { 19 | parent::__construct( 20 | "The `@extends` tag of the class `$reflection->name` is not valid: {$previous->getMessage()}", 21 | 1670193574, 22 | $previous, 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Definition/Exception/InvalidExtendTagClassName.php: -------------------------------------------------------------------------------- 1 | $reflection 16 | */ 17 | public function __construct(ReflectionClass $reflection, Type $invalidExtendTag) 18 | { 19 | /** @var ReflectionClass $parentClass */ 20 | $parentClass = $reflection->getParentClass(); 21 | 22 | parent::__construct( 23 | "The `@extends` tag of the class `$reflection->name` has invalid class `{$invalidExtendTag->toString()}`, it should be `$parentClass->name`.", 24 | 1670183564, 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Definition/Exception/InvalidExtendTagType.php: -------------------------------------------------------------------------------- 1 | $reflection 16 | */ 17 | public function __construct(ReflectionClass $reflection, Type $invalidExtendTag) 18 | { 19 | /** @var ReflectionClass $parentClass */ 20 | $parentClass = $reflection->getParentClass(); 21 | 22 | parent::__construct( 23 | "The `@extends` tag of the class `$reflection->name` has invalid type `{$invalidExtendTag->toString()}`, it should be `{$parentClass->name}`.", 24 | 1670181134, 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Definition/Exception/InvalidTypeAliasImportClass.php: -------------------------------------------------------------------------------- 1 | className()}`.", 17 | 1638535486 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Definition/Exception/InvalidTypeAliasImportClassType.php: -------------------------------------------------------------------------------- 1 | toString()}` was given in class `{$classType->className()}`.", 18 | 1638535608 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Definition/Exception/SeveralExtendTagsFound.php: -------------------------------------------------------------------------------- 1 | $reflection 15 | */ 16 | public function __construct(ReflectionClass $reflection) 17 | { 18 | parent::__construct( 19 | "Only one `@extends` tag should be set for the class `$reflection->name`.", 20 | 1670195494, 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Definition/Exception/UnknownTypeAliasImport.php: -------------------------------------------------------------------------------- 1 | className()}` could not be found in `$importClassName`", 20 | 1638535757 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Definition/FunctionDefinition.php: -------------------------------------------------------------------------------- 1 | definition = $definition; 18 | $this->callback = $callback; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Definition/MethodDefinition.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | final class Properties implements IteratorAggregate, Countable 17 | { 18 | /** @var PropertyDefinition[] */ 19 | private array $properties = []; 20 | 21 | public function __construct(PropertyDefinition ...$properties) 22 | { 23 | foreach ($properties as $property) { 24 | $this->properties[$property->name] = $property; 25 | } 26 | } 27 | 28 | public function has(string $name): bool 29 | { 30 | return isset($this->properties[$name]); 31 | } 32 | 33 | public function get(string $name): PropertyDefinition 34 | { 35 | return $this->properties[$name]; 36 | } 37 | 38 | public function count(): int 39 | { 40 | return count($this->properties); 41 | } 42 | 43 | /** 44 | * @return Traversable 45 | */ 46 | public function getIterator(): Traversable 47 | { 48 | yield from $this->properties; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Definition/PropertyDefinition.php: -------------------------------------------------------------------------------- 1 | |ReflectionProperty|ReflectionMethod|ReflectionFunction|ReflectionParameter $reflection 20 | * @return list 21 | */ 22 | public function for(Reflector $reflection): array; 23 | } 24 | -------------------------------------------------------------------------------- /src/Definition/Repository/Cache/CacheClassDefinitionRepository.php: -------------------------------------------------------------------------------- 1 | */ 18 | private CacheInterface $cache 19 | ) {} 20 | 21 | public function for(ObjectType $type): ClassDefinition 22 | { 23 | // @infection-ignore-all 24 | $key = "class-definition-\0" . $type->toString(); 25 | 26 | $entry = $this->cache->get($key); 27 | 28 | if ($entry) { 29 | return $entry; 30 | } 31 | 32 | $class = $this->delegate->for($type); 33 | 34 | $this->cache->set($key, $class); 35 | 36 | return $class; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php: -------------------------------------------------------------------------------- 1 | */ 18 | private CacheInterface $cache 19 | ) {} 20 | 21 | public function for(callable $function): FunctionDefinition 22 | { 23 | $reflection = Reflection::function($function); 24 | 25 | // @infection-ignore-all 26 | $key = "function-definition-\0" . $reflection->getFileName() . ':' . $reflection->getStartLine() . '-' . $reflection->getEndLine(); 27 | 28 | $entry = $this->cache->get($key); 29 | 30 | if ($entry) { 31 | return $entry; 32 | } 33 | 34 | $definition = $this->delegate->for($function); 35 | 36 | $this->cache->set($key, $definition); 37 | 38 | return $definition; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Definition/Repository/Cache/Compiler/Exception/TypeCannotBeCompiled.php: -------------------------------------------------------------------------------- 1 | extractTypeFromDocBlock($reflection); 19 | 20 | return $this->typeResolver->resolveType($reflection->getType(), $docBlockType); 21 | } 22 | 23 | public function resolveNativeTypeFor(ReflectionProperty $reflection): Type 24 | { 25 | return $this->typeResolver->resolveNativeType($reflection->getType()); 26 | } 27 | 28 | public function extractTypeFromDocBlock(ReflectionProperty $reflection): ?string 29 | { 30 | $docBlock = $reflection->getDocComment(); 31 | 32 | if ($docBlock === false) { 33 | return null; 34 | } 35 | 36 | return (new Annotations($docBlock))->firstOf( 37 | '@phpstan-var', 38 | '@psalm-var', 39 | '@var', 40 | )?->raw(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Mapper/ArgumentsMapper.php: -------------------------------------------------------------------------------- 1 | 12 | * 13 | * @throws MappingError 14 | */ 15 | public function mapArguments(callable $callable, mixed $source): array; 16 | } 17 | -------------------------------------------------------------------------------- /src/Mapper/Exception/InvalidMappingTypeSignature.php: -------------------------------------------------------------------------------- 1 | getMessage()}", 17 | 1630959692, 18 | $exception 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Mapper/Exception/TypeErrorDuringArgumentsMapping.php: -------------------------------------------------------------------------------- 1 | signature`: {$exception->getMessage()}", 18 | 1711534351, 19 | $exception, 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Mapper/Exception/TypeErrorDuringMapping.php: -------------------------------------------------------------------------------- 1 | toString()}`: {$exception->getMessage()}", 18 | 1711526329, 19 | $exception, 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Mapper/MappingError.php: -------------------------------------------------------------------------------- 1 | name}`.", 17 | 1646916477 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mapper/Object/Exception/CannotParseToDateTime.php: -------------------------------------------------------------------------------- 1 | */ 18 | private array $parameters; 19 | 20 | /** 21 | * @param non-empty-list $formats 22 | */ 23 | public function __construct(array $formats) 24 | { 25 | $this->parameters = [ 26 | 'formats' => '`' . implode('`, `', $formats) . '`', 27 | ]; 28 | 29 | parent::__construct(StringFormatter::for($this), 1630686564); 30 | } 31 | 32 | public function body(): string 33 | { 34 | return $this->body; 35 | } 36 | 37 | public function parameters(): array 38 | { 39 | return $this->parameters; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Mapper/Object/Exception/InvalidConstructorClassTypeParameter.php: -------------------------------------------------------------------------------- 1 | toString()}` for the first parameter of the constructor `{$function->signature}`, it should be of type `class-string`.", 18 | 1661517000 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Mapper/Object/Exception/InvalidConstructorMethodWithAttributeReturnType.php: -------------------------------------------------------------------------------- 1 | returnType instanceof UnresolvableType) { 20 | $message = $method->returnType->message(); 21 | } else { 22 | $message = "Invalid return type `{$method->returnType->toString()}` for constructor `{$method->signature}`, it must be `$expectedClassName`."; 23 | } 24 | 25 | parent::__construct($message, 1708104783); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Mapper/Object/Exception/InvalidConstructorReturnType.php: -------------------------------------------------------------------------------- 1 | returnType instanceof UnresolvableType) { 17 | $message = $function->returnType->message(); 18 | } else { 19 | $message = "Invalid return type `{$function->returnType->toString()}` for constructor `{$function->signature}`, it must be a valid class name."; 20 | } 21 | 22 | parent::__construct($message, 1659446121); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mapper/Object/Exception/InvalidSource.php: -------------------------------------------------------------------------------- 1 | */ 20 | private array $parameters; 21 | 22 | public function __construct(mixed $source, Arguments $arguments) 23 | { 24 | $this->parameters = [ 25 | 'expected_type' => TypeHelper::dumpArguments($arguments), 26 | ]; 27 | 28 | $this->body = $source === null 29 | ? 'Cannot be empty and must be filled with a value matching type {expected_type}.' 30 | : 'Value {source_value} does not match type {expected_type}.'; 31 | 32 | parent::__construct(StringFormatter::for($this), 1632903281); 33 | } 34 | 35 | public function body(): string 36 | { 37 | return $this->body; 38 | } 39 | 40 | public function parameters(): array 41 | { 42 | return $this->parameters; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Mapper/Object/Exception/MissingConstructorClassTypeParameter.php: -------------------------------------------------------------------------------- 1 | signature}`.", 17 | 1661516853 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mapper/Object/Exception/ObjectBuildersCollision.php: -------------------------------------------------------------------------------- 1 | signature()}` and `{$builderB->signature()}`.", 17 | 1654955787 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mapper/Object/Exception/PermissiveTypeNotAllowed.php: -------------------------------------------------------------------------------- 1 | toString()}`, which is not " . 17 | "allowed in strict mode. If really needed, the `allowPermissiveTypes` setting can be used.", 18 | 1655389255, 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Mapper/Object/Factory/CacheObjectBuilderFactory.php: -------------------------------------------------------------------------------- 1 | > */ 17 | private CacheInterface $cache 18 | ) {} 19 | 20 | public function for(ClassDefinition $class): array 21 | { 22 | $signature = $class->type->toString(); 23 | 24 | $entry = $this->cache->get($signature); 25 | 26 | if ($entry) { 27 | return $entry; 28 | } 29 | 30 | $builders = $this->delegate->for($class); 31 | 32 | $this->cache->set($signature, $builders); 33 | 34 | return $builders; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Mapper/Object/Factory/ObjectBuilderFactory.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | public function for(ClassDefinition $class): array; 17 | } 18 | -------------------------------------------------------------------------------- /src/Mapper/Object/Factory/ReflectionObjectBuilderFactory.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | final class MethodArguments implements IteratorAggregate 19 | { 20 | /** @var list */ 21 | private array $arguments = []; 22 | 23 | /** 24 | * @param array $arguments 25 | */ 26 | public function __construct(Parameters $parameters, array $arguments) 27 | { 28 | foreach ($parameters as $parameter) { 29 | $name = $parameter->name; 30 | 31 | if ($parameter->isVariadic) { 32 | $this->arguments = [...$this->arguments, ...array_values($arguments[$name])]; // @phpstan-ignore-line we know that the argument is iterable 33 | } else { 34 | $this->arguments[] = $arguments[$name]; 35 | } 36 | } 37 | } 38 | 39 | public function getIterator(): Traversable 40 | { 41 | yield from $this->arguments; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Mapper/Object/MethodObjectBuilder.php: -------------------------------------------------------------------------------- 1 | arguments ??= Arguments::fromParameters($this->parameters); 25 | } 26 | 27 | public function build(array $arguments): object 28 | { 29 | $methodName = $this->methodName; 30 | $arguments = new MethodArguments($this->parameters, $arguments); 31 | 32 | try { 33 | return ($this->className)::$methodName(...$arguments); // @phpstan-ignore-line 34 | } catch (Exception $exception) { 35 | throw UserlandError::from($exception); 36 | } 37 | } 38 | 39 | public function signature(): string 40 | { 41 | return "$this->className::$this->methodName()"; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Mapper/Object/NativeConstructorObjectBuilder.php: -------------------------------------------------------------------------------- 1 | arguments ??= Arguments::fromParameters($this->class->methods->constructor()->parameters); 21 | } 22 | 23 | public function build(array $arguments): object 24 | { 25 | $className = $this->class->name; 26 | $arguments = new MethodArguments($this->class->methods->constructor()->parameters, $arguments); 27 | 28 | try { 29 | return new $className(...$arguments); 30 | } catch (Exception $exception) { 31 | throw UserlandError::from($exception); 32 | } 33 | } 34 | 35 | public function signature(): string 36 | { 37 | return $this->class->methods->constructor()->signature; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Mapper/Object/ObjectBuilder.php: -------------------------------------------------------------------------------- 1 | $arguments 14 | */ 15 | public function build(array $arguments): object; 16 | 17 | /** 18 | * @return non-empty-string 19 | */ 20 | public function signature(): string; 21 | } 22 | -------------------------------------------------------------------------------- /src/Mapper/Object/ReflectionObjectBuilder.php: -------------------------------------------------------------------------------- 1 | arguments ??= Arguments::fromProperties($this->class->properties); 21 | } 22 | 23 | public function build(array $arguments): object 24 | { 25 | $object = new ($this->class->name)(); 26 | 27 | if (count($arguments) > 0) { 28 | (function () use ($arguments): void { 29 | foreach ($arguments as $name => $value) { 30 | $this->{$name} = $value; // @phpstan-ignore-line 31 | } 32 | })->call($object); 33 | } 34 | 35 | return $object; 36 | } 37 | 38 | public function signature(): string 39 | { 40 | return $this->class->name . ' (properties)'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Mapper/Source/Exception/FileExtensionNotHandled.php: -------------------------------------------------------------------------------- 1 | source; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mapper/Source/Exception/InvalidSource.php: -------------------------------------------------------------------------------- 1 | source; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mapper/Source/Exception/SourceNotIterable.php: -------------------------------------------------------------------------------- 1 | source; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mapper/Source/Exception/UnableToReadFile.php: -------------------------------------------------------------------------------- 1 | */ 11 | private array $keys; 12 | 13 | private string $to; 14 | 15 | private int $depth; 16 | 17 | /** 18 | * @param array $keys 19 | */ 20 | public function __construct(array $keys, string $to) 21 | { 22 | $this->keys = $keys; 23 | $this->to = $to; 24 | $this->depth = count($keys) - 1; 25 | } 26 | 27 | public function matches(int|string $key, int $atDepth): bool 28 | { 29 | $from = $this->keys[$atDepth] ?? null; 30 | 31 | return $from === (string)$key || $from === '*'; 32 | } 33 | 34 | public function findMappedKey(int|string $key, int $atDepth): ?string 35 | { 36 | if ($atDepth < $this->depth 37 | || !$this->matches($key, $atDepth) 38 | ) { 39 | return null; 40 | } 41 | 42 | return $this->to; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Builder/MixedNodeBuilder.php: -------------------------------------------------------------------------------- 1 | type() instanceof MixedType); 17 | 18 | if (! $shell->allowPermissiveTypes()) { 19 | throw new CannotMapToPermissiveType($shell); 20 | } 21 | 22 | return TreeNode::leaf($shell, $shell->value()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Builder/NodeBuilder.php: -------------------------------------------------------------------------------- 1 | type(); 19 | $value = $shell->value(); 20 | 21 | assert($type instanceof NullType); 22 | 23 | if ($value !== null) { 24 | return TreeNode::error($shell, new SourceIsNotNull()); 25 | } 26 | 27 | return TreeNode::leaf($shell, null); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Builder/RootNodeBuilder.php: -------------------------------------------------------------------------------- 1 | hasValue()) { 24 | if (! $shell->allowUndefinedValues()) { 25 | return TreeNode::error($shell, new MissingNodeValue($shell->type())); 26 | } 27 | 28 | $shell = $shell->withValue(null); 29 | } 30 | 31 | return $this->root->build($shell, $this); 32 | } 33 | 34 | public function withTypeAsCurrentRoot(Type $type): self 35 | { 36 | $self = clone $this; 37 | $self->currentRootType = $type; 38 | 39 | return $self; 40 | } 41 | 42 | public function typeWasSeen(Type $type): bool 43 | { 44 | return isset($this->currentRootType) 45 | && $type->toString() === $this->currentRootType->toString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Builder/ScalarNodeBuilder.php: -------------------------------------------------------------------------------- 1 | type(); 18 | $value = $shell->value(); 19 | 20 | assert($type instanceof ScalarType); 21 | 22 | if ($type->accepts($value)) { 23 | return TreeNode::leaf($shell, $value); 24 | } 25 | 26 | if (! $shell->allowScalarValueCasting() || ! $type->canCast($value)) { 27 | return TreeNode::error($shell, $type->errorMessage()); 28 | } 29 | 30 | return TreeNode::leaf($shell, $type->cast($value)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Builder/UndefinedObjectNodeBuilder.php: -------------------------------------------------------------------------------- 1 | type() instanceof UndefinedObjectType); 19 | 20 | if (! $shell->allowPermissiveTypes()) { 21 | throw new CannotMapToPermissiveType($shell); 22 | } 23 | 24 | return TreeNode::leaf($shell, $shell->value()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Builder/ValueAlteringNodeBuilder.php: -------------------------------------------------------------------------------- 1 | delegate->build($shell, $rootBuilder); 21 | 22 | if (! $node->isValid()) { 23 | return $node; 24 | } 25 | 26 | $value = $node->value(); 27 | 28 | foreach ($this->functions as $function) { 29 | $parameters = $function->definition->parameters; 30 | 31 | if (count($parameters) === 0) { 32 | continue; 33 | } 34 | 35 | $firstParameterType = $parameters->at(0)->type; 36 | 37 | if (! $firstParameterType->accepts($value)) { 38 | continue; 39 | } 40 | 41 | $value = ($function->callback)($value); 42 | $node = $node->withValue($value); 43 | } 44 | 45 | return $node; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/CannotInferFinalClass.php: -------------------------------------------------------------------------------- 1 | className()}` with function `$function->signature`.", 18 | 1671468163 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/CannotMapToPermissiveType.php: -------------------------------------------------------------------------------- 1 | type()->toString(); 16 | 17 | parent::__construct( 18 | "Type `$type` at path `{$shell->path()}` is not allowed in strict mode. " . 19 | "In case `$type` is really needed, the `allowPermissiveTypes` setting can be used.", 20 | 1736935538, 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/CannotResolveObjectType.php: -------------------------------------------------------------------------------- 1 | signature()}`.", 17 | 1739903374, 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/InterfaceHasBothConstructorAndInfer.php: -------------------------------------------------------------------------------- 1 | */ 19 | private array $parameters; 20 | 21 | public function __construct(int|string $key, int $expected) 22 | { 23 | $this->parameters = [ 24 | 'key' => ValueDumper::dump($key), 25 | 'expected' => (string)$expected, 26 | ]; 27 | 28 | parent::__construct(StringFormatter::for($this), 1654273010); 29 | } 30 | 31 | public function body(): string 32 | { 33 | return $this->body; 34 | } 35 | 36 | public function parameters(): array 37 | { 38 | return $this->parameters; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/InvalidNodeHasNoMappedValue.php: -------------------------------------------------------------------------------- 1 | isValid()`.", 16 | 1657466305 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/InvalidNodeValue.php: -------------------------------------------------------------------------------- 1 | */ 20 | private array $parameters; 21 | 22 | public function __construct(Type $type) 23 | { 24 | $this->parameters = [ 25 | 'expected_type' => TypeHelper::dump($type), 26 | ]; 27 | 28 | $this->body = TypeHelper::containsObject($type) 29 | ? 'Invalid value {source_value}.' 30 | : 'Value {source_value} does not match type {expected_type}.'; 31 | 32 | parent::__construct(StringFormatter::for($this), 1630678334); 33 | } 34 | 35 | public function body(): string 36 | { 37 | return $this->body; 38 | } 39 | 40 | public function parameters(): array 41 | { 42 | return $this->parameters; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/InvalidResolvedImplementationValue.php: -------------------------------------------------------------------------------- 1 | */ 21 | private array $parameters; 22 | 23 | public function __construct(string|int $key, ArrayKeyType $type) 24 | { 25 | $this->parameters = [ 26 | 'key' => ValueDumper::dump($key), 27 | 'expected_type' => TypeHelper::dump($type), 28 | ]; 29 | 30 | parent::__construct(StringFormatter::for($this), 1630946163); 31 | } 32 | 33 | public function body(): string 34 | { 35 | return $this->body; 36 | } 37 | 38 | public function parameters(): array 39 | { 40 | return $this->parameters; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/MissingNodeValue.php: -------------------------------------------------------------------------------- 1 | */ 20 | private array $parameters; 21 | 22 | public function __construct(Type $type) 23 | { 24 | $this->parameters = [ 25 | 'expected_type' => TypeHelper::dump($type), 26 | ]; 27 | 28 | parent::__construct(StringFormatter::for($this), 1655449641); 29 | } 30 | 31 | public function body(): string 32 | { 33 | return $this->body; 34 | } 35 | 36 | public function parameters(): array 37 | { 38 | return $this->parameters; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/MissingObjectImplementationRegistration.php: -------------------------------------------------------------------------------- 1 | returnType->toString()}` of `$functionDefinition->signature`.", 17 | 1653990549 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/ObjectImplementationCallbackError.php: -------------------------------------------------------------------------------- 1 | getMessage(), 17 | 1653983061, 18 | $original 19 | ); 20 | } 21 | 22 | public function original(): Exception 23 | { 24 | return $this->original; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/ObjectImplementationNotRegistered.php: -------------------------------------------------------------------------------- 1 | $allowed 18 | */ 19 | public function __construct(string $implementation, string $name, array $allowed) 20 | { 21 | $allowed = implode('`, `', array_map(fn (ClassType $type) => $type->toString(), $allowed)); 22 | 23 | parent::__construct( 24 | "Invalid implementation `$implementation` for `$name`, it should be one of `$allowed`.", 25 | 1653990989 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/ResolvedImplementationIsNotAccepted.php: -------------------------------------------------------------------------------- 1 | toString()}`, expected a subtype of `$name`.", 17 | 1618049487 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/SourceIsNotNull.php: -------------------------------------------------------------------------------- 1 | body = 'Value {source_value} is not null.'; 18 | 19 | parent::__construct($this->body, 1710263908); 20 | } 21 | 22 | public function body(): string 23 | { 24 | return $this->body; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/SourceValueWasNotFilled.php: -------------------------------------------------------------------------------- 1 | sourceFilled()`.", 16 | 1657466107 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Exception/UnresolvableShellType.php: -------------------------------------------------------------------------------- 1 | message()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Message/ErrorMessage.php: -------------------------------------------------------------------------------- 1 | formatters = $formatters; 18 | } 19 | 20 | public function format(NodeMessage $message): NodeMessage 21 | { 22 | foreach ($this->formatters as $formatter) { 23 | $message = $formatter->format($message); 24 | } 25 | 26 | return $message; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Message/Formatter/CallbackMessageFormatter.php: -------------------------------------------------------------------------------- 1 | match ($message->code()) { 18 | * 'some_code_a', 19 | * 'some_code_b', 20 | * 'some_code_c' => $message->withBody('some new message body'), 21 | * default => $message 22 | * } 23 | * ); 24 | * 25 | * $message = $formatter->format($message); 26 | * ``` 27 | * 28 | * @api 29 | */ 30 | final class CallbackMessageFormatter implements MessageFormatter 31 | { 32 | /** @var callable(NodeMessage): NodeMessage */ 33 | private $callback; 34 | 35 | /** 36 | * @param callable(NodeMessage): NodeMessage $callback 37 | */ 38 | public function __construct(callable $callback) 39 | { 40 | $this->callback = $callback; 41 | } 42 | 43 | public function format(NodeMessage $message): NodeMessage 44 | { 45 | return ($this->callback)($message); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Message/Formatter/LocaleMessageFormatter.php: -------------------------------------------------------------------------------- 1 | withLocale($this->locale); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Message/Formatter/MessageFormatter.php: -------------------------------------------------------------------------------- 1 | someParameter = $someParameter; 22 | * } 23 | * 24 | * public function body(): string 25 | * { 26 | * return 'Some message with {some_parameter}'; 27 | * } 28 | * 29 | * public function parameters(): array 30 | * { 31 | * return [ 32 | * 'some_parameter' => $this->someParameter, 33 | * ]; 34 | * } 35 | * } 36 | * ``` 37 | * 38 | * @api 39 | */ 40 | interface HasParameters extends Message 41 | { 42 | /** 43 | * @return array 44 | */ 45 | public function parameters(): array; 46 | } 47 | -------------------------------------------------------------------------------- /src/Mapper/Tree/Message/Message.php: -------------------------------------------------------------------------------- 1 | getPrevious(); // @phpstan-ignore-line 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Mapper/Tree/NodeTraverser.php: -------------------------------------------------------------------------------- 1 | callback = $callback; 23 | } 24 | 25 | /** 26 | * @return iterable 27 | */ 28 | public function traverse(Node $node): iterable 29 | { 30 | return $this->recurse($node); 31 | } 32 | 33 | /** 34 | * @return iterable 35 | */ 36 | private function recurse(Node $node): iterable 37 | { 38 | yield ($this->callback)($node); 39 | 40 | foreach ($node->children() as $child) { 41 | yield from $this->recurse($child); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Mapper/TreeMapper.php: -------------------------------------------------------------------------------- 1 | $signature 14 | * @return T 15 | * @phpstan-return ( 16 | * $signature is class-string 17 | * ? T 18 | * : ($signature is class-string ? object : mixed) 19 | * ) 20 | * 21 | * @throws MappingError 22 | */ 23 | public function map(string $signature, mixed $source): mixed; 24 | } 25 | -------------------------------------------------------------------------------- /src/Mapper/TypeTreeMapperError.php: -------------------------------------------------------------------------------- 1 | errors(); 18 | $errorsCount = count($errors); 19 | 20 | if ($errorsCount === 1) { 21 | $body = $errors 22 | ->toArray()[0] 23 | ->withParameter('root_type', $node->type()) 24 | ->withBody("Could not map type `{root_type}`. An error occurred at path {node_path}: {original_message}") 25 | ->toString(); 26 | } else { 27 | $source = ValueDumper::dump($node->sourceValue()); 28 | $body = "Could not map type `{$node->type()}` with value $source. A total of $errorsCount errors were encountered."; 29 | } 30 | 31 | parent::__construct($body, 1617193185); 32 | } 33 | 34 | public function node(): Node 35 | { 36 | return $this->node; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Normalizer/ArrayNormalizer.php: -------------------------------------------------------------------------------- 1 | |scalar|null> 14 | */ 15 | final class ArrayNormalizer implements Normalizer 16 | { 17 | public function __construct( 18 | private Transformer $transformer, 19 | ) {} 20 | 21 | public function normalize(mixed $value): mixed 22 | { 23 | /** @var array|scalar|null */ 24 | return $this->format( 25 | $this->transformer->transform($value), 26 | ); 27 | } 28 | 29 | private function format(mixed $value): mixed 30 | { 31 | if (is_iterable($value)) { 32 | if (! is_array($value)) { 33 | $value = iterator_to_array($value); 34 | } 35 | 36 | $value = array_map($this->format(...), $value); 37 | } elseif ($value instanceof EmptyObject) { 38 | return []; 39 | } 40 | 41 | return $value; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Normalizer/Exception/CircularReferenceFoundDuringNormalization.php: -------------------------------------------------------------------------------- 1 | parameters->count()} given for `$method->signature`.", 17 | 1701701102, 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Normalizer/Exception/KeyTransformerParameterInvalidType.php: -------------------------------------------------------------------------------- 1 | parameters->at(0)->type->toString()} given for `$method->signature`.", 17 | 1701706316, 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Normalizer/Exception/TransformerHasInvalidCallableParameter.php: -------------------------------------------------------------------------------- 1 | toString()}` given for `$method->signature`.", 19 | 1695065710, 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Normalizer/Exception/TransformerHasNoParameter.php: -------------------------------------------------------------------------------- 1 | signature`.", 18 | 1695064946, 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Normalizer/Exception/TransformerHasTooManyParameters.php: -------------------------------------------------------------------------------- 1 | parameters->count()} given for `$method->signature`.", 18 | 1695065433, 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Normalizer/Exception/TypeUnhandledByNormalizer.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | final class StreamNormalizer implements Normalizer 16 | { 17 | public function __construct( 18 | private Transformer $transformer, 19 | private JsonFormatter $formatter, 20 | ) {} 21 | 22 | public function normalize(mixed $value): mixed 23 | { 24 | $result = $this->transformer->transform($value); 25 | 26 | return $this->formatter->format($result); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Normalizer/Transformer/Compiler/TypeFormatter/DateTimeFormatter.php: -------------------------------------------------------------------------------- 1 | callMethod('format', [ 18 | Node::value('Y-m-d\\TH:i:s.uP'), // RFC 3339 19 | ]); 20 | } 21 | 22 | public function manipulateTransformerClass(AnonymousClassNode $class, TransformerDefinitionBuilder $definitionBuilder): AnonymousClassNode 23 | { 24 | return $class; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Normalizer/Transformer/Compiler/TypeFormatter/DateTimeZoneFormatter.php: -------------------------------------------------------------------------------- 1 | callMethod('getName'); 18 | } 19 | 20 | public function manipulateTransformerClass(AnonymousClassNode $class, TransformerDefinitionBuilder $definitionBuilder): AnonymousClassNode 21 | { 22 | return $class; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Normalizer/Transformer/Compiler/TypeFormatter/EnumFormatter.php: -------------------------------------------------------------------------------- 1 | type->className(), BackedEnum::class, true) 24 | ? $valueNode->access('value') 25 | : $valueNode->access('name'); 26 | } 27 | 28 | public function manipulateTransformerClass(AnonymousClassNode $class, TransformerDefinitionBuilder $definitionBuilder): AnonymousClassNode 29 | { 30 | return $class; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Normalizer/Transformer/Compiler/TypeFormatter/InterfaceFormatter.php: -------------------------------------------------------------------------------- 1 | type->className() === DateTimeInterface::class) { 24 | return (new DateTimeFormatter())->formatValueNode($valueNode); 25 | } 26 | 27 | return Node::this() 28 | ->access('delegate') 29 | ->callMethod('transform', [$valueNode]); 30 | } 31 | 32 | public function manipulateTransformerClass(AnonymousClassNode $class, TransformerDefinitionBuilder $definitionBuilder): AnonymousClassNode 33 | { 34 | return $class; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Normalizer/Transformer/Compiler/TypeFormatter/NullFormatter.php: -------------------------------------------------------------------------------- 1 | instanceOf(BackedEnum::class), 20 | ifTrue: $valueNode->access('value'), 21 | ifFalse: $valueNode->access('name'), 22 | ); 23 | } 24 | 25 | public function manipulateTransformerClass(AnonymousClassNode $class, TransformerDefinitionBuilder $definitionBuilder): AnonymousClassNode 26 | { 27 | return $class; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Normalizer/Transformer/EmptyObject.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | public function types(): array; 16 | } 17 | -------------------------------------------------------------------------------- /src/Type/CompositeTraversableType.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | public function traverse(): array; 14 | } 15 | -------------------------------------------------------------------------------- /src/Type/FixedType.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | public function generics(): array; 17 | } 18 | -------------------------------------------------------------------------------- /src/Type/IntegerType.php: -------------------------------------------------------------------------------- 1 | */ 13 | private array $types = []; 14 | 15 | public function __construct(private TypeParser $delegate) {} 16 | 17 | public function parse(string $raw): Type 18 | { 19 | return $this->types[$raw] ??= $this->delegate->parse($raw); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Constant/ClassConstantCaseNotFound.php: -------------------------------------------------------------------------------- 1 | $enumName 16 | */ 17 | public function __construct(string $enumName) 18 | { 19 | parent::__construct( 20 | "Missing case name for enum `$enumName::?`.", 21 | 1653468431 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Enum/MissingSpecificEnumCase.php: -------------------------------------------------------------------------------- 1 | $enumName 16 | */ 17 | public function __construct(string $enumName) 18 | { 19 | parent::__construct( 20 | "Missing specific case for enum `$enumName::?` (cannot be `*`).", 21 | 1653468438 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Generic/AssignedGenericNotFound.php: -------------------------------------------------------------------------------- 1 | $type->toString(), $generics)); 20 | 21 | parent::__construct( 22 | "Could not find a template to assign the generic(s) `$list` for the class `$className`.", 23 | 1604660485 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Generic/GenericClosingBracketMissing.php: -------------------------------------------------------------------------------- 1 | $type->toString(), $generics)) . '>'; 24 | 25 | parent::__construct( 26 | "The closing bracket is missing for the generic `$signature`.", 27 | 1604333677 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Generic/GenericCommaMissing.php: -------------------------------------------------------------------------------- 1 | $type->toString(), $generics)) . ', ?>'; 24 | 25 | parent::__construct( 26 | "A comma is missing for the generic `$signature`.", 27 | 1615829484 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Generic/InvalidAssignedGeneric.php: -------------------------------------------------------------------------------- 1 | toString()}` is not a subtype of `{$template->toString()}` for " . 21 | "the template `$name` of the class `$className`.", 22 | 1604613633 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Generic/MissingGenerics.php: -------------------------------------------------------------------------------- 1 | $templates 23 | */ 24 | public function __construct(string $className, array $generics, array $templates) 25 | { 26 | /** @var positive-int $missing */ 27 | $missing = count($templates) - count($generics); 28 | $generics = array_map(fn (Type $type) => $type->toString(), $generics); 29 | $generics += array_fill(count($generics), $missing, '?'); 30 | 31 | $signature = $className . '<' . implode(', ', $generics) . '>'; 32 | 33 | parent::__construct( 34 | "There are $missing missing generics for `$signature`.", 35 | 1618054357 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/InvalidIntersectionType.php: -------------------------------------------------------------------------------- 1 | toString()}`, it must be a class name or an interface name.", 17 | 1608030163 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/InvalidType.php: -------------------------------------------------------------------------------- 1 | toString()}`.", 19 | 1606483975 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ArrayCommaMissing.php: -------------------------------------------------------------------------------- 1 | $arrayType 18 | */ 19 | public function __construct(string $arrayType, Type $type) 20 | { 21 | $signature = "array<{$type->toString()}, ?>"; 22 | 23 | if ($arrayType === NonEmptyArrayType::class) { 24 | $signature = "non-empty-array<{$type->toString()}, ?>"; 25 | } 26 | 27 | parent::__construct( 28 | "A comma is missing for `$signature`.", 29 | 1606483614 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/InvalidArrayKey.php: -------------------------------------------------------------------------------- 1 | toString()}`, it must be a valid string or integer.", 18 | 1604335007 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/InvalidIterableKey.php: -------------------------------------------------------------------------------- 1 | toString()}` for `iterable<{$keyType->toString()}, {$subType->toString()}>`. " . 18 | "It must be one of `array-key`, `int` or `string`.", 19 | 1618994708 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/IterableClosingBracketMissing.php: -------------------------------------------------------------------------------- 1 | toString()}, {$subtype->toString()}>`.", 18 | 1618994728 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/IterableCommaMissing.php: -------------------------------------------------------------------------------- 1 | toString()}, ?>`.", 18 | 1618994669 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ListClosingBracketMissing.php: -------------------------------------------------------------------------------- 1 | toString()}`.", 19 | 1634035071 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ShapedArrayClosingBracketMissing.php: -------------------------------------------------------------------------------- 1 | $element->toString(), $elements)); 23 | 24 | if ($unsealedType === false) { 25 | $signature .= ', ...'; 26 | } elseif ($unsealedType instanceof Type) { 27 | $signature .= ', ...' . $unsealedType->toString(); 28 | } 29 | 30 | parent::__construct( 31 | "Missing closing curly bracket in shaped array signature `$signature`.", 32 | 1631283658 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ShapedArrayColonTokenMissing.php: -------------------------------------------------------------------------------- 1 | $element->toString(), $elements)); 23 | 24 | if (! empty($elements)) { 25 | $signature .= ', '; 26 | } 27 | 28 | $signature .= "{$type->toString()}?"; 29 | 30 | parent::__construct( 31 | "A colon symbol is missing in shaped array signature `$signature`.", 32 | 1631283847 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ShapedArrayCommaMissing.php: -------------------------------------------------------------------------------- 1 | $element->toString(), $elements)); 22 | 23 | parent::__construct( 24 | "Comma missing in shaped array signature `$signature`.", 25 | 1631286589 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ShapedArrayElementDuplicatedKey.php: -------------------------------------------------------------------------------- 1 | $element->toString(), $elements)); 24 | 25 | if (! empty($elements)) { 26 | $signature .= ', '; 27 | } 28 | 29 | $signature .= $key->value(); 30 | 31 | if ($optional) { 32 | $signature .= '?'; 33 | } 34 | 35 | $signature .= ':'; 36 | 37 | parent::__construct( 38 | "Missing element type in shaped array signature `$signature`.", 39 | 1631286250 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ShapedArrayEmptyElements.php: -------------------------------------------------------------------------------- 1 | $element->toString(), $elements)); 24 | $signature .= ', ...' . $unsealedType->toString(); 25 | $signature .= '}'; 26 | 27 | parent::__construct( 28 | "Invalid unsealed type `{$unsealedType->toString()}` in shaped array signature `$signature`, it should be a valid array.", 29 | 1711618899, 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ShapedArrayUnexpectedTokenAfterSealedType.php: -------------------------------------------------------------------------------- 1 | $elements 20 | * @param list $unexpectedTokens 21 | */ 22 | public function __construct(array $elements, Type $unsealedType, array $unexpectedTokens) 23 | { 24 | $unexpected = implode('', array_map(fn (Token $token) => $token->symbol(), $unexpectedTokens)); 25 | 26 | $signature = 'array{'; 27 | $signature .= implode(', ', array_map(fn (ShapedArrayElement $element) => $element->toString(), $elements)); 28 | $signature .= ', ...' . $unsealedType->toString(); 29 | $signature .= $unexpected; 30 | 31 | parent::__construct( 32 | "Unexpected `$unexpected` after sealed type in shaped array signature `$signature`, expected a `}`.", 33 | 1711618958, 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/ShapedArrayWithoutElementsWithSealedType.php: -------------------------------------------------------------------------------- 1 | toString()}}"; 17 | 18 | parent::__construct( 19 | "Missing elements in shaped array signature `$signature`.", 20 | 1711629845, 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Iterable/SimpleArrayClosingBracketMissing.php: -------------------------------------------------------------------------------- 1 | toString()}[]`.", 18 | 1606474266 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Magic/ValueOfClosingBracketMissing.php: -------------------------------------------------------------------------------- 1 | toString()}>`.", 18 | 1717702289 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Magic/ValueOfIncorrectSubType.php: -------------------------------------------------------------------------------- 1 | toString()}>`, it should be a `BackedEnum`.", 18 | 1717702683 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Magic/ValueOfOpeningBracketMissing.php: -------------------------------------------------------------------------------- 1 | `.", 17 | 1717702268 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/MissingClosingQuoteChar.php: -------------------------------------------------------------------------------- 1 | toString()}&?`.", 17 | 1631612575 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/RightUnionTypeMissing.php: -------------------------------------------------------------------------------- 1 | toString()}|?`.", 17 | 1631294715 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/ClassStringClosingBracketMissing.php: -------------------------------------------------------------------------------- 1 | toString()}>`.", 18 | 1606484169 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/IntegerRangeInvalidMaxValue.php: -------------------------------------------------------------------------------- 1 | toString()}` for max value of integer range `int<{$min->value()}, ?>`, it must be either `max` or an integer value.", 19 | 1638788172 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/IntegerRangeInvalidMinValue.php: -------------------------------------------------------------------------------- 1 | toString()}` for min value of integer range, it must be either `min` or an integer value.", 18 | 1638787807 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/IntegerRangeMissingClosingBracket.php: -------------------------------------------------------------------------------- 1 | value()}, {$max->value()}>`.", 18 | 1638788306 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/IntegerRangeMissingComma.php: -------------------------------------------------------------------------------- 1 | value()}, ?>`.", 18 | 1638787915 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/IntegerRangeMissingMaxValue.php: -------------------------------------------------------------------------------- 1 | value()}, max>`.", 18 | 1638788092 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/IntegerRangeMissingMinValue.php: -------------------------------------------------------------------------------- 1 | `.', 17 | 1638787061 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/InvalidClassStringSubType.php: -------------------------------------------------------------------------------- 1 | toString()}`, it must be a class name or an interface name.", 18 | 1608034138 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/ReversedValuesForIntegerRange.php: -------------------------------------------------------------------------------- 1 | `.", 17 | 1638787061 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/Scalar/SameValueForIntegerRange.php: -------------------------------------------------------------------------------- 1 | getMessage()}", 20 | 1630092678, 21 | $exception 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Type/Parser/Exception/UnknownSymbol.php: -------------------------------------------------------------------------------- 1 | symbol() === 'self' || $token->symbol() === 'static') { 21 | return new ObjectToken($this->className); 22 | } 23 | 24 | return $token; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Type/Parser/Factory/Specifications/TypeAliasAssignerSpecification.php: -------------------------------------------------------------------------------- 1 | */ 16 | private array $aliases, 17 | ) {} 18 | 19 | public function manipulateToken(TraversingToken $token): TraversingToken 20 | { 21 | $symbol = $token->symbol(); 22 | 23 | if (isset($this->aliases[$symbol])) { 24 | return TypeToken::withSymbol($this->aliases[$symbol], $symbol); 25 | } 26 | 27 | return $token; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Type/Parser/Factory/Specifications/TypeParserSpecification.php: -------------------------------------------------------------------------------- 1 | $aliases 24 | */ 25 | public function buildAdvancedTypeParserForClass(ObjectType $type, array $aliases = []): TypeParser; 26 | 27 | public function buildNativeTypeParserForFunction(ReflectionFunction $reflection): TypeParser; 28 | 29 | public function buildAdvancedTypeParserForFunction(ReflectionFunction $reflection): TypeParser; 30 | } 31 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/SpecificationsLexer.php: -------------------------------------------------------------------------------- 1 | */ 16 | private array $specifications, 17 | ) {} 18 | 19 | public function tokenize(string $symbol): Token 20 | { 21 | return (new VacantToken($symbol, $this->specifications)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/CallableToken.php: -------------------------------------------------------------------------------- 1 | '; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/ClosingCurlyBracketToken.php: -------------------------------------------------------------------------------- 1 | value); 19 | } 20 | 21 | public function symbol(): string 22 | { 23 | return (string)$this->value; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/IntegerValueToken.php: -------------------------------------------------------------------------------- 1 | value); 19 | } 20 | 21 | public function symbol(): string 22 | { 23 | return (string)$this->value; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/LeftTraversingToken.php: -------------------------------------------------------------------------------- 1 | read()); 21 | } 22 | 23 | public function symbol(): string 24 | { 25 | return '?'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/ObjectToken.php: -------------------------------------------------------------------------------- 1 | className) 22 | ? (new EnumNameToken($this->className))->traverse($stream) 23 | : (new ClassNameToken($this->className))->traverse($stream); 24 | } 25 | 26 | public function symbol(): string 27 | { 28 | return $this->className; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/OpeningBracketToken.php: -------------------------------------------------------------------------------- 1 | done() || ! $stream->forward() instanceof ClosingSquareBracketToken) { 21 | throw new SimpleArrayClosingBracketMissing($type); 22 | } 23 | 24 | return ArrayType::simple($type); 25 | } 26 | 27 | public function symbol(): string 28 | { 29 | return '['; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/StringValueToken.php: -------------------------------------------------------------------------------- 1 | value[0]; 20 | 21 | if ($this->value[-1] !== $quoteType) { 22 | throw new MissingClosingQuoteChar($this->value); 23 | } 24 | 25 | return StringValueType::from($this->value); 26 | } 27 | 28 | public function symbol(): string 29 | { 30 | return $this->value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/Token.php: -------------------------------------------------------------------------------- 1 | type = $type; 20 | $this->symbol = $type->toString(); 21 | } 22 | 23 | public static function withSymbol(Type $type, string $symbol): self 24 | { 25 | $self = new self($type); 26 | $self->symbol = $symbol; 27 | 28 | return $self; 29 | } 30 | 31 | public function traverse(TokenStream $stream): Type 32 | { 33 | return $this->type; 34 | } 35 | 36 | public function symbol(): string 37 | { 38 | return $this->symbol; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/Token/UnionToken.php: -------------------------------------------------------------------------------- 1 | done()) { 21 | throw new RightUnionTypeMissing($type); 22 | } 23 | 24 | return new UnionType($type, $stream->read()); 25 | } 26 | 27 | public function symbol(): string 28 | { 29 | return '|'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Type/Parser/Lexer/TypeLexer.php: -------------------------------------------------------------------------------- 1 | $this->lexer->tokenize($symbol), 19 | (new TokensExtractor($raw))->filtered() 20 | ); 21 | 22 | return (new TokenStream(...$tokens))->read(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Type/Parser/TypeParser.php: -------------------------------------------------------------------------------- 1 | isMatchedBy($this); 33 | } 34 | 35 | return $other instanceof self 36 | || $other instanceof MixedType; 37 | } 38 | 39 | public function nativeType(): Type 40 | { 41 | return $this; 42 | } 43 | 44 | public function toString(): string 45 | { 46 | return 'callable'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Type/Types/Exception/ForbiddenMixedType.php: -------------------------------------------------------------------------------- 1 | toString()}` contains invalid class string element(s).", 18 | 1648830951 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Type/Types/Factory/CannotBuildTypeFromValue.php: -------------------------------------------------------------------------------- 1 | equals(Node::value(null)); 25 | } 26 | 27 | public function matches(Type $other): bool 28 | { 29 | if ($other instanceof UnionType) { 30 | return $other->isMatchedBy($this); 31 | } 32 | 33 | return $other instanceof self 34 | || $other instanceof MixedType; 35 | } 36 | 37 | public function nativeType(): Type 38 | { 39 | return $this; 40 | } 41 | 42 | public function toString(): string 43 | { 44 | return 'null'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Type/Types/ShapedArrayElement.php: -------------------------------------------------------------------------------- 1 | key; 21 | } 22 | 23 | public function type(): Type 24 | { 25 | return $this->type; 26 | } 27 | 28 | public function isOptional(): bool 29 | { 30 | return $this->optional; 31 | } 32 | 33 | public function toString(): string 34 | { 35 | return $this->isOptional() 36 | ? "{$this->key->toString()}?: {$this->type->toString()}" 37 | : "{$this->key->toString()}: {$this->type->toString()}"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Type/Types/UndefinedObjectType.php: -------------------------------------------------------------------------------- 1 | isMatchedBy($this); 34 | } 35 | 36 | return $other instanceof self 37 | || $other instanceof ObjectType 38 | || $other instanceof IntersectionType 39 | || $other instanceof MixedType; 40 | } 41 | 42 | public function nativeType(): UndefinedObjectType 43 | { 44 | return $this; 45 | } 46 | 47 | public function toString(): string 48 | { 49 | return 'object'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Utility/IsSingleton.php: -------------------------------------------------------------------------------- 1 | $array 14 | */ 15 | public static function array_all(array $array, callable $callback): bool 16 | { 17 | foreach ($array as $key => $value) { 18 | if (! $callback($value, $key)) { 19 | return false; 20 | } 21 | } 22 | 23 | return true; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Utility/Priority/HasPriority.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | final class PrioritizedList implements IteratorAggregate 17 | { 18 | /** @var array */ 19 | private array $objects = []; 20 | 21 | /** 22 | * @param T ...$objects 23 | */ 24 | public function __construct(object ...$objects) 25 | { 26 | foreach ($objects as $object) { 27 | $this->objects[$this->priority($object)][] = $object; 28 | } 29 | 30 | krsort($this->objects, SORT_NUMERIC); 31 | } 32 | 33 | /** 34 | * @return Traversable 35 | */ 36 | public function getIterator(): Traversable 37 | { 38 | foreach ($this->objects as $priority => $objects) { 39 | foreach ($objects as $object) { 40 | yield $priority => $object; 41 | } 42 | } 43 | } 44 | 45 | private function priority(object $object): int 46 | { 47 | return $object instanceof HasPriority 48 | ? $object->priority() 49 | : 0; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Utility/Reflection/NamespaceFinder.php: -------------------------------------------------------------------------------- 1 | is(T_NAMESPACE)) { 20 | /* @infection-ignore-all Unneeded because of the nature of namespace-related token */ 21 | if ($pointer === 0) { 22 | return null; 23 | } 24 | 25 | $pointer--; 26 | } 27 | 28 | while (! $tokens[$pointer]->is([T_NAME_QUALIFIED, T_STRING])) { 29 | $pointer++; 30 | } 31 | 32 | return (string)$tokens[$pointer]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Utility/String/StringFormatterError.php: -------------------------------------------------------------------------------- 1 |