Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@prettier/plugin-php

Package Overview
Dependencies
Maintainers
6
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@prettier/plugin-php - npm Package Compare versions

Comparing version 0.0.0-development to 0.1.0

LICENSE

9

package.json
{
"name": "@prettier/plugin-php",
"version": "0.0.0-development",
"version": "0.1.0",
"description": "Prettier PHP Plugin",

@@ -13,4 +13,3 @@ "repository": "prettier/prettier-php",

"dependencies": {
"php-parser": "2.2.0",
"prettier": "prettier/prettier#b449a526ce0f16703cdf5b4b22731b2a94775473"
"php-parser": "glayzzle/php-parser#a8f10d8c9aacf8e90b283229f8bed76363b99fcf"
},

@@ -23,5 +22,9 @@ "devDependencies": {

"eslint-plugin-prettier": "2.4.0",
"prettier": "prettier/prettier",
"jest": "21.1.0",
"jest-runner-eslint": "0.3.0"
},
"peerDependencies": {
"prettier": "^1.11.1"
},
"scripts": {

@@ -28,0 +31,0 @@ "test": "jest",

@@ -37,19 +37,22 @@ <p align="center">

Please note that this plugin is under active development, and might not be ready to run on production code yet.
Please note that this plugin is currently in alpha stage and still under active development. We encourage everyone to try it and give feedback, but we don't recommend it for production use yet.
## Contributing
## Install
If you're interested in contributing to the development of Prettier for PHP, you can follow the [CONTRIBUTING guide from Prettier](https://github.com/prettier/prettier/blob/master/CONTRIBUTING.md), as it all applies to this repository too.
You'll need a current development version of prettier, because the plugin depends on currently unreleased features.
To test it out on a PHP file:
yarn:
* Clone this repository.
* Run `yarn`.
* Create a file called `test.php`.
* Run `yarn prettier test.php` to check the output.
```bash
yarn add --dev prettier/prettier @prettier/plugin-php
# or globally
yarn global add prettier/prettier @prettier/plugin-php
```
## Install
npm:
```bash
yarn add --dev --exact prettier @prettier/plugin-php
npm install --save-dev prettier/prettier @prettier/plugin-php
# or globally
npm install --global prettier/prettier @prettier/plugin-php
```

@@ -59,6 +62,35 @@

If you installed prettier as a local dependency, you can add prettier as a script in your `package.json`,
```json
"scripts": {
"prettier": "prettier"
}
```
and then run it via
```bash
prettier --write "**/*.php"
yarn run prettier path/to/file.php --write
# or
npm run prettier path/to/file.php --write
```
If you installed globally, run
```bash
prettier path/to/file.php --write
```
## Contributing
If you're interested in contributing to the development of Prettier for PHP, you can follow the [CONTRIBUTING guide from Prettier](https://github.com/prettier/prettier/blob/master/CONTRIBUTING.md), as it all applies to this repository too.
To test it out on a PHP file:
* Clone this repository.
* Run `yarn`.
* Create a file called `test.php`.
* Run `yarn prettier test.php` to check the output.
## Maintainers

@@ -73,3 +105,3 @@

</br>
Mike
Mike Grip
</a>

@@ -84,4 +116,11 @@ </td>

</td>
<td align="center">
<a href="https://github.com/evilebottnawi">
<img width="150" height="150" src="https://github.com/evilebottnawi.png?v=3&s=150">
</br>
Evilebot Tnawi
</a>
</td>
</tr>
<tbody>
</table>

@@ -5,2 +5,6 @@ "use strict";

const print = require("./printer");
const clean = require("./clean");
const options = require("./options");
const comments = require("./comments");
const { join, hardline } = require("prettier").doc.builders;

@@ -32,6 +36,38 @@ const languages = [

const loc = function(prop) {
return function(node) {
return node.loc && node.loc[prop] && node.loc[prop].offset;
};
// for anonymous classes, we need to keep track of the parent "new" node.
// this is because in a case like this:
// $test = new class($arg1, $arg2) extends TestClass {};
// we actually want to pretend that the class node starts after the "new"
// node's arguments, since there is logic in prettier that assumes child nodes
// will never overlap each other (ie the "new" node has the arguments, and class
// as children, and we can't have them overlap)
const anonymousClassesNewNodes = [];
const loc = prop => node => {
if (
node.kind === "new" &&
node.what.kind === "class" &&
node.what.isAnonymous &&
node.arguments.length > 0 &&
!anonymousClassesNewNodes.includes(node)
) {
anonymousClassesNewNodes.push(node);
}
if (prop === "start" && node.kind === "class" && node.isAnonymous) {
const parentNewNode = anonymousClassesNewNodes.find(
newNode => newNode.what === node
);
if (parentNewNode && parentNewNode.arguments.length > 0) {
const lastArgumentNode =
parentNewNode.arguments[parentNewNode.arguments.length - 1];
// if this is an anonymous class node with a parent "new" node, use the
// location of the last argument in the new node as the fake start location
// for this class node
return (
(lastArgumentNode.loc &&
lastArgumentNode.loc.end &&
lastArgumentNode.loc.end.offset) + 1
);
}
}
return node.loc && node.loc[prop] && node.loc[prop].offset;
};

@@ -50,3 +86,217 @@

php: {
print
print,
massageAstNode: clean,
// @TODO: determine if it makes sense to abstract this into a "getChildNodes" util function
getCommentChildNodes(node) {
const nodeMap = [
{
kinds: ["constant", "property", "classconstant"],
children: { listNodes: [], nodes: ["value"] }
},
{
kinds: ["return"],
children: { listNodes: [], nodes: ["expr"] }
},
{
kinds: ["static", "array", "usegroup"],
children: { listNodes: ["items"], nodes: [] }
},
{
kinds: ["entry"],
children: { listNodes: [], nodes: ["key", "value"] }
},
{
kinds: ["assign"],
children: { listNodes: [], nodes: ["left", "right"] }
},
{
kinds: ["if"],
children: { listNodes: [], nodes: ["body", "alternate", "test"] }
},
{
kinds: ["block", "program", "namespace", "declare"],
children: { listNodes: ["children"], nodes: [] }
},
{
kinds: ["foreach"],
children: {
listNodes: [],
nodes: ["key", "source", "value", "body"]
}
},
{
kinds: ["try"],
children: {
listNodes: ["catches"],
nodes: ["always", "body"]
}
},
{
kinds: ["call", "new"],
children: { listNodes: ["arguments"], nodes: ["what"] }
},
{
kinds: ["offsetlookup", "staticlookup"],
children: { listNodes: [], nodes: ["what", "offset"] }
},
{
kinds: ["catch"],
children: {
listNodes: ["what"],
nodes: ["variable", "body"]
}
},
{
kinds: ["for", "while", "do"],
children: { listNodes: [], nodes: ["body"] }
},
{
kinds: ["trait", "class"],
children: { listNodes: ["implements", "body"], nodes: ["extends"] }
},
{
kinds: ["interface"],
children: { listNodes: ["extends", "body"], nodes: [] }
},
{
kinds: ["function", "method", "closure"],
children: { listNodes: ["arguments", "uses"], nodes: ["body"] }
},
{
kinds: ["switch", "case"],
children: { listNodes: [], nodes: ["test", "body"] }
},
{
kinds: ["bin"],
children: { listNodes: [], nodes: ["left", "right"] }
},
{
kinds: ["parameter", "yieldfrom"],
children: { listNodes: [], nodes: ["value"] }
},
{
kinds: ["retif"],
children: { listNodes: [], nodes: ["trueExpr", "falseExpr", "test"] }
},
{
kinds: ["echo"],
children: { listNodes: ["arguments"], nodes: [] }
},
{
kinds: ["parenthesis"],
children: { listNodes: [], nodes: ["inner"] }
},
{
kinds: ["include"],
children: { listNodes: [], nodes: ["target"] }
},
{
kinds: ["throw", "clone", "pre", "post", "unary", "cast"],
children: { listNodes: [], nodes: ["what"] }
},
{
kinds: ["list", "isset", "unset", "empty"],
children: { listNodes: ["arguments"], nodes: [] }
},
{
kinds: ["global"],
children: { listNodes: ["items"], nodes: [] }
},
{
kinds: ["print"],
children: { listNodes: [], nodes: ["arguments"] }
},
{
kinds: ["eval"],
children: { listNodes: [], nodes: ["source"] }
},
{
kinds: ["yield"],
children: { listNodes: [], nodes: ["key", "value"] }
},
{
kinds: ["traituse"],
children: { listNodes: ["traits", "adaptations"], nodes: [] }
},
{
kinds: ["traitprecedence"],
children: { listNodes: [], nodes: ["trait", "instead"] }
},
{
kinds: ["traitalias"],
children: { listNodes: [], nodes: ["trait"] }
},
{
kinds: ["silent"],
children: { listNodes: [], nodes: ["expr"] }
},
{
kinds: ["exit"],
children: { listNodes: [], nodes: ["status"] }
}
];
const children = nodeMap.reduce((currentChildren, map) => {
if (map.kinds.includes(node.kind)) {
return [
...map.children.listNodes.reduce((accumulator, listNode) => {
const childValue = node[listNode];
return childValue ? [...accumulator, ...childValue] : accumulator;
}, []),
...map.children.nodes.reduce((accumulator, childNode) => {
const childValue = node[childNode];
return childValue ? [...accumulator, childValue] : accumulator;
}, [])
];
}
return currentChildren;
}, false);
return children !== false ? children : [];
},
canAttachComment(node) {
return (
node.kind && node.kind !== "commentblock" && node.kind !== "commentline"
);
},
handleComments: {
ownLine: comments.handleOwnLineComment,
endOfLine: comments.handleEndOfLineComment,
remaining: comments.handleRemainingComment
},
printComment(commentPath) {
const comment = commentPath.getValue();
switch (comment.kind) {
case "commentblock": {
// for now, don't touch single line block comments
if (!comment.value.includes("\n")) {
return comment.value;
}
const lines = comment.value.split("\n");
// if this is a block comment, handle indentation
if (
lines
.slice(1, lines.length - 1)
.every(line => line.trim()[0] === "*")
) {
return join(
hardline,
lines.map(
(line, index) =>
(index > 0 ? " " : "") +
(index < lines.length - 1 ? line.trim() : line.trimLeft())
)
);
}
// otherwise we can't be sure about indentation, so just print as is
return comment.value;
}
case "commentline": {
return comment.value.trimRight();
}
default:
throw new Error(`Not a comment: ${JSON.stringify(comment)}`);
}
}
}

@@ -58,3 +308,7 @@ };

printers,
parsers
parsers,
options,
defaultOptions: {
tabWidth: 4
}
};
"use strict";
const docBuilders = require("prettier").doc.builders;
const util = require("prettier").util;
const {
concat,
join,
line,
lineSuffix,
lineSuffixBoundary,
group,
conditionalGroup,
indent,
dedent,
ifBreak,
hardline,
softline
} = require("prettier").doc.builders;
const { willBreak } = require("prettier").doc.utils;
const { makeString, isNextLineEmpty } = require("prettier").util;
const comments = require("./comments");
const concat = docBuilders.concat;
const join = docBuilders.join;
const line = docBuilders.line;
const group = docBuilders.group;
const indent = docBuilders.indent;
const hardline = docBuilders.hardline;
const softline = docBuilders.softline;
const {
getNodeListProperty,
getLast,
isControlStructureNode,
isFirstNodeInParentProgramNode,
isFirstNodeInParentNode,
isPrevNodeInline,
isNextNodeInline,
isLastStatement,
lineShouldHaveStartPHPTag,
lineShouldEndWithSemicolon,
lineShouldHaveEndPHPTag,
printNumber,
shouldFlatten,
shouldRemoveLines,
removeNewlines,
maybeStripLeadingSlashFromUse,
fileShouldEndWithHardline,
hasDanglingComments,
docShouldHaveTrailingNewline
} = require("./util");
// polyfill for node 4
function includes(array, val) {
return array.indexOf(val) !== -1;
function shouldPrintComma(options) {
switch (options.trailingComma) {
case "all":
return true;
// fallthrough
case "none":
default:
return false;
}
}
function genericPrint(path, options, print) {
const n = path.getValue();
if (!n) {
const node = path.getValue();
if (!node) {
return "";
} else if (typeof n === "string") {
return n;
} else if (typeof node === "string") {
return node;
}
return printNode(path, options, print);
}
function lineShouldEndWithSemicolon(path) {
const node = path.getValue();
const semiColonWhitelist = [
"assign",
"return",
"break",
"call",
"pre",
"post",
"bin",
"unary",
"yield",
"yieldfrom",
"echo",
"list",
"print",
"isset",
"unset",
"empty",
"traitprecedence",
"traitalias",
"constant",
"classconstant",
"exit",
"global",
"static",
"include",
"goto",
"throw"
];
if (node.kind === "traituse") {
return !node.adaptations;
const isProgramNode = node.kind === "program";
if (isProgramNode && node.children.length === 0) {
return concat([
"<?php",
hardline,
comments.printDanglingComments(path, options, /* sameIndent */ true)
]);
}
return includes(semiColonWhitelist, node.kind);
const printed = printNode(path, options, print);
if (node.kind === "inline") {
const parentNode = path.getParentNode();
return concat([
parentNode &&
parentNode.kind === "declare" &&
parentNode.children.indexOf(node) === 0
? "?>"
: "",
printed
]);
}
if (node.kind === "block") {
const nodeBody = getNodeListProperty(node);
if (nodeBody.length !== 0) {
return concat([
nodeBody[0].kind === "inline" ? "?>" : "",
printed,
nodeBody[nodeBody.length - 1].kind === "inline" ? "<?php" : ""
]);
}
}
return concat([
lineShouldHaveStartPHPTag(path)
? concat([
"<?php",
isFirstNodeInParentProgramNode(path) ||
(!isNextNodeInline(path) && !isControlStructureNode(node))
? hardline
: " "
])
: "",
shouldRemoveLines(path) ? removeNewlines(printed) : printed,
lineShouldEndWithSemicolon(path) ? ";" : "",
lineShouldHaveEndPHPTag(path)
? concat([
isFirstNodeInParentNode(path) || !isPrevNodeInline(path)
? hardline
: " ",
"?>"
])
: ""
]);
}
function isLastStatement(path) {
const parent = path.getParentNode();
if (!parent) {
return true;
// special layout for "chained" function calls, i.e.
// $foo = a()
// ->b()
// ->c();
function printMemberChain(path, options, print) {
// First step: Linearize and reorder the AST.
//
// Example:
// a()->b->c()->d()
// has the AST structure
// Call (PropertyLookup d (
// Call (PropertyLookup c (
// PropertyLookup b (
// Call (Identifier a)
// )
// ))
// ))
// and we transform it into (notice the reversed order)
// [Identifier a, Call, PropertyLookup b, PropertyLookup c, Call,
// PropertyLookup d, Call]
const printedNodes = [];
function traverse(path) {
const node = path.getValue();
if (node.kind === "call") {
printedNodes.unshift({
node,
printed: concat([printArgumentsList(path, options, print)])
});
path.call(what => traverse(what), "what");
} else if (node.kind === "propertylookup") {
printedNodes.unshift({
node,
printed: concat([
"->",
wrapPropertyLookup(node, path.call(print, "offset"))
])
});
path.call(what => traverse(what), "what");
} else {
printedNodes.unshift({
node,
printed: path.call(print)
});
}
}
const node = path.getValue();
const body = parent.children;
return body && body[body.length - 1] === node;
}
traverse(path);
function printLines(path, options, print) {
const text = options.originalText;
const printed = path.map(stmtPath => {
const stmt = stmtPath.getValue();
const parts = [];
parts.push(print(stmtPath));
if (lineShouldEndWithSemicolon(stmtPath)) {
parts.push(";");
// create groups from list of nodes, i.e.
// [Identifier a, Call, PropertyLookup b, PropertyLookup c, Call,
// PropertyLookup d, Call]
// will be grouped as
// [
// [Identifier a, Call],
// [PropertyLookup b, PropertyLookup c, Call],
// [PropertyLookup d, Call]
// ]
// so that we can print it as
// a()
// ->b->c()
// ->d()
const groups = [];
let currentGroup = [];
let hasSeenCall = false;
printedNodes.forEach(printedNode => {
if (hasSeenCall && printedNode.node.kind === "propertylookup") {
groups.push(currentGroup);
currentGroup = [printedNode];
hasSeenCall = false;
} else {
currentGroup.push(printedNode);
}
if (
util.isNextLineEmpty(text, stmt, options) &&
!isLastStatement(stmtPath)
) {
parts.push(hardline);
if (printedNode.node.kind === "call") {
hasSeenCall = true;
}
return concat(parts);
});
return join(hardline, printed);
groups.push(currentGroup);
function printGroup(printedGroup) {
return concat(printedGroup.map(tuple => tuple.printed));
}
function printIndentedGroup(groups) {
if (groups.length === 0) {
return "";
}
return indent(
group(concat([hardline, join(hardline, groups.map(printGroup))]))
);
}
const printedGroups = groups.map(printGroup);
if (groups.length <= 2) {
return group(concat(printedGroups));
}
const expanded = concat([
printGroup(groups[0]),
printIndentedGroup(groups.slice(1))
]);
return expanded;
}
function printArgumentsList(path, options, print, argumentsKey = "arguments") {
const args = path.getValue()[argumentsKey];
const printed = path
.map(print, argumentsKey)
.map(argument => group(argument));
if (printed.length === 0) {
return "()";
}
const breakingIndex = printed.findIndex(willBreak);
const breakingInTheMiddle =
printed.length > 2 &&
breakingIndex !== 0 &&
breakingIndex !== printed.length - 1;
const shouldGroupLast = getLast(args).kind === "array";
const shouldGroupFirst = !shouldGroupLast && args[0].kind === "array";
const shortForm = concat(["(", join(", ", printed), ")"]);
const mediumForm = shouldGroupFirst
? concat([
"(",
group(printed[0], { shouldBreak: true }),
printed.length > 1 ? ", " : "",
join(concat([",", line]), printed.slice(1)),
")"
])
: concat([
"(",
join(concat([",", line]), printed.slice(0, -1)),
printed.length > 1 ? ", " : "",
group(getLast(printed), { shouldBreak: true }),
")"
]);
const longForm = group(
concat([
"(",
indent(concat([softline, join(concat([",", line]), printed)])),
softline,
")"
])
);
const formsToConsider = [
!breakingInTheMiddle ? shortForm : null,
shouldGroupFirst || shouldGroupLast ? mediumForm : null,
longForm
];
return conditionalGroup(formsToConsider.filter(Boolean));
}
function wrapPropertyLookup(node, doc) {
const addCurly =
node.kind === "propertylookup" &&
(node.offset.kind !== "constref" || typeof node.offset.name !== "string");
return addCurly ? concat(["{", doc, "}"]) : doc;
}
function isPropertyLookupChain(node) {
if (node.kind !== "propertylookup") {
return false;
}
if (node.what.kind === "variable") {
return true;
}
return isPropertyLookupChain(node.what);
}
// so this is a bit hacky, but for anonymous classes, there's a chance that an
// assumption core to prettier will break - that child nodes will not overlap. In
// this case, if we have something like this:
// $test = new class($arg1, $arg2) extends TestClass {};
// we end up with a parent "new" node, which has children "arguments", and "what"
// the "what" is a "class" node, but it overlaps with the "arguments". To solve this,
// we use this variable to store off the printed arguments when the "new" node is printing,
// so that the "class" node can then access them later
let anonymousClassesNewArguments = null;
const expressionKinds = [

@@ -117,3 +315,4 @@ "array",

"nowdoc",
"encapsed"
"encapsed",
"variadic"
];

@@ -125,3 +324,4 @@ function printExpression(path, options, print) {

switch (node.kind) {
case "propertylookup":
case "propertylookup": {
const canBreak = path.stack.indexOf("left") === -1;
return group(

@@ -131,5 +331,11 @@ concat([

"->",
indent(concat([softline, path.call(print, "offset")]))
indent(
concat([
canBreak ? softline : "",
wrapPropertyLookup(node, path.call(print, "offset"))
])
)
])
);
}
case "staticlookup":

@@ -141,3 +347,4 @@ return concat([

]);
case "offsetlookup":
case "offsetlookup": {
const isOffsetNumberNode = node.offset && node.offset.kind === "number";
return group(

@@ -147,13 +354,24 @@ concat([

"[",
softline,
node.offset ? path.call(print, "offset") : "",
softline,
node.offset
? group(
concat([
indent(
concat([
isOffsetNumberNode ? "" : softline,
path.call(print, "offset")
])
),
isOffsetNumberNode ? "" : softline
])
)
: "",
"]"
])
);
}
default:
return "Have not implemented lookup kind " + node.kind + " yet.";
return `Have not implemented lookup kind ${node.kind} yet.`;
}
}
if (includes(lookupKinds, node.kind)) {
if (lookupKinds.includes(node.kind)) {
return printLookup(node);

@@ -169,14 +387,72 @@ }

return concat([path.call(print, "what"), node.type + node.type]);
case "bin":
return concat([
path.call(print, "left"),
" ",
node.type,
" ",
path.call(print, "right")
case "bin": {
// general idea here is that we are continually checking nested
// binary expressions to see if we should be starting a new group
// or not (based on operator precedence)
const printBinaryExpression = (
path,
print,
options,
isNested = false
) => {
const node = path.getValue();
if (node.kind !== "bin") {
return path.call(print);
}
const shouldGroupLeft = !(
node.left.kind === "bin" && shouldFlatten(node.type, node.left.type)
);
const printedLeft = path.call(
left => printBinaryExpression(left, print, options, true),
"left"
);
const shouldGroupRight = !(
node.right.kind === "bin" &&
shouldFlatten(node.type, node.right.type)
);
const printedRight = path.call(
right => printBinaryExpression(right, print, options, true),
"right"
);
const printedExpression = concat([
shouldGroupLeft ? group(printedLeft) : printedLeft,
" ",
node.type,
line,
shouldGroupRight ? group(printedRight) : printedRight
]);
return isNested ? printedExpression : group(printedExpression);
};
return printBinaryExpression(path, print, options);
}
case "parenthesis": {
const parentNode = path.getParentNode();
if (parentNode && parentNode.kind === "parenthesis") {
return path.call(print, "inner");
}
const shouldPrintParenthesis =
parentNode.kind !== "print" &&
parentNode.kind !== "echo" &&
parentNode.kind !== "include";
const shouldBeInlined =
node.inner.kind === "new" || node.inner.kind === "clone";
const dangling = comments.printDanglingComments(path, options, true);
const printedInner = concat([
shouldBeInlined || !shouldPrintParenthesis ? "" : softline,
dangling ? concat([dangling, hardline]) : "",
path.call(print, "inner")
]);
case "parenthesis":
return group(
concat(["(", softline, path.call(print, "inner"), softline, ")"])
concat([
shouldPrintParenthesis ? "(" : "",
shouldBeInlined ? printedInner : indent(printedInner),
shouldPrintParenthesis
? concat([shouldBeInlined ? "" : softline, ")"])
: ""
])
);
}
case "unary":

@@ -187,6 +463,6 @@ return concat([node.type, path.call(print, "what")]);

default:
return "Have not implemented operation kind " + node.kind + " yet.";
return `Have not implemented operation kind ${node.kind} yet.`;
}
}
if (includes(operationKinds, node.kind)) {
if (operationKinds.includes(node.kind)) {
return printOperation(node);

@@ -207,3 +483,3 @@ }

if (node.type === "heredoc") {
return opening ? "<<<" + node.label : node.label;
return opening ? `<<<${node.label}` : node.label;
}

@@ -217,3 +493,3 @@ const quotes = {

}
return "Unimplemented encapsed type " + node.type;
return `Unimplemented encapsed type ${node.type}`;
}

@@ -225,2 +501,5 @@

case "string": {
// @TODO: need resolve https://github.com/glayzzle/php-parser/issues/101
// @TODO: need resolve https://github.com/glayzzle/php-parser/issues/123
// @TODO: need resolve https://github.com/glayzzle/php-parser/issues/124
// @TODO: for now just reusing double/single quote preference from doc. could eventually

@@ -230,6 +509,14 @@ // use setting from options. need to figure out how this works w/ complex strings and interpolation

const quote = node.isDoubleQuote ? '"' : "'";
return quote + node.value + quote;
let stringValue = node.raw;
// we need to strip out the quotes from the raw value
if (['"', "'"].includes(stringValue[0])) {
stringValue = stringValue.substr(1);
}
if (['"', "'"].includes(stringValue[stringValue.length - 1])) {
stringValue = stringValue.substr(0, stringValue.length - 1);
}
return makeString(stringValue, quote, false);
}
case "number":
return node.value;
return printNumber(node.value);
case "encapsed":

@@ -241,19 +528,32 @@ if (node.type === "offset") {

getEncapsedQuotes(node),
node.type === "heredoc" ? hardline : "",
// Respect `indent` for `heredoc` nodes
node.type === "heredoc" ? "\n" : "",
concat(
path.map(valuePath => {
// might need to figure out better way to do this. don't want
// to send through printNode() because value is a string and
// we don't want the quotes
const node = valuePath.getValue();
return node.kind === "string" ? node.value : print(valuePath);
if (node.kind === "string") {
return node.raw;
} else if (node.kind === "variable") {
if (typeof node.name === "object") {
return concat(["${", path.call(print, "name"), "}"]);
} else if (node.curly) {
return `{$${node.name}}`;
}
return print(valuePath);
}
return concat(["{", print(valuePath), "}"]);
}, "value")
),
getEncapsedQuotes(node, { opening: false })
getEncapsedQuotes(node, { opening: false }),
node.type === "heredoc" && docShouldHaveTrailingNewline(path)
? hardline
: ""
]);
case "inline":
return node.value;
return node.raw;
case "magic":
return node.value;
// for magic constant we prefer upper case
return node.value.toUpperCase();
case "nowdoc":
// Respect `indent` for `nowdoc` nodes
return concat([

@@ -263,12 +563,13 @@ "<<<'",

"'",
hardline,
"\n",
node.value,
hardline,
node.label
"\n",
node.label,
docShouldHaveTrailingNewline(path) ? "\n" : ""
]);
default:
return "Have not implemented literal kind " + node.kind + " yet.";
return `Have not implemented literal kind ${node.kind} yet.`;
}
}
if (includes(literalKinds, node.kind)) {
if (literalKinds.includes(node.kind)) {
return printLiteral(node);

@@ -283,3 +584,3 @@ }

node.curly ? "{" : "",
node.name,
path.call(print, "name"),
node.curly ? "}" : ""

@@ -292,6 +593,21 @@ ]);

return node.name;
case "array":
case "array": {
const open = node.shortForm ? "[" : "array(";
const close = node.shortForm ? "]" : ")";
if (node.items.length === 0) {
if (!hasDanglingComments(node)) {
return concat([open, close]);
}
return group(
concat([
open,
comments.printDanglingComments(path, options),
softline,
close
])
);
}
return group(
concat([
node.shortForm ? "[" : "array(",
open,
indent(

@@ -303,6 +619,9 @@ concat([

),
ifBreak(shouldPrintComma(options) ? "," : ""),
comments.printDanglingComments(path, options, true),
softline,
node.shortForm ? "]" : ")"
close
])
);
}
case "yield":

@@ -316,4 +635,6 @@ return concat([

return concat(["yield from ", path.call(print, "value")]);
case "variadic":
return concat(["...", path.call(print, "what")]);
default:
return "Have not implemented expression kind " + node.kind + " yet.";
return `Have not implemented expression kind ${node.kind} yet.`;
}

@@ -369,2 +690,20 @@ }

];
function printLines(path, options, print, childrenAttribute = "children") {
return concat(
path.map(childPath => {
const canPrintBlankLine =
!isLastStatement(childPath) &&
childPath.getValue().kind !== "inline" &&
!isNextNodeInline(childPath);
return concat([
print(childPath),
canPrintBlankLine ? hardline : "",
canPrintBlankLine &&
isNextLineEmpty(options.originalText, childPath.getValue(), options)
? hardline
: ""
]);
}, childrenAttribute)
);
}
function printStatement(path, options, print) {

@@ -376,32 +715,32 @@ const node = path.getValue();

case "block":
return path.call(
childrenPath => printLines(childrenPath, options, print),
"children"
);
return concat([
printLines(path, options, print),
comments.printDanglingComments(path, options, true)
]);
case "program": {
return concat([
"<?php",
hardline,
path.call(childrenPath => {
return printLines(childrenPath, options, print);
}, "children")
printLines(path, options, print),
fileShouldEndWithHardline(path) ? hardline : ""
]);
}
case "namespace":
case "namespace": {
const printed = printLines(path, options, print);
const hasName = node.name && typeof node.name === "string";
return concat([
"namespace ",
node.name,
";",
concat(
path.map(
usegroup => concat([hardline, print(usegroup), ";"]),
"children"
)
)
hasName ? node.name : "",
node.withBrackets ? concat([" ", "{"]) : ";",
// don't know why we need 2 line breaks here, but 1 doesn't work
node.children.length > 0 && !node.withBrackets
? concat([hardline, hardline])
: "",
node.withBrackets ? indent(concat([hardline, printed])) : printed,
node.withBrackets ? concat([hardline, "}"]) : ""
]);
}
default:
return "Have not implemented block kind " + node.kind + " yet.";
return `Have not implemented block kind ${node.kind} yet.`;
}
}
if (includes(blockKinds, node.kind)) {
if (blockKinds.includes(node.kind)) {
return printBlock(path, options, print);

@@ -413,6 +752,27 @@ }

switch (node.kind) {
case "echo":
return concat(["echo ", join(", ", path.map(print, "arguments"))]);
case "print":
return concat(["print ", path.call(print, "arguments")]);
case "echo": {
const printedArguments = path.map(argumentPath => {
const node = argumentPath.getValue();
return node.kind === "bin"
? print(argumentPath)
: dedent(print(argumentPath));
}, "arguments");
return indent(
group(
concat([
"echo ",
group(join(concat([",", line]), printedArguments))
])
)
);
}
case "print": {
const printedArguments = path.call(print, "arguments");
return concat([
"print ",
node.arguments.kind === "bin"
? indent(printedArguments)
: printedArguments
]);
}
case "list":

@@ -437,6 +797,6 @@ case "isset":

default:
return "Have not implemented sys kind " + node.kind + " yet.";
return `Have not implemented sys kind ${node.kind} yet.`;
}
}
if (includes(sysKinds, node.kind)) {
if (sysKinds.includes(node.kind)) {
return printSys(node);

@@ -457,21 +817,108 @@ }

function printDeclaration(node) {
function printDeclarationBlock({
declaration,
argumentsList = [],
returnTypeContents = "",
bodyContents = ""
}) {
const isClassLikeNode = ["class", "interface", "trait"].includes(
node.kind
);
const printedDeclaration = group(declaration);
const printedSignature = !isClassLikeNode
? group(
concat([
"(",
argumentsList.length
? concat([
indent(
concat([
softline,
join(concat([",", line]), argumentsList)
])
),
softline
])
: "",
")",
returnTypeContents ? concat([": ", returnTypeContents]) : ""
])
)
: "";
const printedBody = bodyContents
? concat([
"{",
indent(concat([hardline, bodyContents])),
comments.printDanglingComments(path, options, true),
hardline,
"}"
])
: "";
return concat([
group(
concat([
printedDeclaration,
printedSignature,
// see https://github.com/prettier/plugin-php/issues/107
// options.openingBraceNewLine ? hardline : " ",
// Hack, we need `invertLine` command here, as `line`, but have versa vice logic
bodyContents
? node.kind === "function" || node.kind === "method"
? ifBreak(" ", concat([lineSuffix(""), lineSuffixBoundary]))
: hardline
: ""
])
),
printedBody
]);
}
switch (node.kind) {
case "class":
return concat([
group(
case "class": {
const classPrefixes = [
...(node.isFinal ? ["final"] : []),
...(node.isAbstract ? ["abstract"] : [])
];
const parentNode = path.getParentNode();
// if this is an anonymous class, we need to check if the parent was a
// "new" node. if it was, we need to get the arguments from that node
// ex: $test = new class($arg1, $arg2) extends TestClass {};
const anonymousArguments =
node.isAnonymous &&
parentNode.kind === "new" &&
parentNode.arguments.length > 0
? anonymousClassesNewArguments
: "";
return printDeclarationBlock({
declaration: concat([
classPrefixes.join(" "),
classPrefixes.length > 0 ? " " : "",
concat([
node.isAbstract ? "abstract " : "",
node.isFinal ? "final " : "",
"class ",
node.name,
"class",
anonymousArguments,
node.name ? concat([" ", node.name]) : ""
]),
group(
indent(
concat([
node.extends
? concat([line, "extends ", path.call(print, "extends")])
? group(
concat([line, "extends ", path.call(print, "extends")])
)
: "",
line,
node.implements
? concat([
line,
"implements ",
join(", ", path.map(print, "implements"))
"implements",
group(
indent(
concat([
line,
join(
concat([",", line]),
path.map(print, "implements")
)
])
)
)
])

@@ -481,79 +928,42 @@ : ""

)
])
),
hardline,
"{",
hardline,
indent(
concat([
hardline,
path.call(bodyPath => {
return printLines(bodyPath, options, print);
}, "body")
])
),
hardline,
"}"
]);
)
]),
bodyContents: printLines(path, options, print, "body")
});
}
case "function":
return concat([
group(concat(["function ", node.name, "("])),
group(
concat([
indent(
join(
", ",
path.map(
argument => concat([softline, print(argument)]),
"arguments"
)
)
),
softline
])
),
group(") {"),
indent(concat([hardline, path.call(print, "body")])),
concat([hardline, "}"])
]);
case "method":
return concat([
group(
concat([
node.isFinal ? "final " : "",
node.visibility,
node.isStatic ? " static" : "",
" function ",
node.name,
"("
])
),
group(
concat([
indent(
join(
", ",
path.map(
argument => concat([softline, print(argument)]),
"arguments"
)
)
),
softline
])
),
")",
node.body
? concat([
hardline,
"{",
indent(concat([hardline, path.call(print, "body")])),
hardline,
"}"
])
: ""
]);
return printDeclarationBlock({
declaration: concat(["function ", node.byref ? "&" : "", node.name]),
argumentsList: path.map(print, "arguments"),
returnTypeContents: node.type
? concat([node.nullable ? "?" : "", path.call(print, "type")])
: "",
bodyContents: node.body ? path.call(print, "body") : ""
});
case "method": {
const methodPrefixes = [
...(node.isFinal ? ["final"] : []),
...(node.isAbstract ? ["abstract"] : []),
...(node.visibility ? [node.visibility] : []),
...(node.isStatic ? ["static"] : [])
];
return printDeclarationBlock({
declaration: concat([
methodPrefixes.join(" "),
methodPrefixes.length > 0 ? " " : "",
"function ",
node.byref ? "&" : "",
node.name
]),
argumentsList: path.map(print, "arguments"),
returnTypeContents: node.type
? concat([node.nullable ? "?" : "", path.call(print, "type")])
: "",
bodyContents: node.body ? concat([path.call(print, "body")]) : ""
});
}
case "parameter": {
const name = concat([
node.type ? path.call(print, "type") + " " : "",
node.nullable ? "?" : "",
node.type ? concat([path.call(print, "type"), " "]) : "",
node.variadic ? "..." : "",

@@ -577,9 +987,7 @@ node.byref ? "&" : "",

concat([
node.visibility,
node.isStatic ? " static " : "",
" $",
node.visibility ? concat([node.visibility, " "]) : "",
node.isStatic ? "static " : "",
"$",
node.name,
node.value
? indent(concat([line, "= ", path.call(print, "value")]))
: "",
node.value ? concat([" = ", path.call(print, "value")]) : "",
";"

@@ -589,88 +997,115 @@ ])

case "interface":
return concat([
group(
concat([
concat(["interface ", node.name]),
node.extends
? indent(
concat([
line,
"extends ",
join(", ", path.map(print, "extends"))
])
)
: "",
" {"
])
),
indent(
concat(
path.map(element => {
return concat([hardline, print(element), ";"]);
}, "body")
)
),
hardline,
"}"
]);
return printDeclarationBlock({
declaration: concat([
concat(["interface ", node.name]),
node.extends
? indent(
concat([
line,
"extends ",
join(", ", path.map(print, "extends"))
])
)
: ""
]),
bodyContents: printLines(path, options, print, "body")
});
case "trait":
return printDeclarationBlock({
declaration: concat([
concat(["trait ", node.name]),
node.extends
? indent(concat([line, "extends ", path.call(print, "extends")]))
: "",
node.implements
? indent(
concat([
line,
"implements ",
join(", ", path.map(print, "implements"))
])
)
: ""
]),
bodyContents: printLines(path, options, print, "body")
});
case "constant":
case "classconstant":
return concat([
group(
concat([
concat(["trait ", node.name]),
node.extends
? indent(
concat([line, "extends ", path.call(print, "extends")])
)
: "",
node.implements
? indent(
concat([
line,
"implements ",
join(", ", path.map(print, "implements"))
])
)
: "",
" {"
])
),
indent(
concat(
path.map(element => concat([hardline, print(element)]), "body")
)
),
hardline,
"}"
node.visibility ? concat([node.visibility, " "]) : "",
"const ",
node.name,
" = ",
path.call(print, "value")
]);
case "constant":
case "classconstant":
return concat(["const ", node.name, " = ", path.call(print, "value")]);
default:
return "Have not implmented declaration kind " + node.kind + " yet.";
return `Have not implmented declaration kind ${node.kind} yet.`;
}
}
if (includes(declarationKinds, node.kind)) {
if (declarationKinds.includes(node.kind)) {
return printDeclaration(node);
}
function printBodyControlStructure(path, bodyProperty = "body") {
const node = path.getValue();
if (!node[bodyProperty]) {
return ";";
}
const printedBody = path.call(print, bodyProperty);
return concat([
node.shortForm ? ":" : " {",
indent(
concat([
comments.printDanglingComments(path, options, true),
node[bodyProperty].kind !== "block" ||
(node[bodyProperty].children &&
node[bodyProperty].children.length > 0) ||
(node[bodyProperty].comments &&
node[bodyProperty].comments.length > 0)
? concat([hardline, printedBody])
: ""
])
),
node.kind === "if" && bodyProperty === "body"
? ""
: concat([
hardline,
node.shortForm ? concat(["end", node.kind, ";"]) : "}"
])
]);
}
switch (node.kind) {
case "assign":
return join(concat([" ", node.operator, " "]), [
path.call(print, "left"),
path.call(print, "right")
]);
case "assign": {
const canBreak =
["bin", "number", "string"].includes(node.right.kind) ||
(node.right.kind === "retif" && node.right.trueExpr === null) ||
isPropertyLookupChain(node.right);
return group(
concat([
path.call(print, "left"),
" ",
node.operator,
canBreak
? indent(concat([line, path.call(print, "right")]))
: concat([" ", path.call(print, "right")])
])
);
}
case "if": {
const handleIfAlternate = alternate => {
if (!alternate) {
return "}";
return node.shortForm ? "endif;" : "}";
}
if (alternate.kind === "if") {
return concat(["} else", path.call(print, "alternate")]);
return concat([
node.shortForm ? "" : "} ",
"else",
path.call(print, "alternate")
]);
}
return concat([
"} else {",
indent(concat([line, path.call(print, "alternate")])),
line,
"}"
node.shortForm ? "" : "} ",
"else",
printBodyControlStructure(path, "alternate")
]);

@@ -680,17 +1115,4 @@ };

group(
concat(["if (", softline, path.call(print, "test"), softline, ") {"])
),
indent(concat([line, path.call(print, "body")])),
line,
handleIfAlternate(node.alternate)
]);
}
case "do":
return concat([
"do {",
indent(concat([line, path.call(print, "body")])),
line,
group(
concat([
"} while (",
"if (",
group(

@@ -702,23 +1124,44 @@ concat([

),
");"
")",
printBodyControlStructure(path)
])
)
),
hardline,
handleIfAlternate(node.alternate)
]);
case "while":
}
case "do":
return concat([
"do",
printBodyControlStructure(path),
" while (",
group(
concat([
"while (",
softline,
path.call(print, "test"),
softline,
") {"
indent(concat([softline, path.call(print, "test")])),
softline
])
),
indent(concat([line, path.call(print, "body")])),
line,
"}"
");"
]);
case "while":
return group(
concat([
"while (",
group(
concat([
indent(concat([softline, path.call(print, "test")])),
softline
])
),
")",
printBodyControlStructure(path)
])
);
case "for": {
const parts = [
const body = printBodyControlStructure(path);
if (!node.init.length && !node.test.length && !node.increment.length) {
return concat([group(concat(["for (;;)", body]))]);
}
return concat([
"for (",

@@ -731,14 +1174,10 @@ group(

group(
concat([
join(concat([",", line]), path.map(print, "init")),
";"
])
concat([join(concat([",", line]), path.map(print, "init"))])
),
";",
line,
group(
concat([
join(concat([",", line]), path.map(print, "test")),
";"
])
concat([join(concat([",", line]), path.map(print, "test"))])
),
";",
line,

@@ -748,13 +1187,8 @@ group(join(concat([",", line]), path.map(print, "increment")))

),
softline,
node.body ? ") {" : ");"
softline
])
)
];
if (node.body) {
parts.push(
concat([indent(concat([line, path.call(print, "body")])), line, "}"])
);
}
return concat(parts);
),
")",
body
]);
}

@@ -770,19 +1204,19 @@ case "foreach":

path.call(print, "source"),
" as",
line,
"as ",
node.key
? join(" => ", [
path.call(print, "key"),
path.call(print, "value")
])
? indent(
join(concat([" =>", line]), [
path.call(print, "key"),
path.call(print, "value")
])
)
: path.call(print, "value")
])
),
softline,
") {"
softline
])
),
indent(concat([line, path.call(print, "body")])),
line,
"}"
")",
printBodyControlStructure(path)
]);

