Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify hooks formatting #108

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,155 @@ A function or method may be referenced in a way that creates a closure out of it

If so, the `...` MUST NOT include any whitespace before or after. That is, the correct format is `foo(...)`.


### 4.9 Property Hooks

Object properties may also include hooks, which have a number of syntactic options.

When using the long form of hooks:

* The opening brace MUST be on the same line as the property.
* The opening brace MUST be separated from the property name or its default value by a single space.
* The closing brace MUST be on its own line, and have no comment following it.
* The entire body of the hook definition MUST be indented one level.
* The body of each hook MUST be indented one level.
* If multiple hooks are declared, they MUST be separated by at least a single line break. They
MAY be separated by an additional blank line to aid readability.

For example:

```php
class Example
{
public string $newName = 'Me' {
set {
if (strlen($value) < 3) {
throw new \Exception('Too short');
}
$this->newName = ucfirst($value);
}
}

public string $department {
get {
return $this->values[__PROPERTY__];
}
set {
$this->values[__PROPERTY__] = $value;
}
}
// or
public string $department {
get {
return $this->values[__PROPERTY__];
}

set {
$this->values[__PROPERTY__] = $value;
}
}
}
```

Property hooks also support multiple short-hook variations.

For a `set` hook, if the argument name and type do not need to be redefined, then they MAY be omitted.

If a hook consists of a single expression, then PHP allows it to be shortened using `=>`. In that case:

* There MUST be a single space on either side of the `=>` symbol.
* The body MUST be on the same line as the hook declaration, unless it gets prohibitively long. If it gets prohibitively long, the developer SHOULD consider not using the short-hook syntax.

```php
class Example
{
public string $myName {
get => __CLASS__;
}

public string $newName {
set => ucfirst($value);
}
}
```

Additionally, if the following criteria are met:

* There is only one hook implementation.
* That hook uses the short-hook syntax.

Then the hook MAY be listed entirely inline. In that case,

* The hook name MUST be separated from the opening brace and the arrow operator by a single space
* The semicolon ending of the hook MUST be separated from the closing brace by a single space.

For example:

```php
class Example
{
public string $myName { get => __CLASS__; }

public string $newName { set => ucfirst($value); }
}
```

Property hooks MAY also be defined in constructor-promoted properties. However, they
MUST be only a single hook, with a short-syntax body, defined on a single line as above.
If those criteria are not met, then the promoted property MUST NOT have any hooks defined
inline.

```php
class Example
{
public function __construct(
public string $name { set => ucfirst($value); }
) {}
}
```

The following is ***not allowed*** due to the hook being too complex:

```php
class Example
{
public function __construct(
public string $name {
set {
if (strlen($value) < 3) {
throw new \Exception('Too short');
}
$this->newName = ucfirst($value);
}
}
) {}
}
```

## 4.10 Interface properties

Abstract roperties may be defined in interfaces or abstract classes, but are required to
specify if they must support `get` operations, `set` operations, or both.

* The operation block MUST be on the same line as the property.
Copy link
Contributor

@TimWolla TimWolla Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I agree with the MUST here, because that effectively requires the user to use the short-form and thus is inconsistent with hooks themselves.

I find it reasonable to write the following in an interface (using your brace placement):

public string $both {
    get;
    set;
}

And then shortening that to a single line MAY be done (consistently with hooks).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's actually a subtle difference here. For interfaces, there can never be a body to a hook, so I see no point in the extra lines. (If Levi ever re-proposes interface default methods that may change, but we'll cross that bridge when we get to it.)

For abstract classes, though, one could specify one hook as abstract and one as predefined. In that case, multi-lining is probably better.

We should probably address those separately.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so I see no point in the extra lines

The point is allowing for an uniform formatting of similar things. In this case: A property declaration with a list of “operations”.

I also find it much easier to scan the code vertically rather than horizontally, because the of the established pattern of “a line-break indicates that something new begins, with indentation indicating the relationship to the previous line”.

* There MUST be a single space between the property name and the operation block `{}`.
* There MUST be a single space after the opening `{`.
* There MUST be a single space before the closing `}`;
* There MUST NOT be a space between the operation and its required semicolon.
* If multiple operations are specified, they MUST be separated by a single space.
* The `get` operation MUST be listed before the `set` operation.

```php
interface Example
{
public string $readable { get; }

public string $writeable { set; }

public string $both { get; set; }
}
```

## 5. Control Structures

The general style rules for control structures are as follows:
Expand Down