Braces

The braces section decides where curly braces go: on which line the opening brace of a class, a function, a closure (an anonymous function) and a control structure stands, where else and catch go, how an empty body is written, and when braces are required.

Where the { goes is the most visible decision of every style, and also the one where styles differ most often. That is why each kind of construct has its own key: a class, a function, a function with parameters on several lines, a closure, an anonymous class and a control structure. PSR-12 and PER Coding Style 3.1 put the brace of a declaration on the next line, and the brace of everything else on the same line as its head:

braces:
	position:
		class: nextLine
		function: nextLine
		closure: sameLine
		controlStructure: sameLine
		continuingKeyword: sameLine
class Cart {  // Expected a line break before the opening brace.
	public function add(Item $item): void {  // Expected a line break before the opening brace.
		if ($item->isFree())
		{  // Expected no line break before the opening brace.
			return;
		}
		$this->items[] = $item;
	}
}
class Cart
{
	public function add(Item $item): void
	{
		if ($item->isFree()) {
			return;
		}
		$this->items[] = $item;
	}
}

Besides the opening brace, DressCode checks that the body after it starts on a new line and that the closing brace stands on a line of its own. The exceptions have their own keys: an empty body {}, which braces.emptyBody decides separately for a class, a function, a closure, a property hook, an anonymous class and a control structure, and a closure written entirely on one line (braces.singlelineClosure). The indentation of the lines this creates belongs to the indentation section, and the blank lines after and before a brace to the blankLines section.

braces.alternativeSyntax

if: … endif; is written with braces.

  • forbidden: never there
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs keep, psr12 keep, nette forbidden, symfony forbidden, laravel forbidden · covers no_alternative_syntax

braces.bracelessBody

The body of a control structure written without braces, if ($a) foo();.

  • forbidden: never there
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs forbidden, psr12 forbidden, nette forbidden, symfony forbidden, laravel forbidden · covers control_structure_braces, Generic.ControlStructures.InlineControlStructure

braces:
	bracelessBody: forbidden
if ($item->isFree()) return;  // The body of the `if` must be enclosed in braces.
if ($item->isFree()) {
	return;
}

braces.bareStatementGroup

{ … } around statements that nothing opens.

  • forbidden: never there
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs keep, psr12 keep, nette forbidden, symfony forbidden, laravel forbidden · covers no_unneeded_braces, no_unneeded_curly_braces

braces.position.class

Where the { of a class, an interface, a trait and an enum stands, the members starting a line below it and the } taking a line of its own.

  • sameLine: on the line of what comes before
  • nextLine: on the next line
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs nextLine, psr12 nextLine, nette nextLine, symfony nextLine, laravel nextLine · covers braces_position, PSR2.Classes.ClassDeclaration

braces:
	position:
		class: sameLine
class Cart
{  // Expected no line break before the opening brace.
	private array $items = [];
}
class Cart {
	private array $items = [];
}

braces.position.function

Where the { of a function and of a method whose parameters stand on one line stands, the { of a property hook and of the list of hooks staying on the line of its head; the body starts a line below it and the } takes a line of its own.

  • sameLine: on the line of what comes before
  • nextLine: on the next line
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs nextLine, psr12 nextLine, nette nextLine, symfony nextLine, laravel nextLine · covers braces_position, Squiz.Functions.MultiLineFunctionDeclaration

All the standards put the brace of a function on the next line. If you want it on the same line as the function head, write sameLine. A function with parameters on several lines follows the key braces.position.multilineSignature.

braces:
	position:
		function: sameLine
function total(array $items): int
{  // Expected no line break before the opening brace.
	return count($items);
}
function total(array $items): int {
	return count($items);
}

braces.position.multilineSignature

Where the { of a function and of a method whose parameters are spread over lines stands.

  • sameLine: on the line of the )
  • nextLine: on the line below the )
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs sameLine, psr12 sameLine, nette sameLine, symfony sameLine, laravel sameLine · covers braces_position, Squiz.Functions.MultiLineFunctionDeclaration

braces.position.typedMultilineSignature

Where the { of a function and of a method whose parameters are spread over lines stands after a return type; where it is kept, braces.position.multilineSignature says it.

  • sameLine: on the line of the return type
  • nextLine: on the line below the return type
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs keep, psr12 keep, nette nextLine, symfony keep, laravel keep

Nette Coding Standard uses the value nextLine: a function without a return type has ) { as in PER Coding Style, and for a function with a return type, ): void stands on a line of its own and the brace goes below it.

braces:
	position:
		multilineSignature: sameLine
		typedMultilineSignature: nextLine
function send(
	string $to,
	string $subject,
): void {  // Expected a line break before the opening brace.
	mail($to, $subject);
}

function log(
	string $message,
)
{  // Expected no line break before the opening brace.
	echo $message;
}
function send(
	string $to,
	string $subject,
): void
{
	mail($to, $subject);
}

function log(
	string $message,
) {
	echo $message;
}

braces.position.closure

Where the { of a closure stands, the body starting a line below it and the } taking a line of its own.

  • sameLine: on the line of what comes before
  • nextLine: on the next line
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs sameLine, psr12 sameLine, nette sameLine, symfony sameLine, laravel sameLine · covers braces_position, Squiz.Functions.MultiLineFunctionDeclaration

braces:
	position:
		closure: nextLine
$double = function (int $x) {  // Expected a line break before the opening brace.
	return $x * 2;
};
$double = function (int $x)
{
	return $x * 2;
};

braces.position.anonymousClass

Where the { of an anonymous class stands, on the next line always where its interfaces are spread over lines, the members starting a line below it and the } taking a line of its own.

  • sameLine: on the line of what comes before
  • nextLine: on the next line
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs sameLine, psr12 sameLine, nette sameLine, symfony sameLine, laravel nextLine · covers braces_position, PSR12.Classes.AnonClassDeclaration

braces:
	position:
		anonymousClass: nextLine
$logger = new class implements Logger {  // Expected a line break before the opening brace.
	public function log(string $message): void
	{
		echo $message;
	}
};
$logger = new class implements Logger
{
	public function log(string $message): void
	{
		echo $message;
	}
};

braces.position.controlStructure

Where the { of if, else, a loop, declare, try, catch, finally, switch and match stands, the body starting a line below it and the } taking a line of its own.

  • sameLine: on the line of what comes before
  • nextLine: on the next line
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs sameLine, psr12 sameLine, nette sameLine, symfony sameLine, laravel sameLine · covers braces_position, PSR12.Files.DeclareStatement, Squiz.ControlStructures.ControlSignature

braces:
	position:
		controlStructure: nextLine
if ($ready) {  // Expected a line break before the opening brace.
	start();
}
if ($ready)
{
	start();
}

braces.position.continuingKeyword

Where the keyword continuing a structure after its } stands: else, elseif, catch, finally and the while of do.

  • sameLine: on the line of what comes before
  • nextLine: on the next line
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs sameLine, psr12 sameLine, nette sameLine, symfony sameLine, laravel sameLine · covers control_structure_continuation_position, Squiz.ControlStructures.ControlSignature