@@ -794,115 +1228,102 @@ case "switch":

"switch (",
indent(concat([softline, path.call(print, "test")])),
softline,
path.call(print, "test"),
softline,
") {"
")"
])
),
indent(
concat(
path.map(
caseChild => concat([line, print(caseChild)]),
"body",
"children"
)
)
),
line,
"}"
printBodyControlStructure(path)
]);
case "call":
case "call": {
// chain: Call (PropertyLookup (Call (PropertyLookup (...))))
if (node.what.kind === "propertylookup") {
return printMemberChain(path, options, print);
}
return concat([
path.call(print, "what"),
printArgumentsList(path, options, print)
]);
}
case "usegroup":
return group(
concat([
path.call(print, "what"),
concat([
"(",
indent(
concat([
softline,
join(concat([",", line]), path.map(print, "arguments"))
])
),
softline,
")"
])
"use ",
node.type ? concat([node.type, " "]) : "",
indent(
concat([
node.name
? concat([
maybeStripLeadingSlashFromUse(node.name),
"\\{",
softline
])
: "",
join(
concat([",", line]),
path.map(item => concat([print(item)]), "items")
)
])
),
node.name ? concat([softline, "}"]) : "",
";"
])
);
case "usegroup":
return group(
indent(
concat([
"use ",
node.type ? concat([node.type, " "]) : "",
node.name ? concat([node.name, "\\{"]) : "",
join(
concat([",", line]),
path.map(item => concat([print(item)]), "items")
),
node.name ? "}" : ""
])
)
);
case "useitem":
return node.alias ? concat([node.name, " as ", node.alias]) : node.name;
return concat([
node.type ? concat([node.type, " "]) : "",
maybeStripLeadingSlashFromUse(node.name),
node.alias ? concat([" as ", node.alias]) : ""
]);
case "closure":
return concat([
"function (",
group(
concat([
indent(
join(
", ",
path.map(
argument => concat([softline, print(argument)]),
"arguments"
)
)
),
softline
])
),
"function ",
printArgumentsList(path, options, print),
node.uses && node.uses.length > 0
? group(
concat([
") use (",
indent(
join(
", ",
path.map(use => {
return concat([softline, print(use)]);
}, "uses")
)
),
softline
" use ",
printArgumentsList(path, options, print, "uses")
])
)
: "",
group(") {"),
" {",
indent(concat([hardline, path.call(print, "body")])),
concat([hardline, "}"])
]);
case "retif":
case "retif": {
const parent = path.getParentNode();
const canBreak = !node.trueExpr;
const forceNoIndent = parent.kind === "retif" || canBreak;
const printedExpr = concat([
line,
"?",
node.trueExpr ? concat([" ", path.call(print, "trueExpr"), line]) : "",
": ",
path.call(print, "falseExpr")
]);
return group(
concat([
path.call(print, "test"),
indent(
concat([
line,
"?",
node.trueExpr
? concat([" ", path.call(print, "trueExpr"), line])
: "",
": ",
path.call(print, "falseExpr")
])
)
forceNoIndent ? printedExpr : indent(printedExpr)
])
);
}
case "exit":
return concat(["exit(", path.call(print, "status"), ")"]);
return group(
concat([
node.useDie ? "die" : "exit",
"(",
node.status
? concat([
indent(concat([softline, path.call(print, "status")])),
softline
])
: comments.printDanglingComments(path, options),
")"
])
);
case "clone":
return concat(["clone ", path.call(print, "what")]);
case "declare": {
const printDeclareArguments = function(path) {
const directive = Object.keys(path.getValue().what)[0];
const printDeclareArguments = path => {
const [directive] = Object.keys(path.getValue().what);
return concat([directive, "=", path.call(print, "what", directive)]);

@@ -916,6 +1337,3 @@ };

hardline,
path.call(
childrenPath => printLines(childrenPath, options, print),
"children"
),
concat(path.map(print, "children")),
hardline,

@@ -929,11 +1347,3 @@ "enddeclare;"

") {",
indent(
concat([
hardline,
path.call(
childrenPath => printLines(childrenPath, options, print),
"children"
)
])
),
indent(concat([hardline, concat(path.map(print, "children"))])),
hardline,

@@ -948,6 +1358,3 @@ "}"

hardline,
path.call(
childrenPath => printLines(childrenPath, options, print),
"children"
)
concat(path.map(print, "children"))
]);

