Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. Printer.php

function Printer::printArrayFormatPreserving

*

Parameters

Node[] $nodes: * @param Node[] $originalNodes

2 calls to Printer::printArrayFormatPreserving()
Printer::printFormatPreserving in vendor/phpstan/phpdoc-parser/src/Printer/Printer.php
Printer::printNodeFormatPreserving in vendor/phpstan/phpdoc-parser/src/Printer/Printer.php

File

vendor/phpstan/phpdoc-parser/src/Printer/Printer.php, line 544

Class

Printer
Inspired by https://github.com/nikic/PHP-Parser/tree/36a6dcd04e7b0285e8f0868f44bd49…

Namespace

PHPStan\PhpDocParser\Printer

Code

private function printArrayFormatPreserving(array $nodes, array $originalNodes, TokenIterator $originalTokens, int &$tokenIndex, string $parentNodeClass, string $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;
        $newNode = $diffElem->new;
        $originalNode = $diffElem->old;
        if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) {
            $beforeFirstKeepOrReplace = false;
            if (!$newNode instanceof Node || !$originalNode instanceof Node) {
                return null;
            }
            $itemStartPos = $originalNode->getAttribute(Attribute::START_INDEX);
            $itemEndPos = $originalNode->getAttribute(Attribute::END_INDEX);
            if ($itemStartPos < 0 || $itemEndPos < 0 || $itemStartPos < $tokenIndex) {
                throw new LogicException();
            }
            $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 .= '(';
                    }
                    $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($newNode), $this->parenthesesListMap[$mapKey], true) && !in_array(get_class($originalNode), $this->parenthesesListMap[$mapKey], true);
            $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($itemStartPos, $itemEndPos);
            if ($addParentheses) {
                $result .= '(';
            }
            $result .= $this->printNodeFormatPreserving($newNode, $originalTokens);
            if ($addParentheses) {
                $result .= ')';
            }
            $tokenIndex = $itemEndPos + 1;
        }
        elseif ($diffType === DiffElem::TYPE_ADD) {
            if ($insertStr === null) {
                return null;
            }
            if (!$newNode instanceof Node) {
                return null;
            }
            if ($insertStr === ', ' && $isMultiline) {
                $insertStr = ',';
                $insertNewline = true;
            }
            if ($beforeFirstKeepOrReplace) {
                // Will be inserted at the next "replace" or "keep" element
                $delayedAdd[] = $newNode;
                continue;
            }
            $itemEndPos = $tokenIndex - 1;
            if ($insertNewline) {
                $result .= $insertStr . sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent);
            }
            else {
                $result .= $insertStr;
            }
            $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) && in_array(get_class($newNode), $this->parenthesesListMap[$mapKey], true);
            if ($parenthesesNeeded) {
                $result .= '(';
            }
            $result .= $this->printNodeFormatPreserving($newNode, $originalTokens);
            if ($parenthesesNeeded) {
                $result .= ')';
            }
            $tokenIndex = $itemEndPos + 1;
        }
        elseif ($diffType === DiffElem::TYPE_REMOVE) {
            if (!$originalNode instanceof Node) {
                return null;
            }
            $itemStartPos = $originalNode->getAttribute(Attribute::START_INDEX);
            $itemEndPos = $originalNode->getAttribute(Attribute::END_INDEX);
            if ($itemStartPos < 0 || $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;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal