diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index 9931b5a5..f8dca5f8 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -128,6 +128,7 @@ jobs:
php-version:
- "7.1"
- "7.4"
+ - "8.0"
steps:
- name: "Checkout"
diff --git a/Makefile b/Makefile
index 34ee7f25..d9e97c04 100644
--- a/Makefile
+++ b/Makefile
@@ -1,27 +1,36 @@
.PHONY: test test-report test-fix update-compatibility-patch
-PHP_74_OR_NEWER:=$(shell php -r "echo (int) version_compare(PHP_VERSION, '7.4', '>=');")
+PHP_VERSION:=$(shell php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;")
+PATCH_FILE="tests/php$(PHP_VERSION)-compatibility.patch"
test: test-report test-fix
test-report: vendor
- @if [ $(PHP_74_OR_NEWER) -eq 1 ]; then git apply tests/php-compatibility.patch; fi
- @vendor/bin/phpcs `find tests/input/* | sort` --report=summary --report-file=phpcs.log; diff -u tests/expected_report.txt phpcs.log; if [ $$? -ne 0 ]; then if [ $(PHP_74_OR_NEWER) -eq 1 ]; then git apply -R tests/php-compatibility.patch; fi; exit 1; fi
- @if [ $(PHP_74_OR_NEWER) -eq 1 ]; then git apply -R tests/php-compatibility.patch; fi
+ @if [ -f "$(PATCH_FILE)" ]; then git apply $(PATCH_FILE) ; fi
+ @vendor/bin/phpcs `find tests/input/* | sort` --report=summary --report-file=phpcs.log; diff -u tests/expected_report.txt phpcs.log; if [ $$? -ne 0 ] && [ -f "$(PATCH_FILE)" ]; then git apply -R $(PATCH_FILE) ; exit 1; fi
+ @if [ -f "$(PATCH_FILE)" ]; then git apply -R $(PATCH_FILE) ; fi
test-fix: vendor
- @if [ $(PHP_74_OR_NEWER) -eq 1 ]; then git apply tests/php-compatibility.patch; fi
+ @if [ -f "$(PATCH_FILE)" ]; then git apply $(PATCH_FILE) ; fi
@cp -R tests/input/ tests/input2/
- @vendor/bin/phpcbf tests/input2; diff -u tests/input2 tests/fixed; if [ $$? -ne 0 ]; then rm -rf tests/input2/ && if [ $(PHP_74_OR_NEWER) -eq 1 ]; then git apply -R tests/php-compatibility.patch; fi; exit 1; fi
- @rm -rf tests/input2/ && if [ $(PHP_74_OR_NEWER) -eq 1 ]; then git apply -R tests/php-compatibility.patch; fi
+ @vendor/bin/phpcbf tests/input2; diff -u tests/input2 tests/fixed; if [ $$? -ne 0 ]; then rm -rf tests/input2/; if [ -f "$(PATCH_FILE)" ]; then git apply -R $(PATCH_FILE) ; fi; exit 1; fi
+ @rm -rf tests/input2/;
+ @if [ -f "$(PATCH_FILE)" ]; then git apply -R $(PATCH_FILE) ; fi
-update-compatibility-patch:
+update-compatibility-patch-74:
@git apply tests/php-compatibility.patch
@printf "Please open your editor and apply your changes\n"
@until [ "$${compatibility_resolved}" == "y" ]; do read -p "Have finished your changes (y|n)? " compatibility_resolved; done && compatibility_resolved=
@git diff -- tests/expected_report.txt tests/fixed > .tmp-patch && mv .tmp-patch tests/php-compatibility.patch && git apply -R tests/php-compatibility.patch
@git commit -m 'Update compatibility patch' tests/php-compatibility.patch
+update-compatibility-patch-80:
+ @git apply tests/php80-compatibility.patch
+ @printf "Please open your editor and apply your changes\n"
+ @until [ "$${compatibility_resolved}" == "y" ]; do read -p "Have finished your changes (y|n)? " compatibility_resolved; done && compatibility_resolved=
+ @git diff -- tests/expected_report.txt tests/fixed > .tmp-patch-80 && mv .tmp-patch-80 tests/php80-compatibility.patch && git apply -R tests/php80-compatibility.patch
+ @git commit -m 'Update compatibility patch' tests/php80-compatibility.patch
+
vendor: composer.json
composer update
touch -c vendor
diff --git a/lib/Doctrine/ruleset.xml b/lib/Doctrine/ruleset.xml
index 50809b49..d841c154 100644
--- a/lib/Doctrine/ruleset.xml
+++ b/lib/Doctrine/ruleset.xml
@@ -266,6 +266,8 @@
+
+
diff --git a/tests/fixed/null_safe_operator.php b/tests/fixed/null_safe_operator.php
new file mode 100644
index 00000000..5bbb636c
--- /dev/null
+++ b/tests/fixed/null_safe_operator.php
@@ -0,0 +1,5 @@
+property;
diff --git a/tests/input/null_safe_operator.php b/tests/input/null_safe_operator.php
new file mode 100644
index 00000000..5bbb636c
--- /dev/null
+++ b/tests/input/null_safe_operator.php
@@ -0,0 +1,5 @@
+property;
diff --git a/tests/php-compatibility.patch b/tests/php74-compatibility.patch
similarity index 100%
rename from tests/php-compatibility.patch
rename to tests/php74-compatibility.patch
diff --git a/tests/php80-compatibility.patch b/tests/php80-compatibility.patch
new file mode 100644
index 00000000..7cceac94
--- /dev/null
+++ b/tests/php80-compatibility.patch
@@ -0,0 +1,165 @@
+diff --git a/tests/expected_report.txt b/tests/expected_report.txt
+index c644926..d0f0a44 100644
+--- a/tests/expected_report.txt
++++ b/tests/expected_report.txt
+@@ -15,18 +15,19 @@ tests/input/ControlStructures.php 28 0
+ tests/input/doc-comment-spacing.php 11 0
+ tests/input/duplicate-assignment-variable.php 1 0
+ tests/input/EarlyReturn.php 6 0
+-tests/input/example-class.php 38 0
++tests/input/example-class.php 42 0
+ tests/input/forbidden-comments.php 14 0
+ tests/input/forbidden-functions.php 6 0
+ tests/input/inline_type_hint_assertions.php 7 0
+ tests/input/LowCaseTypes.php 2 0
+ tests/input/namespaces-spacing.php 7 0
+-tests/input/NamingCamelCase.php 6 0
++tests/input/NamingCamelCase.php 9 0
+ tests/input/negation-operator.php 2 0
+-tests/input/new_with_parentheses.php 18 0
++tests/input/new_with_parentheses.php 19 0
+ tests/input/not_spacing.php 8 0
+-tests/input/null_coalesce_equal_operator.php 1 0
++tests/input/null_coalesce_equal_operator.php 5 0
+ tests/input/null_coalesce_operator.php 3 0
++tests/input/null_safe_operator.php 1 0
+ tests/input/optimized-functions.php 1 0
+ tests/input/PropertyTypeHintSpacing.php 6 0
+ tests/input/return_type_on_closures.php 21 0
+@@ -39,15 +40,15 @@ tests/input/superfluous-naming.php 11 0
+ tests/input/test-case.php 8 0
+ tests/input/trailing_comma_on_array.php 1 0
+ tests/input/traits-uses.php 11 0
+-tests/input/type-hints.php 4 0
++tests/input/type-hints.php 5 0
+ tests/input/UnusedVariables.php 1 0
+ tests/input/use-ordering.php 1 0
+ tests/input/useless-semicolon.php 2 0
+ tests/input/UselessConditions.php 20 0
+ ----------------------------------------------------------------------
+-A TOTAL OF 377 ERRORS AND 0 WARNINGS WERE FOUND IN 41 FILES
++A TOTAL OF 391 ERRORS AND 0 WARNINGS WERE FOUND IN 42 FILES
+ ----------------------------------------------------------------------
+-PHPCBF CAN FIX 313 OF THESE SNIFF VIOLATIONS AUTOMATICALLY
++PHPCBF CAN FIX 327 OF THESE SNIFF VIOLATIONS AUTOMATICALLY
+ ----------------------------------------------------------------------
+
+
+diff --git a/tests/fixed/NamingCamelCase.php b/tests/fixed/NamingCamelCase.php
+index 57d9f2b..5493471 100644
+--- a/tests/fixed/NamingCamelCase.php
++++ b/tests/fixed/NamingCamelCase.php
+@@ -6,14 +6,11 @@ namespace Example;
+
+ class NamingCamelCase
+ {
+- /** @var mixed */
+- public $A;
++ public mixed $A;
+
+- /** @var mixed */
+- protected $B;
++ protected mixed $B;
+
+- /** @var mixed */
+- private $C;
++ private mixed $C;
+
+ public function fcn(string $A): void
+ {
+diff --git a/tests/fixed/example-class.php b/tests/fixed/example-class.php
+index 998e51d..b47d358 100644
+--- a/tests/fixed/example-class.php
++++ b/tests/fixed/example-class.php
+@@ -25,17 +25,14 @@ class Example implements IteratorAggregate
+ {
+ private const VERSION = PHP_VERSION - (PHP_MINOR_VERSION * 100) - PHP_PATCH_VERSION;
+
+- /** @var int|null */
+- private $foo;
++ private ?int $foo = null;
+
+ /** @var string[] */
+- private $bar;
++ private array $bar;
+
+- /** @var bool */
+- private $baz;
++ private bool $baz;
+
+- /** @var ControlStructureSniff|int|string|null */
+- private $baxBax;
++ private ControlStructureSniff|int|string|null $baxBax = null;
+
+ public function __construct(?int $foo = null, array $bar = [], bool $baz = false, $baxBax = 'unused')
+ {
+diff --git a/tests/fixed/new_with_parentheses.php b/tests/fixed/new_with_parentheses.php
+index 6e81bbe..47a06ec 100644
+--- a/tests/fixed/new_with_parentheses.php
++++ b/tests/fixed/new_with_parentheses.php
+@@ -24,5 +24,5 @@ $y = [new stdClass()];
+
+ $z = new stdClass() ? new stdClass() : new stdClass();
+
+-$q = $q ?: new stdClass();
+-$e = $e ?? new stdClass();
++$q = $q ?: new stdClass();
++$e ??= new stdClass();
+diff --git a/tests/fixed/null_coalesce_equal_operator.php b/tests/fixed/null_coalesce_equal_operator.php
+index b997469..6703d30 100644
+--- a/tests/fixed/null_coalesce_equal_operator.php
++++ b/tests/fixed/null_coalesce_equal_operator.php
+@@ -2,12 +2,12 @@
+
+ declare(strict_types=1);
+
+-$bar = $bar ?? 'bar';
++$bar ??= 'bar';
+
+-$bar['baz'] = $bar['baz'] ?? 'baz';
++$bar['baz'] ??= 'baz';
+
+-$bar = $bar ?? 'bar';
++$bar ??= 'bar';
+
+-$object->property = $object->property ?? 'Default Value';
++$object->property ??= 'Default Value';
+
+-Test::$foo = Test::$foo ?? 123;
++Test::$foo ??= 123;
+diff --git a/tests/fixed/null_coalesce_operator.php b/tests/fixed/null_coalesce_operator.php
+index 8846dd1..51c361c 100644
+--- a/tests/fixed/null_coalesce_operator.php
++++ b/tests/fixed/null_coalesce_operator.php
+@@ -4,7 +4,7 @@ declare(strict_types=1);
+
+ $foo = $_GET['foo'] ?? 'foo';
+
+-$bar = $bar ?? 'bar';
++$bar ??= 'bar';
+
+ $bar = $bar['baz'] ?? 'baz';
+
+diff --git a/tests/fixed/null_safe_operator.php b/tests/fixed/null_safe_operator.php
+index 5bbb636..7ce8a3d 100644
+--- a/tests/fixed/null_safe_operator.php
++++ b/tests/fixed/null_safe_operator.php
+@@ -2,4 +2,4 @@
+
+ declare(strict_types=1);
+
+-$var = $object === null ? null : $object->property;
++$var = $object?->property;
+diff --git a/tests/fixed/type-hints.php b/tests/fixed/type-hints.php
+index 0e952fc..9824fb0 100644
+--- a/tests/fixed/type-hints.php
++++ b/tests/fixed/type-hints.php
+@@ -10,7 +10,7 @@ use Traversable;
+ class TraversableTypeHints
+ {
+ /** @var Traversable */
+- private $parameter;
++ private Traversable $parameter;
+
+ /**
+ * @param Iterator $iterator