braces:
	position:
		continuingKeyword: sameLine
try {
	connect();
}
catch (ConnectionException $e) {  // Expected no line break before the `catch` keyword.
	retry();
}
try {
	connect();
} catch (ConnectionException $e) {
	retry();
}

If your style starts every branch on a new line, use nextLine:

braces:
	position:
		continuingKeyword: nextLine
if ($ready) {
	start();
} else {  // Expected a line break before the `else` keyword.
	wait();
}
if ($ready) {
	start();
}
else {
	wait();
}

braces.emptyBody.class

How the empty body of a class, an interface, a trait and an enum is written; a comment inside makes it not empty.

  • collapsed: {} on the line of the head
  • expanded: { and } placed as those of any other body
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs collapsed, psr12 expanded, nette expanded, symfony expanded, laravel collapsed · covers single_line_empty_body

PER Coding Style shortens empty bodies, so the perCs preset has the value collapsed; PSR-12 and the other standards put each brace on its own line.

braces:
	emptyBody:
		class: collapsed
		function: collapsed
class NotFound extends Exception
{  // Expected no line break before the opening brace.
}  // Expected no line break before the closing brace.

class Point
{
	public function __construct(private int $x, private int $y)
	{  // Expected no line break before the opening brace.
	}  // Expected no line break before the closing brace.
}
class NotFound extends Exception {}

class Point
{
	public function __construct(private int $x, private int $y) {}
}

braces.emptyBody.function

How the empty body of a function and a method is written; a comment inside makes it not empty.

  • collapsed: {} on the line of the head
  • expanded: { and } placed as those of any other body
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs collapsed, psr12 expanded, nette expanded, symfony expanded, laravel collapsed · covers single_line_empty_body

braces.emptyBody.closure

How the empty body of a closure is written; a comment inside makes it not empty.

  • collapsed: {} on the line of the head
  • expanded: { and } placed as those of any other body
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs collapsed, psr12 expanded, nette expanded, symfony expanded, laravel collapsed · covers single_line_empty_body

braces.emptyBody.propertyHook

How the empty body of a property hook is written; a comment inside makes it not empty.

  • collapsed: {} on the line of the head
  • expanded: { and } placed as those of any other body
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs collapsed, psr12 expanded, nette expanded, symfony expanded, laravel keep

braces.emptyBody.anonymousClass

How the empty body of an anonymous class is written, one written on one line staying where it is kept; a comment inside makes it not empty.

  • collapsed: {} on the line of the head, one holding a comment staying on its line as written
  • expanded: { and } placed as those of any other body
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs collapsed, psr12 keep, nette keep, symfony keep, laravel collapsed · covers braces_position, single_line_empty_body

braces.emptyBody.controlStructure

How the empty body of an if, else, a loop, declare, try, catch and finally is written; a comment inside makes it not empty.

  • collapsed: {} on the line of the head
  • expanded: { and } placed as those of any other body
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs keep, psr12 keep, nette keep, symfony keep, laravel keep

No standard shortens an empty control structure; collapsed is for a project that wants to see a loop without a body on one line. A loop whose body holds a comment is not empty, and it stays as it is.

braces:
	emptyBody:
		controlStructure: collapsed
while ($reader->next()) {
}  // Expected no line break before the closing brace.
while ($reader->next()) {}

braces.singlelineClosure

A closure written whole on one line.

  • forbidden: never there
  • keep: nothing is enforced, the code stays as it is

Default keep · standards: perCs forbidden, psr12 forbidden, nette keep, symfony keep, laravel forbidden · covers braces_position

PSR-12 wants the body of every closure on lines of its own, so the psr12 and perCs presets have forbidden.

braces:
	singlelineClosure: forbidden
$ids = array_map(function ($row) { return $row->id; }, $rows);  // Expected a line break after the opening brace. // Expected a line break before the closing brace.
$ids = array_map(function ($row) {
	return $row->id;
}, $rows);