!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.1.30 

uname -a: Linux server1.tuhinhossain.com 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC
2025 x86_64
 

uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root)  

Safe-mode: OFF (not secure)

/home/picotech/domains/sms.picotech.app/public_html/vendor/phpstan/phpdoc-parser/src/Printer/   drwxr-xr-x
Free 28.79 GB of 117.98 GB (24.4%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     Printer.php (30.72 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php declare(strict_types 1);

namespace 
PHPStan\PhpDocParser\Printer;

use 
LogicException;
use 
PHPStan\PhpDocParser\Ast\Attribute;
use 
PHPStan\PhpDocParser\Ast\Comment;
use 
PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprArrayNode;
use 
PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use 
PHPStan\PhpDocParser\Ast\Node;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagMethodValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagPropertyValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineAnnotation;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArgument;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArray;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArrayItem;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\MixinTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ParamClosureThisTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ParamImmediatelyInvokedCallableTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ParamLaterInvokedCallableTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ParamOutTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\RequireExtendsTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\RequireImplementsTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\SelfOutTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasImportTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\UsesTagValueNode;
use 
PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use 
PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode;
use 
PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use 
PHPStan\PhpDocParser\Ast\Type\ArrayShapeUnsealedTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
use 
PHPStan\PhpDocParser\Ast\Type\ConditionalTypeForParameterNode;
use 
PHPStan\PhpDocParser\Ast\Type\ConditionalTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\InvalidTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\ObjectShapeItemNode;
use 
PHPStan\PhpDocParser\Ast\Type\ObjectShapeNode;
use 
PHPStan\PhpDocParser\Ast\Type\OffsetAccessTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\ThisTypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\TypeNode;
use 
PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use 
PHPStan\PhpDocParser\Lexer\Lexer;
use 
PHPStan\PhpDocParser\Parser\TokenIterator;
use function 
array_keys;
use function 
array_map;
use function 
assert;
use function 
count;
use function 
get_class;
use function 
get_object_vars;
use function 
implode;
use function 
in_array;
use function 
is_array;
use function 
preg_match_all;
use function 
sprintf;
use function 
str_replace;
use function 
strlen;
use function 
strpos;
use function 
trim;
use const 
PREG_SET_ORDER;

/**
 * Inspired by https://github.com/nikic/PHP-Parser/tree/36a6dcd04e7b0285e8f0868f44bd4927802f7df1
 *
 * Copyright (c) 2011, Nikita Popov
 * All rights reserved.
 */
final class Printer
{

    
/** @var Differ<Node> */
    
private Differ $differ;

    
/**
     * Map From "{$class}->{$subNode}" to string that should be inserted
     * between elements of this list subnode
     *
     * @var array<string, string>
     */
    
private array $listInsertionMap = [
        
PhpDocNode::class . '->children' => "\n * ",
        
UnionTypeNode::class . '->types' => '|',
        
IntersectionTypeNode::class . '->types' => '&',
        
ArrayShapeNode::class . '->items' => ', ',
        
ObjectShapeNode::class . '->items' => ', ',
        
CallableTypeNode::class . '->parameters' => ', ',
        
CallableTypeNode::class . '->templateTypes' => ', ',
        
GenericTypeNode::class . '->genericTypes' => ', ',
        
ConstExprArrayNode::class . '->items' => ', ',
        
MethodTagValueNode::class . '->parameters' => ', ',
        
DoctrineArray::class . '->items' => ', ',
        
DoctrineAnnotation::class . '->arguments' => ', ',
    ];

    
/**
     * [$find, $extraLeft, $extraRight]
     *
     * @var array<string, array{string|null, string, string}>
     */
    
private array $emptyListInsertionMap = [
        
CallableTypeNode::class . '->parameters' => ['('''''],
        
ArrayShapeNode::class . '->items' => ['{'''''],
        
ObjectShapeNode::class . '->items' => ['{'''''],
        
DoctrineArray::class . '->items' => ['{'''''],
        
DoctrineAnnotation::class . '->arguments' => ['('''''],
    ];

    
/** @var array<string, list<class-string<TypeNode>>> */
    
private array $parenthesesMap = [
        
CallableTypeNode::class . '->returnType' => [
            
CallableTypeNode::class,
            
UnionTypeNode::class,
            
IntersectionTypeNode::class,
        ],
        
ArrayTypeNode::class . '->type' => [
            
CallableTypeNode::class,
            
UnionTypeNode::class,
            
IntersectionTypeNode::class,
            
ConstTypeNode::class,
            
NullableTypeNode::class,
        ],
        
OffsetAccessTypeNode::class . '->type' => [
            
CallableTypeNode::class,
            
UnionTypeNode::class,
            
IntersectionTypeNode::class,
            
NullableTypeNode::class,
        ],
    ];

    
/** @var array<string, list<class-string<TypeNode>>> */
    
private array $parenthesesListMap = [
        
IntersectionTypeNode::class . '->types' => [
            
IntersectionTypeNode::class,
            
UnionTypeNode::class,
            
NullableTypeNode::class,
        ],
        
UnionTypeNode::class . '->types' => [
            
IntersectionTypeNode::class,
            
UnionTypeNode::class,
            
NullableTypeNode::class,
        ],
    ];

    public function 
printFormatPreserving(PhpDocNode $nodePhpDocNode $originalNodeTokenIterator $originalTokens): string
    
{
        
$this->differ = new Differ(static function ($a$b) {
            if (
$a instanceof Node && $b instanceof Node) {
                return 
$a === $b->getAttribute(Attribute::ORIGINAL_NODE);
            }

            return 
false;
        });

        
$tokenIndex 0;
        
$result $this->printArrayFormatPreserving(
            
$node->children,
            
$originalNode->children,
            
$originalTokens,
            
$tokenIndex,
            
PhpDocNode::class,
            
'children',
        );
        if (
$result !== null) {
            return 
$result $originalTokens->getContentBetween($tokenIndex$originalTokens->getTokenCount());
        }

        return 
$this->print($node);
    }

    public function print(
Node $node): string
    
{
        if (
$node instanceof PhpDocNode) {
            return 
"/**\n *" implode("\n *"array_map(
                function (
PhpDocChildNode $child): string {
                    
$s $this->print($child);
                    return 
$s === '' '' ' ' $s;
                },
                
$node->children,
            )) . 
"\n */";
        }
        if (
$node instanceof PhpDocTextNode) {
            return 
$node->text;
        }
        if (
$node instanceof PhpDocTagNode) {
            if (
$node->value instanceof DoctrineTagValueNode) {
                return 
$this->print($node->value);
            }

            return 
trim(sprintf('%s %s'$node->name$this->print($node->value)));
        }
        if (
$node instanceof PhpDocTagValueNode) {
            return 
$this->printTagValue($node);
        }
        if (
$node instanceof TypeNode) {
            return 
$this->printType($node);
        }
        if (
$node instanceof ConstExprNode) {
            return 
$this->printConstExpr($node);
        }
        if (
$node instanceof MethodTagValueParameterNode) {
            
$type $node->type !== null $this->print($node->type) . ' ' '';
            
$isReference $node->isReference '&' '';
            
$isVariadic $node->isVariadic '...' '';
            
$default $node->defaultValue !== null ' = ' $this->print($node->defaultValue) : '';
            return 
"{$type}{$isReference}{$isVariadic}{$node->parameterName}{$default}";
        }
        if (
$node instanceof CallableTypeParameterNode) {
            
$type $this->print($node->type) . ' ';
            
$isReference $node->isReference '&' '';
            
$isVariadic $node->isVariadic '...' '';
            
$isOptional $node->isOptional '=' '';
            return 
trim("{$type}{$isReference}{$isVariadic}{$node->parameterName}") . $isOptional;
        }
        if (
$node instanceof ArrayShapeUnsealedTypeNode) {
            if (
$node->keyType !== null) {
                return 
sprintf('<%s, %s>'$this->printType($node->keyType), $this->printType($node->valueType));
            }
            return 
sprintf('<%s>'$this->printType($node->valueType));
        }
        if (
$node instanceof DoctrineAnnotation) {
            return (string) 
$node;
        }
        if (
$node instanceof DoctrineArgument) {
            return (string) 
$node;
        }
        if (
$node instanceof DoctrineArray) {
            return (string) 
$node;
        }
        if (
$node instanceof DoctrineArrayItem) {
            return (string) 
$node;
        }
        if (
$node instanceof ArrayShapeItemNode) {
            if (
$node->keyName !== null) {
                return 
sprintf(
                    
'%s%s: %s',
                    
$this->print($node->keyName),
                    
$node->optional '?' '',
                    
$this->printType($node->valueType),
                );
            }

            return 
$this->printType($node->valueType);
        }
        if (
$node instanceof ObjectShapeItemNode) {
            if (
$node->keyName !== null) {
                return 
sprintf(
                    
'%s%s: %s',
                    
$this->print($node->keyName),
                    
$node->optional '?' '',
                    
$this->printType($node->valueType),
                );
            }

            return 
$this->printType($node->valueType);
        }

        throw new 
LogicException(sprintf('Unknown node type %s'get_class($node)));
    }

    private function 
printTagValue(PhpDocTagValueNode $node): string
    
{
        
// only nodes that contain another node are handled here
        // the rest falls back on (string) $node

        
if ($node instanceof AssertTagMethodValueNode) {
            
$isNegated $node->isNegated '!' '';
            
$isEquality $node->isEquality '=' '';
            
$type $this->printType($node->type);
            return 
trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->method}() {$node->description}");
        }
        if (
$node instanceof AssertTagPropertyValueNode) {
            
$isNegated $node->isNegated '!' '';
            
$isEquality $node->isEquality '=' '';
            
$type $this->printType($node->type);
            return 
trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->property} {$node->description}");
        }
        if (
$node instanceof AssertTagValueNode) {
            
$isNegated $node->isNegated '!' '';
            
$isEquality $node->isEquality '=' '';
            
$type $this->printType($node->type);
            return 
trim("{$isNegated}{$isEquality}{$type} {$node->parameter} {$node->description}");
        }
        if (
$node instanceof ExtendsTagValueNode || $node instanceof ImplementsTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->description}");
        }
        if (
$node instanceof MethodTagValueNode) {
            
$static $node->isStatic 'static ' '';
            
$returnType $node->returnType !== null $this->printType($node->returnType) . ' ' '';
            
$parameters implode(', 'array_map(fn (MethodTagValueParameterNode $parameter): string => $this->print($parameter), $node->parameters));
            
$description $node->description !== '' {$node->description}'';
            
$templateTypes count($node->templateTypes) > '<' implode(', 'array_map(fn (TemplateTagValueNode $templateTag): string => $this->print($templateTag), $node->templateTypes)) . '>' '';
            return 
"{$static}{$returnType}{$node->methodName}{$templateTypes}({$parameters}){$description}";
        }
        if (
$node instanceof MixinTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->description}");
        }
        if (
$node instanceof RequireExtendsTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->description}");
        }
        if (
$node instanceof RequireImplementsTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->description}");
        }
        if (
$node instanceof ParamOutTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->parameterName} {$node->description}");
        }
        if (
$node instanceof ParamTagValueNode) {
            
$reference $node->isReference '&' '';
            
$variadic $node->isVariadic '...' '';
            
$type $this->printType($node->type);
            return 
trim("{$type} {$reference}{$variadic}{$node->parameterName} {$node->description}");
        }
        if (
$node instanceof ParamImmediatelyInvokedCallableTagValueNode) {
            return 
trim("{$node->parameterName} {$node->description}");
        }
        if (
$node instanceof ParamLaterInvokedCallableTagValueNode) {
            return 
trim("{$node->parameterName} {$node->description}");
        }
        if (
$node instanceof ParamClosureThisTagValueNode) {
            return 
trim("{$node->type} {$node->parameterName} {$node->description}");
        }
        if (
$node instanceof PureUnlessCallableIsImpureTagValueNode) {
            return 
trim("{$node->parameterName} {$node->description}");
        }
        if (
$node instanceof PropertyTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->propertyName} {$node->description}");
        }
        if (
$node instanceof ReturnTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->description}");
        }
        if (
$node instanceof SelfOutTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim($type ' ' $node->description);
        }
        if (
$node instanceof TemplateTagValueNode) {
            
$upperBound $node->bound !== null ' of ' $this->printType($node->bound) : '';
            
$lowerBound $node->lowerBound !== null ' super ' $this->printType($node->lowerBound) : '';
            
$default $node->default !== null ' = ' $this->printType($node->default) : '';
            return 
trim("{$node->name}{$upperBound}{$lowerBound}{$default} {$node->description}");
        }
        if (
$node instanceof ThrowsTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->description}");
        }
        if (
$node instanceof TypeAliasImportTagValueNode) {
            return 
trim(
                
"{$node->importedAlias} from " $this->printType($node->importedFrom)
                . (
$node->importedAs !== null " as {$node->importedAs}''),
            );
        }
        if (
$node instanceof TypeAliasTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$node->alias} {$type}");
        }
        if (
$node instanceof UsesTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} {$node->description}");
        }
        if (
$node instanceof VarTagValueNode) {
            
$type $this->printType($node->type);
            return 
trim("{$type} " trim("{$node->variableName} {$node->description}"));
        }

        return (string) 
$node;
    }

    private function 
printType(TypeNode $node): string
    
{
        if (
$node instanceof ArrayShapeNode) {
            
$items array_map(fn (ArrayShapeItemNode $item): string => $this->print($item), $node->items);

            if (! 
$node->sealed) {
                
$items[] = '...' . ($node->unsealedType === null '' $this->print($node->unsealedType));
            }

            return 
$node->kind '{' implode(', '$items) . '}';
        }
        if (
$node instanceof ArrayTypeNode) {
            return 
$this->printOffsetAccessType($node->type) . '[]';
        }
        if (
$node instanceof CallableTypeNode) {
            if (
$node->returnType instanceof CallableTypeNode || $node->returnType instanceof UnionTypeNode || $node->returnType instanceof IntersectionTypeNode) {
                
$returnType $this->wrapInParentheses($node->returnType);
            } else {
                
$returnType $this->printType($node->returnType);
            }
            
$template $node->templateTypes !== []
                ? 
'<' implode(', 'array_map(fn (TemplateTagValueNode $templateNode): string => $this->print($templateNode), $node->templateTypes)) . '>'
                
'';
            
$parameters implode(', 'array_map(fn (CallableTypeParameterNode $parameterNode): string => $this->print($parameterNode), $node->parameters));
            return 
"{$node->identifier}{$template}({$parameters}): {$returnType}";
        }
        if (
$node instanceof ConditionalTypeForParameterNode) {
            return 
sprintf(
                
'(%s %s %s ? %s : %s)',
                
$node->parameterName,
                
$node->negated 'is not' 'is',
                
$this->printType($node->targetType),
                
$this->printType($node->if),
                
$this->printType($node->else),
            );
        }
        if (
$node instanceof ConditionalTypeNode) {
            return 
sprintf(
                
'(%s %s %s ? %s : %s)',
                
$this->printType($node->subjectType),
                
$node->negated 'is not' 'is',
                
$this->printType($node->targetType),
                
$this->printType($node->if),
                
$this->printType($node->else),
            );
        }
        if (
$node instanceof ConstTypeNode) {
            return 
$this->printConstExpr($node->constExpr);
        }
        if (
$node instanceof GenericTypeNode) {
            
$genericTypes = [];

            foreach (
$node->genericTypes as $index => $type) {
                
$variance $node->variances[$index] ?? GenericTypeNode::VARIANCE_INVARIANT;
                if (
$variance === GenericTypeNode::VARIANCE_INVARIANT) {
                    
$genericTypes[] = $this->printType($type);
                } elseif (
$variance === GenericTypeNode::VARIANCE_BIVARIANT) {
                    
$genericTypes[] = '*';
                } else {
                    
$genericTypes[] = sprintf('%s %s'$variance$this->print($type));
                }
            }

            return 
$node->type '<' implode(', '$genericTypes) . '>';
        }
        if (
$node instanceof IdentifierTypeNode) {
            return 
$node->name;
        }
        if (
$node instanceof IntersectionTypeNode || $node instanceof UnionTypeNode) {
            
$items = [];
            foreach (
$node->types as $type) {
                if (
                    
$type instanceof IntersectionTypeNode
                    
|| $type instanceof UnionTypeNode
                    
|| $type instanceof NullableTypeNode
                
) {
                    
$items[] = $this->wrapInParentheses($type);
                    continue;
                }

                
$items[] = $this->printType($type);
            }

            return 
implode($node instanceof IntersectionTypeNode '&' '|'$items);
        }
        if (
$node instanceof InvalidTypeNode) {
            return (string) 
$node;
        }
        if (
$node instanceof NullableTypeNode) {
            if (
$node->type instanceof IntersectionTypeNode || $node->type instanceof UnionTypeNode) {
                return 
'?(' $this->printType($node->type) . ')';
            }

            return 
'?' $this->printType($node->type);
        }
        if (
$node instanceof ObjectShapeNode) {
            
$items array_map(fn (ObjectShapeItemNode $item): string => $this->print($item), $node->items);

            return 
'object{' implode(', '$items) . '}';
        }
        if (
$node instanceof OffsetAccessTypeNode) {
            return 
$this->printOffsetAccessType($node->type) . '[' $this->printType($node->offset) . ']';
        }
        if (
$node instanceof ThisTypeNode) {
            return (string) 
$node;
        }

        throw new 
LogicException(sprintf('Unknown node type %s'get_class($node)));
    }

    private function 
wrapInParentheses(TypeNode $node): string
    
{
        return 
'(' $this->printType($node) . ')';
    }

    private function 
printOffsetAccessType(TypeNode $type): string
    
{
        if (
            
$type instanceof CallableTypeNode
            
|| $type instanceof UnionTypeNode
            
|| $type instanceof IntersectionTypeNode
            
|| $type instanceof NullableTypeNode
        
) {
            return 
$this->wrapInParentheses($type);
        }

        return 
$this->printType($type);
    }

    private function 
printConstExpr(ConstExprNode $node): string
    
{
        
// this is fine - ConstExprNode classes do not contain nodes that need smart printer logic
        
return (string) $node;
    }

    
/**
     * @param Node[] $nodes
     * @param Node[] $originalNodes
     */
    
private function printArrayFormatPreserving(array $nodes, array $originalNodesTokenIterator $originalTokensint &$tokenIndexstring $parentNodeClassstring $subNodeName): ?string
    
{
        
$diff $this->differ->diffWithReplacements($originalNodes$nodes);
        
$mapKey $parentNodeClass '->' $subNodeName;
        
$insertStr $this->listInsertionMap[$mapKey] ?? null;
        
$result '';
        
$beforeFirstKeepOrReplace true;
        
$delayedAdd = [];

        
$insertNewline false;
        [
$isMultiline$beforeAsteriskIndent$afterAsteriskIndent] = $this->isMultiline($tokenIndex$originalNodes$originalTokens);

        if (
$insertStr === "\n * ") {
            
$insertStr sprintf('%s%s*%s'$originalTokens->getDetectedNewline() ?? "\n"$beforeAsteriskIndent$afterAsteriskIndent);
        }

        foreach (
$diff as $i => $diffElem) {
            
$diffType $diffElem->type;
            
$arrItem $diffElem->new;
            
$origArrayItem $diffElem->old;
            if (
$diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) {
                
$beforeFirstKeepOrReplace false;
                if (!
$arrItem instanceof Node || !$origArrayItem instanceof Node) {
                    return 
null;
                }

                
/** @var int $itemStartPos */
                
$itemStartPos $origArrayItem->getAttribute(Attribute::START_INDEX);

                
/** @var int $itemEndPos */
                
$itemEndPos $origArrayItem->getAttribute(Attribute::END_INDEX);

                if (
$itemStartPos || $itemEndPos || $itemStartPos $tokenIndex) {
                    throw new 
LogicException();
                }

                
$comments $arrItem->getAttribute(Attribute::COMMENTS) ?? [];
                
$origComments $origArrayItem->getAttribute(Attribute::COMMENTS) ?? [];

                
$commentStartPos count($origComments) > $origComments[0]->startIndex $itemStartPos;
                
assert($commentStartPos >= 0);

                
$result .= $originalTokens->getContentBetween($tokenIndex$itemStartPos);

                if (
count($delayedAdd) > 0) {
                    foreach (
$delayedAdd as $delayedAddNode) {
                        
$parenthesesNeeded = isset($this->parenthesesListMap[$mapKey])
                            && 
in_array(get_class($delayedAddNode), $this->parenthesesListMap[$mapKey], true);
                        if (
$parenthesesNeeded) {
                            
$result .= '(';
                        }

                        if (
$insertNewline) {
                            
$delayedAddComments $delayedAddNode->getAttribute(Attribute::COMMENTS) ?? [];
                            if (
count($delayedAddComments) > 0) {
                                
$result .= $this->printComments($delayedAddComments$beforeAsteriskIndent$afterAsteriskIndent);
                                
$result .= sprintf('%s%s*%s'$originalTokens->getDetectedNewline() ?? "\n"$beforeAsteriskIndent$afterAsteriskIndent);
                            }
                        }

                        
$result .= $this->printNodeFormatPreserving($delayedAddNode$originalTokens);
                        if (
$parenthesesNeeded) {
                            
$result .= ')';
                        }

                        if (
$insertNewline) {
                            
$result .= $insertStr sprintf('%s%s*%s'$originalTokens->getDetectedNewline() ?? "\n"$beforeAsteriskIndent$afterAsteriskIndent);
                        } else {
                            
$result .= $insertStr;
                        }
                    }

                    
$delayedAdd = [];
                }

                
$parenthesesNeeded = isset($this->parenthesesListMap[$mapKey])
                    && 
in_array(get_class($arrItem), $this->parenthesesListMap[$mapKey], true)
                    && !
in_array(get_class($origArrayItem), $this->parenthesesListMap[$mapKey], true);
                
$addParentheses $parenthesesNeeded && !$originalTokens->hasParentheses($itemStartPos$itemEndPos);
                if (
$addParentheses) {
                    
$result .= '(';
                }

                if (
$comments !== $origComments) {
                    if (
count($comments) > 0) {
                        
$result .= $this->printComments($comments$beforeAsteriskIndent$afterAsteriskIndent);
                        
$result .= sprintf('%s%s*%s'$originalTokens->getDetectedNewline() ?? "\n"$beforeAsteriskIndent$afterAsteriskIndent);
                    }
                }

                
$result .= $this->printNodeFormatPreserving($arrItem$originalTokens);
                if (
$addParentheses) {
                    
$result .= ')';
                }
                
$tokenIndex $itemEndPos 1;

            } elseif (
$diffType === DiffElem::TYPE_ADD) {
                if (
$insertStr === null) {
                    return 
null;
                }
                if (!
$arrItem instanceof Node) {
                    return 
null;
                }

                if (
$insertStr === ', ' && $isMultiline || count($arrItem->getAttribute(Attribute::COMMENTS) ?? []) > 0) {
                    
$insertStr ',';
                    
$insertNewline true;
                }

                if (
$beforeFirstKeepOrReplace) {
                    
// Will be inserted at the next "replace" or "keep" element
                    
$delayedAdd[] = $arrItem;
                    continue;
                }

                
/** @var int $itemEndPos */
                
$itemEndPos $tokenIndex 1;
                if (
$insertNewline) {
                    
$comments $arrItem->getAttribute(Attribute::COMMENTS) ?? [];
                    
$result .= $insertStr;
                    if (
count($comments) > 0) {
                        
$result .= sprintf('%s%s*%s'$originalTokens->getDetectedNewline() ?? "\n"$beforeAsteriskIndent$afterAsteriskIndent);
                        
$result .= $this->printComments($comments$beforeAsteriskIndent$afterAsteriskIndent);
                    }
                    
$result .= sprintf('%s%s*%s'$originalTokens->getDetectedNewline() ?? "\n"$beforeAsteriskIndent$afterAsteriskIndent);
                } else {
                    
$result .= $insertStr;
                }

                
$parenthesesNeeded = isset($this->parenthesesListMap[$mapKey])
                    && 
in_array(get_class($arrItem), $this->parenthesesListMap[$mapKey], true);
                if (
$parenthesesNeeded) {
                    
$result .= '(';
                }

                
$result .= $this->printNodeFormatPreserving($arrItem$originalTokens);
                if (
$parenthesesNeeded) {
                    
$result .= ')';
                }

                
$tokenIndex $itemEndPos 1;

            } elseif (
$diffType === DiffElem::TYPE_REMOVE) {
                if (!
$origArrayItem instanceof Node) {
                    return 
null;
                }

                
/** @var int $itemStartPos */
                
$itemStartPos $origArrayItem->getAttribute(Attribute::START_INDEX);

                
/** @var int $itemEndPos */
                
$itemEndPos $origArrayItem->getAttribute(Attribute::END_INDEX);
                if (
$itemStartPos || $itemEndPos 0) {
                    throw new 
LogicException();
                }

                if (
$i === 0) {
                    
// If we're removing from the start, keep the tokens before the node and drop those after it,
                    // instead of the other way around.
                    
$originalTokensArray $originalTokens->getTokens();
                    for (
$j $tokenIndex$j $itemStartPos$j++) {
                        if (
$originalTokensArray[$j][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) {
                            break;
                        }
                        
$result .= $originalTokensArray[$j][Lexer::VALUE_OFFSET];
                    }
                }

                
$tokenIndex $itemEndPos 1;
            }
        }

        if (
count($delayedAdd) > 0) {
            if (!isset(
$this->emptyListInsertionMap[$mapKey])) {
                return 
null;
            }

            [
$findToken$extraLeft$extraRight] = $this->emptyListInsertionMap[$mapKey];
            if (
$findToken !== null) {
                
$originalTokensArray $originalTokens->getTokens();
                for (; 
$tokenIndex count($originalTokensArray); $tokenIndex++) {
                    
$result .= $originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET];
                    if (
$originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET] !== $findToken) {
                        continue;
                    }

                    
$tokenIndex++;
                    break;
                }
            }
            
$first true;
            
$result .= $extraLeft;
            foreach (
$delayedAdd as $delayedAddNode) {
                if (!
$first) {
                    
$result .= $insertStr;
                    if (
$insertNewline) {
                        
$result .= sprintf('%s%s*%s'$originalTokens->getDetectedNewline() ?? "\n"$beforeAsteriskIndent$afterAsteriskIndent);
                    }
                }

                
$result .= $this->printNodeFormatPreserving($delayedAddNode$originalTokens);
                
$first false;
            }
            
$result .= $extraRight;
        }

        return 
$result;
    }

    
/**
     * @param list<Comment> $comments
     */
    
private function printComments(array $commentsstring $beforeAsteriskIndentstring $afterAsteriskIndent): string
    
{
        
$formattedComments = [];

        foreach (
$comments as $comment) {
            
$formattedComments[] = str_replace("\n""\n" $beforeAsteriskIndent '*' $afterAsteriskIndent$comment->getReformattedText());
        }

        return 
implode("\n$beforeAsteriskIndent*$afterAsteriskIndent"$formattedComments);
    }

    
/**
     * @param array<Node|null> $nodes
     * @return array{bool, string, string}
     */
    
private function isMultiline(int $initialIndex, array $nodesTokenIterator $originalTokens): array
    {
        
$isMultiline count($nodes) > 1;
        
$pos $initialIndex;
        
$allText '';
        
/** @var Node|null $node */
        
foreach ($nodes as $node) {
            if (!
$node instanceof Node) {
                continue;
            }

            
$endPos $node->getAttribute(Attribute::END_INDEX) + 1;
            
$text $originalTokens->getContentBetween($pos$endPos);
            
$allText .= $text;
            if (
strpos($text"\n") === false) {
                
// We require that a newline is present between *every* item. If the formatting
                // is inconsistent, with only some items having newlines, we don't consider it
                // as multiline
                
$isMultiline false;
            }
            
$pos $endPos;
        }

        
$c preg_match_all('~\n(?<before>[\\x09\\x20]*)\*(?<after>\\x20*)~'$allText$matchesPREG_SET_ORDER);
        if (
$c === 0) {
            return [
$isMultiline' ''  '];
        }

        
$before '';
        
$after '';
        foreach (
$matches as $match) {
            if (
strlen($match['before']) > strlen($before)) {
                
$before $match['before'];
            }
            if (
strlen($match['after']) <= strlen($after)) {
                continue;
            }

            
$after $match['after'];
        }

        
$before strlen($before) === ' ' $before;
        
$after strlen($after) === '  ' $after;

        return [
$isMultiline$before$after];
    }

    private function 
printNodeFormatPreserving(Node $nodeTokenIterator $originalTokens): string
    
{
        
/** @var Node|null $originalNode */
        
$originalNode $node->getAttribute(Attribute::ORIGINAL_NODE);
        if (
$originalNode === null) {
            return 
$this->print($node);
        }

        
$class get_class($node);
        if (
$class !== get_class($originalNode)) {
            throw new 
LogicException();
        }

        
$startPos $originalNode->getAttribute(Attribute::START_INDEX);
        
$endPos $originalNode->getAttribute(Attribute::END_INDEX);
        if (
$startPos || $endPos 0) {
            throw new 
LogicException();
        }

        
$result '';
        
$pos $startPos;
        
$subNodeNames array_keys(get_object_vars($node));
        foreach (
$subNodeNames as $subNodeName) {
            
$subNode $node->$subNodeName;
            
$origSubNode $originalNode->$subNodeName;

            if (
                (!
$subNode instanceof Node && $subNode !== null)
                || (!
$origSubNode instanceof Node && $origSubNode !== null)
            ) {
                if (
$subNode === $origSubNode) {
                    
// Unchanged, can reuse old code
                    
continue;
                }

                if (
is_array($subNode) && is_array($origSubNode)) {
                    
// Array subnode changed, we might be able to reconstruct it
                    
$listResult $this->printArrayFormatPreserving(
                        
$subNode,
                        
$origSubNode,
                        
$originalTokens,
                        
$pos,
                        
$class,
                        
$subNodeName,
                    );

                    if (
$listResult === null) {
                        return 
$this->print($node);
                    }

                    
$result .= $listResult;
                    continue;
                }

                return 
$this->print($node);
            }

            if (
$origSubNode === null) {
                if (
$subNode === null) {
                    
// Both null, nothing to do
                    
continue;
                }

                return 
$this->print($node);
            }

            
$subStartPos $origSubNode->getAttribute(Attribute::START_INDEX);
            
$subEndPos $origSubNode->getAttribute(Attribute::END_INDEX);
            if (
$subStartPos || $subEndPos 0) {
                throw new 
LogicException();
            }

            if (
$subEndPos $subStartPos) {
                return 
$this->print($node);
            }

            if (
$subNode === null) {
                return 
$this->print($node);
            }

            
$result .= $originalTokens->getContentBetween($pos$subStartPos);
            
$mapKey get_class($node) . '->' $subNodeName;
            
$parenthesesNeeded = isset($this->parenthesesMap[$mapKey])
                && 
in_array(get_class($subNode), $this->parenthesesMap[$mapKey], true);

            if (
$subNode->getAttribute(Attribute::ORIGINAL_NODE) !== null) {
                
$parenthesesNeeded $parenthesesNeeded
                    
&& !in_array(get_class($subNode->getAttribute(Attribute::ORIGINAL_NODE)), $this->parenthesesMap[$mapKey], true);
            }

            
$addParentheses $parenthesesNeeded && !$originalTokens->hasParentheses($subStartPos$subEndPos);
            if (
$addParentheses) {
                
$result .= '(';
            }

            
$result .= $this->printNodeFormatPreserving($subNode$originalTokens);
            if (
$addParentheses) {
                
$result .= ')';
            }

            
$pos $subEndPos 1;
        }

        return 
$result $originalTokens->getContentBetween($pos$endPos 1);
    }

}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0082 ]--