@@ -960,3 +1367,3 @@ }

indent(
concat([line, join(concat([",", line]), path.map(print, "items"))])
concat([" ", join(concat([",", line]), path.map(print, "items"))])
)

@@ -971,3 +1378,3 @@ ])

concat([
line,
" ",
join(

@@ -1001,3 +1408,10 @@ concat([",", line]),

return concat(["goto ", node.label]);
case "new":
case "new": {
// if the child node is an anonymous class, we need to store the arguments
// so the child class node can access them later
const isAnonymousClassNode =
node.what && node.what.kind === "class" && node.what.isAnonymous;
if (isAnonymousClassNode && node.arguments.length > 0) {
anonymousClassesNewArguments = printArgumentsList(path, options, print);
}
return group(

@@ -1007,20 +1421,16 @@ concat([

path.call(print, "what"),
"(",
indent(
join(
", ",
path.map(
argument => concat([softline, print(argument)]),
"arguments"
)
)
),
softline,
")"
isAnonymousClassNode ? "" : printArgumentsList(path, options, print)
])
);
}
case "try":
return concat([
"try {",
indent(concat([hardline, path.call(print, "body")])),
indent(
concat([
hardline,
path.call(print, "body"),
comments.printDanglingComments(path, options, true)
])
),
hardline,

@@ -1051,3 +1461,9 @@ "}",

" {",
indent(concat([hardline, path.call(print, "body")])),
indent(
concat([
hardline,
path.call(print, "body"),
comments.printDanglingComments(path, options, true)
])
),
hardline,

@@ -1061,7 +1477,14 @@ "}"

case "halt":
return concat(["__halt_compiler();", node.after]);
//@TODO: leaving eval until we figure out encapsed https://github.com/prettier/prettier-php/pull/2
return concat(["__halt_compiler();", node.after.replace(/\n$/, "")]);
case "eval":
return group(
concat([
"eval(",
indent(concat([softline, path.call(print, "source")])),
softline,
")"
])
);
default:
return "Have not implemented statement kind " + node.kind + " yet.";
return `Have not implemented statement kind ${node.kind} yet.`;
}

@@ -1072,11 +1495,12 @@ }

const node = path.getValue();
if (includes(expressionKinds, node.kind)) {
if (expressionKinds.includes(node.kind)) {
return printExpression(path, options, print);
}
if (includes(statementKinds, node.kind)) {
if (statementKinds.includes(node.kind)) {
return printStatement(path, options, print);
}
switch (node.kind) {
case "identifier":
case "identifier": {
// this is a hack until https://github.com/glayzzle/php-parser/issues/113 is resolved
// for reserved words we prefer lowercase case
if (node.name === "\\array") {

@@ -1087,3 +1511,19 @@ return "array";

}
return node.name;
const lowerCasedName = node.name.toLowerCase();
const isLowerCase =
[
"int",
"float",
"bool",
"string",
"null",
"void",
"iterable",
"object",
"self"
].indexOf(lowerCasedName) !== -1;
return isLowerCase ? lowerCasedName : node.name;
}
case "case":

@@ -1094,36 +1534,66 @@ return concat([

: "default:",
indent(concat([line, path.call(print, "body")]))
node.body
? node.body.children && node.body.children.length
? indent(concat([hardline, path.call(print, "body")]))
: ";"
: ""
]);
case "break":
if (node.level) {
while (node.level.kind == "parenthesis") {
node.level = node.level.inner;
}
if (node.level.kind == "number" && node.level.value != 1) {
return concat(["break ", path.call(print, "level")]);
}
return "break";
}
return "break";
case "return":
case "continue":
if (node.level) {
while (node.level.kind == "parenthesis") {
node.level = node.level.inner;
}
if (node.level.kind == "number" && node.level.value != 1) {
return concat(["continue ", path.call(print, "level")]);
}
return "continue";
}
return "continue";
case "return": {
const parts = [];
parts.push("return");
if (node.expr) {
return concat(["return ", path.call(print, "expr")]);
const printedExpr = path.call(print, "expr");
if (node.expr.kind === "bin") {
parts.push(
group(
concat([
ifBreak(" (", " "),
indent(concat([softline, printedExpr])),
softline,
ifBreak(")")
])
)
);
} else {
parts.push(" ", printedExpr);
}
}
return "return";
case "doc":
return node.isDoc
? concat([
"/**",
// we use the number of lines to determine if this is a single or
// multi line docblock
node.lines.length > 1
? concat(
node.lines.map(
(comment, index) =>
index != 0 && index != node.lines.length - 1
? concat([hardline, " * ", comment])
: ""
)
)
: concat([" ", node.lines[0]], " "),
node.lines.length > 1 ? hardline : "",
" */"
])
: join(hardline, node.lines.map(comment => concat(["// ", comment])));
case "entry":
return concat(parts);
}
case "entry": {
const dangling = comments.printDanglingComments(
path,
options,
/* sameLine */ true
);
const printedComments = dangling ? concat([hardline, dangling]) : "";
return concat([
node.key ? concat([path.call(print, "key"), " => "]) : "",
path.call(print, "value")
path.call(print, "value"),
printedComments
]);
}
case "traituse":

@@ -1140,7 +1610,3 @@ return group(

line,
path.call(
adaptationsPath =>
printLines(adaptationsPath, options, print),
"adaptations"
)
printLines(path, options, print, "adaptations")
])

@@ -1165,7 +1631,9 @@ ),

path.call(print, "trait"),
"::",
node.method,
node.trait ? "::" : "",
node.method || "",
" as ",
node.visibility ? concat([node.visibility, " "]) : "",
node.as
join(" ", [
...(node.visibility ? [node.visibility] : []),
...(node.as ? [node.as] : [])
])
]);

@@ -1176,3 +1644,3 @@ case "label":

default:
return "Have not implemented kind " + node.kind + " yet.";
return `Have not implemented kind ${node.kind} yet.`;
}

@@ -1179,0 +1647,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc