From 0808fc2886a0bde60af4c445df6575ad205618be Mon Sep 17 00:00:00 2001 From: Simon Gamma Date: Thu, 11 Jun 2020 22:30:24 +0200 Subject: [PATCH] documenting the community-plugin benefit and adding more examples --- .../diffplug/spotless/npm/prettier-serve.js | 1 - plugin-gradle/README.md | 22 +- .../spotless/PrettierIntegrationTest.java | 25 + .../resources/npm/prettier/plugins/php.clean | 500 ++++++++++++++++++ .../resources/npm/prettier/plugins/php.dirty | 295 +++++++++++ 5 files changed, 841 insertions(+), 2 deletions(-) create mode 100644 testlib/src/main/resources/npm/prettier/plugins/php.clean create mode 100644 testlib/src/main/resources/npm/prettier/plugins/php.dirty diff --git a/lib/src/main/resources/com/diffplug/spotless/npm/prettier-serve.js b/lib/src/main/resources/com/diffplug/spotless/npm/prettier-serve.js index 28e591f2ac..351ef73f9a 100644 --- a/lib/src/main/resources/com/diffplug/spotless/npm/prettier-serve.js +++ b/lib/src/main/resources/com/diffplug/spotless/npm/prettier-serve.js @@ -55,7 +55,6 @@ app.post("/prettier/format", (req, res) => { var formatted_file_content = ""; try { - console.log("format_data", format_data); formatted_file_content = prettier.format(format_data.file_content, format_data.config_options); } catch(err) { res.status(501).send("Error while formatting: " + err); diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 5b2835d70b..757ec52e15 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -468,8 +468,28 @@ spotless { } ``` + +### Using community plugins for prettier + +Since spotless uses the actual npm prettier package behind the scenes, it is possible to use prettier with +community-plugins in order to support even more file types. + +```gradle +spotless { + format 'prettierJava', { + target '**/*.java' + + prettier(['prettier': '2.0.5', 'prettier-plugin-java': '0.8.0']).config(['parser': 'java', 'tabWidth': 4]) + } + format 'php', { + target '**/*.php' + prettier(['prettier': '2.0.5', '@prettier/plugin-php': '0.14.2']).config(['parser': 'php', 'tabWidth': 3]) + } +} +``` + -Prettier can also be applied from within the [typescript config block](#typescript-formatter): +### Note: Prettier can also be applied from within the [typescript config block](#typescript-formatter) ```gradle spotless { diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/PrettierIntegrationTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/PrettierIntegrationTest.java index 7d4905683e..a3955b476e 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/PrettierIntegrationTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/PrettierIntegrationTest.java @@ -92,4 +92,29 @@ public void useJavaCommunityPlugin() throws IOException { Assertions.assertThat(spotlessApply.getOutput()).contains("BUILD SUCCESSFUL"); assertFile("JavaTest.java").sameAsResource("npm/prettier/plugins/java-test.clean"); } + + @Test + public void usePhpCommunityPlugin() throws IOException { + setFile("build.gradle").toLines( + "buildscript { repositories { mavenCentral() } }", + "plugins {", + " id 'com.diffplug.gradle.spotless'", + "}", + "def prettierConfig = [:]", + "prettierConfig['tabWidth'] = 3", + "prettierConfig['parser'] = 'php'", + "def prettierPackages = [:]", + "prettierPackages['prettier'] = '2.0.5'", + "prettierPackages['@prettier/plugin-php'] = '0.14.2'", + "spotless {", + " format 'php', {", + " target 'php-example.php'", + " prettier(prettierPackages).config(prettierConfig)", + " }", + "}"); + setFile("php-example.php").toResource("npm/prettier/plugins/php.dirty"); + final BuildResult spotlessApply = gradleRunner().withArguments("--stacktrace", "spotlessApply").build(); + Assertions.assertThat(spotlessApply.getOutput()).contains("BUILD SUCCESSFUL"); + assertFile("php-example.php").sameAsResource("npm/prettier/plugins/php.clean"); + } } diff --git a/testlib/src/main/resources/npm/prettier/plugins/php.clean b/testlib/src/main/resources/npm/prettier/plugins/php.clean new file mode 100644 index 0000000000..4c8710bbee --- /dev/null +++ b/testlib/src/main/resources/npm/prettier/plugins/php.clean @@ -0,0 +1,500 @@ +other = $test_string; + $this->current_version = $current_version ?: new Content_Version_Model(); + self::$staticTest = $test_int; + } + + public static function test_static_constructor( + $test, + $test_int, + $test_string + ) { + $model = new self($test, $test_int, $test_string); + $model = new self( + $really_really_really_really_really_really_really_really_long_array, + $test_int, + $test_string + ); + return $model; + } + + public function test_pass_by_reference(&$test) + { + $test + 1; + } + + /** + * This is a function + */ + private function hi($input) + { + $test = 1; + + //testing line spacing + $other_test = 2; + + $one_more_test = 3; + return $input . $this->test; + } + + public function reallyReallyReallyReallyReallyReallyReallyLongMethodName( + $input, + $otherInput = 1 + ) { + return true; + } + + // doc test + public static function testStaticFunction($input) + { + return self::$staticTest[0]; + } + + public function returnTypeTest(): string + { + return 'hi'; + } + + final public static function bar() + { + // Nothing + } + + abstract protected function zim(); + + public function method(iterable $iterable): array + { + // Parameter broadened and return type narrowed. + } + + public function method1() + { + return 'hi'; + } + + public function method2() + { + return 'hi'; + } + + public function method3() + { + return 'hi'; + } + + public function testReturn(?string $name): ?string + { + return $name; + } + + public function swap(&$left, &$right): void + { + if ($left === $right) { + return; + } + + $tmp = $left; + $left = $right; + $right = $tmp; + } + + public function test(object $obj): object + { + return new SplQueue(); + } + + public function longLongAnotherFunction( + string $foo, + string $bar, + int $baz + ): string { + return 'foo'; + } + + public function longLongAnotherFunctionOther( + string $foo, + string $bar, + int $baz + ) { + return 'foo'; + } + + public function testReturnTypeDeclaration(): object + { + return new SplQueue(); + } + + public function testReturnTypeDeclarationOther(): object + { + return new SplQueue(); + } +} + +$this->something->method( + $argument, + $this->more->stuff($this->even->more->things->complicatedMethod()) +); + +class A +{ +} + +$someVar = new ReaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalyLongClassName(); + +class ClassName extends ParentClass implements \ArrayAccess, \Countable +{ + // constants, properties, methods +} + +class FooBar +{ + public $property; + public $property2; + public function method() + { + } + public function method2() + { + } +} + +class FooBarFoo +{ + public function fooBarBaz($x, $y, $z, $foo, $bar) + { + /* Comment */ + } +} + +class ClassName extends ParentClass implements InterfaceClass +{ +} + +class ClassName extends ParentClass implements + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 +{ +} + +class ClassName extends ParentClass implements + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 +{ +} + +class ClassName extends VeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 implements + InterfaceClass +{ +} + +class ClassName + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 + implements InterfaceClass +{ +} + +class ClassName + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 + implements VeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 +{ +} + +class ClassName + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 + implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 +{ +} + +class ClassName extends ParentClass implements + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1, + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName2, + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName3 +{ +} + +class ClassName extends VeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 implements + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1, + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName2, + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName3 +{ +} + +class ClassName + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 + implements + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1, + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName2, + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName3 +{ +} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 + extends ParentClass + implements InterfaceClass +{ +} + +class Custom_Plugin_NotificationPlaceholderSource extends + Notification_Manager_DefaultPlaceholderSource +{ +} + +class field extends \models\base +{ + protected function pre_save($input, $fields) + { + $input['configs'] = json_encode( + array_merge( + $configs, + $field_type->process_field_config_from_user($input['definition']) + ) + ); + unset($input['definition']); + } +} + +class test +{ + public function test_method() + { + $customer = (object) ['name' => 'Bob']; + $job = (object) ['customer' => $customer]; + + return "The customer for that job, {$job->customer->name} has an error that shows up after the line gets waaaaay toooo long."; + } +} + +class EmptyClass +{ +} + +class EmptyClassWithComments +{ + /* Comment */ +} + +class MyClass implements MyOtherClass +{ +} + +class MyClass implements MyOtherClass, MyOtherClass1, MyOtherClass2 +{ +} + +class MyClass implements + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass +{ +} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyOtherClass +{ +} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + implements MyOtherClass +{ +} + +class MyClass implements + MyOtherClass, + MyOtherClass, + MyOtherOtherOtherClass, + MyOtherOtherOtherOtherClass +{ +} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + implements + MyOtherClass, + MyOtherClass, + MyOtherOtherOtherClass, + MyOtherOtherOtherOtherClass +{ +} + +class EmptyClass extends MyOtherClass +{ +} + +class EmptyClass extends + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass +{ +} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + extends EmptyClass +{ +} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass +{ +} + +class MyClass extends MyOtherClass implements MyI +{ +} + +class MyClass extends MyOtherClass implements MyI, MyII, MyIII +{ +} + +class MyClass extends MyOtherClass implements + VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass +{ +} + +class MyClass extends MyOtherClass implements + MyInterface, + MyOtherInterface, + MyOtherOtherInterface +{ +} + +class MyClass + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + implements MyI +{ +} + +class MyClass + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + implements + MyI, + MyII, + MyIII +{ +} + +class MyClass + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass +{ +} + +class MyClass + extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass + implements + MyI, + MyII, + MyIII +{ +} + +final class BaseClass +{ +} + +abstract class BaseClass +{ +} + +final class BaseClass extends MyOtherClass +{ +} + +abstract class BaseClass extends MyOtherClass +{ +} + +final class BaseClass extends MyOtherVeryVeryVeryVeVeryVeryVeryVeryVeryLongClass +{ +} + +abstract class BaseClass extends MyOtherVeryVeryVeryVeVeryVeryVeryVVeryLongClass +{ +} + +final class BaseClass extends + MyOtherVeryVeryVeryVeVeryVeryVeryVeryVeryLongClass1 +{ +} + +abstract class BaseClass extends + MyOtherVeryVeryVeryVeVeryVeryVeryVVeryLongClass1 +{ +} + +final class BaseClass extends MyOtherClass implements + MyInterface, + MyOtherInterface, + MyOtherOtherInterface +{ +} + +abstract class BaseClass extends MyOtherClass implements + MyInterface, + MyOtherInterface, + MyOtherOtherInterface +{ +} + +class User +{ + public int $id; + public string $name; + public ?string $b = 'foo'; + private Foo $prop; + protected static string $static = 'default'; + + public function __construct(int $id, string $name) + { + $this->id = $id; + $this->name = $name; + } +} diff --git a/testlib/src/main/resources/npm/prettier/plugins/php.dirty b/testlib/src/main/resources/npm/prettier/plugins/php.dirty new file mode 100644 index 0000000000..180e059c84 --- /dev/null +++ b/testlib/src/main/resources/npm/prettier/plugins/php.dirty @@ -0,0 +1,295 @@ +other = $test_string; + $this->current_version = $current_version ?: new Content_Version_Model(); + self::$staticTest = $test_int; + } + + public static function test_static_constructor($test, $test_int, $test_string) { + $model = new self($test, $test_int, $test_string); + $model = new self($really_really_really_really_really_really_really_really_long_array, $test_int, $test_string); + return $model; + } + + public function test_pass_by_reference(&$test) + { + $test + 1; + } + + /** + * This is a function + */ + private function hi($input) { + $test = 1; + + //testing line spacing + $other_test = 2; + + + $one_more_test = 3; + return $input . $this->test; + + } + + public function reallyReallyReallyReallyReallyReallyReallyLongMethodName($input, $otherInput = 1) { + return true; + } + + // doc test + public static function testStaticFunction($input) { + return self::$staticTest[0]; + } + + public function returnTypeTest() : string + { + return 'hi'; + } + + final public static function bar() + { + // Nothing + } + + abstract protected function zim(); + + public function method(iterable $iterable): array { + // Parameter broadened and return type narrowed. + } + + public function method1() { return 'hi'; } + + public function method2() { + return 'hi'; } + + public function method3() + { return 'hi'; } + + public function testReturn(?string $name): ?string + { + return $name; + } + + public function swap(&$left, &$right): void + { + if ($left === $right) { + return; + } + + $tmp = $left; + $left = $right; + $right = $tmp; + } + + public function test(object $obj): object + { + return new SplQueue(); + } + + public function longLongAnotherFunction( + string $foo, + string $bar, + int $baz + ): string { + return 'foo'; + } + + public function longLongAnotherFunctionOther( + string $foo, + string $bar, + int $baz + ) { + return 'foo'; + } + + public function testReturnTypeDeclaration() : object + { + return new SplQueue(); + } + + public function testReturnTypeDeclarationOther() + : + object + { + return new SplQueue(); + } +} + +$this->something->method($argument, $this->more->stuff($this->even->more->things->complicatedMethod())); + +class A {} + +$someVar = new ReaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalyLongClassName(); + +class ClassName + +extends ParentClass + +implements \ArrayAccess, \Countable + +{ + + // constants, properties, methods + +} + +class FooBar { public $property; public $property2; public function method() {} public function method2() {} } + +class FooBarFoo +{ + public function fooBarBaz ( $x,$y ,$z, $foo , $bar ) { /* Comment */ } +} + +class ClassName extends ParentClass implements InterfaceClass {} + +class ClassName extends ParentClass implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 {} + +class ClassName extends ParentClass implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 {} + +class ClassName extends VeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 implements InterfaceClass {} + +class ClassName extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 implements InterfaceClass {} + +class ClassName extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 implements VeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 {} + +class ClassName extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 {} + +class ClassName extends ParentClass implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1,VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName2, VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName3 {} + +class ClassName extends VeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1,VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName2, VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName3 {} + +class ClassName extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1,VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName2, VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName3 {} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFileName1 extends ParentClass implements InterfaceClass {} + +class Custom_Plugin_NotificationPlaceholderSource extends Notification_Manager_DefaultPlaceholderSource {} + +class field extends \models\base +{ + protected function pre_save( $input, $fields ) { + $input['configs'] = json_encode( array_merge( $configs, $field_type->process_field_config_from_user( $input['definition'] ) ) ); + unset( $input['definition'] ); + } +} + +class test { + public function test_method() { + $customer = (object) [ 'name' => 'Bob' ]; + $job = (object) [ 'customer' => $customer ]; + + return "The customer for that job, {$job->customer->name} has an error that shows up after the line gets waaaaay toooo long."; + } +} + +class EmptyClass {} + +class EmptyClassWithComments { /* Comment */ } + +class MyClass implements MyOtherClass {} + +class MyClass implements MyOtherClass, MyOtherClass1, MyOtherClass2 {} + +class MyClass implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass {} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyOtherClass {} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass implements MyOtherClass {} + +class MyClass implements MyOtherClass, MyOtherClass, MyOtherOtherOtherClass, MyOtherOtherOtherOtherClass {} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass implements MyOtherClass, MyOtherClass, MyOtherOtherOtherClass, MyOtherOtherOtherOtherClass {} + +class EmptyClass extends MyOtherClass {} + +class EmptyClass extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass {} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass extends EmptyClass {} + +class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass {} + +class MyClass extends MyOtherClass implements MyI {} + +class MyClass extends MyOtherClass implements MyI, MyII, MyIII {} + +class MyClass extends MyOtherClass implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass {} + +class MyClass extends MyOtherClass implements MyInterface, MyOtherInterface, MyOtherOtherInterface {} + +class MyClass extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass implements MyI {} + +class MyClass extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass implements MyI, MyII, MyIII {} + +class MyClass extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass implements VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass {} + +class MyClass extends VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongMyClass implements MyI, MyII, MyIII {} + +final class BaseClass {} + +abstract class BaseClass {} + +final class BaseClass extends MyOtherClass {} + +abstract class BaseClass extends MyOtherClass {} + +final class BaseClass extends MyOtherVeryVeryVeryVeVeryVeryVeryVeryVeryLongClass {} + +abstract class BaseClass extends MyOtherVeryVeryVeryVeVeryVeryVeryVVeryLongClass {} + +final class BaseClass extends MyOtherVeryVeryVeryVeVeryVeryVeryVeryVeryLongClass1 {} + +abstract class BaseClass extends MyOtherVeryVeryVeryVeVeryVeryVeryVVeryLongClass1 {} + +final class BaseClass extends MyOtherClass implements MyInterface, MyOtherInterface, MyOtherOtherInterface {} + +abstract class BaseClass extends MyOtherClass implements MyInterface, MyOtherInterface, MyOtherOtherInterface {} + +class User { + public int $id; + public string $name; + public ?string $b = 'foo'; + private Foo $prop; + protected static string $static = 'default'; + + public function __construct(int $id, string $name) { + $this->id = $id; + $this->name = $name; + } +} \ No newline at end of file