From e0b956ae9cb5863d1de1a0667cdae9e08d8fed0f Mon Sep 17 00:00:00 2001 From: Andru Cherny Date: Mon, 7 Jun 2021 14:32:11 +0300 Subject: [PATCH] stability piplines --- .coveralls.yml | 0 .docker/app_test/Dockerfile | 21 +- .docker/docker.mk | 0 .docker/php7.2-dev/Dockerfile | 16 +- .env | 3 +- .make/static-analysis.mk | 49 +++ .travis.yml | 20 +- Makefile | 38 +- composer.json | 14 +- ecs.php | 39 ++ ecs.yml | 17 - phan.php | 385 ++++++++++++++++++ psalm.xml | 2 +- src/Domain/Exception/ParentExceptionTrait.php | 3 + src/Infrastructure/Testing/RedisInMemory.php | 3 + .../Testing/ValueObjectMockTrait.php | 128 ++++++ src/Utils/LoggerTrait.php | 2 - 17 files changed, 666 insertions(+), 74 deletions(-) create mode 100644 .coveralls.yml create mode 100644 .docker/docker.mk create mode 100644 .make/static-analysis.mk create mode 100644 ecs.php delete mode 100644 ecs.yml create mode 100644 phan.php create mode 100644 src/Infrastructure/Testing/ValueObjectMockTrait.php diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..e69de29 diff --git a/.docker/app_test/Dockerfile b/.docker/app_test/Dockerfile index 253a38c..818d3fd 100644 --- a/.docker/app_test/Dockerfile +++ b/.docker/app_test/Dockerfile @@ -2,6 +2,21 @@ FROM php:7.2-cli RUN apt-get update && apt-get install -y git unzip +RUN set -eux \ + # Installation: Generic + # Type: Built-in extension + && pecl install ast \ + && docker-php-ext-enable ast \ + && true + +# -------------------- Installing PHP Extension: intl -------------------- +RUN set -eux \ + # Installation: Generic + # Type: Built-in extension + && apt install -y libicu-dev \ + && docker-php-ext-install -j$(getconf _NPROCESSORS_ONLN) intl \ + && true + ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_MEMORY_LIMIT -1 @@ -9,8 +24,8 @@ RUN mkdir /.composer_cache ENV COMPOSER_CACHE_DIR /.composer_cache RUN mkdir /packages -COPY . /packages/ValueObject -WORKDIR /packages/ValueObject +COPY . /packages/Base +WORKDIR /packages/Base RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer -RUN composer install +RUN composer -vvv install diff --git a/.docker/docker.mk b/.docker/docker.mk new file mode 100644 index 0000000..e69de29 diff --git a/.docker/php7.2-dev/Dockerfile b/.docker/php7.2-dev/Dockerfile index b52d81e..66eccf4 100644 --- a/.docker/php7.2-dev/Dockerfile +++ b/.docker/php7.2-dev/Dockerfile @@ -2,6 +2,21 @@ FROM php:7.2-cli RUN apt-get update && apt-get install -y git unzip +RUN set -eux \ + # Installation: Generic + # Type: Built-in extension + && pecl install ast \ + && docker-php-ext-enable ast \ + && true + +# -------------------- Installing PHP Extension: intl -------------------- +RUN set -eux \ + # Installation: Generic + # Type: Built-in extension + && apt install -y libicu-dev \ + && docker-php-ext-install -j$(getconf _NPROCESSORS_ONLN) intl \ + && true + ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_MEMORY_LIMIT -1 @@ -10,7 +25,6 @@ ENV COMPOSER_CACHE_DIR /.composer_cache RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer -RUN composer -vvv global require hirak/prestissimo RUN composer -vvv global require ergebnis/composer-normalize RUN composer -vvv global require pyrech/composer-changelogs diff --git a/.env b/.env index b2f4cde..c6f5879 100644 --- a/.env +++ b/.env @@ -2,6 +2,8 @@ # Copy this file to .env file for development, create environment variables when deploying to production # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration +ADGBASE_COMPOSE_PROJECT_NAME=mase + ###> symfony/framework-bundle ### APP_ENV=dev APP_SECRET=secret @@ -9,7 +11,6 @@ APP_SECRET=secret ###> common variables ### DOCKER_SERVER_HOST=docker.local -DOCKER_SERVER_PORT=5001 DOCKER_PROJECT_PATH=adgoal/common/base DOCKER_PHP_VERSION=7.2 DOCKER_IMAGE_VERSION=master diff --git a/.make/static-analysis.mk b/.make/static-analysis.mk new file mode 100644 index 0000000..28d833e --- /dev/null +++ b/.make/static-analysis.mk @@ -0,0 +1,49 @@ +.PHONY: lint layer style coding-standards +static-analysis: lint layer style coding-standards ## Run phpstan, deprac, easycoding standarts code static analysis + +.PHONY: phpstan psalm +style: phpstan psalm ## executes php analizers + + +.PHONY: lint +lint: ## checks syntax of PHP files + docker-compose run --rm --no-deps php sh -lc './vendor/bin/parallel-lint ./ --exclude vendor' + +.PHONY: layer +layer: ## check issues with layers (deptrac tool) + docker-compose run --rm --no-deps php sh -lc './vendor/bin/deptrac analyze' + +.PHONY: coding-standards +coding-standards: ## run check and validate code standards tests + docker-compose run --rm --no-deps php sh -lc './vendor/bin/ecs check src tests' + docker-compose run --rm --no-deps php sh -lc './vendor/bin/phpmd src/ text phpmd.xml' + +.PHONY: coding-standards-fixer +coding-standards-fixer: ## run code standards fixer + docker-compose run --rm --no-deps php sh -lc './vendor/bin/ecs check src tests --fix' + +tests-unit: ## Run unit-tests suite + docker-compose run --rm --no-deps php sh -lc 'vendor/bin/phpunit --configuration /app/phpunit.xml.dist' + +tests-integration: ## Run integration-tests suite + docker-compose run --rm --no-deps php sh -lc 'vendor/bin/phpunit --configuration /app/phpunit.func.xml' + +.PHONY: infection +infection: ## executes mutation framework infection + docker-compose run --rm --no-deps php-fpm sh -lc './vendor/bin/infection --min-msi=70 --min-covered-msi=80 --threads=$(JOBS) --coverage=var/report' + +.PHONY: phpstan +phpstan: ## phpstan - PHP Static Analysis Tool + docker-compose run --rm --no-deps php sh -lc './vendor/bin/phpstan analyse -l 6 -c phpstan.neon src tests' + +.PHONY: psalm +psalm: ## psalm is a static analysis tool for finding errors in PHP applications + docker-compose run --rm --no-deps php sh -lc './vendor/bin/psalm --config=psalm.xml' + +.PHONY: psalm-fixer +psalm-fixer: ## psalm is a static analysis tool for finding errors in PHP applications + docker-compose run --rm --no-deps php sh -lc './vendor/bin/psalm --config=psalm.xml --alter --issues=MissingParamType --dry-run' + +.PHONY: phan +phan: ## phan is a static analyzer for PHP that prefers to minimize false-positives. + docker-compose run --rm --no-deps php sh -lc 'PHAN_DISABLE_XDEBUG_WARN=1 PHAN_ALLOW_XDEBUG=1 php -d zend.enable_gc=0 ./vendor/bin/phan --config-file phan.php --require-config-exists' diff --git a/.travis.yml b/.travis.yml index b5c1885..3d6bf76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,23 +6,19 @@ cache: env: global: - DOCKER_SERVER_HOST=docker.local - - DOCKER_SERVER_PORT=5001 - DOCKER_PROJECT_PATH=components/base - TEST_CONFIG="phpunit.xml.dist" -install: - - export DOCKER_IMAGE_VERSION=`echo $TRAVIS_BRANCH | tr "[:upper:]" "[:lower:]" | sed "s/[^a-zA-Z0-9-]/-/g" | sed "s/-$//g" | tr -d '\n' | tr -d '\r'` - - export DOCKER_IMAGE_TAG=$DOCKER_SERVER_HOST:$DOCKER_SERVER_PORT/$DOCKER_PROJECT_PATH/app_test:$DOCKER_IMAGE_VERSION - - docker build . -f .docker/app_test/Dockerfile -t $DOCKER_IMAGE_TAG +#install: +# - export DOCKER_IMAGE_VERSION=`echo $TRAVIS_BRANCH | tr "[:upper:]" "[:lower:]" | sed "s/[^a-zA-Z0-9-]/-/g" | sed "s/-$//g" | tr -d '\n' | tr -d '\r'` +# - export DOCKER_IMAGE_TAG=$DOCKER_SERVER_HOST/$DOCKER_PROJECT_PATH/app_test:$DOCKER_IMAGE_VERSION +# - docker build . -f .docker/app_test/Dockerfile -t $DOCKER_IMAGE_TAG script: - - docker run $DOCKER_IMAGE_TAG vendor/bin/parallel-lint ./ --exclude vendor - - docker run $DOCKER_IMAGE_TAG vendor/bin/deptrac analyze --formatter-graphviz=0 - - docker run $DOCKER_IMAGE_TAG vendor/bin/phpstan analyse -l 6 -c phpstan.neon src tests - - docker run $DOCKER_IMAGE_TAG vendor/bin/psalm --config=psalm.xml - - docker run $DOCKER_IMAGE_TAG vendor/bin/ecs check src tests - - docker run $DOCKER_IMAGE_TAG vendor/bin/phpmd src/ text phpmd.xml - - docker run -v $(pwd)/build:/packages/Base/build $DOCKER_IMAGE_TAG vendor/bin/phpunit --configuration $TEST_CONFIG + - make lint + - make static-analysis + - make coding-standards + - make tests-unit - git log $(git describe --abbrev=0 --tags)...HEAD --no-merges --pretty=format:"* [%h](http://github.com/${TRAVIS_REPO_SLUG}/commit/%H) %s (%cN)" after_success: diff --git a/Makefile b/Makefile index 7fcb08a..456d19f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ include .env export +include .make/static-analysis.mk +include .docker/docker.mk + sources = bin/console config src version = $(shell git describe --tags --dirty --always) build_name = application-$(version) @@ -16,9 +19,8 @@ fix-permission: ## fix permission for docker env .PHONY: build build: ## build environment and initialize composer and project dependencies - docker build .docker/php$(DOCKER_PHP_VERSION)-dev/ -t $(DOCKER_SERVER_HOST):$(DOCKER_SERVER_PORT)/$(DOCKER_PROJECT_PATH)/php$(DOCKER_PHP_VERSION)-dev:$(DOCKER_IMAGE_VERSION) \ + docker build .docker/php$(DOCKER_PHP_VERSION)-dev/ -t $(DOCKER_SERVER_HOST)/$(DOCKER_PROJECT_PATH)/php$(DOCKER_PHP_VERSION)-dev:$(DOCKER_IMAGE_VERSION) \ --build-arg DOCKER_SERVER_HOST=$(DOCKER_SERVER_HOST) \ - --build-arg DOCKER_SERVER_PORT=$(DOCKER_SERVER_PORT) \ --build-arg DOCKER_PROJECT_PATH=$(DOCKER_PROJECT_PATH) \ --build-arg DOCKER_PHP_VERSION=$(DOCKER_PHP_VERSION) \ --build-arg DOCKER_IMAGE_VERSION=$(DOCKER_IMAGE_VERSION) @@ -39,11 +41,7 @@ composer-update: ## Update project dependencies .PHONY: composer-outdated composer-outdated: ## Show outdated project dependencies - docker-compose run --rm --no-deps php sh -lc 'composer outdated' - -.PHONY: composer-validate -composer-validate: ## Validate composer config - docker-compose run --rm --no-deps php sh -lc 'composer validate --no-check-publish' + docker-compose run --rm --no-deps php sh -lc 'composer outdated's .PHONY: composer composer: ## Execute composer command @@ -53,14 +51,6 @@ composer: ## Execute composer command phpunit: ## execute project unit tests docker-compose run --rm php sh -lc "./vendor/bin/phpunit $(conf)" -.PHONY: style -style: ## executes php analizers - docker-compose run --rm --no-deps php sh -lc './vendor/bin/phpstan analyse -l 6 -c phpstan.neon src tests' - docker-compose run --rm --no-deps php sh -lc './vendor/bin/psalm --config=psalm.xml' - -.PHONY: lint -lint: ## checks syntax of PHP files - docker-compose run --rm --no-deps php sh -lc './vendor/bin/parallel-lint ./ --exclude vendor --exclude bin/phpunit' .PHONY: logs logs: ## look for service logs @@ -74,20 +64,8 @@ help: ## Display this help message php-shell: ## PHP shell docker-compose run --rm php sh -l -unit-tests: ## Run unit-tests suite +tests-unit: ## Run unit-tests suite docker-compose run --rm php sh -lc 'vendor/bin/phpunit --testsuite unit-tests' -static-analysis: style coding-standards ## Run phpstan, deprac, easycoding standarts code static analysis - -coding-standards: ## Run check and validate code standards tests - docker-compose run --rm --no-deps php sh -lc 'vendor/bin/ecs check src tests' - docker-compose run --rm --no-deps php sh -lc 'vendor/bin/phpmd src/ text phpmd.xml' - -coding-standards-fixer: ## Run code standards fixer - docker-compose run --rm --no-deps php sh -lc 'vendor/bin/ecs check src tests --fix' - -security-tests: ## The SensioLabs Security Checker - docker-compose run --rm --no-deps php sh -lc 'vendor/bin/security-checker security:check --end-point=http://security.sensiolabs.org/check_lock' - -.PHONY: test lint static-analysis phpunit coding-standards composer-validate -test: build lint static-analysis coding-standards composer-validate stop ## Run all test suites +.PHONY: test lint static-analysis phpunit coding-standards tests-unit +test: build lint static-analysis coding-standards tests-unit stop ## Run all test suites diff --git a/composer.json b/composer.json index a63f2e9..81a81f4 100644 --- a/composer.json +++ b/composer.json @@ -16,15 +16,15 @@ "jakub-onderka/php-parallel-lint": "^1.0", "mockery/mockery": "^1.2", "phpmd/phpmd": "^2.6", - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-mockery": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-mockery": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", "phpunit/phpunit": "^8.0", "roave/security-advisories": "dev-master", - "sensiolabs-de/deptrac-shim": "^0.4", - "symfony/phpunit-bridge": "*", - "symplify/easy-coding-standard": "^5.4", - "vimeo/psalm": "^3.0" + "sensiolabs-de/deptrac-shim": "^0.12.0", + "symplify/easy-coding-standard": "8.3.*", + "vimeo/psalm": "^4.7", + "phan/phan": "4.0.*" }, "config": { "preferred-install": { diff --git a/ecs.php b/ecs.php new file mode 100644 index 0000000..fe6ea73 --- /dev/null +++ b/ecs.php @@ -0,0 +1,39 @@ +parameters(); + $parameters->set(Option::PATHS, [ + __DIR__ . '/src', + __DIR__ . '/tests', + ]); + + $services = $containerConfigurator->services(); + $services->set(ArraySyntaxFixer::class) + ->call('configure', [[ + 'syntax' => 'short', + ]]); + + // run and fix, one by one + $containerConfigurator->import(SetList::CLEAN_CODE); + $containerConfigurator->import(SetList::SYMFONY); + $containerConfigurator->import(SetList::PHP_71); + $containerConfigurator->import(SetList::PHP_73_MIGRATION); + $containerConfigurator->import(SetList::PSR_12); + + $parameters = $containerConfigurator->parameters(); + $parameters->set(Option::SKIP, [ + \PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer::class => null, + \PhpCsFixer\Fixer\Phpdoc\PhpdocTrimConsecutiveBlankLineSeparationFixer::class => null, + \PhpCsFixer\Fixer\Phpdoc\PhpdocTrimFixer::class => null, + \SlevomatCodingStandard\Sniffs\Whitespaces\DuplicateSpacesSniff::class => null, + \PhpCsFixer\Fixer\Operator\ConcatSpaceFixer::class => null + ]); +}; diff --git a/ecs.yml b/ecs.yml deleted file mode 100644 index 629fafb..0000000 --- a/ecs.yml +++ /dev/null @@ -1,17 +0,0 @@ -imports: - - { resource: 'vendor/symplify/easy-coding-standard/config/clean-code.yml' } - - { resource: 'vendor/symplify/easy-coding-standard/config/symfony.yml' } - - { resource: 'vendor/symplify/easy-coding-standard/config/php71.yml' } - -parameters: - skip: - SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingParameterTypeHint: - - 'src/Infrastructure/Testing/RedisInMemory.php' - SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingReturnTypeHint: - - 'src/Infrastructure/Testing/RedisInMemory.php' - SlevomatCodingStandard\Sniffs\Classes\UnusedPrivateElementsSniff.UnusedMethod: - - 'src/Common/Alerting/AlertingProcessor.php' - Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer: - - 'src/Domain/Exception/ParentExceptionTrait.php' - Symplify\CodingStandard\Fixer\Commenting\ParamReturnAndVarTagMalformsFixer: - - 'src/Domain/Exception/ParentExceptionTrait.php' diff --git a/phan.php b/phan.php new file mode 100644 index 0000000..24ea051 --- /dev/null +++ b/phan.php @@ -0,0 +1,385 @@ + '7.2', + + // If enabled, missing properties will be created when + // they are first seen. If false, we'll report an + // error message if there is an attempt to write + // to a class property that wasn't explicitly + // defined. + 'allow_missing_properties' => false, + + // If enabled, null can be cast to any type and any + // type can be cast to null. Setting this to true + // will cut down on false positives. + 'null_casts_as_any_type' => false, + + // If enabled, allow null to be cast as any array-like type. + // + // This is an incremental step in migrating away from `null_casts_as_any_type`. + // If `null_casts_as_any_type` is true, this has no effect. + 'null_casts_as_array' => false, + + // If enabled, allow any array-like type to be cast to null. + // This is an incremental step in migrating away from `null_casts_as_any_type`. + // If `null_casts_as_any_type` is true, this has no effect. + 'array_casts_as_null' => false, + + // If enabled, scalars (int, float, bool, string, null) + // are treated as if they can cast to each other. + // This does not affect checks of array keys. See `scalar_array_key_cast`. + 'scalar_implicit_cast' => false, + + // If enabled, any scalar array keys (int, string) + // are treated as if they can cast to each other. + // E.g. `array` can cast to `array` and vice versa. + // Normally, a scalar type such as int could only cast to/from int and mixed. + 'scalar_array_key_cast' => false, + + // If this has entries, scalars (int, float, bool, string, null) + // are allowed to perform the casts listed. + // + // E.g. `['int' => ['float', 'string'], 'float' => ['int'], 'string' => ['int'], 'null' => ['string']]` + // allows casting null to a string, but not vice versa. + // (subset of `scalar_implicit_cast`) + 'scalar_implicit_partial' => [], + + // If enabled, Phan will warn if **any** type in a method invocation's object + // is definitely not an object, + // or if **any** type in an invoked expression is not a callable. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_method_checking' => true, + + // If enabled, Phan will warn if **any** type in the argument's union type + // cannot be cast to a type in the parameter's expected union type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_param_checking' => true, + + // If enabled, Phan will warn if **any** type in a returned value's union type + // cannot be cast to the declared return type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_return_checking' => true, + + // If enabled, Phan will warn if **any** type in a property assignment's union type + // cannot be cast to a type in the property's declared union type. + // Setting this to true will introduce numerous false positives + // (and reveal some bugs). + 'strict_property_checking' => true, + + // If true, seemingly undeclared variables in the global + // scope will be ignored. + // + // This is useful for projects with complicated cross-file + // globals that you have no hope of fixing. + 'ignore_undeclared_variables_in_global_scope' => false, + + // Set this to false to emit `PhanUndeclaredFunction` issues for internal functions that Phan has signatures for, + // but aren't available in the codebase, or the internal functions used to run Phan + // (may lead to false positives if an extension isn't loaded) + // + // If this is true(default), then Phan will not warn. + 'ignore_undeclared_functions_with_known_signatures' => false, + + // Backwards Compatibility Checking. This is slow + // and expensive, but you should consider running + // it before upgrading your version of PHP to a + // new version that has backward compatibility + // breaks. + // + // If you are migrating from PHP 5 to PHP 7, + // you should also look into using + // [php7cc (no longer maintained)](https://github.com/sstalle/php7cc) + // and [php7mar](https://github.com/Alexia/php7mar), + // which have different backwards compatibility checks. + 'backward_compatibility_checks' => false, + + // If true, check to make sure the return type declared + // in the doc-block (if any) matches the return type + // declared in the method signature. + 'check_docblock_signature_return_type_match' => true, + + // If true, make narrowed types from phpdoc params override + // the real types from the signature, when real types exist. + // (E.g. allows specifying desired lists of subclasses, + // or to indicate a preference for non-nullable types over nullable types) + // + // Affects analysis of the body of the method and the param types passed in by callers. + // + // (*Requires `check_docblock_signature_param_type_match` to be true*) + 'prefer_narrowed_phpdoc_param_type' => true, + + // (*Requires `check_docblock_signature_return_type_match` to be true*) + // + // If true, make narrowed types from phpdoc returns override + // the real types from the signature, when real types exist. + // + // (E.g. allows specifying desired lists of subclasses, + // or to indicate a preference for non-nullable types over nullable types) + // + // This setting affects the analysis of return statements in the body of the method and the return types passed in by callers. + 'prefer_narrowed_phpdoc_return_type' => true, + + // If enabled, check all methods that override a + // parent method to make sure its signature is + // compatible with the parent's. + // + // This check can add quite a bit of time to the analysis. + // + // This will also check if final methods are overridden, etc. + 'analyze_signature_compatibility' => true, + + // This setting maps case-insensitive strings to union types. + // + // This is useful if a project uses phpdoc that differs from the phpdoc2 standard. + // + // If the corresponding value is the empty string, + // then Phan will ignore that union type (E.g. can ignore 'the' in `@return the value`) + // + // If the corresponding value is not empty, + // then Phan will act as though it saw the corresponding UnionTypes(s) + // when the keys show up in a UnionType of `@param`, `@return`, `@var`, `@property`, etc. + // + // This matches the **entire string**, not parts of the string. + // (E.g. `@return the|null` will still look for a class with the name `the`, but `@return the` will be ignored with the below setting) + // + // (These are not aliases, this setting is ignored outside of doc comments). + // (Phan does not check if classes with these names exist) + // + // Example setting: `['unknown' => '', 'number' => 'int|float', 'char' => 'string', 'long' => 'int', 'the' => '']` + 'phpdoc_type_mapping' => [], + + // Set to true in order to attempt to detect dead + // (unreferenced) code. Keep in mind that the + // results will only be a guess given that classes, + // properties, constants and methods can be referenced + // as variables (like `$class->$property` or + // `$class->$method()`) in ways that we're unable + // to make sense of. + 'dead_code_detection' => true, + + // Set to true in order to attempt to detect unused variables. + // `dead_code_detection` will also enable unused variable detection. + // + // This has a few known false positives, e.g. for loops or branches. + 'unused_variable_detection' => true, + + // Set to true in order to attempt to detect redundant and impossible conditions. + // + // This has some false positives involving loops, + // variables set in branches of loops, and global variables. + 'redundant_condition_detection' => true, + + // If true, this runs a quick version of checks that takes less + // time at the cost of not running as thorough + // of an analysis. You should consider setting this + // to true only when you wish you had more **undiagnosed** issues + // to fix in your code base. + // + // In quick-mode the scanner doesn't rescan a function + // or a method's code block every time a call is seen. + // This means that the problem here won't be detected: + // + // ```php + // false, + + // If true, then before analysis, try to simplify AST into a form + // which improves Phan's type inference in edge cases. + // + // This may conflict with `dead_code_detection`. + // When this is true, this slows down analysis slightly. + // + // E.g. rewrites `if ($a = value() && $a > 0) {...}` + // into `$a = value(); if ($a) { if ($a > 0) {...}}` + 'simplify_ast' => false, + + // Enable or disable support for generic templated + // class types. + 'generic_types_enabled' => true, + + // Override to hardcode existence and types of (non-builtin) globals in the global scope. + // Class names should be prefixed with `\`. + // + // (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`) + 'globals_type_map' => [], + + // The minimum severity level to report on. This can be + // set to `Issue::SEVERITY_LOW`, `Issue::SEVERITY_NORMAL` or + // `Issue::SEVERITY_CRITICAL`. Setting it to only + // critical issues is a good place to start on a big + // sloppy mature code base. + 'minimum_severity' => Issue::SEVERITY_LOW, + + // Add any issue types (such as `'PhanUndeclaredMethod'`) + // to this black-list to inhibit them from being reported. + 'suppress_issue_types' => [ + 'PhanUnusedVariableCaughtException', + 'PhanPartialTypeMismatchArgument', + 'PhanTypeMismatchArgument', + 'PhanPluginDescriptionlessCommentOnPrivateProperty', + 'PhanPluginDescriptionlessCommentOnPublicMethod', + 'PhanPluginDescriptionlessCommentOnPrivateMethod', + 'PhanPluginDescriptionlessCommentOnProtectedMethod', + 'PhanTypeInvalidThrowsIsInterface' + ], + + // A regular expression to match files to be excluded + // from parsing and analysis and will not be read at all. + // + // This is useful for excluding groups of test or example + // directories/files, unanalyzable files, or files that + // can't be removed for whatever reason. + // (e.g. `'@Test\.php$@'`, or `'@vendor/.*/(tests|Tests)/@'`) + 'exclude_file_regex' => '@^vendor/.*/(tests?|Tests?)/@', + + // A file list that defines files that will be excluded + // from parsing and analysis and will not be read at all. + // + // This is useful for excluding hopelessly unanalyzable + // files that can't be removed for whatever reason. + 'exclude_file_list' => [], + + // A directory list that defines files that will be excluded + // from static analysis, but whose class and method + // information should be included. + // + // Generally, you'll want to include the directories for + // third-party code (such as "vendor/") in this list. + // + // n.b.: If you'd like to parse but not analyze 3rd + // party code, directories containing that code + // should be added to the `directory_list` as well as + // to `exclude_analysis_directory_list`. + 'exclude_analysis_directory_list' => [ + 'vendor/', + ], + + // Enable this to enable checks of require/include statements referring to valid paths. + 'enable_include_path_checks' => true, + + // The number of processes to fork off during the analysis + // phase. + 'processes' => 1, + + // List of case-insensitive file extensions supported by Phan. + // (e.g. `['php', 'html', 'htm']`) + 'analyzed_file_extensions' => [ + 'php', + ], + + // You can put paths to stubs of internal extensions in this config option. + // If the corresponding extension is **not** loaded, then Phan will use the stubs instead. + // Phan will continue using its detailed type annotations, + // but load the constants, classes, functions, and classes (and their Reflection types) + // from these stub files (doubling as valid php files). + // Use a different extension from php to avoid accidentally loading these. + // The `tools/make_stubs` script can be used to generate your own stubs (compatible with php 7.0+ right now) + // + // (e.g. `['xdebug' => '.phan/internal_stubs/xdebug.phan_php']`) + 'autoload_internal_extension_signatures' => [], + + // A list of plugin files to execute. + // + // Plugins which are bundled with Phan can be added here by providing their name (e.g. `'AlwaysReturnPlugin'`) + // + // Documentation about available bundled plugins can be found [here](https://github.com/phan/phan/tree/master/.phan/plugins). + // + // Alternately, you can pass in the full path to a PHP file with the plugin's implementation (e.g. `'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'`) + 'plugins' => [ + 'AlwaysReturnPlugin', + 'DollarDollarPlugin', + 'DuplicateArrayKeyPlugin', + 'DuplicateExpressionPlugin', + 'PregRegexCheckerPlugin', + 'PrintfCheckerPlugin', + 'SleepCheckerPlugin', + 'UnreachableCodePlugin', + 'UseReturnValuePlugin', + 'EmptyStatementListPlugin', + 'InvokePHPNativeSyntaxCheckPlugin', + 'PHPUnitAssertionPlugin', + 'HasPHPDocPlugin' + + ], + + // A list of directories that should be parsed for class and + // method information. After excluding the directories + // defined in `exclude_analysis_directory_list`, the remaining + // files will be statically analyzed for errors. + // + // Thus, both first-party and third-party code being used by + // your application should be included in this list. + 'directory_list' => [ + 'src/', + 'vendor/' + //'tests' + ], + + // A list of individual files to include in analysis + // with a path relative to the root directory of the + // project. + 'file_list' => [], +]; diff --git a/psalm.xml b/psalm.xml index 39b4cb3..51f6547 100644 --- a/psalm.xml +++ b/psalm.xml @@ -4,6 +4,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config file:///app/vendor/vimeo/psalm/config.xsd" + cacheDirectory="/tmp" > @@ -34,7 +35,6 @@ - diff --git a/src/Domain/Exception/ParentExceptionTrait.php b/src/Domain/Exception/ParentExceptionTrait.php index 4aef36e..57f382e 100644 --- a/src/Domain/Exception/ParentExceptionTrait.php +++ b/src/Domain/Exception/ParentExceptionTrait.php @@ -14,6 +14,9 @@ trait ParentExceptionTrait { /** + * + * Parent Exception. + * * @var Throwable */ protected $parentException; diff --git a/src/Infrastructure/Testing/RedisInMemory.php b/src/Infrastructure/Testing/RedisInMemory.php index b44f1ee..d002aaf 100644 --- a/src/Infrastructure/Testing/RedisInMemory.php +++ b/src/Infrastructure/Testing/RedisInMemory.php @@ -34,6 +34,8 @@ class RedisInMemory extends Redis */ public function connect($host, $port = 6379, $timeout = 0.0, $reserved = null, $retryInterval = 0, $readTimeout = 0.0) { + unset($host, $port, $timeout, $reserved, $retryInterval, $readTimeout); + return true; } @@ -64,6 +66,7 @@ public function get($key) */ public function set($key, $value, $timeout = 0): bool { + unset($timeout); $this->storage[$key] = $value; return true; diff --git a/src/Infrastructure/Testing/ValueObjectMockTrait.php b/src/Infrastructure/Testing/ValueObjectMockTrait.php new file mode 100644 index 0000000..6f83fdf --- /dev/null +++ b/src/Infrastructure/Testing/ValueObjectMockTrait.php @@ -0,0 +1,128 @@ +shouldReceive('toString'); + + if (null === $times) { + $uuidMockedToStringMethod->zeroOrMoreTimes(); + } else { + $uuidMockedToStringMethod->times($times); + } + $uuidMockedToStringMethod->andReturn($uuid); + + return $mock; + } + + /** + * Create StringLiteral mock. + * + * @param string $string + * @param int $times + * + * @return MockInterface|StringLiteral + */ + protected function createStringLiteralMock(string $string, int $times = 0): MockInterface + { + $mock = Mockery::mock(StringLiteral::class); + $mock + ->shouldReceive('toString') + ->times($times) + ->andReturn($string); + + return $mock; + } + + /** + * Create Integer mock. + * + * @param int $integer + * @param int $times + * + * @return MockInterface|ValueObjectInteger + */ + protected function createIntegerMock(int $integer, int $times = 0): MockInterface + { + $mock = Mockery::mock(ValueObjectInteger::class); + $mock + ->shouldReceive('toNative') + ->times($times) + ->andReturn($integer); + + $mock + ->shouldReceive('inc') + ->times(0) + ->andReturn(++$integer); + + return $mock; + } + + /** + * Create ObjectStorage mock. + * + * @param mixed[] $data + * @param int $times + * + * @return MockInterface|ObjectStorage + */ + protected function createObjectStorageMock(array $data, int $times = 0): MockInterface + { + $mock = Mockery::mock(ObjectStorage::class); + $mock + ->shouldReceive('toArray') + ->times($times) + ->andReturn($data); + + return $mock; + } + + /** + * Create Collection mock. + * + * @param mixed[] $data + * @param int $times + * + * @return MockInterface|Collection + */ + protected function createCollectionMock(array $data, int $times = 0): MockInterface + { + $mock = Mockery::mock(Collection::class); + $mock + ->shouldReceive('toArray') + ->times($times) + ->andReturn($data); + + return $mock; + } +} diff --git a/src/Utils/LoggerTrait.php b/src/Utils/LoggerTrait.php index 1cf75e3..228b9c7 100644 --- a/src/Utils/LoggerTrait.php +++ b/src/Utils/LoggerTrait.php @@ -95,7 +95,6 @@ public function logMessage(string $message, int $level, array $context = []): se default: throw new LoggerException(sprintf("Try to log invalid message level type '%s'", $level)); - break; } @@ -148,7 +147,6 @@ public function logException(Throwable $exception, int $level, string $message): default: throw new LoggerException(sprintf("Try to log invalid error level type '%s'", $level)); - break; }