diff --git a/Library/Compiler.php b/Library/Compiler.php index a312f8e5b5..95cc950539 100644 --- a/Library/Compiler.php +++ b/Library/Compiler.php @@ -32,7 +32,7 @@ */ class Compiler { - const VERSION = '0.9.9'; + const VERSION = '0.9.10'; public $parserCompiled = false; diff --git a/Library/Expression/NativeArrayAccess.php b/Library/Expression/NativeArrayAccess.php index ed56620937..c008a6e911 100644 --- a/Library/Expression/NativeArrayAccess.php +++ b/Library/Expression/NativeArrayAccess.php @@ -143,9 +143,12 @@ protected function _accessStringOffset($expression, Variable $variableVariable, } /** - * @param array $expression - * @param Variable $variableVariable + * @param array $expression + * @param Variable $variableVariable * @param CompilationContext $compilationContext + * @return CompiledExpression + * + * @throws CompilerException */ protected function _accessDimensionArray($expression, Variable $variableVariable, CompilationContext $compilationContext) { diff --git a/Library/FunctionCall.php b/Library/FunctionCall.php index 0728d2d669..14caa871fd 100644 --- a/Library/FunctionCall.php +++ b/Library/FunctionCall.php @@ -207,6 +207,9 @@ protected function markReferences($funcName, $parameters, CompilationContext $co * @param array $expression * @param Call $call * @param CompilationContext $compilationContext + * @return bool|mixed + * + * @throws \Exception */ protected function optimize($funcName, array $expression, Call $call, CompilationContext $compilationContext) { @@ -218,6 +221,7 @@ protected function optimize($funcName, array $expression, Call $call, Compilatio if (!isset(self::$_optimizers[$funcName])) { $camelizeFunctionName = Utils::camelize($funcName); + /** * Check every optimizer directory for an optimizer */ @@ -257,6 +261,7 @@ protected function optimize($funcName, array $expression, Call $call, Compilatio * Checks if the function is a built-in provided by Zephir * * @param string $functionName + * @return bool */ public function isBuiltInFunction($functionName) { @@ -309,8 +314,11 @@ public function functionExists($functionName, CompilationContext $context) } /** - * @param array $expression + * @param array $expression * @param CompilationContext $compilationContext + * @return CompiledExpression + * + * @throws CompilerException */ protected function _callNormal(array $expression, CompilationContext $compilationContext) { diff --git a/Library/Optimizers/FunctionCall/FunctionExistsOptimizer.php b/Library/Optimizers/FunctionCall/FunctionExistsOptimizer.php index 1094ff09c8..21add72b2a 100644 --- a/Library/Optimizers/FunctionCall/FunctionExistsOptimizer.php +++ b/Library/Optimizers/FunctionCall/FunctionExistsOptimizer.php @@ -21,7 +21,6 @@ use Zephir\Call; use Zephir\CompilationContext; -use Zephir\CompilerException; use Zephir\CompiledExpression; use Zephir\Optimizers\OptimizerAbstract; use Zephir\Utils; diff --git a/appveyor.yml b/appveyor.yml index 56bf5f2ce7..34a0d0a9cf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,22 @@ -version: 0.9.9-{build} +#---------------------------------# +# general configuration # +#---------------------------------# -build: false +# version format +version: 0.9.10-{build} + +# branches to build +branches: + # whitelist + only: + - master + - development + +#---------------------------------# +# environment configuration # +#---------------------------------# + +# environment variables environment: matrix: - PHP_TARGET: 5.6 @@ -8,14 +24,13 @@ environment: PHP_SDK: c:\projects\php-sdk PHP_DEVPACK: c:\projects\php-devpack +# clone entire repository history if not defined clone_depth: 1 -clone_folder: c:\projects\zephir -branches: - only: - - master - - development +# clone directory +clone_folder: c:\projects\zephir +# scripts that are called at very beginning, before repo cloning init: - SET ANSICON=121x90 (121x90) - SET COMPOSER_NO_INTERACTION=1 @@ -23,31 +38,51 @@ init: - SET PARSER_VERSION=1.0.3-258 - ps: IF ($env:APPVEYOR_REPO_BRANCH -eq "development") {$env:APPVEYOR_CACHE_SKIP_SAVE = "true"} +# build cache to preserve files/folders between builds cache: - vendor -> composer.json - composer.phar -> composer.json +matrix: + # immediately finish build once one of the jobs fails + fast_finish: true + +# Operating system (build VM template) os: Windows Server 2012 R2 + +#---------------------------------# +# build configuration # +#---------------------------------# + +# add platforms to build matrix (i.e. x86, x64, AnyCPU): platform: - x86 -matrix: - fast_finish: true +# disable automatic builds +build: false +# scripts that run after cloning repository install: # ================================================== - echo Setting PHP version... # ================================================== - appveyor DownloadFile http://windows.php.net/downloads/releases/sha1sum.txt - - ps: $env:PHP_VERSION=type sha1sum.txt | where { $_ -match "php-(${env:PHP_TARGET}\.\d+)-src" } | foreach { $matches[1] } + - ps: | + $matched_versions = type sha1sum.txt | where { $_ -match "php-(${env:PHP_TARGET}\.\d+)-src" } | foreach { $matches[1] } + $cleaned_version = $matched_versions.Split(' ')[-1] + $env:PHP_VERSION=${cleaned_version} - ps: $env:PARSER_DOWNLOAD_URL="https://github.com/phalcon/php-zephir-parser/releases/download/v${env:PARSER_RELEASE}/zephir_parser_${env:PLATFORM}_vc${env:PHP_VC}_php${env:PHP_TARGET}_${env:PARSER_VERSION}.zip" + # ================================================== - echo Initializing Build... + # ================================================== - cd %APPVEYOR_BUILD_FOLDER% - git submodule update --init --recursive - echo Preparing zephir win32 build... - - echo Downloading PHP source code [%PHP_VERSION%] + # ================================================== + - echo Downloading PHP source code [http://windows.php.net/downloads/releases/php-%PHP_VERSION%-Win32-VC%PHP_VC%-%PLATFORM%.zip] + # ================================================== - ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/releases/php-' + ${env:PHP_VERSION} + '-Win32-VC' + ${env:PHP_VC} + '-' + ${env:PLATFORM} + '.zip', ${env:APPVEYOR_BUILD_FOLDER} + '\..\php.zip') - cd .. - 'mkdir php && mv php.zip php\php.zip && cd php' @@ -82,23 +117,38 @@ install: - 'set PATH=%cd%;%PATH%' - php --ri "Zephir Parser" - # ================================================== - - echo Download tests dependencies... - # ================================================== +#---------------------------------# +# tests configuration # +#---------------------------------# + +# disable automatic tests +test: off + +# scripts to run before tests +before_test: + - ps: Write-Host "Download tests dependencies.." - cd %APPVEYOR_BUILD_FOLDER% - if not exist vendor (php -r "readfile('https://getcomposer.org/installer');" | php && php composer.phar --version) - if not exist vendor (php composer.phar update --quiet --no-ansi --no-interaction --no-progress --optimize-autoloader --dev --prefer-dist --no-suggest) + - php composer.phar dump-autoload -build_script: + - ps: Write-Host "Start custom build.." + - cd %APPVEYOR_BUILD_FOLDER% + - 'bin\zephir build -Wnonexistent-function -Wnonexistent-class -Wunused-variable' - 'cd %APPVEYOR_BUILD_FOLDER%\..\php' - 'echo extension=%APPVEYOR_BUILD_FOLDER%\ext\Release_TS\php_test.dll >> php.ini' - - cd %APPVEYOR_BUILD_FOLDER% - - 'bin\zephir build' +# run custom scripts instead of automatic tests test_script: + - ps: Write-Host "Start unit test.." - cd %APPVEYOR_BUILD_FOLDER% - 'php unit-tests/phpunit -c phpunit.xml.dist --not-exit --debug' +#---------------------------------# +# global handlers # +#---------------------------------# + +# on build failure on_failure: - 'dir' - ps: >- diff --git a/kernels/ZendEngine3/main.c b/kernels/ZendEngine3/main.c index 5d5397ae97..144acc784e 100644 --- a/kernels/ZendEngine3/main.c +++ b/kernels/ZendEngine3/main.c @@ -254,11 +254,13 @@ int zephir_fast_count_int(zval *value) } /** - * Check if a function exists using explicit char param (using precomputed hash key) + * Check if a function exists using explicit function length + * + * @todo Deprecated. Will be removed in future */ -int zephir_function_quick_exists_ex(const char *method_name, unsigned int method_len) +int zephir_function_quick_exists_ex(const char *function_name, size_t function_len) { - if (zend_hash_str_exists(CG(function_table), method_name, method_len)) { + if (zend_hash_str_exists(CG(function_table), function_name, function_len)) { return SUCCESS; } @@ -267,19 +269,23 @@ int zephir_function_quick_exists_ex(const char *method_name, unsigned int method /** * Check if a function exists + * + * @param function_name + * @return */ int zephir_function_exists(const zval *function_name) { + if (zend_hash_str_exists(CG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name))) { + return SUCCESS; + } - return zephir_function_quick_exists_ex( - Z_STRVAL_P(function_name), - Z_STRLEN_P(function_name) + 1 - ); + return FAILURE; } /** - * Check if a function exists using explicit char param + * Check if a function exists using explicit function length * + * @todo Deprecated. Will be removed in future * @param function_name * @param function_len strlen(function_name) + 1 */ diff --git a/test/functionexists.zep b/test/functionexists.zep new file mode 100644 index 0000000000..c7020fe8f6 --- /dev/null +++ b/test/functionexists.zep @@ -0,0 +1,33 @@ + +namespace Test; + +class FunctionExists +{ + public function testWithPassedName(string func) -> bool + { + return function_exists(func); + } + + public function testBuiltInFunctions() -> array + { + var func; + array result = []; + + array functions = [ + "substr", + "cubstr", + "ucfirst", + "bcfirst", + "stripos", + "ktripos", + "trim", + "prim" + ]; + + for func in functions { + let result[func] = function_exists(func); + } + + return result; + } +} diff --git a/unit-tests/Extension/FunctionExistsTest.php b/unit-tests/Extension/FunctionExistsTest.php new file mode 100644 index 0000000000..6ddb80fe8e --- /dev/null +++ b/unit-tests/Extension/FunctionExistsTest.php @@ -0,0 +1,73 @@ +assertTrue($t->testWithPassedName($func)); + } + + /** + * @test + * @issue 1547 + */ + public function shouldCorrectDetectestExistenceInsideTheZephirCode() + { + $t = new FunctionExists(); + $expected = [ + "substr" => true, + "cubstr" => false, + "ucfirst" => true, + "bcfirst" => false, + "stripos" => true, + "ktripos" => false, + "trim" => true, + "prim" => false, + ]; + + $this->assertSame($expected, $t->testBuiltInFunctions()); + } + + public function providerInternalFunctions() + { + $allFunctions = get_defined_functions(); + shuffle($allFunctions['internal']); + + $functions = array_map( + function ($value) { + return [$value]; + }, + $allFunctions['internal'] + ); + + return array_slice($functions, 0, 10); + } +}