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

Breadcrumb

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

function Renderer::renderNode

Renders a node

Parameters

Syntax\Node\Node $node Node to render:

bool $addSemicolon True to add semicolon after node: rendered code

Return value

string

3 calls to Renderer::renderNode()
Renderer::joinNodes in vendor/mck89/peast/lib/Peast/Renderer.php
Joins an array of nodes with the given separator
Renderer::render in vendor/mck89/peast/lib/Peast/Renderer.php
Renders the given node
Renderer::renderStatementBlock in vendor/mck89/peast/lib/Peast/Renderer.php
Renders a node as a block statement

File

vendor/mck89/peast/lib/Peast/Renderer.php, line 124

Class

Renderer
Nodes renderer class

Namespace

Peast

Code

protected function renderNode(Syntax\Node\Node $node, $addSemicolon = false) {
    $code = "";
    if ($this->renderOpts->com) {
        $code .= $this->renderComments($node);
    }
    $type = $node->getType();
    switch ($type) {
        case "ArrayExpression":
        case "ArrayPattern":
            $code .= "[" . $this->joinNodes($node->getElements(), "," . $this->renderOpts->sao) . "]";
            break;
        case "ArrowFunctionExpression":
            if ($node->getAsync()) {
                $code .= "async" . $this->renderOpts->sao;
            }
            $code .= "(" . $this->renderOpts->sirb . $this->joinNodes($node->getParams(), "," . $this->renderOpts->sao) . $this->renderOpts->sirb . ")" . $this->renderOpts->sao . "=>";
            $body = $node->getBody();
            if ($body->getType() !== "BlockStatement") {
                $code .= $this->renderOpts->sao . $this->renderNode($body);
            }
            else {
                $code .= $this->renderStatementBlock($node, $body, true);
            }
            break;
        case "AwaitExpression":
            $code .= "await " . $this->renderNode($node->getArgument());
            break;
        case "AssignmentExpression":
        case "AssignmentPattern":
        case "BinaryExpression":
        case "LogicalExpression":
            $operator = $type === "AssignmentPattern" ? "=" : $node->getOperator();
            $code .= $this->renderNode($node->getLeft());
            $codeRight = $this->renderNode($node->getRight());
            if (preg_match("#^[a-z]+\$#i", $operator)) {
                $code .= " " . $operator . " ";
            }
            else {
                
                //If there's no space around the operator, additional checks must
                
                //be performed to prevent errors when rendering unary and update
                
                //expressions inside binary expressions
                $checkSpace = !$this->renderOpts->sao && $type === "BinaryExpression";
                
                //The space is mandatory if the left part ends with the same
                
                //character used as operator
                if ($checkSpace && $code && substr($code, -1) === $operator) {
                    $code .= " ";
                }
                $code .= $this->renderOpts->sao . $operator . $this->renderOpts->sao;
                
                //The space is mandatory if the right part begins with the same
                
                //character used as operator
                if ($checkSpace && $codeRight && $codeRight[0] === $operator) {
                    $code .= " ";
                }
            }
            $code .= $codeRight;
            break;
        case "BlockStatement":
        case "ClassBody":
        case "Program":
            $code .= $this->renderStatementBlock($node, $node->getBody(), false, false, true, false);
            break;
        case "BreakStatement":
        case "ContinueStatement":
            $code .= $type === "BreakStatement" ? "break" : "continue";
            if ($label = $node->getLabel()) {
                $code .= " " . $this->renderNode($label);
            }
            break;
        case "CallExpression":
        case "NewExpression":
            if ($type === "NewExpression") {
                $code .= "new ";
                $optional = false;
            }
            else {
                $optional = $node->getOptional();
            }
            $code .= $this->renderNode($node->getCallee()) . ($optional ? "?." : "") . "(" . $this->renderOpts->sirb . $this->joinNodes($node->getArguments(), "," . $this->renderOpts->sao) . $this->renderOpts->sirb . ")";
            break;
        case "CatchClause":
            $code .= "catch";
            if ($params = $node->getParam()) {
                $code .= $this->renderOpts->sao . "(" . $this->renderOpts->sirb . $this->renderNode($params) . $this->renderOpts->sirb . ")";
            }
            $code .= $this->renderStatementBlock($node, $node->getBody(), true);
            break;
        case "ChainExpression":
        case "ExpressionStatement":
            $code .= $this->renderNode($node->getExpression());
            break;
        case "ClassExpression":
        case "ClassDeclaration":
            $code .= "class";
            if ($id = $node->getId()) {
                $code .= " " . $this->renderNode($id);
            }
            if ($superClass = $node->getSuperClass()) {
                $code .= " extends " . $this->renderNode($superClass);
            }
            $code .= $this->renderStatementBlock($node, $node->getBody(), true);
            break;
        case "ConditionalExpression":
            $code .= $this->renderNode($node->getTest()) . $this->renderOpts->sao . "?" . $this->renderOpts->sao . $this->renderNode($node->getConsequent()) . $this->renderOpts->sao . ":" . $this->renderOpts->sao . $this->renderNode($node->getAlternate());
            break;
        case "DebuggerStatement":
            $code .= "debugger";
            break;
        case "DoWhileStatement":
            $code .= "do" . $this->renderStatementBlock($node, $node->getBody(), null, true) . $this->renderOpts->sao . "while" . $this->renderOpts->sao . "(" . $this->renderOpts->sirb . $this->renderNode($node->getTest()) . $this->renderOpts->sirb . ")";
            break;
        case "JSXEmptyExpression":
        case "EmptyStatement":
            break;
        case "ExportAllDeclaration":
            $code .= "export *";
            $exported = $node->getExported();
            if ($exported) {
                $code .= " as " . $this->renderNode($exported);
            }
            $code .= " from " . $this->renderNode($node->getSource());
            break;
        case "ExportDefaultDeclaration":
            $declaration = $node->getDeclaration();
            $code .= "export default " . $this->renderNode($declaration);
            if ($this->requiresSemicolon($declaration)) {
                $code .= ";";
            }
            break;
        case "ExportNamedDeclaration":
            $code .= "export";
            if ($dec = $node->getDeclaration()) {
                $code .= " " . $this->renderNode($dec);
            }
            else {
                $code .= $this->renderOpts->sao . "{" . $this->joinNodes($node->getSpecifiers(), "," . $this->renderOpts->sao) . "}";
                if ($source = $node->getSource()) {
                    $code .= $this->renderOpts->sao . "from " . $this->renderNode($source);
                }
            }
            break;
        case "ExportSpecifier":
            $local = $this->renderNode($node->getLocal());
            $ref = $this->renderNode($node->getExported());
            $code .= $local === $ref ? $local : $local . " as " . $ref;
            break;
        case "ForInStatement":
        case "ForOfStatement":
            
            //Force single line mode for substatements
            $this->renderOpts->forceSingleLine = true;
            $code .= "for" . ($type === "ForOfStatement" && $node->getAwait() ? " await" : "") . $this->renderOpts->sao . "(" . $this->renderOpts->sirb . $this->renderNode($node->getLeft()) . " " . ($type === "ForInStatement" ? "in" : "of") . " " . $this->renderNode($node->getRight()) . $this->renderOpts->sirb . ")" . $this->renderStatementBlock($node, $node->getBody());
            unset($this->renderOpts->forceSingleLine);
            break;
        case "ForStatement":
            
            //Force single line mode for substatements
            $this->renderOpts->forceSingleLine = true;
            $code .= "for" . $this->renderOpts->sao . "(" . $this->renderOpts->sirb;
            if ($init = $node->getInit()) {
                $code .= $this->renderNode($init);
            }
            $code .= ";" . $this->renderOpts->sao;
            if ($test = $node->getTest()) {
                $code .= $this->renderNode($test);
            }
            $code .= ";" . $this->renderOpts->sao;
            if ($update = $node->getUpdate()) {
                $code .= $this->renderNode($update);
            }
            $code .= $this->renderOpts->sirb . ")" . $this->renderStatementBlock($node, $node->getBody());
            unset($this->renderOpts->forceSingleLine);
            break;
        case "FunctionDeclaration":
        case "FunctionExpression":
            $id = $node->getId();
            if ($node->getAsync()) {
                $code .= "async ";
            }
            $code .= "function";
            if ($node->getGenerator()) {
                $code .= $this->renderOpts->sao . "*";
            }
            elseif ($id) {
                $code .= " ";
            }
            if ($id) {
                if ($node->getGenerator()) {
                    $code .= $this->renderOpts->sao;
                }
                $code .= $this->renderNode($id);
            }
            $code .= $this->renderOpts->sao . "(" . $this->renderOpts->sirb . $this->joinNodes($node->getParams(), "," . $this->renderOpts->sao) . $this->renderOpts->sirb . ")" . $this->renderStatementBlock($node, $node->getBody(), true);
            break;
        case "ImportExpression":
            $code .= "import(" . $this->renderOpts->sirb . $this->renderNode($node->getSource()) . $this->renderOpts->sirb . ")";
            break;
        case "JSXIdentifier":
        case "Identifier":
            $code .= $node->getRawName();
            break;
        case "IfStatement":
            $code .= "if" . $this->renderOpts->sao . "(" . $this->renderOpts->sirb . $this->renderNode($node->getTest()) . $this->renderOpts->sirb . ")";
            $code .= $this->renderStatementBlock($node, $node->getConsequent());
            if ($alternate = $node->getAlternate()) {
                $code .= $this->renderOpts->sao . "else" . $this->renderStatementBlock($node, $alternate, null, true);
            }
            break;
        case "ImportDeclaration":
            $code .= "import ";
            $specifiers = $node->getSpecifiers();
            if (count($specifiers)) {
                $sep = "," . $this->renderOpts->sao;
                $groups = $parts = array();
                foreach ($specifiers as $spec) {
                    $specType = $spec->getType();
                    if (!isset($groups[$specType])) {
                        $groups[$specType] = array();
                    }
                    $groups[$specType][] = $spec;
                }
                if (isset($groups["ImportDefaultSpecifier"])) {
                    foreach ($groups["ImportDefaultSpecifier"] as $s) {
                        $parts[] = $this->renderNode($s);
                    }
                }
                if (isset($groups["ImportNamespaceSpecifier"])) {
                    foreach ($groups["ImportNamespaceSpecifier"] as $s) {
                        $parts[] = $this->renderNode($s);
                    }
                }
                if (isset($groups["ImportSpecifier"])) {
                    $impSpec = array();
                    foreach ($groups["ImportSpecifier"] as $s) {
                        $impSpec[] = $this->renderNode($s);
                    }
                    $parts[] = "{" . implode($sep, $impSpec) . "}";
                }
                $code .= implode($sep, $parts) . " from ";
            }
            $code .= $this->renderNode($node->getSource());
            break;
        case "ImportDefaultSpecifier":
            $code .= $this->renderNode($node->getLocal());
            break;
        case "ImportNamespaceSpecifier":
            $code .= "* as " . $this->renderNode($node->getLocal());
            break;
        case "ImportSpecifier":
            $local = $this->renderNode($node->getLocal());
            $ref = $this->renderNode($node->getImported());
            $code .= $local === $ref ? $local : $ref . " as " . $local;
            break;
        case "JSXAttribute":
            $code .= $this->renderNode($node->getName());
            if ($value = $node->getValue()) {
                $code .= "=" . $this->renderNode($value);
            }
            break;
        case "JSXClosingElement":
            $code .= "</" . $this->renderNode($node->getName()) . ">";
            break;
        case "JSXClosingFragment":
            $code .= "</>";
            break;
        case "JSXElement":
            $code .= $this->renderNode($node->getOpeningElement()) . $this->joinNodes($node->getChildren(), "");
            if ($closing = $node->getClosingElement()) {
                $code .= $this->renderNode($closing);
            }
            break;
        case "JSXExpressionContainer":
            $code .= "{" . $this->renderNode($node->getExpression()) . "}";
            break;
        case "JSXFragment":
            $code .= $this->renderNode($node->getOpeningFragment()) . $this->joinNodes($node->getChildren(), "") . $this->renderNode($node->getClosingFragment());
            break;
        case "JSXNamespacedName":
            $code .= $this->renderNode($node->getNamespace()) . ":" . $this->renderNode($node->getName());
            break;
        case "JSXOpeningElement":
            $code .= "<" . $this->renderNode($node->getName());
            $attributes = $node->getAttributes();
            if (count($attributes)) {
                $code .= " " . $this->joinNodes($attributes, " ");
            }
            if ($node->getSelfClosing()) {
                $code .= "/";
            }
            $code .= ">";
            break;
        case "JSXOpeningFragment":
            $code .= "<>";
            break;
        case "JSXSpreadAttribute":
            $code .= "{..." . $this->renderNode($node->getArgument()) . "}";
            break;
        case "JSXSpreadChild":
            $code .= "{..." . $this->renderNode($node->getExpression()) . "}";
            break;
        case "LabeledStatement":
            $body = $node->getBody();
            $code .= $this->renderNode($node->getLabel()) . ":";
            if ($body->getType() === "BlockStatement") {
                $code .= $this->renderStatementBlock($node, $body, true);
            }
            else {
                $code .= $this->renderOpts->nl . $this->getIndentation() . $this->renderNode($body);
            }
            if ($this->requiresSemicolon($body)) {
                $code .= ";";
            }
            break;
        case "JSXText":
        case "Literal":
        case "RegExpLiteral":
            $code .= $node->getRaw();
            break;
        case "JSXMemberExpression":
        case "MemberExpression":
            $property = $node->getProperty();
            $compiledProperty = $this->renderNode($property);
            $code .= $this->renderNode($node->getObject());
            $optional = false;
            if ($type === "MemberExpression") {
                $optional = $node->getOptional();
            }
            $propertyType = $property->getType();
            if ($type === "MemberExpression" && ($node->getComputed() || $propertyType !== "Identifier" && $propertyType !== "PrivateIdentifier")) {
                $code .= ($optional ? "?." : "") . "[" . $compiledProperty . "]";
            }
            else {
                $code .= ($optional ? "?." : ".") . $compiledProperty;
            }
            break;
        case "MetaProperty":
            $code .= $node->getMeta() . "." . $node->getProperty();
            break;
        case "MethodDefinition":
            if ($node->getStatic()) {
                $code .= "static ";
            }
            $value = $node->getValue();
            $key = $node->getKey();
            $kind = $node->getKind();
            if ($kind === $node::KIND_GET || $kind === $node::KIND_SET) {
                $code .= $kind . " ";
            }
            else {
                if ($value->getAsync()) {
                    $code .= "async ";
                }
                if ($value->getGenerator()) {
                    $code .= "*" . $this->renderOpts->sao;
                }
            }
            if ($node->getComputed()) {
                $code .= "[" . $this->renderNode($key) . "]";
            }
            else {
                $code .= $this->renderNode($key);
            }
            $code .= $this->renderOpts->sao . preg_replace("/^[^(]+/", "", $this->renderNode($value));
            break;
        case "ObjectExpression":
            $currentIndentation = $this->getIndentation();
            $this->renderOpts->indLevel++;
            $indentation = $this->getIndentation();
            
            //Handle single line mode
            if (isset($this->renderOpts->forceSingleLine)) {
                $start = $end = "";
                $separator = "," . $this->renderOpts->sao;
            }
            else {
                $end = $this->renderOpts->nl . $currentIndentation;
                $start = $this->renderOpts->nl . $indentation;
                $separator = "," . $this->renderOpts->nl . $indentation;
            }
            $code .= "{";
            $properties = $node->getProperties();
            if (count($properties)) {
                $code .= $start . $this->joinNodes($properties, $separator) . $end;
            }
            $code .= "}";
            $this->renderOpts->indLevel--;
            break;
        case "ObjectPattern":
            $code .= "{" . $this->joinNodes($node->getProperties(), "," . $this->renderOpts->sao) . "}";
            break;
        case "ParenthesizedExpression":
            $code .= "(" . $this->renderOpts->sirb . $this->renderNode($node->getExpression()) . $this->renderOpts->sirb . ")";
            break;
        case "PrivateIdentifier":
            $code .= "#" . $node->getName();
            break;
        case "Property":
            $value = $node->getValue();
            $key = $node->getKey();
            $compiledKey = $this->renderNode($key);
            $compiledValue = $this->renderNode($value);
            $keyType = $key->getType();
            $valueType = $value->getType();
            if ($valueType === "AssignmentPattern" && $compiledKey === $this->renderNode($value->getLeft())) {
                $code .= $compiledValue;
            }
            else {
                $kind = $node->getKind();
                $getterSetter = $kind === $node::KIND_GET || $kind === $node::KIND_SET;
                if ($getterSetter) {
                    $code .= $kind . " ";
                }
                elseif ($value->getType() === "FunctionExpression" && $value->getGenerator()) {
                    $code .= "*" . $this->renderOpts->sao;
                }
                if ($node->getMethod() && $value->getAsync()) {
                    $code .= "async ";
                }
                if ($node->getComputed()) {
                    $code .= "[" . $compiledKey . "]";
                }
                else {
                    $code .= $compiledKey;
                }
                if ($node->getMethod() || $getterSetter) {
                    $code .= $this->renderOpts->sao . preg_replace("/^[^(]+/", "", $compiledValue);
                }
                elseif ($keyType !== "Identifier" || $valueType !== "Identifier" || $compiledKey !== $compiledValue) {
                    $code .= ($node->getShorthand() ? "=" : ":") . $this->renderOpts->sao . $compiledValue;
                }
            }
            break;
        case "PropertyDefinition":
            if ($node->getStatic()) {
                $code .= "static ";
            }
            $compiledKey = $this->renderNode($node->getKey());
            if ($node->getComputed()) {
                $code .= "[" . $compiledKey . "]";
            }
            else {
                $code .= $compiledKey;
            }
            if ($value = $node->getValue()) {
                $code .= $this->renderOpts->sao . "=" . $this->renderOpts->sao . $this->renderNode($value);
            }
            break;
        case "RestElement":
        case "SpreadElement":
            $code .= "..." . $this->renderNode($node->getArgument());
            break;
        case "ReturnStatement":
            $code .= "return";
            if ($argument = $node->getArgument()) {
                $code .= " " . $this->renderNode($argument);
            }
            break;
        case "SequenceExpression":
            $code .= $this->joinNodes($node->getExpressions(), "," . $this->renderOpts->sao);
            break;
        case "StaticBlock":
            $code .= "static";
            $code .= $this->renderStatementBlock($node, $node->getBody(), true);
            break;
        case "Super":
            $code .= "super";
            break;
        case "SwitchCase":
            if ($test = $node->getTest()) {
                $code .= "case " . $this->renderNode($test);
            }
            else {
                $code .= "default";
            }
            $code .= ":";
            if (count($node->getConsequent())) {
                $code .= $this->renderStatementBlock($node, $node->getConsequent());
            }
            break;
        case "SwitchStatement":
            $code .= "switch" . $this->renderOpts->sao . "(" . $this->renderOpts->sirb . $this->renderNode($node->getDiscriminant()) . $this->renderOpts->sirb . ")" . $this->renderStatementBlock($node, $node->getCases(), true, false, false);
            break;
        case "TaggedTemplateExpression":
            $code .= $this->renderNode($node->getTag()) . $this->renderNode($node->getQuasi());
            break;
        case "TemplateElement":
            $code .= $node->getRawValue();
            break;
        case "TemplateLiteral":
            $code .= "`";
            foreach ($node->getParts() as $part) {
                if ($part->getType() === "TemplateElement") {
                    $code .= $this->renderNode($part);
                }
                else {
                    $code .= "\$" . "{" . $this->renderNode($part) . "}";
                }
            }
            $code .= "`";
            break;
        case "ThisExpression":
            $code .= "this";
            break;
        case "ThrowStatement":
            $code .= "throw " . $this->renderNode($node->getArgument());
            break;
        case "TryStatement":
            $code .= "try" . $this->renderStatementBlock($node, $node->getBlock(), true);
            if ($handler = $node->getHandler()) {
                $code .= $this->renderOpts->sao . $this->renderNode($handler);
            }
            if ($finalizer = $node->getFinalizer()) {
                $code .= $this->renderOpts->sao . "finally" . $this->renderStatementBlock($node, $finalizer, true);
            }
            break;
        case "UnaryExpression":
        case "UpdateExpression":
            $prefix = $node->getPrefix();
            if ($prefix) {
                $code .= $node->getOperator();
                if (preg_match("#^[a-z]+\$#i", $node->getOperator())) {
                    $code .= " ";
                }
            }
            $code .= $this->renderNode($node->getArgument());
            if (!$prefix) {
                $code .= $node->getOperator();
            }
            break;
        case "VariableDeclaration":
            $this->renderOpts->indLevel++;
            $indentation = $this->getIndentation();
            
            //Handle single line mode
            if (isset($this->renderOpts->forceSingleLine)) {
                $separator = "," . $this->renderOpts->sao;
            }
            else {
                $separator = "," . $this->renderOpts->nl . $indentation;
            }
            $code .= $node->getKind() . " " . $this->joinNodes($node->getDeclarations(), $separator);
            $this->renderOpts->indLevel--;
            break;
        case "VariableDeclarator":
            $code .= $this->renderNode($node->getId());
            if ($init = $node->getInit()) {
                $code .= $this->renderOpts->sao . "=" . $this->renderOpts->sao . $this->renderNode($init);
            }
            break;
        case "WhileStatement":
            $code .= "while" . $this->renderOpts->sao . "(" . $this->renderOpts->sirb . $this->renderNode($node->getTest()) . $this->renderOpts->sirb . ")" . $this->renderStatementBlock($node, $node->getBody());
            break;
        case "WithStatement":
            $code .= "with" . $this->renderOpts->sao . "(" . $this->renderOpts->sirb . $this->renderNode($node->getObject()) . $this->renderOpts->sirb . ")" . $this->renderStatementBlock($node, $node->getBody());
            break;
        case "YieldExpression":
            $code .= "yield";
            if ($node->getDelegate()) {
                $code .= " *";
            }
            if ($argument = $node->getArgument()) {
                $code .= " " . $this->renderNode($argument);
            }
            break;
    }
    if ($addSemicolon) {
        $code .= ";";
    }
    if ($this->renderOpts->com) {
        $code .= $this->renderComments($node, false);
    }
    return $code;
}

API Navigation

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