From 7538cc15438768d7d0449c68783acf6c49aa5088 Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Fri, 3 Jan 2025 17:35:20 -0600 Subject: [PATCH 01/12] Renumber object sections to make room for property hooks next to properties. --- spec.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/spec.md b/spec.md index 76315d8..4489238 100644 --- a/spec.md +++ b/spec.md @@ -477,7 +477,9 @@ class ClassName } ``` -### 4.4 Methods and Functions +### 4.4 Property Hooks + +### 4.5 Methods and Functions Visibility MUST be declared on all methods. @@ -542,7 +544,7 @@ class Point } ``` -### 4.5 Method and Function Parameters +### 4.6 Method and Function Parameters In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma. @@ -660,7 +662,7 @@ public function process(string $algorithm, &...$parts) } ``` -### 4.6 Modifier Keywords +### 4.7 Modifier Keywords Classes, properties, and methods have numerous keyword modifiers that alter how the engine and language handles them. When present, they MUST be in the following order: @@ -701,7 +703,7 @@ readonly class ValueObject } ``` -### 4.7 Method and Function Calls +### 4.8 Method and Function Calls When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis, there MUST NOT be a space @@ -766,7 +768,7 @@ $someInstance ->run(); ``` -### 4.8 Function Callable References +### 4.9 Function Callable References A function or method may be referenced in a way that creates a closure out of it, by providing `...` in place of arguments. From 4b2b715bf38694709558d2d110e5ed785ea507ef Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Fri, 3 Jan 2025 18:15:26 -0600 Subject: [PATCH 02/12] Document hooks formatting. --- spec.md | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/spec.md b/spec.md index 4489238..1d8d869 100644 --- a/spec.md +++ b/spec.md @@ -479,6 +479,109 @@ class ClassName ### 4.4 Property Hooks +Object properties may also include hooks, which have a number of syntactic options. + +If there is only one hook implementation, and that hook implementation itself uses +the short-hook syntax, then the hook declaration MAY be listed entirely inline. The hook +name MUST be separated from the opening brace and the arrow operator by a single +space, and the semicolon ending of the hook MUST be separated from the cosing brace +by a single space. For example: + +```php +class Example +{ + public string $myName { get => __CLASS__; } + + public string $newName { set => ucfirst($value); } +} +``` + +If those two criteria are not met, then the hook block MUST be spread across multiple lines: + +```php +class Example +{ + public string $myName { + get => __CLASS__; + } + + public string $newName { + set => ucfirst($value); + } +} +``` + +When using the multi-line form, the opening brace MUST be on the same line as the property and +the closing brace MUST be on its own line, with the body indented one level. + +The `=>` operator MUST have a single space on either side. + +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. + +If the property includes a default value, there MUST be a single space between the default value +and the opening brace. + +```php +class Example +{ + public string $newName = 'Me' { + set => ucfirst($value); + } +} +``` + +If a hook is using its multi-line form, the opening brace MUST be on the same line as the hook +name, and the closing brace MUST be on its own line. The body MUST be indented one level. + +```php +class Example +{ + public string $newName = 'Me' { + set { + if (strlen($value) < 3) { + throw new \Exception('Too short'); + } + $this->newName = ucfirst($value); + } + } +} +``` + +For a `set` hook, if the argument name and type do not need to be redefined, then they MAY be omitted. + +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, and SHOULD instead be defined as normal property and not promoted. + +```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.5 Methods and Functions Visibility MUST be declared on all methods. From 314954d28c6d743da26ec3eba6f444b130809dd9 Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Mon, 20 Jan 2025 17:22:46 -0600 Subject: [PATCH 03/12] Restore original section order. --- spec.md | 221 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 111 insertions(+), 110 deletions(-) diff --git a/spec.md b/spec.md index 1d8d869..cfbb464 100644 --- a/spec.md +++ b/spec.md @@ -477,112 +477,7 @@ class ClassName } ``` -### 4.4 Property Hooks - -Object properties may also include hooks, which have a number of syntactic options. - -If there is only one hook implementation, and that hook implementation itself uses -the short-hook syntax, then the hook declaration MAY be listed entirely inline. The hook -name MUST be separated from the opening brace and the arrow operator by a single -space, and the semicolon ending of the hook MUST be separated from the cosing brace -by a single space. For example: - -```php -class Example -{ - public string $myName { get => __CLASS__; } - - public string $newName { set => ucfirst($value); } -} -``` - -If those two criteria are not met, then the hook block MUST be spread across multiple lines: - -```php -class Example -{ - public string $myName { - get => __CLASS__; - } - - public string $newName { - set => ucfirst($value); - } -} -``` - -When using the multi-line form, the opening brace MUST be on the same line as the property and -the closing brace MUST be on its own line, with the body indented one level. - -The `=>` operator MUST have a single space on either side. - -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. - -If the property includes a default value, there MUST be a single space between the default value -and the opening brace. - -```php -class Example -{ - public string $newName = 'Me' { - set => ucfirst($value); - } -} -``` - -If a hook is using its multi-line form, the opening brace MUST be on the same line as the hook -name, and the closing brace MUST be on its own line. The body MUST be indented one level. - -```php -class Example -{ - public string $newName = 'Me' { - set { - if (strlen($value) < 3) { - throw new \Exception('Too short'); - } - $this->newName = ucfirst($value); - } - } -} -``` - -For a `set` hook, if the argument name and type do not need to be redefined, then they MAY be omitted. - -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, and SHOULD instead be defined as normal property and not promoted. - -```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.5 Methods and Functions +### 4.4 Methods and Functions Visibility MUST be declared on all methods. @@ -647,7 +542,7 @@ class Point } ``` -### 4.6 Method and Function Parameters +### 4.5 Method and Function Parameters In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma. @@ -765,7 +660,7 @@ public function process(string $algorithm, &...$parts) } ``` -### 4.7 Modifier Keywords +### 4.6 Modifier Keywords Classes, properties, and methods have numerous keyword modifiers that alter how the engine and language handles them. When present, they MUST be in the following order: @@ -806,7 +701,7 @@ readonly class ValueObject } ``` -### 4.8 Method and Function Calls +### 4.7 Method and Function Calls When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis, there MUST NOT be a space @@ -871,12 +766,118 @@ $someInstance ->run(); ``` -### 4.9 Function Callable References +### 4.8 Function Callable References A function or method may be referenced in a way that creates a closure out of it, by providing `...` in place of arguments. 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. + +If there is only one hook implementation, and that hook implementation itself uses +the short-hook syntax, then the hook declaration MAY be listed entirely inline. The hook +name MUST be separated from the opening brace and the arrow operator by a single +space, and 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); } +} +``` + +If those two criteria are not met, then the hook block MUST be spread across multiple lines: + +```php +class Example +{ + public string $myName { + get => __CLASS__; + } + + public string $newName { + set => ucfirst($value); + } +} +``` + +When using the multi-line form, the opening brace MUST be on the same line as the property and +the closing brace MUST be on its own line, with the body indented one level. + +The `=>` operator MUST have a single space on either side. + +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. + +If the property includes a default value, there MUST be a single space between the default value +and the opening brace. + +```php +class Example +{ + public string $newName = 'Me' { + set => ucfirst($value); + } +} +``` + +If a hook is using its multi-line form, the opening brace MUST be on the same line as the hook +name, and the closing brace MUST be on its own line. The body MUST be indented one level. + +```php +class Example +{ + public string $newName = 'Me' { + set { + if (strlen($value) < 3) { + throw new \Exception('Too short'); + } + $this->newName = ucfirst($value); + } + } +} +``` + +For a `set` hook, if the argument name and type do not need to be redefined, then they MAY be omitted. + +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, and SHOULD instead be defined as normal property and not promoted. + +```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); + } + } + ) {} +} +``` + ## 5. Control Structures The general style rules for control structures are as follows: From 5a7b88e4b5054754ed39022bf8023cfc6786dbcf Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Mon, 20 Jan 2025 17:28:07 -0600 Subject: [PATCH 04/12] Typo fix. --- spec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec.md b/spec.md index cfbb464..d2f0e07 100644 --- a/spec.md +++ b/spec.md @@ -849,13 +849,13 @@ For a `set` hook, if the argument name and type do not need to be redefined, the 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, and SHOULD instead be defined as normal property and not promoted. +inline. ```php class Example { public function __construct( - public string $name { set => ucfirst($value; } + public string $name { set => ucfirst($value); } ) {} } ``` From 8320af51628b8ae44cd77c462b145b5d5d11e74f Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Mon, 20 Jan 2025 17:45:41 -0600 Subject: [PATCH 05/12] Restructure hook descriptions. --- spec.md | 91 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 36 deletions(-) diff --git a/spec.md b/spec.md index d2f0e07..6e9fd1f 100644 --- a/spec.md +++ b/spec.md @@ -777,22 +777,59 @@ If so, the `...` MUST NOT include any whitespace before or after. That is, the c Object properties may also include hooks, which have a number of syntactic options. -If there is only one hook implementation, and that hook implementation itself uses -the short-hook syntax, then the hook declaration MAY be listed entirely inline. The hook -name MUST be separated from the opening brace and the arrow operator by a single -space, and the semicolon ending of the hook MUST be separated from the closing brace -by a single space. For example: +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 $myName { get => __CLASS__; } + public string $newName = 'Me' { + set { + if (strlen($value) < 3) { + throw new \Exception('Too short'); + } + $this->newName = ucfirst($value); + } + } - public string $newName { set => 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; + } + } } ``` -If those two criteria are not met, then the hook block MUST be spread across multiple lines: +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 @@ -807,45 +844,27 @@ class Example } ``` -When using the multi-line form, the opening brace MUST be on the same line as the property and -the closing brace MUST be on its own line, with the body indented one level. - -The `=>` operator MUST have a single space on either side. +Additionally, if the following criteria are met: -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. +* There is only one hook implementation. +* That hook uses the short-hook syntax. -If the property includes a default value, there MUST be a single space between the default value -and the opening brace. +Then the hook MAY be listed entirely inline. In that case, -```php -class Example -{ - public string $newName = 'Me' { - set => ucfirst($value); - } -} -``` +* 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. -If a hook is using its multi-line form, the opening brace MUST be on the same line as the hook -name, and the closing brace MUST be on its own line. The body MUST be indented one level. +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 $myName { get => __CLASS__; } + + public string $newName { set => ucfirst($value); } } ``` -For a `set` hook, if the argument name and type do not need to be redefined, then they MAY be omitted. - 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 From 3273f943639be0f8c6a69f7d2d1f1d3a5a7890ba Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Mon, 20 Jan 2025 17:52:45 -0600 Subject: [PATCH 06/12] Interface properties. --- spec.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/spec.md b/spec.md index 6e9fd1f..b8e665b 100644 --- a/spec.md +++ b/spec.md @@ -897,6 +897,30 @@ class Example } ``` +## 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. +* 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: From 7901d610645380bd34a50201dcacc010abc636b4 Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Tue, 21 Jan 2025 11:52:10 -0600 Subject: [PATCH 07/12] Show extra-long version. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tim Düsterhus --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index b8e665b..60f5d06 100644 --- a/spec.md +++ b/spec.md @@ -793,7 +793,7 @@ For example: class Example { public string $newName = 'Me' { - set { + set(string $value) { if (strlen($value) < 3) { throw new \Exception('Too short'); } From 6dfd0abfa3a64561cde7a41fee5d9b1c71996cdc Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Tue, 21 Jan 2025 22:35:04 -0600 Subject: [PATCH 08/12] Disallow very-long short-hooks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tim Düsterhus --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index 60f5d06..1b5bf14 100644 --- a/spec.md +++ b/spec.md @@ -829,7 +829,7 @@ For a `set` hook, if the argument name and type do not need to be redefined, the 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. +* The body MUST be on the same line as the hook declaration and MUST NOT be wrapped. If wrapping is necessary to keep the line within the line length or desired for other reasons the short-hook syntax MUST NOT be used. ```php class Example From 81328fff49c002e44dc2d07adc7a42119e440314 Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Tue, 21 Jan 2025 22:35:45 -0600 Subject: [PATCH 09/12] Spelling fix Co-authored-by: Korvin Szanto --- spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec.md b/spec.md index 1b5bf14..e241409 100644 --- a/spec.md +++ b/spec.md @@ -899,7 +899,7 @@ class Example ## 4.10 Interface properties -Abstract roperties may be defined in interfaces or abstract classes, but are required to +Abstract properties 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. From a8d1a28ee23c9dd05f76a32ff8f46965a4250339 Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Fri, 28 Mar 2025 23:59:51 -0400 Subject: [PATCH 10/12] Clarify abstract properties with partial implementation. --- spec.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/spec.md b/spec.md index e241409..dba1c14 100644 --- a/spec.md +++ b/spec.md @@ -772,7 +772,6 @@ 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. @@ -897,10 +896,27 @@ class Example } ``` -## 4.10 Interface properties +## 4.10 Interface and abstract properties Abstract properties may be defined in interfaces or abstract classes, but are required to -specify if they must support `get` operations, `set` operations, or both. +specify if they must support `get` operations, `set` operations, or both. In the case +of abstract classes, they MAY include a body for one or another hook. + +If there is a body for any hook, then the entire hook block MUST follow +the same rules as for defined hooks above. The only difference is that +a hook that has no body specified have a single semicolon after the hook +keyword, with no space before it. + +```php +abstract class Example { + abstract public string $name { + get => ucfirst($this->name); + set; + } +} +``` + +If there is no body for either hook, then the following rules apply: * The operation block MUST be on the same line as the property. * There MUST be a single space between the property name and the operation block `{}`. From e3e40370df9f6e9a3fe327e93859868fc75e162f Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Sat, 5 Apr 2025 21:30:01 -0500 Subject: [PATCH 11/12] Soften rules for short-hooks. --- spec.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec.md b/spec.md index dba1c14..7371dcf 100644 --- a/spec.md +++ b/spec.md @@ -828,7 +828,8 @@ For a `set` hook, if the argument name and type do not need to be redefined, the 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 and MUST NOT be wrapped. If wrapping is necessary to keep the line within the line length or desired for other reasons the short-hook syntax MUST NOT be used. +* The body MUST begin on the same line as the hook name and `=>`. +* Wrapping is allowed if the expression used allows for wrapping, using the rules defined elsewhere in this document. ```php class Example From 0a13031a227b8e9d0fcd47a6d37adfc523b889b4 Mon Sep 17 00:00:00 2001 From: Larry Garfield Date: Sat, 5 Apr 2025 21:31:38 -0500 Subject: [PATCH 12/12] Disallow wrapping in inline hook bodies. --- spec.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spec.md b/spec.md index 7371dcf..e9420f1 100644 --- a/spec.md +++ b/spec.md @@ -848,6 +848,7 @@ Additionally, if the following criteria are met: * There is only one hook implementation. * That hook uses the short-hook syntax. +* That hook expression does not contain any wrapping. Then the hook MAY be listed entirely inline. In that case,