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
PeastCode
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;
}