diff --git a/.github/workflows/continuous-integration-pecl.yml b/.github/workflows/continuous-integration-pecl.yml deleted file mode 100644 index 5b72cbf6..00000000 --- a/.github/workflows/continuous-integration-pecl.yml +++ /dev/null @@ -1,135 +0,0 @@ -name: Test with Ray.Aop PECL Extension - -on: - push: - pull_request: - workflow_dispatch: - -jobs: - build-and-test: - runs-on: ubuntu-latest - - strategy: - matrix: - php-version: ['8.1', '8.2', '8.3'] - fail-fast: false - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up PHP ${{ matrix.php-version }} - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl, dom, json, libxml, xml, xmlwriter, tokenizer - tools: phpize, composer:v2 - - - name: Install build tools and Valgrind - run: | - sudo apt-get update - sudo apt-get install -y autoconf automake libtool bison re2c valgrind - - - name: Install Composer dependencies - run: composer install --prefer-dist --no-progress - - - name: Build extension - id: build_extension - run: | - git clone https://github.com/ray-di/ext-rayaop.git - cd ext-rayaop - phpize - ./configure - make - continue-on-error: true - - # Run the demo script - - name: Run demo script - run: | - # Running demo script under Valgrind - valgrind \ - --leak-check=full \ - --show-leak-kinds=all \ - --track-origins=yes \ - php -n \ - -d extension=./ext-rayaop/modules/rayaop.so \ - demo/05-pecl.php - - # Combined step for PHPUnit and Valgrind analysis - - name: Run Tests with Valgrind - if: success() || failure() - id: test_with_valgrind - run: | - # Create Valgrind suppression file - cat << EOF > rayaop.supp - { - php_startup_leak - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:php_module_startup - ... - } - { - zend_mm_startup_leak - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:zend_mm_startup - ... - } - EOF - - # Run PHPUnit under Valgrind - valgrind \ - --suppressions=rayaop.supp \ - --leak-check=full \ - --show-leak-kinds=all \ - --track-origins=yes \ - --verbose \ - --error-exitcode=0 \ - --log-file=valgrind.log \ - php -n \ - -d extension=./ext-rayaop/modules/rayaop.so \ - -d memory_limit=256M \ - vendor/bin/phpunit \ - --coverage-clover=coverage.xml || true - - # Display Valgrind log - echo "=== Valgrind Log ===" - cat valgrind.log - - # Upload debug information with unique names per PHP version - - name: Upload debug logs - if: always() - uses: actions/upload-artifact@v4 - with: - name: debug-logs-php${{ matrix.php-version }} - path: | - valgrind.log - coverage.xml - core* - if-no-files-found: warn - - # Upload coverage report - - name: Upload coverage report - if: always() - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - continue-on-error: true - - - name: Final status check - if: always() - run: | - echo "PHP Version: ${{ matrix.php-version }}" - echo "Extension build status: ${{ steps.build_extension.outcome }}" - echo "Test with Valgrind status: ${{ steps.test_with_valgrind.outcome }}" - - # Check for critical issues in Valgrind log - if [ -f valgrind.log ]; then - echo "=== Valgrind Error Summary ===" - grep "ERROR SUMMARY:" valgrind.log || true - grep "definitely lost:" valgrind.log || true - grep "indirectly lost:" valgrind.log || true - fi diff --git a/src/AbstractMatcher.php b/src/AbstractMatcher.php index b57545f3..1c055c4a 100644 --- a/src/AbstractMatcher.php +++ b/src/AbstractMatcher.php @@ -12,8 +12,8 @@ /** * Abstract matcher base class * - * @psalm-type MatcherArguments = array - * @psalm-type Arguments = array + * @psalm-import-type MatcherArguments from Types + * @psalm-import-type Arguments from Types */ abstract class AbstractMatcher { diff --git a/src/Aspect.php b/src/Aspect.php index 4b69a3f0..bfd3183f 100644 --- a/src/Aspect.php +++ b/src/Aspect.php @@ -16,16 +16,13 @@ /** * Aspect class manages aspect weaving and method interception * - * @psalm-type MethodInterceptors = array - * @psalm-type MethodBindings = array - * @psalm-type ClassBindings = array - * @psalm-type MatcherConfig = array{ - * classMatcher: AbstractMatcher, - * methodMatcher: AbstractMatcher, - * interceptors: MethodInterceptors - * } - * @psalm-type MatcherConfigList = array - * @psalm-type Arguments = array + * @psalm-import-type MethodInterceptors from Types + * @psalm-import-type MethodBindings from Types + * @psalm-import-type ClassBindings from Types + * @psalm-import-type MatcherConfig from Types + * @psalm-import-type MatcherConfigList from Types + * @psalm-import-type Arguments from Types + * @psalm-import-type MethodName from Types */ final class Aspect { @@ -135,7 +132,9 @@ private function createBind(string $className): Bind continue; // @codeCoverageIgnore } - $bind->bindInterceptors($method->getName(), $matcher['interceptors']); + /** @var MethodName $methodName */ + $methodName = $method->getName(); + $bind->bindInterceptors($methodName, $matcher['interceptors']); } } diff --git a/src/AspectPecl.php b/src/AspectPecl.php index f6e9ab6e..a38c2146 100644 --- a/src/AspectPecl.php +++ b/src/AspectPecl.php @@ -17,10 +17,10 @@ use function method_intercept; /** - * @psalm-type MethodBoundInterceptors = array - * @psalm-type ClassBoundInterceptors = array - * @psalm-import-type MatcherConfigList from Aspect - * @psalm-import-type MethodInterceptors from Aspect + * @psalm-import-type MethodBoundInterceptors from Types + * @psalm-import-type ClassBoundInterceptors from Types + * @psalm-import-type MatcherConfigList from Types + * @psalm-import-type MethodInterceptors from Types * @codeCoverageIgnore */ final class AspectPecl diff --git a/src/Bind.php b/src/Bind.php index 53744418..3defbbaa 100644 --- a/src/Bind.php +++ b/src/Bind.php @@ -11,9 +11,10 @@ /** * Bind class manages method interception bindings * - * @psalm-import-type MethodInterceptors from Aspect - * @psalm-import-type MethodBindings from Aspect - * @psalm-type Pointcuts = array + * @psalm-import-type MethodInterceptors from Types + * @psalm-import-type MethodBindings from Types + * @psalm-import-type Pointcuts from Types + * @psalm-import-type MethodName from Types */ final class Bind implements BindInterface { @@ -69,7 +70,7 @@ public function bind(string $class, array $pointcuts): BindInterface /** * Bind interceptors to a method * - * @param string $method Method name + * @param MethodName $method Method name * @param MethodInterceptors $interceptors List of interceptors */ public function bindInterceptors(string $method, array $interceptors): BindInterface diff --git a/src/BindInterface.php b/src/BindInterface.php index 278b0e98..3d379337 100644 --- a/src/BindInterface.php +++ b/src/BindInterface.php @@ -4,6 +4,7 @@ namespace Ray\Aop; +/** @psalm-import-type MethodName from Types */ interface BindInterface { /** @@ -17,6 +18,7 @@ public function bind(string $class, array $pointcuts): self; /** * Bind interceptors to method * + * @param MethodName $method * @param MethodInterceptor[] $interceptors */ public function bindInterceptors(string $method, array $interceptors): self; diff --git a/src/BuiltinMatcher.php b/src/BuiltinMatcher.php index 685b7d19..0c17d6a3 100644 --- a/src/BuiltinMatcher.php +++ b/src/BuiltinMatcher.php @@ -13,7 +13,7 @@ /** * @psalm-suppress PropertyNotSetInConstructor - * @psalm-import-type MatcherArguments from AbstractMatcher + * @psalm-import-type MatcherArguments from Types */ class BuiltinMatcher extends AbstractMatcher { diff --git a/src/Compiler.php b/src/Compiler.php index 840fce2e..0f009cf3 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -28,7 +28,7 @@ * AOP (Aspect-Oriented Programming) classes. Handles the binding of * methods and ensures the classes are writable. * - * @psalm-import-type ConstructorArguments from CompilerInterface + * @psalm-import-type ConstructorArguments from Types */ final class Compiler implements CompilerInterface { diff --git a/src/CompilerInterface.php b/src/CompilerInterface.php index 173a160c..087be02a 100644 --- a/src/CompilerInterface.php +++ b/src/CompilerInterface.php @@ -5,11 +5,11 @@ namespace Ray\Aop; /** - * @psalm-import-type MethodInterceptors from Aspect - * @psalm-import-type MethodBindings from Aspect - * @psalm-import-type ClassBindings from Aspect - * @psalm-import-type MatcherConfig from Aspect - * @psalm-type ConstructorArguments = list + * @psalm-import-type MethodInterceptors from Types + * @psalm-import-type MethodBindings from Types + * @psalm-import-type ClassBindings from Types + * @psalm-import-type MatcherConfig from Types + * @psalm-import-type ConstructorArguments from Types */ interface CompilerInterface { diff --git a/src/Matcher/AnyMatcher.php b/src/Matcher/AnyMatcher.php index e9e4012f..6d0664cd 100644 --- a/src/Matcher/AnyMatcher.php +++ b/src/Matcher/AnyMatcher.php @@ -6,15 +6,23 @@ use ArrayObject; use Ray\Aop\AbstractMatcher; +use Ray\Aop\Types; use ReflectionClass; use ReflectionMethod; use function in_array; use function strpos; +/** + * @psalm-import-type Arguments from Types + * @psalm-import-type BuiltinMethodsNames from Types + */ final class AnyMatcher extends AbstractMatcher { - /** @var string[] */ + /** + * @var BuiltinMethodsNames + * @readonly + */ private static $builtinMethods = []; public function __construct() diff --git a/src/MethodMatch.php b/src/MethodMatch.php index d8e0408c..07a33126 100644 --- a/src/MethodMatch.php +++ b/src/MethodMatch.php @@ -11,12 +11,12 @@ use function get_class; /** - * @psalm-import-type MethodInterceptors from Aspect - * @psalm-import-type MethodBindings from Aspect - * @psalm-import-type ClassBindings from Aspect - * @psalm-import-type MatcherConfig from Aspect - * @psalm-import-type Arguments from Aspect - * @psalm-import-type Pointcuts from Bind + * @psalm-import-type MethodInterceptors from Types + * @psalm-import-type MethodBindings from Types + * @psalm-import-type ClassBindings from Types + * @psalm-import-type MatcherConfig from Types + * @psalm-import-type Arguments from Types + * @psalm-import-type Pointcuts from Types */ final class MethodMatch { diff --git a/src/ReflectiveMethodInvocation.php b/src/ReflectiveMethodInvocation.php index 918f9ef4..7695f848 100644 --- a/src/ReflectiveMethodInvocation.php +++ b/src/ReflectiveMethodInvocation.php @@ -14,10 +14,10 @@ use function is_callable; /** + * @psalm-import-type ArgumentList from Types + * @psalm-import-type NamedArguments from Types + * @psalm-import-type InterceptorList from Types * @template T of object - * @psalm-type ArgumentList = ArrayObject - * @psalm-type NamedArguments = ArrayObject - * @psalm-type InterceptorList = array * @implements MethodInvocation */ final class ReflectiveMethodInvocation implements MethodInvocation diff --git a/src/Types.php b/src/Types.php new file mode 100644 index 00000000..54a0ac0a --- /dev/null +++ b/src/Types.php @@ -0,0 +1,58 @@ + + * @psalm-type NamedArguments = ArrayObject + * @psalm-type InterceptorList = array + * @psalm-type ConstructorArguments = list + * @psalm-type ReflectionClassTemplate = ReflectionClass + * + * Matcher Types + * @psalm-type MatcherArguments = array + * @psalm-type MethodInterceptors = array + * @psalm-type MatcherConfig = array{ + * classMatcher: AbstractMatcher, + * methodMatcher: AbstractMatcher, + * interceptors: MethodInterceptors + * } + * @psalm-type Arguments = array + * @psalm-type BuiltinMethodsNames = list + * + * Method and Binding Types + * @psalm-type MethodBindings = array + * @psalm-type ClassBindings = array + * @psalm-type MatcherConfigList = array + * @psalm-type MethodBoundInterceptors = array + * @psalm-type ClassBoundInterceptors = array + * + * PointCut Types + * @psalm-type Pointcuts = array + * @phpcs:enable + */ +final class Types +{ + /** @codeCoverageIgnore */ + private function __construct() + { + } +}