From 9f8c415b8aedfab3b40f7c9cd21c321b45694375 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Thu, 15 Dec 2022 18:28:25 +0100 Subject: [PATCH 01/17] Support for PHP 8.2 stable --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5a9c675..f4b9777 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ define PHP_VERSIONS "7.4 3.1.1"\ "8.0 3.1.1"\ "8.1 3.1.1"\ -"8.2-rc 3.2.0alpha3" +"8.2 3.2.0" endef define DOCKER_RUN From fa261d25231c8bfe1ea0a29da9033f575d0860a8 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Tue, 20 Dec 2022 12:59:40 +0100 Subject: [PATCH 02/17] Test with iterator_count() --- test/JsonMachineTest/ItemsTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/JsonMachineTest/ItemsTest.php b/test/JsonMachineTest/ItemsTest.php index d0d06d7..9c4ab18 100644 --- a/test/JsonMachineTest/ItemsTest.php +++ b/test/JsonMachineTest/ItemsTest.php @@ -139,4 +139,11 @@ class ItemsTest extends \PHPUnit_Framework_TestCase $this->assertSame(['/one', '/two'], $items->getJsonPointers()); } + + public function testCountViaIteratorCount() + { + $items = Items::fromIterable(['{"results":', '[1,2,3]}'], ['pointer' => ['/results']]); + + $this->assertSame(3, iterator_count($items)); + } } From 68f51511fc12fae735f0da8d6db2b113eeb50fdb Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Thu, 4 May 2023 11:56:37 +0200 Subject: [PATCH 03/17] Performance testing with JIT enabled --- build/build-image.sh | 1 + composer.json | 2 +- test/performance/testPerformance.php | 18 ++++++++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/build/build-image.sh b/build/build-image.sh index 223552e..d9e1835 100755 --- a/build/build-image.sh +++ b/build/build-image.sh @@ -31,6 +31,7 @@ printf " && wget http://pear.php.net/go-pear.phar && php go-pear.phar \ && pecl install xdebug-$XDEBUG_VERSION \ && docker-php-ext-enable xdebug \ + && docker-php-ext-enable opcache \ && wget https://getcomposer.org/download/2.2.18/composer.phar -O /usr/local/bin/composer \ && chmod +x /usr/local/bin/composer " | docker build --quiet --tag "$CONTAINER_NAME" - > /dev/null diff --git a/composer.json b/composer.json index c50c538..8d8ff16 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "tests-coverage": "build/composer-update.sh && XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-clover clover.xml", "cs-check": "build/composer-update.sh && vendor/bin/php-cs-fixer fix --dry-run --verbose --allow-risky=yes", "cs-fix": "build/composer-update.sh && vendor/bin/php-cs-fixer fix --verbose --allow-risky=yes", - "performance-tests": "php -n test/performance/testPerformance.php" + "performance-tests": "php -d xdebug.mode=off -d opcache.enable_cli=1 -d opcache.jit_buffer_size=100M test/performance/testPerformance.php" }, "config": { "lock": false, diff --git a/test/performance/testPerformance.php b/test/performance/testPerformance.php index a851487..fc7c50f 100644 --- a/test/performance/testPerformance.php +++ b/test/performance/testPerformance.php @@ -6,8 +6,22 @@ use JsonMachine\Items; require_once __DIR__.'/../../vendor/autoload.php'; -if (in_array('xdebug', get_loaded_extensions())) { - trigger_error('Xdebug enabled. Results may be affected.', E_USER_WARNING); +if ( ! ini_get('xdebug.mode')) { + echo "Xdebug disabled\n"; +} else { + echo "Xdebug enabled\n"; +} + +if ( ! function_exists('opcache_get_status')) { + echo "Opcache disabled\n"; + echo "JIT disabled\n"; +} else { + echo "Opcache enabled\n"; + if (opcache_get_status()['jit']['enabled']) { + echo "JIT enabled\n"; + } else { + echo "JIT disabled\n"; + } } ini_set('memory_limit', '-1'); // for json_decode use case From 403dcbc26e25625cda70fccd830e6fa2508e5d86 Mon Sep 17 00:00:00 2001 From: Anton Ukhanev Date: Thu, 14 Sep 2023 12:54:42 +0200 Subject: [PATCH 04/17] `testToArrayReturnsJsonPointers()` now uses a data provider --- test/JsonMachineTest/ValidJsonPointersTest.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/test/JsonMachineTest/ValidJsonPointersTest.php b/test/JsonMachineTest/ValidJsonPointersTest.php index f92a78b..48fbf84 100644 --- a/test/JsonMachineTest/ValidJsonPointersTest.php +++ b/test/JsonMachineTest/ValidJsonPointersTest.php @@ -70,11 +70,21 @@ class ValidJsonPointersTest extends \PHPUnit_Framework_TestCase (new ValidJsonPointers(['/one', '/one']))->toArray(); } - public function testToArrayReturnsJsonPointers() + /** + * @dataProvider data_testToArrayReturnsJsonPointers + */ + public function testToArrayReturnsJsonPointers(string $pointerA, string $pointerB) { $this->assertSame( - ['/one', '/two'], - (new ValidJsonPointers(['/one', '/two']))->toArray() + [$pointerA, $pointerB], + (new ValidJsonPointers([$pointerA, $pointerB]))->toArray() ); } + + public function data_testToArrayReturnsJsonPointers() + { + return [ + ['/one', '/two'], + ]; + } } From 536481ae4faf27d70f4f36c69d136eb967e9164f Mon Sep 17 00:00:00 2001 From: Anton Ukhanev Date: Thu, 14 Sep 2023 12:55:56 +0200 Subject: [PATCH 05/17] Add test to demonstrate 2 non-conflicting pointers seen as conflicting --- test/JsonMachineTest/ValidJsonPointersTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/JsonMachineTest/ValidJsonPointersTest.php b/test/JsonMachineTest/ValidJsonPointersTest.php index 48fbf84..041c880 100644 --- a/test/JsonMachineTest/ValidJsonPointersTest.php +++ b/test/JsonMachineTest/ValidJsonPointersTest.php @@ -85,6 +85,8 @@ class ValidJsonPointersTest extends \PHPUnit_Framework_TestCase { return [ ['/one', '/two'], + ['/companies/-/id', '/companies/0/idempotency_key'], + ['/companies/1/id', '/companies/1/idempotency_key'], ]; } } From 716fb33b7836c9107883296a8bde1003eb0d8022 Mon Sep 17 00:00:00 2001 From: Anton Ukhanev Date: Thu, 14 Sep 2023 12:57:58 +0200 Subject: [PATCH 06/17] Path separator now terminates pointers when compared for intersection This fixes halaxa/json-machine#106. --- src/ValidJsonPointers.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ValidJsonPointers.php b/src/ValidJsonPointers.php index 9bece75..7a7b44a 100644 --- a/src/ValidJsonPointers.php +++ b/src/ValidJsonPointers.php @@ -64,8 +64,8 @@ final class ValidJsonPointers continue; } if ($jsonPointerA === $jsonPointerB - || self::str_contains($jsonPointerA, $jsonPointerB) - || self::str_contains($jsonPointerA, self::wildcardify($jsonPointerB)) + || self::str_contains("$jsonPointerA/", "$jsonPointerB/") + || self::str_contains("$jsonPointerA/", self::wildcardify("$jsonPointerB/")) ) { throw new InvalidArgumentException( sprintf( From a7091c705032eab36d121197ee2989495becd487 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Sat, 18 Nov 2023 17:27:39 +0100 Subject: [PATCH 07/17] Added missing @throws annotations --- src/FileChunks.php | 1 + src/Items.php | 10 ++++++++++ src/ItemsOptions.php | 3 +++ src/Parser.php | 6 ++++++ src/StreamChunks.php | 3 ++- 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/FileChunks.php b/src/FileChunks.php index 26d170f..f3c7fee 100644 --- a/src/FileChunks.php +++ b/src/FileChunks.php @@ -24,6 +24,7 @@ class FileChunks implements \IteratorAggregate /** * @return \Generator + * @throws Exception\InvalidArgumentException */ #[\ReturnTypeWillChange] public function getIterator() diff --git a/src/Items.php b/src/Items.php index 1dfb958..6787a5f 100644 --- a/src/Items.php +++ b/src/Items.php @@ -117,6 +117,7 @@ final class Items implements \IteratorAggregate, PositionAware /** * @return \Generator + * @throws Exception\PathNotFoundException */ #[\ReturnTypeWillChange] public function getIterator() @@ -124,6 +125,9 @@ final class Items implements \IteratorAggregate, PositionAware return $this->parser->getIterator(); } + /** + * @throws Exception\JsonMachineException + */ public function getPosition() { return $this->parser->getPosition(); @@ -134,11 +138,17 @@ final class Items implements \IteratorAggregate, PositionAware return $this->parser->getJsonPointers(); } + /** + * @throws Exception\JsonMachineException + */ public function getCurrentJsonPointer(): string { return $this->parser->getCurrentJsonPointer(); } + /** + * @throws Exception\JsonMachineException + */ public function getMatchedJsonPointer(): string { return $this->parser->getMatchedJsonPointer(); diff --git a/src/ItemsOptions.php b/src/ItemsOptions.php index 0e528b9..e0b9d68 100644 --- a/src/ItemsOptions.php +++ b/src/ItemsOptions.php @@ -12,6 +12,9 @@ class ItemsOptions extends \ArrayObject { private $options = []; + /** + * @throws InvalidArgumentException + */ public function __construct(array $options = []) { $this->validateOptions($options); diff --git a/src/Parser.php b/src/Parser.php index 8a18265..c4a6b55 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -321,6 +321,9 @@ class Parser implements \IteratorAggregate, PositionAware return array_values($this->jsonPointers); } + /** + * @throws JsonMachineException + */ public function getCurrentJsonPointer(): string { if ($this->currentPath === null) { @@ -330,6 +333,9 @@ class Parser implements \IteratorAggregate, PositionAware return self::pathToJsonPointer($this->currentPath); } + /** + * @throws JsonMachineException + */ public function getMatchedJsonPointer(): string { if ($this->matchedJsonPointer === null) { diff --git a/src/StreamChunks.php b/src/StreamChunks.php index d6c6e72..2733433 100644 --- a/src/StreamChunks.php +++ b/src/StreamChunks.php @@ -16,7 +16,8 @@ class StreamChunks implements \IteratorAggregate /** * @param resource $stream - * @param int $chunkSize + * @param int $chunkSize + * @throws InvalidArgumentException */ public function __construct($stream, $chunkSize = 1024 * 8) { From 1b3aa897fa552896ee4af7d4e021346178c837d6 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Sat, 18 Nov 2023 19:05:57 +0100 Subject: [PATCH 08/17] build fix --- build/build-image.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build/build-image.sh b/build/build-image.sh index d9e1835..bef1785 100755 --- a/build/build-image.sh +++ b/build/build-image.sh @@ -21,7 +21,12 @@ docker ps --all --format "{{.Names}}" | grep "$CONTAINER_NAME" && docker rm -f " printf " FROM $FROM_IMAGE - RUN apk add --update \ + RUN apk update && apk upgrade + # https://stackoverflow.com/questions/76507083/pecl-install-no-releases-available#comment136513209_76651916 + RUN rm /etc/ssl/certs/ca-cert-DST_Root_CA_X3.pem || true \ + && cat /etc/ssl/certs/*.pem > /etc/ssl/certs/ca-certificates.crt \ + && cat /etc/ssl/certs/*.pem > /etc/ssl/cert.pem + RUN apk add \ autoconf \ g++ \ libtool \ From 8a6178d0adbdd12dc1bd673acf75cefb262bb8d3 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Sat, 18 Nov 2023 19:36:19 +0100 Subject: [PATCH 09/17] make cs-fix --- src/FileChunks.php | 1 + src/Items.php | 1 + src/StreamChunks.php | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/FileChunks.php b/src/FileChunks.php index f3c7fee..3085a1a 100644 --- a/src/FileChunks.php +++ b/src/FileChunks.php @@ -24,6 +24,7 @@ class FileChunks implements \IteratorAggregate /** * @return \Generator + * * @throws Exception\InvalidArgumentException */ #[\ReturnTypeWillChange] diff --git a/src/Items.php b/src/Items.php index 6787a5f..03568b0 100644 --- a/src/Items.php +++ b/src/Items.php @@ -117,6 +117,7 @@ final class Items implements \IteratorAggregate, PositionAware /** * @return \Generator + * * @throws Exception\PathNotFoundException */ #[\ReturnTypeWillChange] diff --git a/src/StreamChunks.php b/src/StreamChunks.php index 2733433..da8502e 100644 --- a/src/StreamChunks.php +++ b/src/StreamChunks.php @@ -16,7 +16,8 @@ class StreamChunks implements \IteratorAggregate /** * @param resource $stream - * @param int $chunkSize + * @param int $chunkSize + * * @throws InvalidArgumentException */ public function __construct($stream, $chunkSize = 1024 * 8) From 5c1d6c1d63ba7e09f1a38ee17320cd20d5fa8047 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Sat, 18 Nov 2023 21:46:57 +0100 Subject: [PATCH 10/17] Issue #108 test (url with utf-8 decoding) --- test/JsonMachineTest/ParserTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/JsonMachineTest/ParserTest.php b/test/JsonMachineTest/ParserTest.php index 6065450..af12ede 100644 --- a/test/JsonMachineTest/ParserTest.php +++ b/test/JsonMachineTest/ParserTest.php @@ -48,6 +48,11 @@ class ParserTest extends \PHPUnit_Framework_TestCase ['', '[{"c":1},"string",{"d":2},false]', [[0 => ['c' => 1]], [1 => 'string'], [2 => ['d' => 2]], [3 => false]]], ['', '[false,{"c":1},"string",{"d":2}]', [[0 => false], [1 => ['c' => 1]], [2 => 'string'], [3 => ['d' => 2]]]], ['', '[{"c":1,"d":2}]', [[['c' => 1, 'd' => 2]]]], + 'ISSUE-108' => [ + '', + '["https://click.justwatch.com/a?cx=eyJzY2hlbWEiOiJpZ2x1OmNvbS5zbm93cGxvd2FuYWx5dGljcy5zbm93cGxvdy9jb250ZXh0cy9qc29uc2NoZW1hLzEtMC0wIiwiZGF0YSI6W3sic2NoZW1hIjoiaWdsdTpjb20uanVzdHdhdGNoL2NsaWNrb3V0X2NvbnRleHQvanNvbnNjaGVtYS8xLTItMCIsImRhdGEiOnsicHJvdmlkZXIiOiJBcHBsZSBUViIsIm1vbmV0aXphdGlvblR5cGUiOiJidXkiLCJwcmVzZW50YXRpb25UeXBlIjoiaGQiLCJjdXJyZW5jeSI6IlVTRCIsInByaWNlIjo1MTkuNzQsIm9yaWdpbmFsUHJpY2UiOjAsImF1ZGlvTGFuZ3VhZ2UiOiIiLCJzdWJ0aXRsZUxhbmd1YWdlIjoiIiwiY2luZW1hSWQiOjAsInNob3d0aW1lIjoiIiwiaXNGYXZvcml0ZUNpbmVtYSI6ZmFsc2UsInBhcnRuZXJJZCI6MTI3MCwicHJvdmlkZXJJZCI6MiwiY2xpY2tvdXRUeXBlIjoianctY29udGVudC1wYXJ0bmVyLWFwaSJ9fSx7InNjaGVtYSI6ImlnbHU6Y29tLmp1c3R3YXRjaC90aXRsZV9jb250ZXh0L2pzb25zY2hlbWEvMS0wLTAiLCJkYXRhIjp7InRpdGxlSWQiOjIwOTgxLCJvYmplY3RUeXBlIjoic2hvdyIsImp3RW50aXR5SWQiOiJ0czIwOTgxIn19XX0\u0026r=https%3A%2F%2Ftv.apple.com%2Fus%2Fshow%2Fsurvivor%2Fumc.cmc.6ozd0mt09a86bpa19l885jv4z\u0026uct_country=us"]', + [['https://click.justwatch.com/a?cx=eyJzY2hlbWEiOiJpZ2x1OmNvbS5zbm93cGxvd2FuYWx5dGljcy5zbm93cGxvdy9jb250ZXh0cy9qc29uc2NoZW1hLzEtMC0wIiwiZGF0YSI6W3sic2NoZW1hIjoiaWdsdTpjb20uanVzdHdhdGNoL2NsaWNrb3V0X2NvbnRleHQvanNvbnNjaGVtYS8xLTItMCIsImRhdGEiOnsicHJvdmlkZXIiOiJBcHBsZSBUViIsIm1vbmV0aXphdGlvblR5cGUiOiJidXkiLCJwcmVzZW50YXRpb25UeXBlIjoiaGQiLCJjdXJyZW5jeSI6IlVTRCIsInByaWNlIjo1MTkuNzQsIm9yaWdpbmFsUHJpY2UiOjAsImF1ZGlvTGFuZ3VhZ2UiOiIiLCJzdWJ0aXRsZUxhbmd1YWdlIjoiIiwiY2luZW1hSWQiOjAsInNob3d0aW1lIjoiIiwiaXNGYXZvcml0ZUNpbmVtYSI6ZmFsc2UsInBhcnRuZXJJZCI6MTI3MCwicHJvdmlkZXJJZCI6MiwiY2xpY2tvdXRUeXBlIjoianctY29udGVudC1wYXJ0bmVyLWFwaSJ9fSx7InNjaGVtYSI6ImlnbHU6Y29tLmp1c3R3YXRjaC90aXRsZV9jb250ZXh0L2pzb25zY2hlbWEvMS0wLTAiLCJkYXRhIjp7InRpdGxlSWQiOjIwOTgxLCJvYmplY3RUeXBlIjoic2hvdyIsImp3RW50aXR5SWQiOiJ0czIwOTgxIn19XX0&r=https%3A%2F%2Ftv.apple.com%2Fus%2Fshow%2Fsurvivor%2Fumc.cmc.6ozd0mt09a86bpa19l885jv4z&uct_country=us']], + ], ['/', '{"":{"c":1,"d":2}}', [['c' => 1], ['d' => 2]]], ['/~0', '{"~":{"c":1,"d":2}}', [['c' => 1], ['d' => 2]]], ['/~1', '{"/":{"c":1,"d":2}}', [['c' => 1], ['d' => 2]]], From 52b913c7f143f4f85f7e4978fcd9d64f6c8d9e07 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Sat, 18 Nov 2023 23:13:17 +0100 Subject: [PATCH 11/17] Build support for php 8.3 --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f4b9777..715cb2f 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,8 @@ define PHP_VERSIONS "7.4 3.1.1"\ "8.0 3.1.1"\ "8.1 3.1.1"\ -"8.2 3.2.0" +"8.2 3.2.0"\ +"8.3-rc 3.3.0alpha3" endef define DOCKER_RUN From 8d583e9765b9e78bc81897f8b98feb734ddd4937 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Sun, 19 Nov 2023 13:39:04 +0100 Subject: [PATCH 12/17] README heading --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2a42cca..bd288ee 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ - - -(README in sync with the code) +# JSON Machine Very easy to use and memory efficient drop-in replacement for inefficient iteration of big JSON files or streams -for PHP >=7.0. See [TL;DR](#tl-dr). No dependencies in production except optional `ext-json`. +for PHP >=7.0. See [TL;DR](#tl-dr). No dependencies in production except optional `ext-json`. README in sync with the code [![Build Status](https://github.com/halaxa/json-machine/actions/workflows/makefile.yml/badge.svg)](https://github.com/halaxa/json-machine/actions) [![codecov](https://img.shields.io/codecov/c/gh/halaxa/json-machine?label=phpunit%20%40covers)](https://codecov.io/gh/halaxa/json-machine) From fd08806159aa5342da401a668e6d5508a69fd330 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Wed, 15 Nov 2023 14:21:24 +0100 Subject: [PATCH 13/17] Phpstan level 5 --- Makefile | 25 +++++++++++-------- composer.json | 2 ++ phpstan.neon | 21 ++++++++++++++++ src/Exception/SyntaxErrorException.php | 2 +- src/FileChunks.php | 3 +++ src/Parser.php | 8 +++--- src/StreamChunks.php | 3 +++ src/TokensWithDebugging.php | 13 ++++++++-- src/ValidJsonPointers.php | 13 ++++++++++ src/autoloader.php | 5 +++- .../Exception/SyntaxErrorExceptionTest.php | 2 +- .../JsonDecoder/DecodingErrorTest.php | 2 +- test/JsonMachineTest/StreamChunksTest.php | 1 + .../JsonMachineTest/ValidJsonPointersTest.php | 1 - 14 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 phpstan.neon diff --git a/Makefile b/Makefile index 715cb2f..965027a 100644 --- a/Makefile +++ b/Makefile @@ -30,16 +30,15 @@ help: @grep -E '^[-a-zA-Z0-9_\.\/]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[32m%-15s\033[0m\t%s\n", $$1, $$2}' -build: tests-all cs-check ## Run all necessary stuff before commit. +build: tests-all cs-check phpstan ## Run all necessary stuff before commit. -tests: CMD=composer tests -- $(ARGS) -tests: docker-run ## Run tests on recent PHP version. Pass args to phpunit via ARGS="" +tests: ## Run tests on recent PHP version. Pass args to phpunit via ARGS="" + @$(call DOCKER_RUN,$(COVERAGE_PHP),composer tests -- $(ARGS)) -tests-coverage: CMD=composer tests-coverage -- $(ARGS) tests-coverage: ## Runs tests and creates ./clover.xml. Pass args to phpunit via ARGS="" - @$(call DOCKER_RUN,$(COVERAGE_PHP),$(CMD)) + @$(call DOCKER_RUN,$(COVERAGE_PHP),composer tests-coverage -- $(ARGS)) tests-all: ## Run tests on all supported PHP versions. Pass args to phpunit via ARGS="" @@ -52,16 +51,20 @@ tests-all: ## Run tests on all supported PHP versions. Pass args to phpunit via done -cs-check: CMD=composer cs-check -cs-check: docker-run ## Check code style +cs-check: ## Check code style + @$(call DOCKER_RUN,$(LATEST_PHP),composer cs-check) -cs-fix: CMD=composer cs-fix -cs-fix: docker-run ## Fix code style +phpstan: ## Run phpstan + @$(call DOCKER_RUN,$(LATEST_PHP),composer phpstan) -performance-tests: CMD=composer performance-tests -performance-tests: docker-run ## Run performance tests +cs-fix: ## Fix code style + @$(call DOCKER_RUN,$(LATEST_PHP),composer cs-fix) + + +performance-tests: ## Run performance tests + @$(call DOCKER_RUN,$(LATEST_PHP),composer performance-tests) release: .env build diff --git a/composer.json b/composer.json index 8d8ff16..61d9dc0 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "tests-coverage": "build/composer-update.sh && XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-clover clover.xml", "cs-check": "build/composer-update.sh && vendor/bin/php-cs-fixer fix --dry-run --verbose --allow-risky=yes", "cs-fix": "build/composer-update.sh && vendor/bin/php-cs-fixer fix --verbose --allow-risky=yes", + "phpstan": "build/composer-update.sh && vendor/bin/phpstan analyse", "performance-tests": "php -d xdebug.mode=off -d opcache.enable_cli=1 -d opcache.jit_buffer_size=100M test/performance/testPerformance.php" }, "config": { @@ -25,6 +26,7 @@ "require-dev": { "ext-json": "*", "friendsofphp/php-cs-fixer": "^3.0", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^8.0" }, "suggest": { diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..628eda7 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,21 @@ +parameters: + level: 5 + paths: + - src + - test + bootstrapFiles: + - %rootDir%/../../../test/bootstrap.php + treatPhpDocTypesAsCertain: false + exceptions: + implicitThrows: false + check: + missingCheckedExceptionInThrows: true + tooWideThrowType: true + reportUncheckedExceptionDeadCatch: true + checkedExceptionClasses: + - JsonMachine\Exception\PathNotFoundException + - JsonMachine\Exception\SyntaxErrorException + - JsonMachine\Exception\UnexpectedEndSyntaxErrorException + uncheckedExceptionClasses: + - JsonMachine\Exception\InvalidArgumentException + - JsonMachine\Exception\JsonMachineException diff --git a/src/Exception/SyntaxErrorException.php b/src/Exception/SyntaxErrorException.php index 9593e54..5f8be95 100644 --- a/src/Exception/SyntaxErrorException.php +++ b/src/Exception/SyntaxErrorException.php @@ -6,7 +6,7 @@ namespace JsonMachine\Exception; class SyntaxErrorException extends JsonMachineException { - public function __construct($message, $position) + public function __construct(string $message, int $position) { parent::__construct($message." At position $position."); } diff --git a/src/FileChunks.php b/src/FileChunks.php index 3085a1a..dbcbf3e 100644 --- a/src/FileChunks.php +++ b/src/FileChunks.php @@ -4,6 +4,9 @@ declare(strict_types=1); namespace JsonMachine; +/** + * @implements \IteratorAggregate + */ class FileChunks implements \IteratorAggregate { /** @var string */ diff --git a/src/Parser.php b/src/Parser.php index c4a6b55..2c8326f 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -37,13 +37,13 @@ class Parser implements \IteratorAggregate, PositionAware /** @var ItemDecoder */ private $jsonDecoder; - /** @var string */ + /** @var string|null */ private $matchedJsonPointer; /** @var array */ private $paths; - /** @var array */ + /** @var array|null */ private $currentPath; /** @var array */ @@ -247,7 +247,7 @@ class Parser implements \IteratorAggregate, PositionAware } if ($token === null) { - $this->error('Cannot iterate empty JSON', $token); + $this->error('Cannot iterate empty JSON', ''); } if ($currentLevel > -1 && ! $subtreeEnded) { @@ -352,7 +352,7 @@ class Parser implements \IteratorAggregate, PositionAware */ private function error($msg, $token, $exception = SyntaxErrorException::class) { - throw new $exception($msg." '".$token."'", $this->tokens->getPosition()); + throw new $exception($msg." '".$token."'", $this->tokens instanceof PositionAware ? $this->tokens->getPosition() : 0); } /** diff --git a/src/StreamChunks.php b/src/StreamChunks.php index da8502e..5248c1c 100644 --- a/src/StreamChunks.php +++ b/src/StreamChunks.php @@ -6,6 +6,9 @@ namespace JsonMachine; use JsonMachine\Exception\InvalidArgumentException; +/** + * @implements \IteratorAggregate + */ class StreamChunks implements \IteratorAggregate { /** @var resource */ diff --git a/src/TokensWithDebugging.php b/src/TokensWithDebugging.php index 59b9400..acd3d36 100644 --- a/src/TokensWithDebugging.php +++ b/src/TokensWithDebugging.php @@ -4,17 +4,25 @@ declare(strict_types=1); namespace JsonMachine; +/** + * @implements \IteratorAggregate + */ class TokensWithDebugging implements \IteratorAggregate, PositionAware { - /** @var iterable */ + /** @var iterable */ private $jsonChunks; + /** @var int */ private $position = 0; + + /** @var int */ private $line = 1; + + /** @var int */ private $column = 0; /** - * @param iterable $jsonChunks + * @param iterable $jsonChunks */ public function __construct($jsonChunks) { @@ -53,6 +61,7 @@ class TokensWithDebugging implements \IteratorAggregate, PositionAware foreach ($this->jsonChunks as $bytes) { $bytesLength = strlen($bytes); for ($i = 0; $i < $bytesLength; ++$i) { + /** @var string $byte */ $byte = $bytes[$i]; if ($inString) { if ($byte == '"' && ! $escaping) { diff --git a/src/ValidJsonPointers.php b/src/ValidJsonPointers.php index 7a7b44a..334c8a2 100644 --- a/src/ValidJsonPointers.php +++ b/src/ValidJsonPointers.php @@ -8,16 +8,23 @@ use JsonMachine\Exception\InvalidArgumentException; final class ValidJsonPointers { + /** @var string[] */ private $jsonPointers = []; + /** @var bool */ private $validated = false; + /** + * @param string[] $jsonPointers + */ public function __construct(array $jsonPointers) { $this->jsonPointers = array_values($jsonPointers); } /** + * @return string[] + * * @throws InvalidArgumentException */ public function toArray(): array @@ -30,6 +37,8 @@ final class ValidJsonPointers } /** + * @return void + * * @throws InvalidArgumentException */ private function validate() @@ -40,6 +49,8 @@ final class ValidJsonPointers } /** + * @return void + * * @throws InvalidArgumentException */ private function validateFormat() @@ -54,6 +65,8 @@ final class ValidJsonPointers } /** + * @return void + * * @throws InvalidArgumentException */ private function validateJsonPointersDoNotIntersect() diff --git a/src/autoloader.php b/src/autoloader.php index fa3ddc1..7ae1079 100644 --- a/src/autoloader.php +++ b/src/autoloader.php @@ -19,7 +19,10 @@ namespace JsonMachine; */ class Autoloading { - static public function autoloader($class) + /** + * @return void + */ + static public function autoloader(string $class) { $prefix = 'JsonMachine\\'; $baseDir = __DIR__.DIRECTORY_SEPARATOR; diff --git a/test/JsonMachineTest/Exception/SyntaxErrorExceptionTest.php b/test/JsonMachineTest/Exception/SyntaxErrorExceptionTest.php index baae02c..2be2902 100644 --- a/test/JsonMachineTest/Exception/SyntaxErrorExceptionTest.php +++ b/test/JsonMachineTest/Exception/SyntaxErrorExceptionTest.php @@ -14,7 +14,7 @@ class SyntaxErrorExceptionTest extends TestCase { public function testMessageContainsDataFromConstructor() { - $exception = new SyntaxErrorException('msg 42', '24'); + $exception = new SyntaxErrorException('msg 42', 24); $this->assertContains('msg 42', $exception->getMessage()); $this->assertContains('24', $exception->getMessage()); diff --git a/test/JsonMachineTest/JsonDecoder/DecodingErrorTest.php b/test/JsonMachineTest/JsonDecoder/DecodingErrorTest.php index 2dcbdaa..c9a0e8f 100644 --- a/test/JsonMachineTest/JsonDecoder/DecodingErrorTest.php +++ b/test/JsonMachineTest/JsonDecoder/DecodingErrorTest.php @@ -14,7 +14,7 @@ class DecodingErrorTest extends TestCase { public function testGetMalformedJson() { - $decodingError = new DecodingError('"json\"', null); + $decodingError = new DecodingError('"json\"', ''); $this->assertSame('"json\"', $decodingError->getMalformedJson()); } diff --git a/test/JsonMachineTest/StreamChunksTest.php b/test/JsonMachineTest/StreamChunksTest.php index 2344e0c..1c495ee 100644 --- a/test/JsonMachineTest/StreamChunksTest.php +++ b/test/JsonMachineTest/StreamChunksTest.php @@ -15,6 +15,7 @@ class StreamChunksTest extends \PHPUnit_Framework_TestCase public function testThrowsIfNoResource() { $this->expectException(InvalidArgumentException::class); + /* @phpstan-ignore-next-line */ new StreamChunks(false); } diff --git a/test/JsonMachineTest/ValidJsonPointersTest.php b/test/JsonMachineTest/ValidJsonPointersTest.php index 041c880..def210f 100644 --- a/test/JsonMachineTest/ValidJsonPointersTest.php +++ b/test/JsonMachineTest/ValidJsonPointersTest.php @@ -16,7 +16,6 @@ class ValidJsonPointersTest extends \PHPUnit_Framework_TestCase * @dataProvider data_testThrowsOnIntersectingPaths * * @param $jsonPointers - * @param ParserTest $parserTest */ public function testThrowsOnIntersectingPaths($jsonPointers) { From 1c54d5081933c57c3475d6c551a74d1156351b51 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Tue, 28 Nov 2023 19:18:26 +0100 Subject: [PATCH 14/17] CHANGELOG --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a275597..7139ec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## master -Nothing yet +- Minor fixes and added some tests. +### Added +- Support for PHP 8.3 +- Added PHPStan to build pipeline +### Fixed +- Fixed the case when non-intersecting pointers were considered intersecting (#106). Thanks @XedinUnknown
From 27780c5c42673333ba6d826d672060dbc42d5bf3 Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Tue, 28 Nov 2023 20:33:04 +0100 Subject: [PATCH 15/17] Introduced PHP upper version constraint for better future compatibility --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 61d9dc0..b1594c7 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "sort-packages": true }, "require": { - "php": ">=7.0" + "php": "7.0-8.3" }, "require-dev": { "ext-json": "*", From 05744e13b3623a4ab0ddf069b43ac0c7bb5a3c5f Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Tue, 28 Nov 2023 21:01:36 +0100 Subject: [PATCH 16/17] Fixed composer.json constraint + added 'composer validate' to the build pipeline. --- Makefile | 6 +++++- composer.json | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 965027a..a4f6d5d 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ help: @grep -E '^[-a-zA-Z0-9_\.\/]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[32m%-15s\033[0m\t%s\n", $$1, $$2}' -build: tests-all cs-check phpstan ## Run all necessary stuff before commit. +build: composer-validate cs-check phpstan tests-all ## Run all necessary stuff before commit. tests: ## Run tests on recent PHP version. Pass args to phpunit via ARGS="" @@ -67,6 +67,10 @@ performance-tests: ## Run performance tests @$(call DOCKER_RUN,$(LATEST_PHP),composer performance-tests) +composer-validate: ## Validate composer.json contents + @$(call DOCKER_RUN,$(LATEST_PHP),composer validate) + + release: .env build @\ branch=$$(git branch --show-current); \ diff --git a/composer.json b/composer.json index b1594c7..aba62e7 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "sort-packages": true }, "require": { - "php": "7.0-8.3" + "php": "7.0 - 8.3" }, "require-dev": { "ext-json": "*", From 5147f38f74d7ab3e27733e3f3bdabbd2fd28e3fa Mon Sep 17 00:00:00 2001 From: Filip Halaxa Date: Tue, 28 Nov 2023 22:12:40 +0100 Subject: [PATCH 17/17] Release 1.1.4 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7139ec6..072f285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## master +Nothing yet + +
+ +## 1.1.4 - 2023-11-28 - Minor fixes and added some tests. ### Added - Support for PHP 8.3