From 3d0d517993417e11444cc2d187ce7e435771660b Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Wed, 3 Jan 2018 23:43:56 +0200 Subject: [PATCH 01/40] Updated README [ci skip] --- README.md | 55 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index efca36832f..b9a480b435 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ -# Zephir - -[![Dependency Status](https://www.versioneye.com/package/phalcon:zephir/badge.png)](https://www.versioneye.com/package/phalcon:zephir) -[![Latest Stable Version](https://poser.pugx.org/phalcon/zephir/v/stable.png)](https://packagist.org/packages/phalcon/zephir) -[![Total Downloads](https://poser.pugx.org/phalcon/zephir/downloads.png)](https://packagist.org/packages/phalcon/zephir) -[![License](https://poser.pugx.org/phalcon/zephir/license.svg)](https://packagist.org/packages/phalcon/zephir) -[![Build on Linux](https://secure.travis-ci.org/phalcon/zephir.svg?branch=master)](http://travis-ci.org/phalcon/zephir) -[![Build on Windows](https://ci.appveyor.com/api/projects/status/cxa1810md7v6n095/branch/master?svg=true)](https://ci.appveyor.com/project/sergeyklay/zephir/branch/master) +# Zephir +[![Latest Stable Version][badge-zep-version]][zep-packagist] +[![Total Downloads][badge-zep-downloads]][zep-packagist] +[![License][badge-zep-license]][zep-packagist] +[![Build on Linux][badge-zep-travisci]][zep-travisci] +[![Build on Windows][badge-zep-appveyor]][zep-appveyor] **Zephir** - Ze(nd Engine) Ph(p) I(nt)r(mediate) - is a high level language that eases the creation and maintainability of extensions for PHP. Zephir extensions are exported to C code that can be compiled and optimized by major C compilers @@ -28,22 +26,24 @@ Compiler design goals: ## Requirements -* [re2c](http://re2c.org/) >= 0.13.6 -* [Zephir Parser](https://github.com/phalcon/php-zephir-parser) >= 1.1.0 -* `g++` >= 4.4 | `clang++` >= 3.x | `vc++` >= 11 +* [re2c][re2c] >= 0.13.6 +* [Zephir Parser][zephir-parser] >= 1.1.0 +* A C compiler such as `gcc` 4.4/later or an alternative such as `clang` 3.x/later, + `Visual C++` 11/later or `Intel C++`. It is recommended to use `gcc` 4.4 or later * GNU `make` >= 3.81 * `automake` * PHP development headers and tools +* The `build-essential` package when using `gcc` on Ubuntu (and likely other distros as well) ## Installation **NOTE:** The `development` branch will always contain the latest **unstable** version. If you wish to check older versions or formal, tagged release, please switch to the relevant -[branch](https://github.com/phalcon/zephir/branches)/[tag](https://github.com/phalcon/zephir/tags). +[branch][zep-branches]/[tag][zep-tags]. ### Windows -To install Zephir on Windows [follow this guide](https://github.com/phalcon/zephir/blob/master/WINDOWS.md). +To install Zephir on Windows [follow this guide][zep-doc-windows]. ### Linux | macOS | BSD | Solaris @@ -76,16 +76,35 @@ zephir compile ## External Links -* [Documentation](https://zephir-lang.com/) -* [Official Blog](https://blog.zephir-lang.com/) -* [Forum](https://forum.zephir-lang.com/) -* [Twitter](https://twitter.com/zephirlang) +* [Documentation][zep-docs-site] +* [Official Blog][zep-blog-site] +* [Forum][zep-forum] +* [Twitter][zep-twitter] ## Contributing -See [CONTRIBUTING.md](https://github.com/phalcon/zephir/blob/master/CONTRIBUTING.md) for details about contributions to this repository. +See [CONTRIBUTING.md][zep-doc-contributting] for details about contributions to this repository. ## License Zephir is open-sourced software licensed under the MIT License. See the LICENSE file for more information. + +[zep-packagist]: https://packagist.org/packages/phalcon/zephir +[zep-travisci]: https://travis-ci.org/phalcon/zephir +[zep-appveyor]: https://ci.appveyor.com/project/sergeyklay/zephir/branch/master +[re2c]: http://re2c.org/ +[zephir-parser]: https://github.com/phalcon/php-zephir-parser +[zep-branches]: https://github.com/phalcon/zephir/branches +[zep-tags]: https://github.com/phalcon/zephir/tags +[zep-doc-windows]: https://github.com/phalcon/zephir/blob/master/WINDOWS.md +[zep-doc-contributting]: https://github.com/phalcon/zephir/blob/master/CONTRIBUTING.md +[zep-docs-site]: https://docs.zephir-lang.com/ +[zep-blog-site]: https://blog.zephir-lang.com/ +[zep-forum]: https://forum.zephir-lang.com/ +[zep-twitter]: https://twitter.com/zephirlang +[badge-zep-version]: https://poser.pugx.org/phalcon/zephir/v/stable.png +[badge-zep-downloads]: https://poser.pugx.org/phalcon/zephir/downloads.png +[badge-zep-license]: https://poser.pugx.org/phalcon/zephir/license.svg +[badge-zep-travisci]: https://img.shields.io/travis/phalcon/zephir/master.svg +[badge-zep-appveyor]: https://ci.appveyor.com/api/projects/status/cxa1810md7v6n095?svg=true From eb1b5e3c02ec15edeac259204f49ee8f36dd8c17 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Wed, 3 Jan 2018 23:45:51 +0200 Subject: [PATCH 02/40] Updated README [ci skip] --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b9a480b435..d81dff5c34 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ Compiler design goals: * [re2c][re2c] >= 0.13.6 * [Zephir Parser][zephir-parser] >= 1.1.0 -* A C compiler such as `gcc` 4.4/later or an alternative such as `clang` 3.x/later, - `Visual C++` 11/later or `Intel C++`. It is recommended to use `gcc` 4.4 or later +* A C compiler such as `gcc` >= 4.4 or an alternative such as `clang` >= 3.0, + `Visual C++` >= 11 or `Intel C++`. It is recommended to use `gcc` 4.4 or later * GNU `make` >= 3.81 * `automake` * PHP development headers and tools From d30c75b07ed3cbb4246aafd21e4d100f692cd440 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Wed, 3 Jan 2018 23:50:00 +0200 Subject: [PATCH 03/40] Updated README [ci skip] --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d81dff5c34..dfc5097d93 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ zephir compile * [Official Blog][zep-blog-site] * [Forum][zep-forum] * [Twitter][zep-twitter] +* [Facebook Group][zep-facebook] ## Contributing @@ -103,6 +104,7 @@ See the LICENSE file for more information. [zep-blog-site]: https://blog.zephir-lang.com/ [zep-forum]: https://forum.zephir-lang.com/ [zep-twitter]: https://twitter.com/zephirlang +[zep-facebook]: https://www.facebook.com/groups/zephir.language/ [badge-zep-version]: https://poser.pugx.org/phalcon/zephir/v/stable.png [badge-zep-downloads]: https://poser.pugx.org/phalcon/zephir/downloads.png [badge-zep-license]: https://poser.pugx.org/phalcon/zephir/license.svg From 872b4e195375568e11d97eec3d62684cfb8230fa Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sat, 14 Apr 2018 13:36:09 +0300 Subject: [PATCH 04/40] Do not throw exeption when superglobal does not exist --- Library/Backends/ZendEngine3/Backend.php | 34 +++++++-------- kernels/ZendEngine2/array.c | 2 +- kernels/ZendEngine3/array.c | 2 +- test/globals/post.zep | 15 +++++++ unit-tests/Extension/Globals/PostTest.php | 51 +++++++++++++++++++++++ 5 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 test/globals/post.zep create mode 100644 unit-tests/Extension/Globals/PostTest.php diff --git a/Library/Backends/ZendEngine3/Backend.php b/Library/Backends/ZendEngine3/Backend.php index 0edcda5843..803847c2cb 100644 --- a/Library/Backends/ZendEngine3/Backend.php +++ b/Library/Backends/ZendEngine3/Backend.php @@ -214,19 +214,20 @@ public function onPostCompile($method, CompilationContext $context) public function generateInitCode(&$groupVariables, $type, $pointer, Variable $variable) { - $isComplex = ($type == 'variable' || $type == 'string' || $type == 'array' || $type == 'resource' || $type == 'callable' || $type == 'object'); if ($isComplex && !$variable->isDoublePointer() && !$variable->isSuperGlobal()) { /* && $variable->mustInitNull() */ $groupVariables[] = $variable->getName(); - if ($variable->getRealname() == '__$null') { - return "\t" . 'ZVAL_NULL(&' . $variable->getName() . ');'; - } else if ($variable->getRealname() == '__$true') { - return "\t" . 'ZVAL_BOOL(&' . $variable->getName() . ', 1);'; - } else if ($variable->getRealname() == '__$false') { - return "\t" . 'ZVAL_BOOL(&' . $variable->getName() . ', 0);'; + switch ($variable->getRealname()) { + case '__$null': + return "\t" . 'ZVAL_NULL(&' . $variable->getName() . ');'; + case '__$true': + return "\t" . 'ZVAL_BOOL(&' . $variable->getName() . ', 1);'; + case '__$false': + return "\t" . 'ZVAL_BOOL(&' . $variable->getName() . ', 0);'; + default: + return "\t".'ZVAL_UNDEF(&' . $variable->getName() . ');'; } - return "\t".'ZVAL_UNDEF(&' . $variable->getName() . ');'; } if ($variable->isLocalOnly()) { @@ -528,19 +529,14 @@ public function arrayUnset(Variable $variable, $exprIndex, $flags, CompilationCo public function fetchGlobal(Variable $globalVar, CompilationContext $compilationContext, $useCodePrinter = true) { - $name = $globalVar->getName(); - $lines = array(); - $lines[] = 'zephir_get_global(&' . $name . ', SL("' . $name . '"));'; - $lines[] = 'if (!' . $name . ') {'; - $lines[] = "\t" . 'ZEPHIR_THROW_EXCEPTION_STR(zend_exception_get_default(), "Invalid superglobal");'; - $lines[] = "\t" . 'return;'; - $lines[] = '}'; + $name = $globalVar->getName(); + $output = strtr('zephir_get_global(&:name, SL(":name"));', [':name' => $name]); + if ($useCodePrinter) { - foreach ($lines as $line) { - $compilationContext->codePrinter->output($line); - } + $compilationContext->codePrinter->output($output); } - return join("\n\t", $lines); + + return $output; } public function fetchClass(Variable $zendClassEntry, $className, $guarded, CompilationContext $context) diff --git a/kernels/ZendEngine2/array.c b/kernels/ZendEngine2/array.c index d7c5fcf56a..6acef72e1c 100644 --- a/kernels/ZendEngine2/array.c +++ b/kernels/ZendEngine2/array.c @@ -184,7 +184,7 @@ int ZEPHIR_FASTCALL zephir_array_isset(const zval *arr, zval *index) { HashTable *h; - if (Z_TYPE_P(arr) != IS_ARRAY) { + if (UNEXPECTED(!arr || Z_TYPE_P(arr) != IS_ARRAY)) { return 0; } diff --git a/kernels/ZendEngine3/array.c b/kernels/ZendEngine3/array.c index 059d2b564c..1e6289a849 100644 --- a/kernels/ZendEngine3/array.c +++ b/kernels/ZendEngine3/array.c @@ -151,7 +151,7 @@ int ZEPHIR_FASTCALL zephir_array_isset(const zval *arr, zval *index) { HashTable *h; - if (Z_TYPE_P(arr) != IS_ARRAY) { + if (UNEXPECTED(!arr || Z_TYPE_P(arr) != IS_ARRAY)) { return 0; } diff --git a/test/globals/post.zep b/test/globals/post.zep new file mode 100644 index 0000000000..46f731fc7c --- /dev/null +++ b/test/globals/post.zep @@ -0,0 +1,15 @@ + +namespace Test\Globals; + +class Post +{ + /** + * Tests "Invalid superglobal for _POST" + * + * @issue 1623 + */ + public function hasValue(string name) -> boolean + { + return isset _POST[name]; + } +} diff --git a/unit-tests/Extension/Globals/PostTest.php b/unit-tests/Extension/Globals/PostTest.php new file mode 100644 index 0000000000..982adb150d --- /dev/null +++ b/unit-tests/Extension/Globals/PostTest.php @@ -0,0 +1,51 @@ +assertFalse(isset($_POST)); + $this->assertFalse($tester->hasValue('issue-1623')); + } + + /** + * @test + * @issue 1623 + */ + public function shouldReturnFalseIfVariableIsUndefined() + { + $tester = new Post(); + + $_POST = []; + + $this->assertTrue(isset($_POST)); + $this->assertFalse($tester->hasValue('issue-1623')); + } + + /** + * @test + * @issue 1623 + */ + public function shouldReturnTrueIfVariableIsDefined() + { + $tester = new Post(); + + $_POST = ['issue-1623' => true]; + + $this->assertTrue(isset($_POST)); + $this->assertTrue($tester->hasValue('issue-1623')); + } +} From 07400cf7a4e884e93f6fe08e23cc6600743b27bb Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sat, 14 Apr 2018 16:26:54 +0300 Subject: [PATCH 05/40] Fixed AppVeyor builds --- appveyor.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 6a571ee1a0..94d08ab73a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,7 +3,7 @@ #---------------------------------# # version format -version: 0.10.7-{build} +version: 0.10.8-{build} # branches to build branches: @@ -66,11 +66,17 @@ install: # ================================================== - echo Setting PHP version... # ================================================== - - appveyor DownloadFile http://windows.php.net/downloads/releases/sha1sum.txt - - 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: Invoke-WebRequest http://windows.php.net/downloads/releases/sha1sum.txt -OutFile ${Env:Temp}\sha1sum.txt + - ps: >- + $VersionString = Get-Content ${Env:Temp}\sha1sum.txt | Where-Object { + $_ -match "php-($Env:PHP_TARGET\.\d+)-src" + } | ForEach-Object { $matches[1] } + + If ($VersionString -NotMatch '\d+\.\d+\.\d+') { + Throw "Unable to obtain PHP version string using pattern 'php-($Env:PHP_TARGET\.\d+)-src'" + } + + $Env:PHP_VERSION = ${VersionString} - ps: $env:PARSER_DOWNLOAD_URL="https://github.com/phalcon/php-zephir-parser/releases/download/v${env:PARSER_VERSION}/zephir_parser_${env:PLATFORM}_vc${env:PHP_VC}_php${env:PHP_TARGET}_${env:PARSER_VERSION}-${env:PARSER_RELEASE}.zip" # ================================================== From 7582e86aeff01bb0a920e6221b273c5415ec7797 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 15 Apr 2018 11:21:47 +0300 Subject: [PATCH 06/40] Added alias for namespaced phpunit --- unit-tests/phpunit | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/unit-tests/phpunit b/unit-tests/phpunit index 0086bb2ad9..bf187b62f6 100755 --- a/unit-tests/phpunit +++ b/unit-tests/phpunit @@ -14,6 +14,11 @@ require dirname(__DIR__) . DIRECTORY_SEPARATOR . 'bootstrap.php'; +if (!class_exists('\PHPUnit\Framework\TestCase') and class_exists('PHPUnit_Framework_TestCase')) { + /** @noinspection PhpIgnoredClassAliasDeclaration */ + class_alias('PHPUnit_Framework_TestCase', '\PHPUnit\Framework\TestCase'); +} + $exit = true; if ($index = array_search('--not-exit', $_SERVER['argv'])) { $exit = false; From 40791d8e598a5a4b236dce94a9f746f18967ce81 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 15 Apr 2018 11:22:48 +0300 Subject: [PATCH 07/40] Fixed processing uchar globals --- Library/Compiler.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Library/Compiler.php b/Library/Compiler.php index 5d275c5980..c9bab5b526 100644 --- a/Library/Compiler.php +++ b/Library/Compiler.php @@ -31,7 +31,7 @@ */ class Compiler { - const VERSION = '0.10.7'; + const VERSION = '0.10.8'; public $parserCompiled = false; @@ -1576,9 +1576,9 @@ public function processExtensionGlobals($namespace) case 'uchar': $globalsDefault[$isModuleGlobal][] = "\t" . $namespace . '_globals->' . $name . ' = \'' . - $global['default'] . '\'";' . PHP_EOL; + $global['default'] . '\';' . PHP_EOL; break; - + // TODO: Add 'string', 'hash' default: throw new Exception( "Unknown type '" . $global['type'] . "' for extension global '" . $name . "'" From 2729f3d3e1a30af023fefa8701b50d7249fee344 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 15 Apr 2018 14:57:22 +0300 Subject: [PATCH 08/40] Fixed PHPdoc --- Library/Compiler.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Library/Compiler.php b/Library/Compiler.php index c9bab5b526..864901a3f0 100644 --- a/Library/Compiler.php +++ b/Library/Compiler.php @@ -568,7 +568,7 @@ public function isExtensionGlobal($name) * * @param string $name * - * @return boolean + * @return array */ public function getExtensionGlobal($name) { @@ -1552,6 +1552,8 @@ public function processExtensionGlobals($namespace) $isModuleGlobal = (int) !empty($global['module']); $type = $global['type']; + // @todo Add support for 'string', 'hash' + // @todo Zephir\Optimizers\FunctionCall\GlobalsSetOptimizer switch ($global['type']) { case 'boolean': case 'bool': @@ -1578,7 +1580,6 @@ public function processExtensionGlobals($namespace) = "\t" . $namespace . '_globals->' . $name . ' = \'' . $global['default'] . '\';' . PHP_EOL; break; - // TODO: Add 'string', 'hash' default: throw new Exception( "Unknown type '" . $global['type'] . "' for extension global '" . $name . "'" From b1424475ac990affad65e93a3977536db32f5ec3 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 15 Apr 2018 15:01:52 +0300 Subject: [PATCH 09/40] Fixed globals_set --- .../FunctionCall/GlobalsSetOptimizer.php | 109 +++++++++++++++--- config.json | 4 + test/globals.zep | 51 +++++++- unit-tests/Extension/GlobalsTest.php | 82 +++++++++++-- 4 files changed, 220 insertions(+), 26 deletions(-) diff --git a/Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php b/Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php index f04e3c23ab..367441b368 100644 --- a/Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php +++ b/Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php @@ -7,7 +7,7 @@ | | | This source file is subject the MIT license, that is bundled with this | | package in the file LICENSE, and is available through the world-wide-web | - | at the following url: http://zephir-lang.com/license.html | + | at the following url: https://zephir-lang.com/license.html | +--------------------------------------------------------------------------+ */ @@ -15,22 +15,25 @@ use Zephir\Call; use Zephir\CompilationContext; -use Zephir\Compiler\CompilerException; use Zephir\CompiledExpression; +use Zephir\Compiler\CompilerException; +use Zephir\Exception; use Zephir\Optimizers\OptimizerAbstract; /** - * GlobalsSetOptimizer + * Zephir\Optimizers\FunctionCall\GlobalsSetOptimizer * * Writes values from extensions globals */ class GlobalsSetOptimizer extends OptimizerAbstract { /** - * @param array $expression - * @param Call $call - * @param CompilationContext $context - * @return bool|CompiledExpression|mixed + * @param array $expression + * @param Call $call + * @param CompilationContext $context + * + * @return CompiledExpression + * * @throws CompilerException */ public function optimize(array $expression, Call $call, CompilationContext $context) @@ -50,20 +53,98 @@ public function optimize(array $expression, Call $call, CompilationContext $cont $globalName = $expression['parameters'][0]['parameter']['value']; if (!$context->compiler->isExtensionGlobal($globalName)) { - throw new CompilerException("Global '" . $globalName . "' cannot be written because it wasn't defined", $expression); + throw new CompilerException( + "Global '{$globalName}' cannot be written because it wasn't defined", $expression + ); } unset($expression['parameters'][0]); - $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression); + try { + $globalDefinition = $context->compiler->getExtensionGlobal($globalName); + $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression); + + if (!isset($resolvedParams[0]) || empty($resolvedParams[0]) || !is_string($resolvedParams[0])) { + throw new CompilerException( + "Unable to reslove value for '{$globalName}' global variable.", + $expression + ); + } + + if (!isset($globalDefinition['type'])) { + throw new CompilerException( + "Unable to determine type for '{$globalName}' global variable.", + $expression + ); + } + + $internalAccessor = $this->resolveInternalAccessor($globalName); + $internalValue = $this->resolveInternalValue($globalDefinition, $expression, $globalName, $resolvedParams[0]); - $globalDefinition = $context->compiler->getExtensionGlobal($globalName); + $context->codePrinter->output("{$internalAccessor} = {$internalValue};"); - if (strpos($globalName, '.') !== false) { - $parts = explode('.', $globalName); - $context->codePrinter->output('ZEPHIR_GLOBAL(' . $parts[0] . ').' . $parts[1] . ' = zend_is_true(' . $resolvedParams[0] . ');'); + return new CompiledExpression('null', null, $expression); + } catch (Exception $e) { + throw new CompilerException($e->getMessage(), $expression); } + } + + private function resolveInternalAccessor($globalName) + { + $parts = explode('.', $globalName); - return new CompiledExpression('null', null, $expression); + if (isset($parts[1])) { + return strtr('ZEPHIR_GLOBAL(:v).:parts', [':v' => $parts[0], ':parts' => $parts[1]]); + } + + return strtr('ZEPHIR_GLOBAL(:v)', [':v' => $parts[0]]); + } + + /** + * @todo Add 'hash' support + * @todo Use zval_get_string, zval_get_long, zval_get_double for ZE3 + * + * @param array $definition + * @param array $expression + * @param string $name + * @param string $value + * + * @return string + */ + private function resolveInternalValue(array $definition, array $expression, $name, $value) + { + $type = $definition['type']; + + switch ($type) { + case 'boolean': + case 'bool': + return strtr('zend_is_true(:v)', [':v' => $value]); + case 'int': + case 'uint': + case 'integer': + case 'long': + case 'ulong': + // TODO: Use zval_get_long when we'll drop Zend Engine 2 + return strtr('Z_LVAL_P(:v)', [':v' => $value]); + case 'string': + // TODO: Use zval_get_string when we'll drop Zend Engine 2 + return strtr('Z_STRVAL_P(:v)', [':v' => $value]); + case 'char': + case 'uchar': + // TODO: Use zval_get_string and zval_get_long when we'll drop Zend Engine 2 + return strtr( + '(Z_TYPE_P(:v) == IS_STRING ? (Z_STRLEN_P(:v) ? Z_STRVAL_P(:v)[0] : NULL) : Z_LVAL_P(:v))', + [':v' => $value] + ); + case 'double': + case 'float': + // TODO: Use zval_get_double when we'll drop Zend Engine 2 + return strtr('Z_DVAL_P(:v)', [':v' => $value]); + default: + throw new CompilerException( + "Unknown type '{$type}' to setting global variable '{$name}'.", + $expression + ); + } } } diff --git a/config.json b/config.json index 5552a11394..beb914ce54 100644 --- a/config.json +++ b/config.json @@ -79,6 +79,10 @@ "type": "double", "default": 15.2 }, + "my_setting_4": { + "type": "char", + "default": "A" + }, "test.my_setting_1": { "type": "bool", "default": true diff --git a/test/globals.zep b/test/globals.zep index a9c7758997..0709a5afc5 100644 --- a/test/globals.zep +++ b/test/globals.zep @@ -1,40 +1,81 @@ -/** - * Extension Globals - */ - namespace Test; class Globals { - + /** + * @return mixed + */ public function getDefaultGlobals1() { return globals_get("test.my_setting_1"); } + /** + * @return mixed + */ public function getDefaultGlobals2() { return globals_get("test.my_setting_2"); } + /** + * @return mixed + */ public function getDefaultGlobals3() { return globals_get("test.my_setting_3"); } + /** + * @return mixed + */ public function getDefaultGlobals4() { return globals_get("my_setting_1"); } + /** + * @return mixed + */ public function getDefaultGlobals5() { return globals_get("my_setting_2"); } + /** + * @return mixed + */ public function getDefaultGlobals6() { return globals_get("my_setting_3"); } + + /** + * @return mixed + */ + public function getDefaultGlobals7() + { + return globals_get("my_setting_4"); + } + + public function setBoolValueUsingDotNotation(value) -> void + { + globals_set("test.my_setting_1", value); + } + + public function setIntValueUsingDotNotation(value) -> void + { + globals_set("test.my_setting_2", value); + } + + public function setCharValue(value) -> void + { + globals_set("my_setting_4", value); + } + + public function setBoolValue(value) -> void + { + globals_set("my_setting_1", value); + } } diff --git a/unit-tests/Extension/GlobalsTest.php b/unit-tests/Extension/GlobalsTest.php index 386f8728b2..8db38a9993 100644 --- a/unit-tests/Extension/GlobalsTest.php +++ b/unit-tests/Extension/GlobalsTest.php @@ -13,17 +13,85 @@ namespace Extension; -class GlobalsTest extends \PHPUnit_Framework_TestCase +use Test\Globals; +use PHPUnit\Framework\TestCase; + +/** + * Extension\GlobalsTest + * + * @package Extension + */ +class GlobalsTest extends TestCase { - public function testGlobals() + /** @test */ + public function shouldGetGlobalExtensionSettings() { - $t = new \Test\Globals(); + $t = new Globals(); $this->assertTrue($t->getDefaultGlobals1()); - $this->assertSame($t->getDefaultGlobals2(), 100); - $this->assertSame($t->getDefaultGlobals3(), 7.5); $this->assertTrue($t->getDefaultGlobals4()); - $this->assertSame($t->getDefaultGlobals5(), 10); - $this->assertSame($t->getDefaultGlobals6(), 15.2); + + $this->assertSame(100, $t->getDefaultGlobals2()); + $this->assertSame(7.5, $t->getDefaultGlobals3()); + $this->assertSame(10, $t->getDefaultGlobals5()); + $this->assertSame(15.2, $t->getDefaultGlobals6()); + $this->assertSame(65, $t->getDefaultGlobals7()); + } + + /** @test */ + public function shouldSetGlobalExtensionSetting() + { + $t = new Globals(); + + $t->setBoolValueUsingDotNotation(false); + $this->assertFalse($t->getDefaultGlobals1()); + } + + /** @test */ + public function setIntValueUsingDotNotation() + { + $t = new Globals(); + + $t->setIntValueUsingDotNotation(900); + $this->assertSame(900, $t->getDefaultGlobals2()); + } + + /** @test */ + public function setCharValueUsingString() + { + $t = new Globals(); + + $t->setCharValue("B"); + $this->assertSame(66, $t->getDefaultGlobals7()); + } + + /** @test */ + public function setCharValueUsingInt() + { + $t = new Globals(); + + $t->setCharValue(90); + $this->assertSame(90, $t->getDefaultGlobals7()); + } + + /** @test */ + public function setBoolValueUsingInt() + { + $t = new Globals(); + + $t->setBoolValue(0); + $this->assertFalse($t->getDefaultGlobals4()); + } + + /** @test */ + public function setBoolValueUsingBool() + { + $t = new Globals(); + + $t->setBoolValue(true); + $this->assertTrue($t->getDefaultGlobals4()); + + $t->setBoolValue(false); + $this->assertFalse($t->getDefaultGlobals4()); } } From dc2fd0f04eb13c7afb0519732f2868bc3cadad9b Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 15 Apr 2018 15:09:49 +0300 Subject: [PATCH 10/40] PSR-related fixes --- Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php | 3 ++- unit-tests/Extension/GlobalsTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php b/Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php index 367441b368..9d5238961c 100644 --- a/Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php +++ b/Library/Optimizers/FunctionCall/GlobalsSetOptimizer.php @@ -54,7 +54,8 @@ public function optimize(array $expression, Call $call, CompilationContext $cont if (!$context->compiler->isExtensionGlobal($globalName)) { throw new CompilerException( - "Global '{$globalName}' cannot be written because it wasn't defined", $expression + "Global variable '{$globalName}' cannot be written because it wasn't defined", + $expression ); } diff --git a/unit-tests/Extension/GlobalsTest.php b/unit-tests/Extension/GlobalsTest.php index 8db38a9993..b7129a3b2e 100644 --- a/unit-tests/Extension/GlobalsTest.php +++ b/unit-tests/Extension/GlobalsTest.php @@ -31,11 +31,11 @@ public function shouldGetGlobalExtensionSettings() $this->assertTrue($t->getDefaultGlobals1()); $this->assertTrue($t->getDefaultGlobals4()); - $this->assertSame(100, $t->getDefaultGlobals2()); - $this->assertSame(7.5, $t->getDefaultGlobals3()); - $this->assertSame(10, $t->getDefaultGlobals5()); + $this->assertSame(100, $t->getDefaultGlobals2()); + $this->assertSame(7.5, $t->getDefaultGlobals3()); + $this->assertSame(10, $t->getDefaultGlobals5()); $this->assertSame(15.2, $t->getDefaultGlobals6()); - $this->assertSame(65, $t->getDefaultGlobals7()); + $this->assertSame(65, $t->getDefaultGlobals7()); } /** @test */ From 3e0eaf9bbde0ae6fe3e08ed8144397355c22ff27 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 15 Apr 2018 20:57:41 +0300 Subject: [PATCH 11/40] Refactor AppVeyor builds --- .editorconfig | 65 +-- Library/Compiler.php | 54 ++- Library/Utils.php | 50 ++- appveyor.yml | 262 +++++------- unit-tests/Extension/Globals/EnvTest.php | 14 +- unit-tests/ci/appveyor.psm1 | 494 +++++++++++++++++++++++ 6 files changed, 727 insertions(+), 212 deletions(-) create mode 100644 unit-tests/ci/appveyor.psm1 diff --git a/.editorconfig b/.editorconfig index e62cc92756..39ed10eb08 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,31 +1,44 @@ -; http://editorconfig.org/ -root = true +# EditorConfig is awesome: http://EditorConfig.org -[*] -charset = utf-8 -end_of_line = LF +# top-most EditorConfig file +root = true +charset = utf-8 trim_trailing_whitespace = true -insert_final_newline = true - -[*.php] -indent_style = space -indent_size = 4 - -[*.zep] -indent_style = tab -indent_size = 4 - -[*.c] -indent_style = tab - -[*.h] -indent_style = tab -[*.lemon] -indent_style = tab +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 + +[*.{c,h,awk,w32,bat,mk,Makefile,frag,zep,lemon,re,psm1}] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = tab +tab_width = 4 +trim_trailing_whitespace = true +insert_final_newline = true -[*.re] -indent_style = tab +[*.{yml,m4,sh,json,xml}] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +trim_trailing_whitespace = true +insert_final_newline = true -[.gitmodules] -indent_style = tab +[*.{php,phpt}] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +charset = utf-8 +end_of_line = lf +indent_style = space +trim_trailing_whitespace = false +insert_final_newline = true diff --git a/Library/Compiler.php b/Library/Compiler.php index 864901a3f0..cced1f3bfc 100644 --- a/Library/Compiler.php +++ b/Library/Compiler.php @@ -461,11 +461,9 @@ protected function recursiveProcess($src, $dest, $pattern = null, $callback = "c } $this->recursiveProcess($pathName, $dest . DIRECTORY_SEPARATOR . $fileName, $pattern, $callback); } - } else { - if (!$pattern || ($pattern && preg_match($pattern, $fileName) === 1)) { - $path = $dest . DIRECTORY_SEPARATOR . $fileName; - $success = $success && call_user_func($callback, $pathName, $path); - } + } elseif (!$pattern || ($pattern && preg_match($pattern, $fileName) === 1)) { + $path = $dest . DIRECTORY_SEPARATOR . $fileName; + $success = $success && call_user_func($callback, $pathName, $path); } } @@ -475,15 +473,23 @@ protected function recursiveProcess($src, $dest, $pattern = null, $callback = "c /** * Recursively deletes files in a specified location * - * @param string $path - * @param string $mask + * @param string $path Directory to deletes files + * @param string $mask Regular expression to deletes files + * + * @return void */ protected function recursiveDeletePath($path, $mask) { + if (!file_exists($path) || !is_dir($path) || !is_readable($path)) { + $this->logger->output("Directory {$path} does not exist or it is not readble. Skip..."); + return; + } + $objects = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($path), \RecursiveIteratorIterator::SELF_FIRST ); + foreach ($objects as $name => $object) { if (preg_match($mask, $name)) { @unlink($name); @@ -1008,9 +1014,9 @@ public function generate(CommandInterface $command) * Compiles the extension without installing it * * @param CommandInterface $command - * @param boolean $development + * @param bool $development * - * @throws CompilerException + * @throws Exception|CompilerException */ public function compile(CommandInterface $command, $development = false) { @@ -1023,20 +1029,25 @@ public function compile(CommandInterface $command, $development = false) $extensionName = $namespace; } $needConfigure = $this->generate($command); + if ($needConfigure) { if (Utils::isWindows()) { exec('cd ext && %PHP_DEVPACK%\\phpize --clean', $output, $exit); - if (file_exists('ext/Release')) { - exec('rd /s /q ext/Release', $output, $exit); + + $releaseFolder = Utils::resolveWindowsReleaseFolder(); + if (file_exists($releaseFolder)) { + exec('rd /s /q ' . $releaseFolder, $output, $exit); } $this->logger->output('Preparing for PHP compilation...'); exec('cd ext && %PHP_DEVPACK%\\phpize', $output, $exit); /* fix until https://github.com/php/php-src/commit/9a3af83ee2aecff25fd4922ef67c1fb4d2af6201 hits all supported PHP builds */ $fixMarker = "/* zephir_phpize_fix */"; - $configureFile = file_get_contents("ext/configure.js"); - $configureFix = array("var PHP_ANALYZER = 'disabled';", "var PHP_PGO = 'no';", "var PHP_PGI = 'no';"); + + $configureFile = file_get_contents('ext\\configure.js'); + $configureFix = ["var PHP_ANALYZER = 'disabled';", "var PHP_PGO = 'no';", "var PHP_PGI = 'no';"]; $hasChanged = false; + if (strpos($configureFile, $fixMarker) === false) { $configureFile = $fixMarker . PHP_EOL . implode($configureFix, PHP_EOL) . PHP_EOL . $configureFile; $hasChanged = true; @@ -1056,7 +1067,7 @@ public function compile(CommandInterface $command, $development = false) } if ($hasChanged) { - file_put_contents("ext/configure.js", $configureFile); + file_put_contents('ext\\configure.js', $configureFile); } $this->logger->output('Preparing configuration file...'); @@ -2266,15 +2277,15 @@ protected function checkKernelFile($src, $dst) * Checks which files in the base kernel must be copied * * @return boolean + * @throws Exception */ protected function checkKernelFiles() { - $kernelPath = "ext/kernel"; + $kernelPath = 'ext' . DIRECTORY_SEPARATOR . 'kernel'; if (!file_exists($kernelPath)) { - $kernelDone = mkdir($kernelPath, 0775, true); - if (!$kernelDone) { - throw new Exception("Cannot create kernel directory"); + if (!mkdir($kernelPath, 0775, true)) { + throw new Exception("Cannot create kernel directory: {$kernelPath}"); } } @@ -2285,13 +2296,16 @@ protected function checkKernelFiles() $sourceKernelPath, $kernelPath, '@.*\.[ch]$@', - array($this, 'checkKernelFile') + [$this, 'checkKernelFile'] ); if (!$configured) { - $this->logger->output('Copying new kernel files...'); + $this->logger->output('Cleaning old kernel files...'); $this->recursiveDeletePath($kernelPath, '@^.*\.[lcho]$@'); + @mkdir($kernelPath); + + $this->logger->output('Copying new kernel files...'); $this->recursiveProcess($sourceKernelPath, $kernelPath, '@^.*\.[ch]$@'); } diff --git a/Library/Utils.php b/Library/Utils.php index 65c6bd13c5..34409d0236 100644 --- a/Library/Utils.php +++ b/Library/Utils.php @@ -172,7 +172,7 @@ public static function getFullName($className, $currentNamespace, AliasManager $ } /** - * Check if the host OS is windows + * Check if the host OS is Windows * * @return boolean */ @@ -230,4 +230,52 @@ public static function recursiveRmDir($dir) // Ignore } } + + /** + * Resolves Windows release folder. + * + * @return string + */ + public static function resolveWindowsReleaseFolder() + { + if (self::isThreadSafe()) { + if (PHP_INT_SIZE === 4) { + // 32-bit version of PHP + return "ext\\Release_TS"; + } elseif (PHP_INT_SIZE === 8) { + // 64-bit version of PHP + return "ext\\x64\\Release_TS"; + } else { + // fallback + return "ext\\Release_TS"; + } + } else { + if (PHP_INT_SIZE === 4) { + // 32-bit version of PHP + return "ext\\Release"; + } elseif (PHP_INT_SIZE === 8) { + // 64-bit version of PHP + return "ext\\x64\\Release"; + } else { + // fallback + return "ext\\Release"; + } + } + } + + /** + * Checks if current PHP is thread safe. + * + * @return boolean true + */ + public static function isThreadSafe() + { + if (defined('PHP_ZTS') && PHP_ZTS == 1) { + return true; + } + + ob_start(); + phpinfo(INFO_GENERAL); + return (bool) preg_match('/Thread\s*Safety\s*enabled/i', strip_tags(ob_get_clean())); + } } diff --git a/appveyor.yml b/appveyor.yml index 94d08ab73a..613d99108b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,185 +1,123 @@ -#---------------------------------# -# general configuration # -#---------------------------------# - -# version format version: 0.10.8-{build} -# branches to build -branches: - # whitelist - only: - - master - - development - -#---------------------------------# -# environment configuration # -#---------------------------------# - -# environment variables environment: matrix: - - PHP_TARGET: 5.6 - PHP_VC: 11 - PHP_SDK: c:\projects\php-sdk - PHP_DEVPACK: c:\projects\php-devpack - -# clone entire repository history if not defined -clone_depth: 1 - -# 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 - - SET PARSER_VERSION=1.1.1 - - SET PARSER_RELEASE=268 - - 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 + - PHP_MINOR: 7.0 + VC_VERSION: 14 + BUILD_TYPE: Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + + - PHP_MINOR: 7.0 + VC_VERSION: 14 + BUILD_TYPE: nts-Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + + # - PHP_MINOR: 7.1 + # VC_VERSION: 14 + # BUILD_TYPE: Win32 + # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + + # - PHP_MINOR: 7.1 + # VC_VERSION: 14 + # BUILD_TYPE: nts-Win32 + # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + + # - PHP_MINOR: 7.2 + # VC_VERSION: 15 + # BUILD_TYPE: Win32 + # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + + # - PHP_MINOR: 7.2 + # VC_VERSION: 15 + # BUILD_TYPE: nts-Win32 + # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + + PHP_PATH: C:\Projects\php + PHP_SDK_PATH: C:\Projects\php-sdk + PHP_DEVPACK: C:\Projects\php-devpack + TEST_PHP_EXECUTABLE: C:\Projects\php\php.exe + PHP_SDK_VERSION: 2.0.7 + PACKAGE_PREFIX: test + EXTENSION_NAME: test + EXTENSION_FILE: php_test.dll + NO_INTERACTION: 1 + REPORT_EXIT_STATUS: 1 + COMPOSER_NO_INTERACTION: 1 + PARSER_VERSION: 1.1.2 + PARSER_RELEASE: 290 + ZEPHIRDIR: c:\projects\zephir matrix: - # immediately finish build once one of the jobs fails fast_finish: true -# Operating system (build VM template) -os: Windows Server 2012 R2 +cache: + - 'C:\Downloads -> appveyor.yml' + - 'vendor -> composer.json' + - 'composer.phar -> composer.json' -#---------------------------------# -# build configuration # -#---------------------------------# +clone_depth: 1 +clone_folder: c:\projects\zephir -# add platforms to build matrix (i.e. x86, x64, AnyCPU): platform: - x86 + - x64 -# disable automatic builds -build: false +branches: + only: + - master + - development + +init: + - ps: IF ($env:APPVEYOR_REPO_BRANCH -eq "development") {$env:APPVEYOR_CACHE_SKIP_SAVE = "true"} -# scripts that run after cloning repository install: - # ================================================== - - echo Setting PHP version... - # ================================================== - - ps: Invoke-WebRequest http://windows.php.net/downloads/releases/sha1sum.txt -OutFile ${Env:Temp}\sha1sum.txt - - ps: >- - $VersionString = Get-Content ${Env:Temp}\sha1sum.txt | Where-Object { - $_ -match "php-($Env:PHP_TARGET\.\d+)-src" - } | ForEach-Object { $matches[1] } - - If ($VersionString -NotMatch '\d+\.\d+\.\d+') { - Throw "Unable to obtain PHP version string using pattern 'php-($Env:PHP_TARGET\.\d+)-src'" - } - - $Env:PHP_VERSION = ${VersionString} - - ps: $env:PARSER_DOWNLOAD_URL="https://github.com/phalcon/php-zephir-parser/releases/download/v${env:PARSER_VERSION}/zephir_parser_${env:PLATFORM}_vc${env:PHP_VC}_php${env:PHP_TARGET}_${env:PARSER_VERSION}-${env:PARSER_RELEASE}.zip" - - # ================================================== - - echo Initializing Build... - # ================================================== - - cd %APPVEYOR_BUILD_FOLDER% - git submodule update --init --recursive - - echo Preparing zephir win32 build... - - # ================================================== - - 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' - - 7z.exe x php.zip | FIND /V "ing " - - cd .. - - - echo Downloading PHP-SDK - - mkdir php-sdk && cd php-sdk - - ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip', ${env:APPVEYOR_BUILD_FOLDER} + '\..\php-sdk.zip') - - '7z.exe x ..\php-sdk.zip | FIND /V "ing "' - - cd .. - - # ================================================== - - echo Install PHP Dev pack - # ================================================== - - ps: >- - If ($env:PHP_TYPE -Match "nts-Win32") { - $env:DEVEL_PACK_VERSION="${env:PHP_VERSION}-nts-Win32-VC${env:PHP_VC}-${env:PLATFORM}" - } Else { - $env:DEVEL_PACK_VERSION="${env:PHP_VERSION}-Win32-VC${env:PHP_VC}-${env:PLATFORM}" - } - # ================================================== - - echo Downloading PHP Dev pack source code [http://windows.php.net/downloads/releases/php-devel-pack-%DEVEL_PACK_VERSION%.zip] - # ================================================== - - ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/releases/php-devel-pack-' + ${env:DEVEL_PACK_VERSION} + '.zip', ${env:APPVEYOR_BUILD_FOLDER} + '\..\php-dev.zip') - - 7z.exe x php-dev.zip | FIND /V "ing " - - mv php-%PHP_VERSION%-devel-VC11-%PLATFORM% php-devpack - - - echo Enable Zephir Parser - - 'cd %APPVEYOR_BUILD_FOLDER%\..\php\ext' - # ================================================== - - echo Downloading Zephir Parser [%PARSER_DOWNLOAD_URL%] - # ================================================== - - curl --location --silent --show-error %PARSER_DOWNLOAD_URL% --output zephir_parser.zip - - 7z.exe x zephir_parser.zip | FIND /V "ing " - - - echo Building PHP [%PHP_VERSION%] - - '"%VS110COMNTOOLS%\VsDevCmd" %PLATFORM%' - - '%PHP_SDK%\bin\phpsdk_setvars' - - 'cd %APPVEYOR_BUILD_FOLDER%\..\php' - - 'echo extension_dir=%APPVEYOR_BUILD_FOLDER%\..\php\ext > php.ini' - - 'echo extension=php_openssl.dll >> php.ini' - - 'echo extension=php_pdo_sqlite.dll >> php.ini' - - 'echo extension=php_gmp.dll >> php.ini' - - 'echo extension=php_zephir_parser.dll >> php.ini' - - 'set PATH=%cd%;%PATH%' - - php --ri "Zephir Parser" - -#---------------------------------# -# tests configuration # -#---------------------------------# - -# disable automatic tests -test: off - -# scripts to run before tests -before_test: - - ps: Write-Host "Download tests dependencies.." + - ps: Import-Module .\unit-tests\ci\appveyor.psm1 + - ps: AppendSessionPath + - ps: SetupPhpVersionString + - ps: EnsureRequiredDirectoriesPresent + - ps: Ensure7ZipIsInstalled + - ps: InstallSdk + - ps: InstallPhp + - ps: InstallPhpDevPack + - ps: InstallParser + - ps: TuneUpPhp + +build_script: + - ps: InitializeBuildVars + - ps: InitializeReleaseVars + - ps: InstallBuildDependencies + - '"%VSCOMNTOOLS%\VsDevCmd" %PLATFORM%' + - '"%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %ARCH%' + - '%PHP_SDK_PATH%\bin\phpsdk_setvars' - 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 + - 'bin\zephir compile -Wnonexistent-function -Wnonexistent-class -Wunused-variable' + - cd %APPVEYOR_BUILD_FOLDER%\ext + - nmake 2> compile-errors.log 1> compile.log + - ps: EnableExtension - - 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' - -# 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' + - 'php unit-tests/phpunit -c phpunit.xml.dist --not-exit --debug unit-tests/' + - 'php unit-tests/microbench.php' + +after_test: + - ps: PrepareReleasePackage -#---------------------------------# -# global handlers # -#---------------------------------# +artifacts: + - path: '.\$(RELEASE_ZIPBALL).zip' + type: zip + name: Zephir -# on build failure on_failure: - - 'dir' - - ps: >- - IF (Test-Path -Path compile-errors.log) { - type compile-errors.log - } - - IF (Test-Path -Path compile.log) { - type compile.log - } - - IF (Test-Path -Path configure.js) { - type configure.js - } + - ps: PrintLogs "${Env:APPVEYOR_BUILD_FOLDER}\ext" + - ps: PrintVars + - ps: PrintDirectoriesContent + - ps: PrintPhpInfo + +notifications: + - provider: Email + to: + - build@phalconphp.com + subject: "Build Zephir [{{status}}]" + on_build_status_changed: true diff --git a/unit-tests/Extension/Globals/EnvTest.php b/unit-tests/Extension/Globals/EnvTest.php index e0379b29a0..bfb4ba91e3 100644 --- a/unit-tests/Extension/Globals/EnvTest.php +++ b/unit-tests/Extension/Globals/EnvTest.php @@ -12,9 +12,11 @@ namespace Extension\Globals; +use PHPUnit\Framework\TestCase; use Test\Globals\Env; +use Zephir\Utils; -class EnvTest extends \PHPUnit_Framework_TestCase +class EnvTest extends TestCase { /** * This method is called before a test is executed. @@ -40,8 +42,14 @@ public function readStandard() { $tester = new Env(); - $this->assertSame($_ENV['USER'], $tester->read('USER')); - $this->assertSame($_ENV['USER'], getenv('USER')); + if (Utils::isWindows()) { + $var = 'USERNAME'; + } else { + $var = 'USER'; + } + + $this->assertSame($_ENV[$var], $tester->read($var)); + $this->assertSame($_ENV[$var], getenv($var)); } /** @test */ diff --git a/unit-tests/ci/appveyor.psm1 b/unit-tests/ci/appveyor.psm1 new file mode 100644 index 0000000000..94ff34b35c --- /dev/null +++ b/unit-tests/ci/appveyor.psm1 @@ -0,0 +1,494 @@ +Function AppendSessionPath { + $PathsCollection = @("C:\Program Files (x86)\MSBuild\${Env:VC_VERSION}.0\Bin") + $PathsCollection += "C:\Program Files (x86)\Microsoft Visual Studio ${Env:VC_VERSION}.0\VC" + $PathsCollection += "C:\Program Files (x86)\Microsoft Visual Studio ${Env:VC_VERSION}.0\VC\bin" + $PathsCollection += "${Env:PHP_SDK_PATH}\bin" + $PathsCollection += "${Env:PHP_PATH}\bin" + $PathsCollection += "${Env:PHP_PATH}" + + $CurrentPath = (Get-Item -Path ".\" -Verbose).FullName + + ForEach ($PathItem In $PathsCollection) { + Set-Location Env: + $AllPaths = (Get-ChildItem Path).value.split(";") | Sort-Object -Unique + $AddToPath = $true + + ForEach ($AddedPath In $AllPaths) { + If (-not "${AddedPath}") { + continue + } + + $AddedPath = $AddedPath -replace '\\$', '' + + If ($PathItem -eq $AddedPath) { + $AddToPath = $false + } + } + + If ($AddToPath) { + $Env:Path += ";$PathItem" + } + } + + Set-Location "${CurrentPath}" +} + +Function SetupPhpVersionString { + $RemoteUrl = 'http://windows.php.net/downloads/releases/sha1sum.txt'; + $DestinationPath = "${Env:Temp}\php-sha1sum.txt" + + If (-not [System.IO.File]::Exists($DestinationPath)) { + Write-Host "Downloading PHP SHA sums file: ${RemoteUrl} ..." + DownloadFile $RemoteUrl $DestinationPath + } + + $VersionString = Get-Content $DestinationPath | Where-Object { + $_ -match "php-($Env:PHP_MINOR\.\d+)-src" + } | ForEach-Object { $matches[1] } + + If ($VersionString -NotMatch '\d+\.\d+\.\d+') { + Throw "Unable to obtain PHP version string using pattern 'php-($Env:PHP_MINOR\.\d+)-src'" + } + + $Env:PHP_VERSION = $VersionString +} + +Function EnsureRequiredDirectoriesPresent { + If (-not (Test-Path 'C:\Downloads')) { + New-Item -ItemType Directory -Force -Path 'C:\Downloads' | Out-Null + } + + If (-not (Test-Path 'C:\Downloads\Choco')) { + New-Item -ItemType Directory -Force -Path 'C:\Downloads\Choco' | Out-Null + } + + If (-not (Test-Path 'C:\Projects')) { + New-Item -ItemType Directory -Force -Path 'C:\Projects' | Out-Null + } +} + +Function Ensure7ZipIsInstalled { + If (-not (Get-Command "7z" -ErrorAction SilentlyContinue)) { + $7zipInstallationDirectory = "${Env:ProgramFiles}\7-Zip" + + If (-not (Test-Path "$7zipInstallationDirectory")) { + Throw "The 7-zip file archiver is needed to use this module" + } + + $Env:Path += ";$7zipInstallationDirectory" + } +} + +Function EnsureChocolateyIsInstalled { + If (-not (Get-Command "choco" -ErrorAction SilentlyContinue)) { + $ChocolateyInstallationDirectory = "${Env:ProgramData}\chocolatey\bin" + + If (-not (Test-Path "$ChocolateyInstallationDirectory")) { + Throw "The choco is needed to use this module" + } + + $Env:Path += ";$ChocolateyInstallationDirectory" + } +} + +Function EnsurePandocIsInstalled { + If (-not (Get-Command "pandoc" -ErrorAction SilentlyContinue)) { + $PandocInstallationDirectory = "${Env:ProgramData}\chocolatey\bin" + + If (-not (Test-Path "$PandocInstallationDirectory")) { + Throw "The pandoc is needed to use this module" + } + + $Env:Path += ";$PandocInstallationDirectory" + } + + & "pandoc" -v +} + +Function InstallSdk { + Write-Host "Install PHP SDK binary tools: ${Env:PHP_SDK_VERSION}" -foregroundcolor Cyan + + $RemoteUrl = "https://github.com/OSTC/php-sdk-binary-tools/archive/php-sdk-${Env:PHP_SDK_VERSION}.zip" + $DestinationPath = "C:\Downloads\php-sdk-${Env:PHP_SDK_VERSION}.zip" + + If (-not (Test-Path $Env:PHP_SDK_PATH)) { + If (-not [System.IO.File]::Exists($DestinationPath)) { + Write-Host "Downloading PHP SDK binary tools: $RemoteUrl ..." + DownloadFile $RemoteUrl $DestinationPath + } + + $DestinationUnzipPath = "${Env:Temp}\php-sdk-binary-tools-php-sdk-${Env:PHP_SDK_VERSION}" + + If (-not (Test-Path "$DestinationUnzipPath")) { + Expand-Item7zip $DestinationPath $Env:Temp + } + + Move-Item -Path $DestinationUnzipPath -Destination $Env:PHP_SDK_PATH + } +} + +Function InstallPhp { + Write-Host "Install PHP: ${Env:PHP_VERSION}" -foregroundcolor Cyan + + $RemoteUrl = "http://windows.php.net/downloads/releases/php-${Env:PHP_VERSION}-${Env:BUILD_TYPE}-vc${Env:VC_VERSION}-${Env:PLATFORM}.zip" + $DestinationPath = "C:\Downloads\php-${Env:PHP_VERSION}-${Env:BUILD_TYPE}-VC${Env:VC_VERSION}-${Env:PLATFORM}.zip" + + If (-not (Test-Path $Env:PHP_PATH)) { + If (-not [System.IO.File]::Exists($DestinationPath)) { + Write-Host "Downloading PHP source code: $RemoteUrl ..." + DownloadFile $RemoteUrl $DestinationPath + } + + Expand-Item7zip "$DestinationPath" "${Env:PHP_PATH}" + } + + If (-not (Test-Path "${Env:PHP_PATH}\php.ini")) { + Copy-Item "${Env:PHP_PATH}\php.ini-development" "${Env:PHP_PATH}\php.ini" + } +} + +Function InstallPhpDevPack { + Write-Host "Install PHP Dev pack: ${Env:PHP_VERSION}" -foregroundcolor Cyan + + $RemoteUrl = "http://windows.php.net/downloads/releases/php-devel-pack-${Env:PHP_VERSION}-${Env:BUILD_TYPE}-vc${Env:VC_VERSION}-${Env:PLATFORM}.zip" + $DestinationPath = "C:\Downloads\php-devel-pack-${Env:PHP_VERSION}-${Env:BUILD_TYPE}-VC${Env:VC_VERSION}-${Env:PLATFORM}.zip" + + If (-not (Test-Path $Env:PHP_DEVPACK)) { + If (-not [System.IO.File]::Exists($DestinationPath)) { + Write-Host "Downloading PHP Dev pack: ${RemoteUrl} ..." + DownloadFile $RemoteUrl $DestinationPath + } + + $DestinationUnzipPath = "${Env:Temp}\php-${Env:PHP_VERSION}-devel-VC${Env:VC_VERSION}-${Env:PLATFORM}" + + If (-not (Test-Path "$DestinationUnzipPath")) { + Expand-Item7zip $DestinationPath $Env:Temp + } + + Move-Item -Path $DestinationUnzipPath -Destination $Env:PHP_DEVPACK + } +} + +Function InstallParser { + $BaseUri = "https://github.com/phalcon/php-zephir-parser/releases/download" + $LocalPart = "zephir_parser_${Env:PLATFORM}_vc${Env:VC_VERSION}_php${Env:PHP_MINOR}" + + If ($Env:BUILD_TYPE -Match "nts-Win32") { + $VersionPrefix = "-nts" + } Else { + $VersionPrefix = "" + } + + $RemoteUrl = "${BaseUri}/v${Env:PARSER_VERSION}/${LocalPart}${VersionPrefix}_${Env:PARSER_VERSION}-${Env:PARSER_RELEASE}.zip" + $DestinationPath = "C:\Downloads\${LocalPart}${VersionPrefix}_${Env:PARSER_VERSION}-${Env:PARSER_RELEASE}.zip" + + If (-not (Test-Path "${Env:PHP_PATH}\ext\php_zephir_parser.dll")) { + If (-not [System.IO.File]::Exists($DestinationPath)) { + Write-Host "Downloading Zephir Parser: ${RemoteUrl} ..." + DownloadFile $RemoteUrl $DestinationPath + } + + Expand-Item7zip $DestinationPath "${Env:PHP_PATH}\ext" + } +} + +Function TuneUpPhp { + $IniFile = "${Env:PHP_PATH}\php.ini" + $ExtPath = "${Env:PHP_PATH}\ext" + + If (-not [System.IO.File]::Exists($IniFile)) { + Throw "Unable to locate $IniFile file" + } + + Write-Output "" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension_dir = ${ExtPath}" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "memory_limit = 256M" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "variables_order = EGPCS" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_curl.dll" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_openssl.dll" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_mbstring.dll" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_pdo_sqlite.dll" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_fileinfo.dll" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_gettext.dll" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_gd2.dll" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_gmp.dll" | Out-File -Encoding "ASCII" -Append $IniFile + Write-Output "extension = php_zephir_parser.dll" | Out-File -Encoding "ASCII" -Append $IniFile +} + +Function InitializeBuildVars { + switch ($Env:VC_VERSION) { + '14' { + If (-not (Test-Path $Env:VS120COMNTOOLS)) { + Throw'The VS120COMNTOOLS environment variable is not set. Check your MS VS installation' + } + $Env:VSCOMNTOOLS = $Env:VS120COMNTOOLS -replace '\\$', '' + + break + } + '15' { + If (-not (Test-Path $Env:VS140COMNTOOLS)) { + Throw'The VS140COMNTOOLS environment variable is not set. Check your MS VS installation' + } + $Env:VSCOMNTOOLS = $Env:VS140COMNTOOLS -replace '\\$', '' + break + } + default { + Throw'This script is designed to run with MS VS 14/15. Check your MS VS installation' + break + } + } + + If ($Env:PLATFORM -eq 'x64') { + $Env:ARCH = 'x86_amd64' + } Else { + $Env:ARCH = 'x86' + } +} + +Function InitializeReleaseVars { + If ($Env:BUILD_TYPE -Match "nts-Win32") { + $Env:RELEASE_ZIPBALL = "${Env:PACKAGE_PREFIX}_${Env:PLATFORM}_vc${Env:VC_VERSION}_php${Env:PHP_MINOR}_${Env:APPVEYOR_BUILD_VERSION}_nts" + + If ($Env:PLATFORM -eq 'x86') { + $Env:RELEASE_FOLDER = "Release" + } Else { + $Env:RELEASE_FOLDER = "x64\Release" + } + } Else { + $Env:RELEASE_ZIPBALL = "${Env:PACKAGE_PREFIX}_${Env:PLATFORM}_vc${Env:VC_VERSION}_php${Env:PHP_MINOR}_${Env:APPVEYOR_BUILD_VERSION}" + + If ($Env:PLATFORM -eq 'x86') { + $Env:RELEASE_FOLDER = "Release_TS" + } Else { + $Env:RELEASE_FOLDER = "x64\Release_TS" + } + } + + $Env:RELEASE_DLL_PATH = "${Env:APPVEYOR_BUILD_FOLDER}\ext\${Env:RELEASE_FOLDER}\${Env:EXTENSION_FILE}" +} + +Function InstallBuildDependencies { + EnsureChocolateyIsInstalled + + $InstallProcess = Start-Process "choco" -WindowStyle Hidden -ArgumentList 'install', '-y --cache-location=C:\Downloads\Choco pandoc' -WorkingDirectory "${Env:APPVEYOR_BUILD_FOLDER}" + + If (-not (Test-Path "${Env:APPVEYOR_BUILD_FOLDER}\package")) { + New-Item -ItemType Directory -Force -Path "${Env:APPVEYOR_BUILD_FOLDER}\package" | Out-Null + } + + $BuildFile = "${Env:APPVEYOR_BUILD_FOLDER}\install-php-deps.bat" + + If (-not (Test-Path "${Env:APPVEYOR_BUILD_FOLDER}\vendor")) { + $Php = "${Env:PHP_PATH}\php.exe" + $ComposerOptions = "--quiet --no-interaction --no-progress --optimize-autoloader --prefer-dist --no-suggest --ignore-platform-reqs" + + Write-Output "@echo off" | Out-File -Encoding "ASCII" -Append $BuildFile + Write-Output "${Php} -r `"readfile('https://getcomposer.org/installer');`" | ${Env:PHP_PATH}\php.exe" | Out-File -Encoding "ASCII" -Append $BuildFile + Write-Output "${Php} ${Env:APPVEYOR_BUILD_FOLDER}\composer.phar install ${ComposerOptions}" | Out-File -Encoding "ASCII" -Append $BuildFile + + Set-Location "${Env:APPVEYOR_BUILD_FOLDER}" + & cmd /c ".\install-php-deps.bat" + } +} + +Function EnableExtension { + If (-not (Test-Path "${Env:RELEASE_DLL_PATH}")) { + Throw "Unable to locate extension path: ${Env:RELEASE_DLL_PATH}" + } + + Copy-Item "${Env:RELEASE_DLL_PATH}" "${Env:PHP_PATH}\ext\${Env:EXTENSION_FILE}" + Write-Output "extension = ${Env:EXTENSION_FILE}" | Out-File -Encoding "ASCII" -Append "${Env:PHP_PATH}\php.ini" + + $IniFile = "${Env:PHP_PATH}\php.ini" + $PhpExe = "${Env:PHP_PATH}\php.exe" + + If (-not [System.IO.File]::Exists($IniFile)) { + Throw "Unable to locate ${IniFile}" + } + + If (Test-Path -Path "${PhpExe}") { + & "${PhpExe}" --ri "${Env:EXTENSION_NAME}" + + $PhpExitCode = $LASTEXITCODE + If ($PhpExitCode -ne 0) { + PrintPhpInfo + Throw "An error occurred while enabling [${Env:EXTENSION_NAME}] in [$IniFile]. PHP Exit Code was [$PhpExitCode]." + } + } +} + +Function PrepareReleasePackage { + PrepareReleaseNote + + $CurrentPath = (Get-Item -Path ".\" -Verbose).FullName + $PackagePath = "${Env:APPVEYOR_BUILD_FOLDER}\package" + + FormatReleaseFiles + + Copy-Item -Path (Join-Path -Path $Env:APPVEYOR_BUILD_FOLDER -ChildPath '\*') -Filter '*.txt' -Destination "${PackagePath}" -Force + Copy-Item "${Env:RELEASE_DLL_PATH}" "${PackagePath}" + + Set-Location "${PackagePath}" + $result = (& 7z a "${Env:RELEASE_ZIPBALL}.zip" *.*) + + $7zipExitCode = $LASTEXITCODE + If ($7zipExitCode -ne 0) { + Set-Location "${CurrentPath}" + Throw "An error occurred while creating release zippbal to [${Env:RELEASE_ZIPBALL}.zip]. 7Zip Exit Code was [${7zipExitCode}]" + } + + Move-Item "${Env:RELEASE_ZIPBALL}.zip" -Destination "${Env:APPVEYOR_BUILD_FOLDER}" + + Set-Location "${CurrentPath}" +} + +Function PrepareReleaseNote { + $ReleaseFile = "${Env:APPVEYOR_BUILD_FOLDER}\package\RELEASE.txt" + $ReleaseDate = Get-Date -Format g + + Write-Output "Release date: ${ReleaseDate}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" + Write-Output "Release version: ${Env:APPVEYOR_BUILD_VERSION}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" + Write-Output "Git commit: ${Env:APPVEYOR_REPO_COMMIT}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" + Write-Output "Build type: ${Env:BUILD_TYPE}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" + Write-Output "Platform: ${Env:PLATFORM}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" + Write-Output "Target PHP version: ${Env:PHP_MINOR}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" + Write-Output "Build worker image: ${Env:APPVEYOR_BUILD_WORKER_IMAGE}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" +} + +Function FormatReleaseFiles { + EnsurePandocIsInstalled + + $CurrentPath = (Get-Item -Path ".\" -Verbose).FullName + + Set-Location "${Env:APPVEYOR_BUILD_FOLDER}" + + Get-ChildItem (Get-Item -Path ".\" -Verbose).FullName *.md | + ForEach-Object{ + $BaseName = $_.BaseName + pandoc -f markdown -t html5 "${BaseName}.md" > "package/${BaseName}.html" + } + + If (Test-Path -Path "package/CHANGELOG.html") { + (Get-Content "package/CHANGELOG.html") | ForEach-Object { $_ -replace ".md", ".html" } | Set-Content "package/CHANGELOG.html" + } + + Set-Location "${CurrentPath}" +} + +Function PrintLogs { + Param([Parameter(Mandatory=$true)][System.String] $BasePath) + + If (Test-Path -Path "${Env:BasePath}\compile-errors.log") { + Get-Content -Path "${Env:BasePath}\compile-errors.log" + } + + If (Test-Path -Path "${Env:BasePath}\compile.log") { + Get-Content -Path "${Env:BasePath}\compile.log" + } + + If (Test-Path -Path "${Env:BasePath}\configure.js") { + Get-Content -Path "${Env:BasePath}\configure.js" + } +} + +Function PrintVars { + Write-Host ($Env:Path).Replace(';', "`n") + + Get-ChildItem Env: +} + +Function PrintDirectoriesContent { + Get-ChildItem -Path "${Env:APPVEYOR_BUILD_FOLDER}" + + If (Test-Path -Path "C:\Downloads") { + Get-ChildItem -Path "C:\Downloads" + } + + If (Test-Path -Path "C:\Projects") { + Get-ChildItem -Path "C:\Projects" + } + + If (Test-Path -Path "${Env:PHP_PATH}\ext") { + Get-ChildItem -Path "${Env:PHP_PATH}\ext" + } + + $ReleasePath = Split-Path -Path "${Env:RELEASE_DLL_PATH}" + If (Test-Path -Path "${ReleasePath}") { + Get-ChildItem -Path "${ReleasePath}" + } + + $BuildPath = Split-Path -Path "${ReleasePath}" + If (Test-Path -Path "${BuildPath}") { + Get-ChildItem -Path "${BuildPath}" + } +} + +Function PrintPhpInfo { + $IniFile = "${Env:PHP_PATH}\php.ini" + $PhpExe = "${Env:PHP_PATH}\php.exe" + + If (Test-Path -Path "${PhpExe}") { + Write-Host "" + & "${PhpExe}" -v + + Write-Host "" + & "${PhpExe}" -m + + Write-Host "" + & "${PhpExe}" -i + } ElseIf (Test-Path -Path "${IniFile}") { + Get-Content -Path "${IniFile}" + } +} + +Function Expand-Item7zip { + Param( + [Parameter(Mandatory=$true)][System.String] $Archive, + [Parameter(Mandatory=$true)][System.String] $Destination + ) + + If (-not (Test-Path -Path $Archive -PathType Leaf)) { + Throw "Specified archive File is invalid: [$Archive]" + } + + If (-not (Test-Path -Path $Destination -PathType Container)) { + New-Item $Destination -ItemType Directory | Out-Null + } + + $Result = (& 7z x "$Archive" "-o$Destination" -aoa -bd -y -r) + + $7zipExitCode = $LASTEXITCODE + If ($7zipExitCode -ne 0) { + Throw "An error occurred while unzipping [$Archive] to [$Destination]. 7Zip Exit Code was [$7zipExitCode]" + } +} + +Function DownloadFile { + Param( + [Parameter(Mandatory=$true)][System.String] $RemoteUrl, + [Parameter(Mandatory=$true)][System.String] $DestinationPath + ) + + $RetryMax = 5 + $RetryCount = 0 + $Completed = $false + + $WebClient = New-Object System.Net.WebClient + $WebClient.Headers.Add('User-Agent', 'AppVeyor PowerShell Script') + + While (-not $Completed) { + Try { + $WebClient.DownloadFile($RemoteUrl, $DestinationPath) + $Completed = $true + } Catch { + If ($RetryCount -ge $RetryMax) { + $ErrorMessage = $_.Exception.Message + Write-Host "Error downloadingig ${RemoteUrl}: $ErrorMessage" + $Completed = $true + } Else { + $RetryCount++ + } + } + } +} From ad5dcaf24ddb96e0eef6e65b35d39561ac7f9460 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Mon, 16 Apr 2018 21:32:31 +0300 Subject: [PATCH 12/40] Simplify build process --- appveyor.yml | 3 +- unit-tests/ci/appveyor.psm1 | 78 +++++-------------------------------- 2 files changed, 11 insertions(+), 70 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 613d99108b..ab72a8873c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -102,7 +102,7 @@ test_script: - 'php unit-tests/microbench.php' after_test: - - ps: PrepareReleasePackage + - ps: PrintReleaseNotes artifacts: - path: '.\$(RELEASE_ZIPBALL).zip' @@ -114,6 +114,7 @@ on_failure: - ps: PrintVars - ps: PrintDirectoriesContent - ps: PrintPhpInfo + - ps: PrintReleaseNotes notifications: - provider: Email diff --git a/unit-tests/ci/appveyor.psm1 b/unit-tests/ci/appveyor.psm1 index 94ff34b35c..1cfd7b2ac9 100644 --- a/unit-tests/ci/appveyor.psm1 +++ b/unit-tests/ci/appveyor.psm1 @@ -91,20 +91,6 @@ Function EnsureChocolateyIsInstalled { } } -Function EnsurePandocIsInstalled { - If (-not (Get-Command "pandoc" -ErrorAction SilentlyContinue)) { - $PandocInstallationDirectory = "${Env:ProgramData}\chocolatey\bin" - - If (-not (Test-Path "$PandocInstallationDirectory")) { - Throw "The pandoc is needed to use this module" - } - - $Env:Path += ";$PandocInstallationDirectory" - } - - & "pandoc" -v -} - Function InstallSdk { Write-Host "Install PHP SDK binary tools: ${Env:PHP_SDK_VERSION}" -foregroundcolor Cyan @@ -318,62 +304,16 @@ Function EnableExtension { } } -Function PrepareReleasePackage { - PrepareReleaseNote - - $CurrentPath = (Get-Item -Path ".\" -Verbose).FullName - $PackagePath = "${Env:APPVEYOR_BUILD_FOLDER}\package" - - FormatReleaseFiles - - Copy-Item -Path (Join-Path -Path $Env:APPVEYOR_BUILD_FOLDER -ChildPath '\*') -Filter '*.txt' -Destination "${PackagePath}" -Force - Copy-Item "${Env:RELEASE_DLL_PATH}" "${PackagePath}" - - Set-Location "${PackagePath}" - $result = (& 7z a "${Env:RELEASE_ZIPBALL}.zip" *.*) - - $7zipExitCode = $LASTEXITCODE - If ($7zipExitCode -ne 0) { - Set-Location "${CurrentPath}" - Throw "An error occurred while creating release zippbal to [${Env:RELEASE_ZIPBALL}.zip]. 7Zip Exit Code was [${7zipExitCode}]" - } +Function PrintReleaseNotes { + $BuildDate = Get-Date -Format g - Move-Item "${Env:RELEASE_ZIPBALL}.zip" -Destination "${Env:APPVEYOR_BUILD_FOLDER}" - - Set-Location "${CurrentPath}" -} - -Function PrepareReleaseNote { - $ReleaseFile = "${Env:APPVEYOR_BUILD_FOLDER}\package\RELEASE.txt" - $ReleaseDate = Get-Date -Format g - - Write-Output "Release date: ${ReleaseDate}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" - Write-Output "Release version: ${Env:APPVEYOR_BUILD_VERSION}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" - Write-Output "Git commit: ${Env:APPVEYOR_REPO_COMMIT}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" - Write-Output "Build type: ${Env:BUILD_TYPE}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" - Write-Output "Platform: ${Env:PLATFORM}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" - Write-Output "Target PHP version: ${Env:PHP_MINOR}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" - Write-Output "Build worker image: ${Env:APPVEYOR_BUILD_WORKER_IMAGE}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" -} - -Function FormatReleaseFiles { - EnsurePandocIsInstalled - - $CurrentPath = (Get-Item -Path ".\" -Verbose).FullName - - Set-Location "${Env:APPVEYOR_BUILD_FOLDER}" - - Get-ChildItem (Get-Item -Path ".\" -Verbose).FullName *.md | - ForEach-Object{ - $BaseName = $_.BaseName - pandoc -f markdown -t html5 "${BaseName}.md" > "package/${BaseName}.html" - } - - If (Test-Path -Path "package/CHANGELOG.html") { - (Get-Content "package/CHANGELOG.html") | ForEach-Object { $_ -replace ".md", ".html" } | Set-Content "package/CHANGELOG.html" - } - - Set-Location "${CurrentPath}" + Write-Host "Release date: ${BuildDate}" + Write-Host "Release version: ${Env:APPVEYOR_BUILD_VERSION}" + Write-Host "Git commit: ${Env:APPVEYOR_REPO_COMMIT}" + Write-Host "Build type: ${Env:BUILD_TYPE}" + Write-Host "Platform: ${Env:PLATFORM}" + Write-Host "Target PHP version: ${Env:PHP_MINOR}" + Write-Host "Build worker image: ${Env:APPVEYOR_BUILD_WORKER_IMAGE}" } Function PrintLogs { From 5a8ed25448a3a1fa4c79020b487855dabf320b49 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Mon, 16 Apr 2018 21:56:58 +0300 Subject: [PATCH 13/40] Enable PHP 7.1 --- .travis.yml => .travis.yml.disabled | 0 appveyor.yml | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) rename .travis.yml => .travis.yml.disabled (100%) diff --git a/.travis.yml b/.travis.yml.disabled similarity index 100% rename from .travis.yml rename to .travis.yml.disabled diff --git a/appveyor.yml b/appveyor.yml index ab72a8873c..3276d49fc3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,21 +2,21 @@ version: 0.10.8-{build} environment: matrix: - - PHP_MINOR: 7.0 - VC_VERSION: 14 - BUILD_TYPE: Win32 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - - - PHP_MINOR: 7.0 - VC_VERSION: 14 - BUILD_TYPE: nts-Win32 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - - # - PHP_MINOR: 7.1 + # - PHP_MINOR: 7.0 # VC_VERSION: 14 # BUILD_TYPE: Win32 # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + # - PHP_MINOR: 7.0 + # VC_VERSION: 14 + # BUILD_TYPE: nts-Win32 + # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + + - PHP_MINOR: 7.1 + VC_VERSION: 14 + BUILD_TYPE: Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + # - PHP_MINOR: 7.1 # VC_VERSION: 14 # BUILD_TYPE: nts-Win32 From d503d06f930a1999966ef4950165d7f16d20c2bb Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Mon, 16 Apr 2018 22:15:03 +0300 Subject: [PATCH 14/40] Fixed printing logs --- appveyor.yml | 13 ++++--------- unit-tests/ci/appveyor.psm1 | 16 +++++++--------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3276d49fc3..0ba6cf10a0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -101,20 +101,15 @@ test_script: - 'php unit-tests/phpunit -c phpunit.xml.dist --not-exit --debug unit-tests/' - 'php unit-tests/microbench.php' -after_test: - - ps: PrintReleaseNotes - -artifacts: - - path: '.\$(RELEASE_ZIPBALL).zip' - type: zip - name: Zephir +on_success: + - ps: PrintBuildDetails on_failure: - - ps: PrintLogs "${Env:APPVEYOR_BUILD_FOLDER}\ext" + - ps: PrintBuildDetails + - ps: PrintLogs - ps: PrintVars - ps: PrintDirectoriesContent - ps: PrintPhpInfo - - ps: PrintReleaseNotes notifications: - provider: Email diff --git a/unit-tests/ci/appveyor.psm1 b/unit-tests/ci/appveyor.psm1 index 1cfd7b2ac9..9f77d2d2e7 100644 --- a/unit-tests/ci/appveyor.psm1 +++ b/unit-tests/ci/appveyor.psm1 @@ -304,7 +304,7 @@ Function EnableExtension { } } -Function PrintReleaseNotes { +Function PrintBuildDetails { $BuildDate = Get-Date -Format g Write-Host "Release date: ${BuildDate}" @@ -317,18 +317,16 @@ Function PrintReleaseNotes { } Function PrintLogs { - Param([Parameter(Mandatory=$true)][System.String] $BasePath) - - If (Test-Path -Path "${Env:BasePath}\compile-errors.log") { - Get-Content -Path "${Env:BasePath}\compile-errors.log" + If (Test-Path -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile-errors.log") { + Get-Content -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile-errors.log" } - If (Test-Path -Path "${Env:BasePath}\compile.log") { - Get-Content -Path "${Env:BasePath}\compile.log" + If (Test-Path -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile.log") { + Get-Content -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile.log" } - If (Test-Path -Path "${Env:BasePath}\configure.js") { - Get-Content -Path "${Env:BasePath}\configure.js" + If (Test-Path -Path "${Env:APPVEYOR_BUILD_FOLDER}\ext\configure.js") { + Get-Content -Path "${Env:APPVEYOR_BUILD_FOLDER}\ext\configure.js" } } From 02d38b2105577a4b8773596a0f9cfd0d04f0e293 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Mon, 16 Apr 2018 22:42:28 +0300 Subject: [PATCH 15/40] Revert 37d5b12 due to "unresolved external symbol" issue --- kernels/ZendEngine3/fcall.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/kernels/ZendEngine3/fcall.h b/kernels/ZendEngine3/fcall.h index ab7e7e1201..fb19036c2c 100644 --- a/kernels/ZendEngine3/fcall.h +++ b/kernels/ZendEngine3/fcall.h @@ -417,4 +417,22 @@ ZEPHIR_ATTR_WARN_UNUSED_RESULT ZEPHIR_ATTR_NONNULL static inline int zephir_has_ void zephir_eval_php(zval *str, zval *retval_ptr, char *context); +static inline void zephir_set_called_scope(zend_execute_data *ex, zend_class_entry *called_scope) +{ + while (ex) { + if (Z_TYPE(ex->This) == IS_OBJECT) { + Z_OBJCE(ex->This) = called_scope; + return; + } else if (Z_CE(ex->This)) { + Z_CE(ex->This) = called_scope; + return; + } else if (ex->func) { + if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) { + return; + } + } + ex = ex->prev_execute_data; + } +} + #endif /* ZEPHIR_KERNEL_FCALL_H */ From 4bb8ac78b15c451bd80221dc16bf968ac568fc06 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Mon, 16 Apr 2018 22:43:00 +0300 Subject: [PATCH 16/40] Better build reporting on success --- appveyor.yml | 1 - unit-tests/ci/appveyor.psm1 | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 0ba6cf10a0..5c74377acc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -105,7 +105,6 @@ on_success: - ps: PrintBuildDetails on_failure: - - ps: PrintBuildDetails - ps: PrintLogs - ps: PrintVars - ps: PrintDirectoriesContent diff --git a/unit-tests/ci/appveyor.psm1 b/unit-tests/ci/appveyor.psm1 index 9f77d2d2e7..6cac0ecc2d 100644 --- a/unit-tests/ci/appveyor.psm1 +++ b/unit-tests/ci/appveyor.psm1 @@ -307,13 +307,13 @@ Function EnableExtension { Function PrintBuildDetails { $BuildDate = Get-Date -Format g - Write-Host "Release date: ${BuildDate}" - Write-Host "Release version: ${Env:APPVEYOR_BUILD_VERSION}" - Write-Host "Git commit: ${Env:APPVEYOR_REPO_COMMIT}" + Write-Host "Build date: ${BuildDate}" + Write-Host "Build version: ${Env:APPVEYOR_BUILD_VERSION}" Write-Host "Build type: ${Env:BUILD_TYPE}" + Write-Host "Build worker image: ${Env:APPVEYOR_BUILD_WORKER_IMAGE}" + Write-Host "Git commit: ${Env:APPVEYOR_REPO_COMMIT}" Write-Host "Platform: ${Env:PLATFORM}" Write-Host "Target PHP version: ${Env:PHP_MINOR}" - Write-Host "Build worker image: ${Env:APPVEYOR_BUILD_WORKER_IMAGE}" } Function PrintLogs { From ad10b6054b3abf3733cf32d405a23ec103e973c9 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Mon, 16 Apr 2018 22:49:32 +0300 Subject: [PATCH 17/40] Enable tests for PHP 7.2 on AppVeyor --- appveyor.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 5c74377acc..285713e476 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,25 +12,25 @@ environment: # BUILD_TYPE: nts-Win32 # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - - PHP_MINOR: 7.1 - VC_VERSION: 14 - BUILD_TYPE: Win32 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + # - PHP_MINOR: 7.1 + # VC_VERSION: 14 + # BUILD_TYPE: Win32 + # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 # - PHP_MINOR: 7.1 # VC_VERSION: 14 # BUILD_TYPE: nts-Win32 # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - # - PHP_MINOR: 7.2 - # VC_VERSION: 15 - # BUILD_TYPE: Win32 - # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - PHP_MINOR: 7.2 + VC_VERSION: 15 + BUILD_TYPE: Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - # - PHP_MINOR: 7.2 - # VC_VERSION: 15 - # BUILD_TYPE: nts-Win32 - # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - PHP_MINOR: 7.2 + VC_VERSION: 15 + BUILD_TYPE: nts-Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 PHP_PATH: C:\Projects\php PHP_SDK_PATH: C:\Projects\php-sdk From ad7d04a23351c39222fb515d02eff80d6554b2b2 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Mon, 16 Apr 2018 22:54:02 +0300 Subject: [PATCH 18/40] Enabled all tests --- .travis.yml.disabled => .travis.yml | 0 appveyor.yml | 38 ++++++++++++++--------------- 2 files changed, 19 insertions(+), 19 deletions(-) rename .travis.yml.disabled => .travis.yml (100%) diff --git a/.travis.yml.disabled b/.travis.yml similarity index 100% rename from .travis.yml.disabled rename to .travis.yml diff --git a/appveyor.yml b/appveyor.yml index 285713e476..746a5e6cea 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,25 +2,25 @@ version: 0.10.8-{build} environment: matrix: - # - PHP_MINOR: 7.0 - # VC_VERSION: 14 - # BUILD_TYPE: Win32 - # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - - # - PHP_MINOR: 7.0 - # VC_VERSION: 14 - # BUILD_TYPE: nts-Win32 - # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - - # - PHP_MINOR: 7.1 - # VC_VERSION: 14 - # BUILD_TYPE: Win32 - # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - - # - PHP_MINOR: 7.1 - # VC_VERSION: 14 - # BUILD_TYPE: nts-Win32 - # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + - PHP_MINOR: 7.0 + VC_VERSION: 14 + BUILD_TYPE: Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + + - PHP_MINOR: 7.0 + VC_VERSION: 14 + BUILD_TYPE: nts-Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + + - PHP_MINOR: 7.1 + VC_VERSION: 14 + BUILD_TYPE: Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + + - PHP_MINOR: 7.1 + VC_VERSION: 14 + BUILD_TYPE: nts-Win32 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - PHP_MINOR: 7.2 VC_VERSION: 15 From ccc0dc6085ba50add3ab59af4b0ff956e43b3b40 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 17 Apr 2018 00:08:20 +0300 Subject: [PATCH 19/40] Cleaned up static constant access expression --- Library/ClassConstant.php | 53 ++++++++++++++------ Library/Expression/StaticConstantAccess.php | 54 +++++++++++++-------- 2 files changed, 70 insertions(+), 37 deletions(-) diff --git a/Library/ClassConstant.php b/Library/ClassConstant.php index c4fe319c3c..3c473a0288 100644 --- a/Library/ClassConstant.php +++ b/Library/ClassConstant.php @@ -7,7 +7,7 @@ | | | This source file is subject the MIT license, that is bundled with this | | package in the file LICENSE, and is available through the world-wide-web | - | at the following url: http://zephir-lang.com/license.html | + | at the following url: https://zephir-lang.com/license.html | +--------------------------------------------------------------------------+ */ @@ -15,6 +15,7 @@ use Zephir\Compiler\CompilerException; use Zephir\Expression\Constants; +use Zephir\Expression\StaticConstantAccess; /** * ClassConstant @@ -23,23 +24,29 @@ */ class ClassConstant { + /** + * @var string + */ protected $name; /** * @var array */ - protected $value; + protected $value = []; + /** + * @var string + */ protected $docblock; /** * ClassConstant constructor * - * @param $name - * @param $value - * @param $docBlock + * @param string $name + * @param array $value + * @param string $docBlock */ - public function __construct($name, $value, $docBlock) + public function __construct($name, array $value, $docBlock) { $this->name = $name; $this->value = $value; @@ -115,29 +122,33 @@ public function getType() /** * Process the value of the class constant if needed * - * @param compilationContext $compilationContext + * @param CompilationContext $compilationContext + * + * @return void + * + * @throws Exception */ - public function processValue($compilationContext) + public function processValue(CompilationContext $compilationContext) { if ($this->value['type'] == 'constant') { $constant = new Constants(); $compiledExpression = $constant->compile($this->value, $compilationContext); - $this->value = array( + $this->value = [ 'type' => $compiledExpression->getType(), 'value' => $compiledExpression->getCode() - ); + ]; return; } if ($this->value['type'] == 'static-constant-access') { - $expression = new Expression($this->value); - $compiledExpression = $expression->compile($compilationContext); + $staticConstantAccess = new StaticConstantAccess(); + $compiledExpression = $staticConstantAccess->compile($this->value, $compilationContext); - $this->value = array( + $this->value = [ 'type' => $compiledExpression->getType(), - 'value' => $compiledExpression->getCode() - ); + 'value' => $compiledExpression->getCode(), + ]; return; } } @@ -146,6 +157,9 @@ public function processValue($compilationContext) * Produce the code to register a class constant * * @param CompilationContext $compilationContext + * + * @return void + * * @throws CompilerException * @throws Exception */ @@ -153,6 +167,13 @@ public function compile(CompilationContext $compilationContext) { $this->processValue($compilationContext); - $compilationContext->backend->declareConstant($this->value['type'], $this->getName(), isset($this->value['value']) ? $this->value['value'] : null, $compilationContext); + $constanValue = isset($this->value['value']) ? $this->value['value'] : null; + + $compilationContext->backend->declareConstant( + $this->value['type'], + $this->getName(), + $constanValue, + $compilationContext + ); } } diff --git a/Library/Expression/StaticConstantAccess.php b/Library/Expression/StaticConstantAccess.php index f18630bcdd..c8bd5f95bc 100644 --- a/Library/Expression/StaticConstantAccess.php +++ b/Library/Expression/StaticConstantAccess.php @@ -7,17 +7,18 @@ | | | This source file is subject the MIT license, that is bundled with this | | package in the file LICENSE, and is available through the world-wide-web | - | at the following url: http://zephir-lang.com/license.html | + | at the following url: https://zephir-lang.com/license.html | +--------------------------------------------------------------------------+ */ namespace Zephir\Expression; -use Zephir\Variable; +use Zephir\ClassConstant; use Zephir\CompilationContext; use Zephir\CompiledExpression; use Zephir\Compiler\CompilerException; -use Zephir\ClassConstant; +use Zephir\Exception; +use Zephir\Variable; /** * StaticConstantAccess @@ -26,23 +27,26 @@ */ class StaticConstantAccess { - protected $_expecting = true; + /** @var bool */ + protected $expecting = true; - protected $_readOnly = false; + /** @var bool */ + protected $readOnly = false; - protected $_expectingVariable; + /** @var Variable|null */ + protected $expectingVariable; /** * Sets if the variable must be resolved into a direct variable symbol * create a temporary value or ignore the return value * - * @param boolean $expecting - * @param Variable $expectingVariable + * @param bool $expecting + * @param Variable|null $expectingVariable */ public function setExpectReturn($expecting, Variable $expectingVariable = null) { - $this->_expecting = $expecting; - $this->_expectingVariable = $expectingVariable; + $this->expecting = $expecting; + $this->expectingVariable = $expectingVariable; } /** @@ -52,27 +56,29 @@ public function setExpectReturn($expecting, Variable $expectingVariable = null) */ public function setReadOnly($readOnly) { - $this->_readOnly = $readOnly; + $this->readOnly = (bool) $readOnly; } /** * Access a static constant class * - * @param array $expression + * @param array $expression * @param CompilationContext $compilationContext + * * @return CompiledExpression + * @throws Exception|CompilerException */ - public function compile($expression, CompilationContext $compilationContext) + public function compile(array $expression, CompilationContext $compilationContext) { $compiler = &$compilationContext->compiler; $className = $expression['left']['value']; - $constant = $expression['right']['value']; + $constant = $expression['right']['value']; /** * Fetch the class definition according to the class where the constant * is supposed to be declared */ - if (!in_array($className, array('this', 'self', 'static', 'parent'))) { + if (!in_array($className, ['this', 'self', 'static', 'parent'])) { $className = $compilationContext->getFullName($className); if ($compiler->isClass($className) || $compiler->isInterface($className)) { $classDefinition = $compiler->getClassDefinition($className); @@ -84,7 +90,7 @@ public function compile($expression, CompilationContext $compilationContext) } } } else { - if (in_array($className, array('self', 'static', 'this'))) { + if (in_array($className, ['self', 'static', 'this'])) { $classDefinition = $compilationContext->classDefinition; } else { if ($className == 'parent') { @@ -104,7 +110,14 @@ public function compile($expression, CompilationContext $compilationContext) * so we need to check that they effectively do exist */ if (!$classDefinition->hasConstant($constant)) { - throw new CompilerException("Class '" . $classDefinition->getCompleteName() . "' does not have a constant called: '" . $constant . "'", $expression); + throw new CompilerException( + sprintf( + "Class '%s' does not have a constant called: '%s'", + $classDefinition->getCompleteName(), + $constant + ), + $expression + ); } /** @@ -114,9 +127,9 @@ public function compile($expression, CompilationContext $compilationContext) /** * Resolves the symbol that expects the value */ - if ($this->_expecting) { - if ($this->_expectingVariable) { - $symbolVariable = $this->_expectingVariable; + if ($this->expecting) { + if ($this->expectingVariable) { + $symbolVariable = $this->expectingVariable; $symbolVariable->initVariant($compilationContext); } else { $symbolVariable = $compilationContext->symbolTable->getTempVariableForWrite('variable', $compilationContext, $expression); @@ -161,7 +174,6 @@ public function compile($expression, CompilationContext $compilationContext) case 'bool': case 'null': break; - default: $compilationContext->logger->warning($constantDefinition->getName(), 'nonexistent-constant', $expression); return new CompiledExpression('null', null, $expression); From 6e836577d550c62992152a28ceb1c6181a2223f6 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 17 Apr 2018 15:14:06 +0300 Subject: [PATCH 20/40] Renamed iIsPrivateProperty Optimizer --- ...rty.php => IsPrivatePropertyOptimizer.php} | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) rename Library/Optimizers/FunctionCall/{IsPrivateProperty.php => IsPrivatePropertyOptimizer.php} (61%) diff --git a/Library/Optimizers/FunctionCall/IsPrivateProperty.php b/Library/Optimizers/FunctionCall/IsPrivatePropertyOptimizer.php similarity index 61% rename from Library/Optimizers/FunctionCall/IsPrivateProperty.php rename to Library/Optimizers/FunctionCall/IsPrivatePropertyOptimizer.php index ba76adf379..8379b4a162 100644 --- a/Library/Optimizers/FunctionCall/IsPrivateProperty.php +++ b/Library/Optimizers/FunctionCall/IsPrivatePropertyOptimizer.php @@ -7,7 +7,7 @@ | | | This source file is subject the MIT license, that is bundled with this | | package in the file LICENSE, and is available through the world-wide-web | - | at the following url: http://zephir-lang.com/license.html | + | at the following url: https://zephir-lang.com/license.html | +--------------------------------------------------------------------------+ */ @@ -16,20 +16,25 @@ use Zephir\Call; use Zephir\CompilationContext; use Zephir\CompiledExpression; +use Zephir\Compiler\CompilerException; +use Zephir\Exception; use Zephir\Optimizers\OptimizerAbstract; /** - * IsPrivateProperty + * Zephir\Optimizers\FunctionCall\IsPrivatePropertyOptimizer * * Allows to fastly check if a property has private visibility */ class IsPrivatePropertyOptimizer extends OptimizerAbstract { /** - * @param array $expression - * @param Call $call - * @param CompilationContext $context - * @return bool|CompiledExpression|mixed + * @param array $expression + * @param Call $call + * @param CompilationContext $context + * + * @return bool|CompiledExpression + * + * @throws CompilerException */ public function optimize(array $expression, Call $call, CompilationContext $context) { @@ -43,7 +48,11 @@ public function optimize(array $expression, Call $call, CompilationContext $cont $context->headersManager->add('kernel/object'); - $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression); - return new CompiledExpression('bool', 'zephir_is_private_prop(' . $resolvedParams[0] . ')', $expression); + try { + $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression); + return new CompiledExpression('bool', 'zephir_is_private_prop(' . $resolvedParams[0] . ')', $expression); + } catch (Exception $e) { + throw new CompilerException($e->getMessage(), $expression); + } } } From 4d546807162b886364de556c76028a0c00493d8a Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 17 Apr 2018 15:14:51 +0300 Subject: [PATCH 21/40] Code cleanup --- Library/FunctionCall.php | 64 ++++++++++++------- .../FunctionCall/IsPhpVersionOptimizer.php | 7 +- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/Library/FunctionCall.php b/Library/FunctionCall.php index c9b2cf84b8..e82b5a6637 100644 --- a/Library/FunctionCall.php +++ b/Library/FunctionCall.php @@ -146,17 +146,18 @@ protected function isReadOnly($funcName, array $expression) * Once the function processes the parameters we should mark * specific parameters to be passed by reference * - * @param string $funcName - * @param array $parameters + * @param string $funcName + * @param array $parameters * @param CompilationContext $compilationContext - * @param array $references - * @param array $expression - * @return boolean + * @param array $references + * @param array $expression + * + * @return void */ protected function markReferences($funcName, $parameters, CompilationContext $compilationContext, &$references, $expression) { if ($this->isBuiltInFunction($funcName)) { - return false; + return; } $reflector = $this->getReflector($funcName); @@ -175,7 +176,11 @@ protected function markReferences($funcName, $parameters, CompilationContext $co } if (!preg_match('/^[a-zA-Z0-9$\_]+$/', $parameters[$n - 1])) { - $compilationContext->logger->warning("Cannot mark complex expression as reference", "invalid-reference", $expression); + $compilationContext->logger->warning( + "Cannot mark complex expression as reference", + "invalid-reference", + $expression + ); continue; } @@ -203,7 +208,7 @@ protected function markReferences($funcName, $parameters, CompilationContext $co * @param CompilationContext $compilationContext * @return bool|mixed * - * @throws \Exception + * @throws Exception */ protected function optimize($funcName, array $expression, Call $call, CompilationContext $compilationContext) { @@ -215,7 +220,6 @@ 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 */ @@ -226,13 +230,13 @@ protected function optimize($funcName, array $expression, Call $call, Compilatio $className = 'Zephir\Optimizers\FunctionCall\\' . $camelizeFunctionName . 'Optimizer'; if (!class_exists($className, false)) { - throw new \Exception('Class ' . $className . ' cannot be loaded'); + throw new Exception("Class {$className} cannot be loaded"); } $optimizer = new $className(); if (!($optimizer instanceof OptimizerAbstract)) { - throw new \Exception('Class ' . $className . ' must be instance of OptimizerAbstract'); + throw new Exception("Class {$className} must be instance of OptimizerAbstract"); } break; @@ -284,6 +288,8 @@ public function isBuiltInFunction($functionName) * Checks if a function exists or is a built-in Zephir function * * @param string $functionName + * @param CompilationContext $context + * * @return boolean */ public function functionExists($functionName, CompilationContext $context) @@ -295,24 +301,33 @@ public function functionExists($functionName, CompilationContext $context) return true; } - $internalName = array('f__'.$functionName); + $internalName = ['f__'.$functionName]; if (isset($context->classDefinition)) { - $internalName[] = 'f_'.str_replace('\\', '_', strtolower($context->classDefinition->getNamespace())).'_'.$functionName; + $prefix = 'f_' . str_replace( + '\\', + '_', + strtolower($context->classDefinition->getNamespace()) + ); + + $internalName[] = $prefix . '_' . $functionName; } + foreach ($internalName as $name) { if (isset($context->compiler->functionDefinitions[$name])) { return true; } } + return false; } /** * @param array $expression * @param CompilationContext $compilationContext + * * @return CompiledExpression * - * @throws CompilerException + * @throws Exception|CompilerException */ protected function _callNormal(array $expression, CompilationContext $compilationContext) { @@ -330,10 +345,14 @@ protected function _callNormal(array $expression, CompilationContext $compilatio return $compiledExpr; } - $exists = true; - if (!$this->functionExists($funcName, $compilationContext)) { - $compilationContext->logger->warning("Function \"$funcName\" does not exist at compile time", "nonexistent-function", $expression); - $exists = false; + $exists = $this->functionExists($funcName, $compilationContext); + + if (!$exists) { + $compilationContext->logger->warning( + sprintf('Function "%s" does not exist at compile time', $funcName), + 'nonexistent-function', + $expression + ); } /** @@ -355,7 +374,7 @@ protected function _callNormal(array $expression, CompilationContext $compilatio $params = $this->getResolvedParams($expression['parameters'], $compilationContext, $expression); } } else { - $params = array(); + $params = []; } /** @@ -599,12 +618,13 @@ protected function _callDynamic(array $expression, CompilationContext $compilati } /** - * Compiles a function + * Compiles a function. * - * @param Expression $expr + * @param Expression $expr * @param CompilationContext $compilationContext + * * @return CompiledExpression - * @throws CompilerException + * @throws Exception|CompilerException */ public function compile(Expression $expr, CompilationContext $compilationContext) { diff --git a/Library/Optimizers/FunctionCall/IsPhpVersionOptimizer.php b/Library/Optimizers/FunctionCall/IsPhpVersionOptimizer.php index 770e2e16ae..1c693c7025 100644 --- a/Library/Optimizers/FunctionCall/IsPhpVersionOptimizer.php +++ b/Library/Optimizers/FunctionCall/IsPhpVersionOptimizer.php @@ -27,10 +27,11 @@ class IsPhpVersionOptimizer extends OptimizerAbstract { /** - * - * @param array $expression - * @param Call $call + * @param array $expression + * @param Call $call * @param CompilationContext $context + * + * @return CompiledExpression */ public function optimize(array $expression, Call $call, CompilationContext $context) { From d0709ae2b798bafcac919971136b2d3385e5da65 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 17 Apr 2018 22:21:01 +0300 Subject: [PATCH 22/40] Cleaned abstractclass stub --- test/oo/abstractclass.zep | 41 +++++---------------------------------- 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/test/oo/abstractclass.zep b/test/oo/abstractclass.zep index dc3d2a8fb8..944c60dfa0 100644 --- a/test/oo/abstractclass.zep +++ b/test/oo/abstractclass.zep @@ -3,43 +3,12 @@ namespace Test\Oo; abstract class AbstractClass { - abstract public function testMethodDeclaration() - { - - } - - abstract public function testMethodDeclarationWithReturnType() -> string - { - - } - - abstract public function testMethodDeclarationWithParameter(var a) - { - - } - - abstract public function testMethodDeclarationWithParameterAndReturnType(var a) -> string - { - - } - - /** - * - */ + abstract public function testMethodDeclaration(); + abstract public function testMethodDeclarationWithReturnType() -> string; + abstract public function testMethodDeclarationWithParameter(var a); + abstract public function testMethodDeclarationWithParameterAndReturnType(var a) -> string; abstract public function testAbstractMethodDeclaration(); - - /** - * - */ abstract public function testAbstractMethodDeclarationWithReturnType() -> string; - - /** - * - */ abstract public function testAbstractMethodDeclarationWithParameter(var a); - - /** - * - */ abstract public function testAbstractMethodDeclarationWithParameterAndReturnType(var a) -> string; -} \ No newline at end of file +} From b20961fb846e1a174a6af64561bd15d1ff067519 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 17 Apr 2018 23:09:40 +0300 Subject: [PATCH 23/40] ClassMethodParameters now implements ArrayAccess --- Library/ClassMethodParameters.php | 66 +++++++++++++++++++------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/Library/ClassMethodParameters.php b/Library/ClassMethodParameters.php index 71125bc468..c2258b1624 100644 --- a/Library/ClassMethodParameters.php +++ b/Library/ClassMethodParameters.php @@ -1,20 +1,14 @@ _parameters = $parameters; + $this->parameters = $parameters; } /** @@ -60,7 +54,7 @@ public function __construct(array $parameters) */ public function getParameters() { - return $this->_parameters; + return $this->parameters; } /** @@ -68,31 +62,51 @@ public function getParameters() */ public function count() { - return count($this->_parameters); + return count($this->parameters); } public function rewind() { - $this->_position = 0; + $this->position = 0; } public function key() { - return $this->_position; + return $this->position; } public function valid() { - return isset($this->_parameters[$this->_position]); + return isset($this->parameters[$this->position]); } public function current() { - return $this->_parameters[$this->_position]; + return $this->parameters[$this->position]; } public function next() { - $this->_position++; + $this->position++; + } + + public function offsetExists($offset) + { + return isset($this->parameters[$offset]); + } + + public function offsetGet($offset) + { + return $this->parameters[$offset]; + } + + public function offsetSet($offset, $value) + { + $this->parameters[$offset] = $value; + } + + public function offsetUnset($offset) + { + unset($this->parameters[$offset]); } } From 9ecea43886ae5e7397b0d743d86142e76f4e1219 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 17 Apr 2018 23:10:03 +0300 Subject: [PATCH 24/40] Code cleanup (PHP part) --- Library/ClassMethodParameters.php | 2 +- Library/CompilationContext.php | 11 +- Library/FunctionCall.php | 173 +++++++++++++++++++----------- 3 files changed, 117 insertions(+), 69 deletions(-) diff --git a/Library/ClassMethodParameters.php b/Library/ClassMethodParameters.php index c2258b1624..5736b276b8 100644 --- a/Library/ClassMethodParameters.php +++ b/Library/ClassMethodParameters.php @@ -20,7 +20,7 @@ * * Represents the parameters defined in a method */ -class ClassMethodParameters implements \Countable, \Iterator , \ArrayAccess +class ClassMethodParameters implements \Countable, \Iterator, \ArrayAccess { private $parameters = []; diff --git a/Library/CompilationContext.php b/Library/CompilationContext.php index 67c23378d5..240a54db73 100644 --- a/Library/CompilationContext.php +++ b/Library/CompilationContext.php @@ -75,9 +75,9 @@ class CompilationContext public $classDefinition; /** - * Current method being compiled + * Current method or function that being compiled * - * @var ClassMethod + * @var ClassMethod|FunctionDefinition */ public $currentMethod; @@ -128,7 +128,7 @@ class CompilationContext * * @var array */ - public $cycleBlocks = array(); + public $cycleBlocks = []; /** * The current branch, variables declared in conditional branches @@ -201,9 +201,8 @@ class CompilationContext */ public function getFullName($className) { - $namespace = (isset($this->currentMethod) && $this->currentMethod instanceof FunctionDefinition) ? - $this->currentMethod->getNamespace() : - $this->classDefinition->getNamespace(); + $isFunction = $this->currentMethod && $this->currentMethod instanceof FunctionDefinition; + $namespace = $isFunction ? $this->currentMethod->getNamespace() : $this->classDefinition->getNamespace(); return Utils::getFullName($className, $namespace, $this->aliasManager); } diff --git a/Library/FunctionCall.php b/Library/FunctionCall.php index e82b5a6637..6dd2b31d98 100644 --- a/Library/FunctionCall.php +++ b/Library/FunctionCall.php @@ -18,7 +18,6 @@ /** * FunctionCall - * * Call functions. By default functions are called in the PHP userland if an optimizer * was not found or there is not a user-handler for it */ @@ -39,11 +38,11 @@ class FunctionCall extends Call */ const CALL_DYNAMIC_STRING = 3; - protected static $_optimizers = array(); + protected static $_optimizers = []; - protected static $_functionReflection = array(); + protected static $_functionReflection = []; - protected static $_optimizerDirectories = array(); + protected static $_optimizerDirectories = []; private static $_functionCache = null; @@ -51,6 +50,7 @@ class FunctionCall extends Call * Process the ReflectionFunction for the specified function name * * @param string $funcName + * * @return \ReflectionFunction */ public function getReflector($funcName) @@ -66,10 +66,12 @@ public function getReflector($funcName) } self::$_functionReflection[$funcName] = $reflectionFunction; $this->_reflection = $reflectionFunction; + return $reflectionFunction; } $reflectionFunction = self::$_functionReflection[$funcName]; $this->_reflection = $reflectionFunction; + return $reflectionFunction; } @@ -79,7 +81,7 @@ public function getReflector($funcName) * Built-in functions rarely change the parameters if they aren't passed by reference * * @param string $funcName - * @param array $expression + * @param array $expression * * @return bool * @throws CompilerException @@ -104,42 +106,44 @@ protected function isReadOnly($funcName, array $expression) } $reflector = $this->getReflector($funcName); - if ($reflector) { - if (isset($expression['parameters'])) { - /** - * Check if the number of parameters - */ - $numberParameters = count($expression['parameters']); - if ($funcName == "unpack" && (version_compare(PHP_VERSION, '7.1.0') == 0 || version_compare(PHP_VERSION, '7.1.1') == 0)) { - if ($numberParameters < 2) { - throw new CompilerException("The number of parameters passed is lesser than the number of required parameters by '" . $funcName . "'", $expression); - } - } else { - if ($numberParameters < $reflector->getNumberOfRequiredParameters()) { - throw new CompilerException( - "The number of parameters passed is lesser than the number of required parameters by '".$funcName."'", - $expression - ); - } + if (!$reflector instanceof \ReflectionFunction) { + return false; + } + + $messageFormat = "The number of parameters passed is lesser than the number of required parameters by '%s'"; + + if (isset($expression['parameters'])) { + /** + * Check if the number of parameters + */ + $numberParameters = count($expression['parameters']); + if ($funcName == "unpack" && + (version_compare(PHP_VERSION, '7.1.0') == 0 || + version_compare(PHP_VERSION, '7.1.1') == 0) + ) { + if ($numberParameters < 2) { + throw new CompilerException(sprintf($messageFormat, $funcName), $expression); } } else { - $numberParameters = 0; - if ($reflector->getNumberOfRequiredParameters() > 0) { - throw new CompilerException("The number of parameters passed is lesser than the number of required parameters by '" . $funcName . "'", $expression); + if ($numberParameters < $reflector->getNumberOfRequiredParameters()) { + throw new CompilerException(sprintf($messageFormat, $funcName), $expression); } } + } else { + if ($reflector->getNumberOfRequiredParameters() > 0) { + throw new CompilerException(sprintf($messageFormat, $funcName), $expression); + } + } - if ($reflector->getNumberOfParameters() > 0) { - foreach ($reflector->getParameters() as $parameter) { - if ($parameter->isPassedByReference()) { - return false; - } + if ($reflector->getNumberOfParameters() > 0) { + foreach ($reflector->getParameters() as $parameter) { + if ($parameter->isPassedByReference()) { + return false; } } - return true; } - return false; + return true; } /** @@ -154,8 +158,13 @@ protected function isReadOnly($funcName, array $expression) * * @return void */ - protected function markReferences($funcName, $parameters, CompilationContext $compilationContext, &$references, $expression) - { + protected function markReferences( + $funcName, + $parameters, + CompilationContext $compilationContext, + &$references, + $expression + ) { if ($this->isBuiltInFunction($funcName)) { return; } @@ -189,7 +198,7 @@ protected function markReferences($funcName, $parameters, CompilationContext $co $variable->setDynamicTypes('undefined'); $referenceSymbol = $compilationContext->backend->getVariableCode($variable); $compilationContext->codePrinter->output('ZEPHIR_MAKE_REF(' . $referenceSymbol . ');'); - $references[] = $parameters[$n - 1] ; + $references[] = $parameters[$n - 1]; } } } @@ -202,12 +211,12 @@ protected function markReferences($funcName, $parameters, CompilationContext $co /** * Tries to find specific an specialized optimizer for function calls * - * @param string $funcName - * @param array $expression - * @param Call $call + * @param string $funcName + * @param array $expression + * @param Call $call * @param CompilationContext $compilationContext - * @return bool|mixed * + * @return bool|mixed * @throws Exception */ protected function optimize($funcName, array $expression, Call $call, CompilationContext $compilationContext) @@ -224,7 +233,7 @@ protected function optimize($funcName, array $expression, Call $call, Compilatio * Check every optimizer directory for an optimizer */ foreach (self::$_optimizerDirectories as $directory) { - $path = $directory . DIRECTORY_SEPARATOR . $camelizeFunctionName . 'Optimizer.php'; + $path = $directory . DIRECTORY_SEPARATOR . $camelizeFunctionName . 'Optimizer.php'; if (file_exists($path)) { require_once $path; @@ -259,6 +268,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) @@ -281,16 +291,17 @@ public function isBuiltInFunction($functionName) case 'get_class_lower': return true; } + return false; } /** * Checks if a function exists or is a built-in Zephir function * - * @param string $functionName + * @param string $functionName * @param CompilationContext $context * - * @return boolean + * @return bool */ public function functionExists($functionName, CompilationContext $context) { @@ -301,13 +312,10 @@ public function functionExists($functionName, CompilationContext $context) return true; } - $internalName = ['f__'.$functionName]; + $internalName = ['f__' . $functionName]; if (isset($context->classDefinition)) { - $prefix = 'f_' . str_replace( - '\\', - '_', - strtolower($context->classDefinition->getNamespace()) - ); + $lowerNamespace = strtolower($context->classDefinition->getNamespace()); + $prefix = 'f_' . str_replace('\\', '_', $lowerNamespace); $internalName[] = $prefix . '_' . $functionName; } @@ -326,7 +334,6 @@ public function functionExists($functionName, CompilationContext $context) * @param CompilationContext $compilationContext * * @return CompiledExpression - * * @throws Exception|CompilerException */ protected function _callNormal(array $expression, CompilationContext $compilationContext) @@ -396,7 +403,10 @@ protected function _callNormal(array $expression, CompilationContext $compilatio $symbolVariable = $this->getSymbolVariable(); if ($symbolVariable) { if (!$symbolVariable->isVariable()) { - throw new CompilerException("Returned values by functions can only be assigned to variant variables", $expression); + throw new CompilerException( + "Returned values by functions can only be assigned to variant variables", + $expression + ); } /** @@ -430,13 +440,17 @@ protected function _callNormal(array $expression, CompilationContext $compilatio if (!count($params)) { if ($this->isExpectingReturn()) { if ($symbolVariable->getName() == 'return_value') { - $codePrinter->output('ZEPHIR_RETURN_CALL_FUNCTION("' . $funcName . '", ' . $cachePointer . ');'); + $codePrinter->output( + 'ZEPHIR_RETURN_CALL_FUNCTION("' . $funcName . '", ' . $cachePointer . ');' + ); } else { if ($this->mustInitSymbolVariable()) { $symbolVariable->setMustInitNull(true); $symbolVariable->trackVariant($compilationContext); } - $codePrinter->output('ZEPHIR_CALL_FUNCTION(' . $symbol . ', "' . $funcName . '", ' . $cachePointer . ');'); + $codePrinter->output( + 'ZEPHIR_CALL_FUNCTION(' . $symbol . ', "' . $funcName . '", ' . $cachePointer . ');' + ); } } else { $codePrinter->output('ZEPHIR_CALL_FUNCTION(NULL, "' . $funcName . '", ' . $cachePointer . ');'); @@ -444,16 +458,36 @@ protected function _callNormal(array $expression, CompilationContext $compilatio } else { if ($this->isExpectingReturn()) { if ($symbolVariable->getName() == 'return_value') { - $codePrinter->output('ZEPHIR_RETURN_CALL_FUNCTION("' . $funcName . '", ' . $cachePointer . ', ' . join(', ', $params) . ');'); + $codePrinter->output( + strtr('ZEPHIR_RETURN_CALL_FUNCTION(":func", :pointer, :params);', [ + ':func' => $funcName, + ':pointer' => $cachePointer, + ':params' => implode(', ', $params), + ]) + ); } else { if ($this->mustInitSymbolVariable()) { $symbolVariable->setMustInitNull(true); $symbolVariable->trackVariant($compilationContext); } - $codePrinter->output('ZEPHIR_CALL_FUNCTION(' . $symbol . ', "' . $funcName . '", ' . $cachePointer . ', ' . join(', ', $params) . ');'); + + $codePrinter->output( + strtr('ZEPHIR_CALL_FUNCTION(:symbol, ":func", :pointer, :params);', [ + ':symbol' => $symbol, + ':func' => $funcName, + ':pointer' => $cachePointer, + ':params' => implode(', ', $params), + ]) + ); } } else { - $codePrinter->output('ZEPHIR_CALL_FUNCTION(NULL, "' . $funcName . '", ' . $cachePointer . ', ' . join(', ', $params) . ');'); + $codePrinter->output( + strtr('ZEPHIR_CALL_FUNCTION(NULL, ":func", :pointer, :params);', [ + ':func' => $funcName, + ':pointer' => $cachePointer, + ':params' => implode(', ', $params), + ]) + ); } } @@ -488,8 +522,7 @@ protected function _callNormal(array $expression, CompilationContext $compilatio } /** - * - * @param array $expression + * @param array $expression * @param CompilationContext $compilationContext * * @return CompiledExpression @@ -497,14 +530,22 @@ protected function _callNormal(array $expression, CompilationContext $compilatio */ protected function _callDynamic(array $expression, CompilationContext $compilationContext) { - $variable = $compilationContext->symbolTable->getVariableForRead($expression['name'], $compilationContext, $expression); + $variable = $compilationContext->symbolTable->getVariableForRead( + $expression['name'], + $compilationContext, + $expression + ); + switch ($variable->getType()) { case 'variable': case 'string': break; default: - throw new CompilerException("Variable type: " . $variable->getType() . " cannot be used as dynamic caller", $expression['left']); + throw new CompilerException( + "Variable type: " . $variable->getType() . " cannot be used as dynamic caller", + $expression['left'] + ); } /** @@ -513,7 +554,7 @@ protected function _callDynamic(array $expression, CompilationContext $compilati if (isset($expression['parameters'])) { $params = $this->getResolvedParams($expression['parameters'], $compilationContext, $expression); } else { - $params = array(); + $params = []; } $codePrinter = $compilationContext->codePrinter; @@ -530,7 +571,10 @@ protected function _callDynamic(array $expression, CompilationContext $compilati $symbolVariable = $this->getSymbolVariable(); if ($symbolVariable) { if (!$symbolVariable->isVariable()) { - throw new CompilerException("Returned values by functions can only be assigned to variant variables", $expression); + throw new CompilerException( + "Returned values by functions can only be assigned to variant variables", + $expression + ); } /** @@ -575,7 +619,12 @@ protected function _callDynamic(array $expression, CompilationContext $compilati $symbolVariable->trackVariant($compilationContext); } } - $compilationContext->backend->callDynamicFunction($symbolVariable, $variable, $compilationContext, $params); + $compilationContext->backend->callDynamicFunction( + $symbolVariable, + $variable, + $compilationContext, + $params + ); } else { $compilationContext->backend->callDynamicFunction(null, $variable, $compilationContext, $params); } From c807fe7d61a7b52de2eecff6933bea73be56bb4a Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 24 Apr 2018 00:46:47 +0300 Subject: [PATCH 25/40] Fixed Copy-On-Write violation for arrays zvals --- kernels/ZendEngine3/object.c | 54 ++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/kernels/ZendEngine3/object.c b/kernels/ZendEngine3/object.c index e97eec9770..c2b5e0848b 100644 --- a/kernels/ZendEngine3/object.c +++ b/kernels/ZendEngine3/object.c @@ -623,6 +623,7 @@ int zephir_update_property_array(zval *object, const char *property, zend_uint p ZVAL_DUP(&new_zv, &tmp); ZVAL_COPY_VALUE(&tmp, &new_zv); Z_TRY_DELREF(new_zv); + Z_ADDREF(tmp); separated = 1; } } @@ -631,6 +632,7 @@ int zephir_update_property_array(zval *object, const char *property, zend_uint p ZVAL_DUP(&new_zv, &tmp); ZVAL_COPY_VALUE(&tmp, &new_zv); Z_TRY_DELREF(new_zv); + Z_ADDREF(tmp); separated = 1; } @@ -642,7 +644,14 @@ int zephir_update_property_array(zval *object, const char *property, zend_uint p array_init(&tmp); separated = 1; } - Z_DELREF(tmp); + + if (Z_REFCOUNTED(tmp)) { + if (Z_REFCOUNT(tmp) > 1) { + if (!Z_ISREF(tmp)) { + Z_DELREF(tmp); + } + } + } } Z_TRY_ADDREF_P(value); @@ -657,6 +666,14 @@ int zephir_update_property_array(zval *object, const char *property, zend_uint p if (separated) { zephir_update_property_zval(object, property, property_length, &tmp); } + + if (Z_REFCOUNTED(tmp)) { + if (Z_REFCOUNT(tmp) > 1) { + if (!Z_ISREF(tmp)) { + Z_DELREF(tmp); + } + } + } } return SUCCESS; @@ -741,6 +758,7 @@ int zephir_update_property_array_multi(zval *object, const char *property, zend_ ZVAL_DUP(&new_zv, &tmp_arr); ZVAL_COPY_VALUE(&tmp_arr, &new_zv); Z_TRY_DELREF(new_zv); + Z_ADDREF(tmp_arr); separated = 1; } } @@ -760,7 +778,14 @@ int zephir_update_property_array_multi(zval *object, const char *property, zend_ array_init(&tmp_arr); separated = 1; } - Z_DELREF(tmp_arr); + + if (Z_REFCOUNTED(tmp_arr)) { + if (Z_REFCOUNT(tmp_arr) > 1) { + if (!Z_ISREF(tmp_arr)) { + Z_DELREF(tmp_arr); + } + } + } } va_start(ap, types_count); @@ -770,6 +795,14 @@ int zephir_update_property_array_multi(zval *object, const char *property, zend_ if (separated) { zephir_update_property_zval(object, property, property_length, &tmp_arr); } + + if (Z_REFCOUNTED(tmp_arr)) { + if (Z_REFCOUNT(tmp_arr) > 1) { + if (!Z_ISREF(tmp_arr)) { + Z_DELREF(tmp_arr); + } + } + } } return SUCCESS; @@ -939,6 +972,7 @@ int zephir_update_static_property_array_multi_ce(zend_class_entry *ce, const cha ZVAL_DUP(&new_zv, &tmp_arr); ZVAL_COPY_VALUE(&tmp_arr, &new_zv); Z_TRY_DELREF(new_zv); + Z_ADDREF(tmp_arr); separated = 1; } } @@ -958,7 +992,13 @@ int zephir_update_static_property_array_multi_ce(zend_class_entry *ce, const cha array_init(&tmp_arr); separated = 1; } - Z_DELREF(tmp_arr); + if (Z_REFCOUNTED(tmp_arr)) { + if (Z_REFCOUNT(tmp_arr) > 1) { + if (!Z_ISREF(tmp_arr)) { + Z_DELREF(tmp_arr); + } + } + } } va_start(ap, types_count); @@ -970,6 +1010,14 @@ int zephir_update_static_property_array_multi_ce(zend_class_entry *ce, const cha zend_update_static_property(ce, property, property_length, &tmp_arr); } + if (Z_REFCOUNTED(tmp_arr)) { + if (Z_REFCOUNT(tmp_arr) > 1) { + if (!Z_ISREF(tmp_arr)) { + Z_DELREF(tmp_arr); + } + } + } + return SUCCESS; } From 198f0e27c95d0e4399d8ab1240fdd236c89a6dca Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 24 Apr 2018 00:47:50 +0300 Subject: [PATCH 26/40] Added zval's reference count helper --- kernels/ZendEngine3/debug.c | 1 + kernels/ZendEngine3/debug.h | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/kernels/ZendEngine3/debug.c b/kernels/ZendEngine3/debug.c index 0d7ab82121..71ac24c51e 100644 --- a/kernels/ZendEngine3/debug.c +++ b/kernels/ZendEngine3/debug.c @@ -36,6 +36,7 @@ void zephir_vdump(zval *var, const char *func) } if (!Z_REFCOUNTED_P(var)) { + fprintf(stderr, "%s: (%p) is not reference-counted, type=%d\n", func, var, Z_TYPE_P(var)); return; } diff --git a/kernels/ZendEngine3/debug.h b/kernels/ZendEngine3/debug.h index 223060298e..c42ad6151f 100644 --- a/kernels/ZendEngine3/debug.h +++ b/kernels/ZendEngine3/debug.h @@ -37,5 +37,23 @@ typedef struct _zephir_debug_entry { int lineno; } zephir_debug_entry; -#endif -#endif +/** The zval's reference count dump */ +#define RC_DUMP(zv) \ + do { \ + char *_n = (strrchr((#zv), '&') ? strrchr((#zv), '&') + 1 : (#zv)); \ + char *_f = (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__); \ + zval *_z = (zv); \ + if (Z_REFCOUNTED_P(_z)) { \ + fprintf(stderr, "[DUMP]: %s:%d %s (%p) refcount=%d, type=%d\n", _f, __LINE__, _n, _z, Z_REFCOUNT_P(_z), Z_TYPE_P(_z)); \ + } else { \ + fprintf(stderr, "[DUMP]: %s:%d %s (%p) is not reference-counted, type=%d\n", _f, __LINE__, _n, _z, Z_TYPE_P(_z)); \ + } \ + } while (0) + + +#else + +#define RC_DUMP(zv) + +#endif /* ZEPHIR_RELEASE */ +#endif /* ZEPHIR_KERNEL_DEBUG_H */ From 915e19027516c5200e01785ee7a09522dd6f81ae Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 24 Apr 2018 20:29:50 +0300 Subject: [PATCH 27/40] Fixed error message in case of absence class --- Library/CompilerFile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/CompilerFile.php b/Library/CompilerFile.php index 371c776aad..2d8eb09329 100644 --- a/Library/CompilerFile.php +++ b/Library/CompilerFile.php @@ -714,7 +714,7 @@ public function preCompile(Compiler $compiler) if (!$this->_external) { $expectedPath = strtolower(str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR . $name) . '.zep'; if (strtolower($this->_filePath) != $expectedPath) { - $className = str_replace('\\', '/', $namespace) . '\\' . $name; + $className = $namespace . '\\' . $name; $message = 'Unexpected class name ' . $className . ' in file: ' . $this->_filePath . ', expected: ' . $expectedPath; throw new CompilerException($message); } From dc2c7a5d98aac8151cda7c133f404418c2a9e46c Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 24 Apr 2018 20:50:37 +0300 Subject: [PATCH 28/40] Test for calling private methods --- test/oo/scopes/hasprivatemethod.zep | 14 ++++++++++ test/oo/scopes/privatescopetester.zep | 9 +++++++ test/oo/scopes/scopetesterinterface.zep | 6 +++++ .../Extension/Oo/Scopes/PrivateScopeTest.php | 26 +++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 test/oo/scopes/hasprivatemethod.zep create mode 100644 test/oo/scopes/privatescopetester.zep create mode 100644 test/oo/scopes/scopetesterinterface.zep create mode 100644 unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php diff --git a/test/oo/scopes/hasprivatemethod.zep b/test/oo/scopes/hasprivatemethod.zep new file mode 100644 index 0000000000..30b7303355 --- /dev/null +++ b/test/oo/scopes/hasprivatemethod.zep @@ -0,0 +1,14 @@ +namespace Test\Oo\Scopes; + +class HasPrivateMethod +{ + public function callPrivateMethod() -> string + { + return this->isPrivate(); + } + + private function isPrivate() -> string + { + return __FUNCTION__; + } +} diff --git a/test/oo/scopes/privatescopetester.zep b/test/oo/scopes/privatescopetester.zep new file mode 100644 index 0000000000..8476eb792d --- /dev/null +++ b/test/oo/scopes/privatescopetester.zep @@ -0,0 +1,9 @@ +namespace Test\Oo\Scopes; + +class PrivateScopeTester extends HasPrivateMethod implements ScopeTesterInterface +{ + public function run() -> string + { + return this->callPrivateMethod(); + } +} diff --git a/test/oo/scopes/scopetesterinterface.zep b/test/oo/scopes/scopetesterinterface.zep new file mode 100644 index 0000000000..005a683671 --- /dev/null +++ b/test/oo/scopes/scopetesterinterface.zep @@ -0,0 +1,6 @@ +namespace Test\Oo\Scopes; + +interface ScopeTesterInterface +{ + public function run() -> string; +} diff --git a/unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php b/unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php new file mode 100644 index 0000000000..6905dddd21 --- /dev/null +++ b/unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php @@ -0,0 +1,26 @@ +assertSame('isPrivate', (new PrivateScopeTester())->run()); + } +} From 73a5a6aeb34c6b81494f46c9a0bb8c29a4c73944 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Tue, 24 Apr 2018 21:07:53 +0300 Subject: [PATCH 29/40] Correct tests for PHP < 5.6 --- unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php b/unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php index 6905dddd21..1d8d3f3147 100644 --- a/unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php +++ b/unit-tests/Extension/Oo/Scopes/PrivateScopeTest.php @@ -21,6 +21,12 @@ class PrivateScopeTest extends TestCase /** @test */ public function shouldCallPrivateMethod() { + if (PHP_VERSION_ID < 50600) { + $this->markTestSkipped( + "Calling parent's private methods from the child's public ones doesn't provided for PHP < 5.6" + ); + } + $this->assertSame('isPrivate', (new PrivateScopeTester())->run()); } } From 1a0a2f645a363df9ebadf40c31376958553e81a8 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Fri, 27 Apr 2018 00:04:54 +0300 Subject: [PATCH 30/40] Added missed ZEPHIR_CALL_CE_STATIC_ZVAL --- kernels/ZendEngine3/fcall.h | 17 +++++++ test/scall.zep | 26 ++++++++--- test/scallparent.zep | 8 ++-- unit-tests/Extension/ScallTest.php | 71 +++++++++++++++++++++--------- 4 files changed, 92 insertions(+), 30 deletions(-) diff --git a/kernels/ZendEngine3/fcall.h b/kernels/ZendEngine3/fcall.h index fb19036c2c..5ba275abab 100644 --- a/kernels/ZendEngine3/fcall.h +++ b/kernels/ZendEngine3/fcall.h @@ -232,6 +232,23 @@ typedef enum _zephir_call_type { ZEPHIR_LAST_CALL_STATUS = zephir_return_call_class_method(return_value, class_entry, zephir_fcall_ce, NULL, method, strlen(method), cache, cache_slot, ZEPHIR_CALL_NUM_PARAMS(params_), ZEPHIR_PASS_CALL_PARAMS(params_)); \ } while (0) +#define ZEPHIR_CALL_CE_STATIC_ZVAL(return_value_ptr, class_entry, method, cache, cache_slot, ...) \ + do { \ + char *method_name; \ + int method_len; \ + zval *params_[] = {ZEPHIR_FETCH_VA_ARGS __VA_ARGS__}; \ + if (Z_TYPE(method) == IS_STRING) { \ + method_len = Z_STRLEN(method); \ + method_name = zend_str_tolower_dup(Z_STRVAL(method), method_len); \ + } else { \ + method_len = 0; \ + method_name = zend_str_tolower_dup("", 0); \ + } \ + ZEPHIR_OBSERVE_OR_NULLIFY_PPZV(return_value_ptr); \ + ZEPHIR_LAST_CALL_STATUS = zephir_call_class_method_aparams(return_value_ptr, class_entry, zephir_fcall_ce, NULL, method_name, method_len, cache, cache_slot, ZEPHIR_CALL_NUM_PARAMS(params_), ZEPHIR_PASS_CALL_PARAMS(params_)); \ + efree(method_name); \ + } while (0) + #define ZEPHIR_RETURN_CALL_CE_STATIC_ZVAL(class_entry, method, cache, cache_slot, ...) \ do { \ char *method_name; \ diff --git a/test/scall.zep b/test/scall.zep index 791e7014bf..83aa46dacb 100644 --- a/test/scall.zep +++ b/test/scall.zep @@ -7,17 +7,17 @@ namespace Test; class Scall extends ScallParent { - static public function testMethod1() + static public function testMethod1() -> string { return "hello public"; } - static protected function testMethod2() + static protected function testMethod2() -> string { return "hello protected"; } - static private function testMethod3() + static private function testMethod3() -> string { return "hello private"; } @@ -117,7 +117,7 @@ class Scall extends ScallParent return self::testMethod7(); } - public static function testMethod16(long a, long b) + public static function testMethod16(long a, long b) -> long { return a + b; } @@ -140,8 +140,24 @@ class Scall extends ScallParent return j; } - static protected function testMethodStatic() + static protected function testMethodStatic() -> string { return "hello Scall"; } + + public function interpolatedStaticReturn() -> string + { + string className = "Test\\Scall"; + string methodName = "testMethodStatic"; + + return {className}::{methodName}(); + } + + public function interpolatedStaticEcho() -> void + { + string className = "Test\\Scall"; + string methodName = "testMethodStatic"; + + echo {className}::{methodName}(); + } } diff --git a/test/scallparent.zep b/test/scallparent.zep index 9a267fd460..d10af53768 100644 --- a/test/scallparent.zep +++ b/test/scallparent.zep @@ -7,22 +7,22 @@ namespace Test; class ScallParent { - static public function testMethod1() + static public function testMethod1() -> string { return "hello parent public"; } - static protected function testMethod2() + static protected function testMethod2() -> string { return "hello parent protected"; } - static public function testCallStatic() + static public function testCallStatic() -> string { return static::testMethodStatic(); } - static protected function testMethodStatic() + static protected function testMethodStatic() -> string { return "hello ScallParent"; } diff --git a/unit-tests/Extension/ScallTest.php b/unit-tests/Extension/ScallTest.php index c0a224ead1..241e083117 100644 --- a/unit-tests/Extension/ScallTest.php +++ b/unit-tests/Extension/ScallTest.php @@ -7,42 +7,71 @@ | | | This source file is subject the MIT license, that is bundled with this | | package in the file LICENSE, and is available through the world-wide-web | - | at the following url: http://zephir-lang.com/license.html | + | at the following url: https://zephir-lang.com/license.html | +--------------------------------------------------------------------------+ */ namespace Extension; -class ScallTest extends \PHPUnit_Framework_TestCase +use Test\Scall; +use Test\Scallparent; +use PHPUnit\Framework\TestCase; + +class ScallTest extends TestCase { public function testScall() { - $t = new \Test\Scall(); + $t = new Scall(); - $this->assertSame($t->testMethod1(), 'hello public'); - $this->assertSame($t::testMethod1(), 'hello public'); - $this->assertSame(\Test\Scall::testMethod1(), 'hello public'); + $this->assertSame('hello public', $t->testMethod1()); + $this->assertSame('hello public', $t::testMethod1()); + $this->assertSame('hello public', Scall::testMethod1()); - $this->assertSame($t->testCall1(), 'hello public'); - $this->assertSame($t->testCall2(), 'hello protected'); - $this->assertSame($t->testCall3(), 'hello private'); + $this->assertSame('hello public', $t->testCall1()); + $this->assertSame('hello protected', $t->testCall2()); + $this->assertSame('hello private', $t->testCall3()); - $this->assertSame($t->testCall4(2, 3), 5); - $this->assertSame($t->testCall5(6, 7), 13); - $this->assertSame($t->testCall6(4, 5), 9); + $this->assertSame(5, $t->testCall4(2, 3)); + $this->assertSame(13, $t->testCall5(6, 7)); + $this->assertSame(9, $t->testCall6(4, 5)); - $this->assertSame($t->testCall7(), 'hello public'); - $this->assertSame($t->testCall8(), 'hello protected'); - $this->assertSame($t->testCall9(), 'hello private'); + $this->assertSame('hello public', $t->testCall7()); + $this->assertSame('hello protected', $t->testCall8()); + $this->assertSame('hello private', $t->testCall9()); - $this->assertSame($t->testCall10(2, 3), 5); - $this->assertSame($t->testCall11(6, 7), 13); - $this->assertSame($t->testCall12(4, 5), 9); + $this->assertSame(5, $t->testCall10(2, 3)); + $this->assertSame(13, $t->testCall11(6, 7)); + $this->assertSame(9, $t->testCall12(4, 5)); - $this->assertSame($t->testCall13(), 'hello parent public'); - $this->assertSame($t->testCall14(), 'hello parent protected'); + $this->assertSame('hello parent public', $t->testCall13()); + $this->assertSame('hello parent protected', $t->testCall14()); - $this->assertSame('hello ScallParent', \Test\Scallparent::testCallStatic()); + $this->assertSame('hello ScallParent', Scallparent::testCallStatic()); $this->assertSame('hello Scall', $t::testCallStatic()); } + + /** + * @test + * @issue 1622 + */ + public function shouldReturnInterpolatedMethodFromZephir() + { + $t = new Scall(); + $this->assertSame('hello Scall', $t->interpolatedStaticReturn()); + } + + /** + * @test + * @issue 1622 + */ + public function shouldEchoInterpolatedMethodFromZephir() + { + $t = new Scall(); + + ob_start(); + $t->interpolatedStaticEcho(); + $content = ob_get_clean(); + + $this->assertSame('hello Scall', $content); + } } From a4f4e151a4fed8508cf5036316af62362d24772b Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sat, 28 Apr 2018 10:43:11 +0300 Subject: [PATCH 31/40] Improved build on Travis CI [skip appveyor] --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b12739e4c0..d6509dda02 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,8 @@ env: - LIBRARY_PATH="$TRAVIS_BUILD_DIR/build/lib":$LIBRARY_PATH - C_INCLUDE_PATH="$TRAVIS_BUILD_DIR/build/include" - CFLAGS="-g3 -O0 -Wall -fvisibility=hidden" + - USE_ZEND_ALLOC=0 + - ZEND_DONT_UNLOAD_MODULES=1 - REPORT_EXIT_STATUS=1 - PATH="${HOME}/bin:${PATH}" - RE2C_VERSION="1.0.3" @@ -70,7 +72,7 @@ install: - ./install before_script: - #- $CC --version + - $CC --version - $(phpenv which php) compiler.php help - $(phpenv which php) compiler.php generate - $(phpenv which php) compiler.php stubs @@ -94,6 +96,7 @@ script: --fullpath-after= \ --track-origins=yes \ --leak-check=full \ + --num-callers=20 \ --run-libc-freeres=no \ ./unit-tests/phpunit \ --not-exit \ From 20d762adacec81917f8ecc86bb447fe944337eea Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sat, 28 Apr 2018 11:04:59 +0300 Subject: [PATCH 32/40] Increased verbosity on build stage (Travis CI) [skip appveyor] --- .travis.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d6509dda02..9fd4df8cf9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,6 +64,9 @@ cache: before_install: - if [[ ! -z "${GH_TOKEN}" ]]; then composer config github-oauth.github.com ${GH_TOKEN}; echo "Configured Github token"; fi; + - $CC --version + - $(phpenv which php) -v + - $(phpenv which php) -m install: - composer --prefer-source install @@ -72,19 +75,17 @@ install: - ./install before_script: - - $CC --version - $(phpenv which php) compiler.php help - - $(phpenv which php) compiler.php generate + - $(phpenv which php) compiler.php generate -Wnonexistent-function -Wnonexistent-class -Wunused-variable - $(phpenv which php) compiler.php stubs - $(phpenv which php) compiler.php api - (cd ext; $(phpenv which phpize) && ./configure --silent --with-php-config=$(phpenv which php-config) --enable-test && make -j"$(getconf _NPROCESSORS_ONLN)" && make --silent install && phpenv config-add ../unit-tests/ci/test.ini) #- ls -1 `$(phpenv which php-config) --extension-dir` - #- $(phpenv which php) -m #- phpenv versions - ulimit -c unlimited || true # Uncomment to setting core dump #- echo '/tmp/core_%e.%p' | sudo tee /proc/sys/kernel/core_pattern &> /dev/null - - sudo chmod +s $(which gdb) + #- sudo chmod +s $(which gdb) script: - echo 'variables_order=EGPCS' >> "$(phpenv root)/versions/$(phpenv version-name)/etc/php.ini" @@ -111,6 +112,7 @@ after_success: after_failure: # Uncomment to debug core dump # - ./unit-tests/ci/after_failure.sh + - $(phpenv which php) -v - $(phpenv which php) -m - $(phpenv which php) -i From d51c635598a9d52392525bff55edfd395a039f9b Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sat, 28 Apr 2018 11:11:20 +0300 Subject: [PATCH 33/40] Improved test's docs --- test/arraysearch.zep | 4 ++-- test/bitwise.zep | 2 +- test/globals/post.zep | 2 +- test/statements.zep | 2 +- unit-tests/Extension/ArraySearchTest.php | 4 ++-- unit-tests/Extension/BitwiseTest.php | 2 +- unit-tests/Extension/ConcatTest.php | 2 +- unit-tests/Extension/FunctionExistsTest.php | 6 +++--- unit-tests/Extension/Globals/PostTest.php | 6 +++--- unit-tests/Extension/Oo/ExtendClassTest.php | 4 ++-- .../Extension/Properties/StaticPrivatePropertiesTest.php | 2 +- unit-tests/Extension/ReturnsTest.php | 8 ++++---- unit-tests/Extension/ScallTest.php | 4 ++-- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/arraysearch.zep b/test/arraysearch.zep index d174e01e3a..ca5b34e86b 100644 --- a/test/arraysearch.zep +++ b/test/arraysearch.zep @@ -2,13 +2,13 @@ namespace Test; class ArraySearch { - /** @issue 1609 */ + /** @issue https://github.com/phalcon/zephir/issues/1609 */ public function simpleSearch(var needle, array haystack, bool strict = false) -> var { return array_search(needle, haystack, strict); } - /** @issue 1609 */ + /** @issue https://github.com/phalcon/zephir/issues/1609 */ public function searchUsingArrayInsideZephir() -> var { array itoA64 = [".", "/", "0", "1", "2", "3", "4", "value", "OtherValue"]; diff --git a/test/bitwise.zep b/test/bitwise.zep index de7134cf7e..272795570c 100644 --- a/test/bitwise.zep +++ b/test/bitwise.zep @@ -955,7 +955,7 @@ class Bitwise } /** - * @issue 1581 + * @issue https://github.com/phalcon/zephir/issues/1581 */ public function testbitwiseXor() { diff --git a/test/globals/post.zep b/test/globals/post.zep index 46f731fc7c..08410281b5 100644 --- a/test/globals/post.zep +++ b/test/globals/post.zep @@ -6,7 +6,7 @@ class Post /** * Tests "Invalid superglobal for _POST" * - * @issue 1623 + * @issue https://github.com/phalcon/zephir/issues/1623 */ public function hasValue(string name) -> boolean { diff --git a/test/statements.zep b/test/statements.zep index f343f69ddd..dc8da1f904 100644 --- a/test/statements.zep +++ b/test/statements.zep @@ -6,7 +6,7 @@ class Statements public tmp2 = "test string"; /** - * Vars for 544 Issue test + * @issue https://github.com/phalcon/zephir/issues/544 */ private totalSteps = 100; diff --git a/unit-tests/Extension/ArraySearchTest.php b/unit-tests/Extension/ArraySearchTest.php index 697e3dcfe0..91aa49c9bf 100644 --- a/unit-tests/Extension/ArraySearchTest.php +++ b/unit-tests/Extension/ArraySearchTest.php @@ -18,7 +18,7 @@ class ArraySearchTest extends \PHPUnit_Framework_TestCase { /** * @test - * @issue 1609 + * @issue https://github.com/phalcon/zephir/issues/1609 */ public function shouldSearchInTheExternalArrayForAGivenValueAndReturnTheFirstCorrespondingKey() { @@ -32,7 +32,7 @@ public function shouldSearchInTheExternalArrayForAGivenValueAndReturnTheFirstCor /** * @test - * @issue 1609 + * @issue https://github.com/phalcon/zephir/issues/1609 */ public function shouldSearchInTheInternalArrayForAGivenValueAndReturnTheFirstCorrespondingKey() { diff --git a/unit-tests/Extension/BitwiseTest.php b/unit-tests/Extension/BitwiseTest.php index bf3aa41923..f71d9cd043 100644 --- a/unit-tests/Extension/BitwiseTest.php +++ b/unit-tests/Extension/BitwiseTest.php @@ -125,7 +125,7 @@ public function testBitwise() /** * Bitwise XOR - * @issue 1581 + * @issue https://github.com/phalcon/zephir/issues/1581 */ $this->assertSame(123 ^ 321, $t->testbitwiseXor()); } diff --git a/unit-tests/Extension/ConcatTest.php b/unit-tests/Extension/ConcatTest.php index 9e86016250..de1196e0b5 100644 --- a/unit-tests/Extension/ConcatTest.php +++ b/unit-tests/Extension/ConcatTest.php @@ -48,7 +48,7 @@ public function shouldConcatenateVariableWithString() /** * @test - * @issue 1573 + * @issue https://github.com/phalcon/zephir/issues/1573 */ public function shouldConcatenateStringsSimilarToIntegersNumbers() { diff --git a/unit-tests/Extension/FunctionExistsTest.php b/unit-tests/Extension/FunctionExistsTest.php index 87775dbff4..fbe661af3e 100644 --- a/unit-tests/Extension/FunctionExistsTest.php +++ b/unit-tests/Extension/FunctionExistsTest.php @@ -20,7 +20,7 @@ class FunctionExistsTest extends \PHPUnit_Framework_TestCase /** * @test * @dataProvider providerInternalFunctions - * @issue 1547 + * @issue https://github.com/phalcon/zephir/issues/1547 * @param string $func The internal (built-in) function name */ public function shouldCorrectDetectestExistenceWithPassedName($func) @@ -31,7 +31,7 @@ public function shouldCorrectDetectestExistenceWithPassedName($func) /** * @test - * @issue 1547 + * @issue https://github.com/phalcon/zephir/issues/1547 */ public function shouldCorrectDetectestExistenceInsideTheZephirCode() { @@ -52,7 +52,7 @@ public function shouldCorrectDetectestExistenceInsideTheZephirCode() /** * @test - * @issue 1547 + * @issue https://github.com/phalcon/zephir/issues/1547 */ public function shouldCorrectDetectestExistenceByUsingString() { diff --git a/unit-tests/Extension/Globals/PostTest.php b/unit-tests/Extension/Globals/PostTest.php index 982adb150d..64b677fe68 100644 --- a/unit-tests/Extension/Globals/PostTest.php +++ b/unit-tests/Extension/Globals/PostTest.php @@ -9,7 +9,7 @@ class PostTest extends PHPUnit_Framework_TestCase { /** * @test - * @issue 1623 + * @issue https://github.com/phalcon/zephir/issues/1623 */ public function shouldNotTriggerAnyErrorIfPostIsUndefined() { @@ -23,7 +23,7 @@ public function shouldNotTriggerAnyErrorIfPostIsUndefined() /** * @test - * @issue 1623 + * @issue https://github.com/phalcon/zephir/issues/1623 */ public function shouldReturnFalseIfVariableIsUndefined() { @@ -37,7 +37,7 @@ public function shouldReturnFalseIfVariableIsUndefined() /** * @test - * @issue 1623 + * @issue https://github.com/phalcon/zephir/issues/1623 */ public function shouldReturnTrueIfVariableIsDefined() { diff --git a/unit-tests/Extension/Oo/ExtendClassTest.php b/unit-tests/Extension/Oo/ExtendClassTest.php index 6977bef812..7f2730cdaf 100644 --- a/unit-tests/Extension/Oo/ExtendClassTest.php +++ b/unit-tests/Extension/Oo/ExtendClassTest.php @@ -58,7 +58,7 @@ public function testInstanceOfMemcache() /** * @test - * @issue 1392 + * @issue https://github.com/phalcon/zephir/issues/1392 */ public function shouldCorrectWorkWithLateStaticBinding() { @@ -67,7 +67,7 @@ public function shouldCorrectWorkWithLateStaticBinding() /** * @test - * @issue 1372 + * @issue https://github.com/phalcon/zephir/issues/1372 */ public function shouldCallParentMethodFromStaticByUsingSelf() { diff --git a/unit-tests/Extension/Properties/StaticPrivatePropertiesTest.php b/unit-tests/Extension/Properties/StaticPrivatePropertiesTest.php index 2179f615f7..9c96fdde71 100644 --- a/unit-tests/Extension/Properties/StaticPrivatePropertiesTest.php +++ b/unit-tests/Extension/Properties/StaticPrivatePropertiesTest.php @@ -20,7 +20,7 @@ class StaticPrivatePropertiesTest extends \PHPUnit_Framework_TestCase { /** * @test - * @issue #1530 + * @issue https://github.com/phalcon/zephir/issues/1530 */ public function shouldGetInstanceByUsingSingleton() { diff --git a/unit-tests/Extension/ReturnsTest.php b/unit-tests/Extension/ReturnsTest.php index fa4b445268..bfdb24aaee 100644 --- a/unit-tests/Extension/ReturnsTest.php +++ b/unit-tests/Extension/ReturnsTest.php @@ -19,7 +19,7 @@ class ReturnsTest extends \PHPUnit_Framework_TestCase { /** * @test - * @issue 1534 + * @issue https://github.com/phalcon/zephir/issues/1534 */ public function shouldReturnWithParameter() { @@ -29,7 +29,7 @@ public function shouldReturnWithParameter() /** * @test - * @issue 1534 + * @issue https://github.com/phalcon/zephir/issues/1534 */ public function shouldReturnWithParameterStaticVersion() { @@ -38,7 +38,7 @@ public function shouldReturnWithParameterStaticVersion() /** * @test - * @issue 1534 + * @issue https://github.com/phalcon/zephir/issues/1534 */ public function shouldReturnWithoutParameter() { @@ -48,7 +48,7 @@ public function shouldReturnWithoutParameter() /** * @test - * @issue 1534 + * @issue https://github.com/phalcon/zephir/issues/1534 */ public function shouldReturnWithoutParameterStaticVersion() { diff --git a/unit-tests/Extension/ScallTest.php b/unit-tests/Extension/ScallTest.php index 241e083117..7ac1fa4a73 100644 --- a/unit-tests/Extension/ScallTest.php +++ b/unit-tests/Extension/ScallTest.php @@ -52,7 +52,7 @@ public function testScall() /** * @test - * @issue 1622 + * @link https://github.com/phalcon/zephir/issues/1622 */ public function shouldReturnInterpolatedMethodFromZephir() { @@ -62,7 +62,7 @@ public function shouldReturnInterpolatedMethodFromZephir() /** * @test - * @issue 1622 + * @link https://github.com/phalcon/zephir/issues/1622 */ public function shouldEchoInterpolatedMethodFromZephir() { From 1830a84df2166d3799ec8b6ff38d4b9f2af69c21 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sat, 28 Apr 2018 11:36:38 +0300 Subject: [PATCH 34/40] Bump minimal PHPUnit during build process [skip appveyor] --- .travis.yml | 13 +++++++++---- unit-tests/ci/install_zephir_parser.sh | 18 ++++++++++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9fd4df8cf9..291f9e22a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ cache: ccache: true timeout: 604800 directories: - - vendor + - $HOME/.composer/cache - $HOME/.ccache - $HOME/.composer/cache - $HOME/.local/opt/re2c @@ -65,11 +65,16 @@ cache: before_install: - if [[ ! -z "${GH_TOKEN}" ]]; then composer config github-oauth.github.com ${GH_TOKEN}; echo "Configured Github token"; fi; - $CC --version - - $(phpenv which php) -v - - $(phpenv which php) -m + - export PHP_MAJOR="$(`phpenv which php` -r 'echo phpversion();' | cut -d '.' -f 1)" + - export PHP_MINOR="$(`phpenv which php` -r 'echo phpversion();' | cut -d '.' -f 2)" install: - - composer --prefer-source install + - composer install --prefer-source --no-suggest + - | + if [ "${PHP_MAJOR}.${PHP_MINOR}" != "5.5" ]; then + composer remove --dev phpunit/phpunit + composer require -q -n --dev --no-progress --prefer-dist --no-suggest "phpunit/phpunit:5.7.*" + fi - bash ./unit-tests/ci/install-re2c $RE2C_VERSION - bash ./unit-tests/ci/install_zephir_parser.sh - ./install diff --git a/unit-tests/ci/install_zephir_parser.sh b/unit-tests/ci/install_zephir_parser.sh index c5ba59e18c..c30d793911 100644 --- a/unit-tests/ci/install_zephir_parser.sh +++ b/unit-tests/ci/install_zephir_parser.sh @@ -1,16 +1,30 @@ #!/usr/bin/env bash +# Exit the script if any statement returns a non-true return value +set -e + # Ensure that this is being run inside a CI container if [ "${CI}" != "true" ]; then echo "This script is designed to run inside a CI container only. Exiting" exit 1 fi -PHP_MAJOR=`$(phpenv which php-config) --version | cut -d '.' -f 1,2` +required_vars=(ZEPHIR_PARSER_VERSION PHP_MAJOR PHP_MINOR) +missing_vars=() + +for i in "${required_vars[@]}"; do + test -n "${!i:+y}" || missing_vars+=("$i") +done + +if [ ${#missing_vars[@]} -ne 0 ]; then + echo "Variables aren't set: " >&2 + printf ' %q\n' "${missing_vars[@]}" >&2 + exit 1 +fi LOCAL_SRC_DIR=${HOME}/.cache/zephir-parser/src LOCAL_LIB_DIR=${HOME}/.local/lib -LOCAL_LIBRARY=${LOCAL_LIB_DIR}/zephir-parser-${ZEPHIR_PARSER_VERSION}-${PHP_MAJOR}.so +LOCAL_LIBRARY=${LOCAL_LIB_DIR}/zephir-parser-${ZEPHIR_PARSER_VERSION}-${PHP_MAJOR}.${PHP_MINOR}.so EXTENSION_DIR=`$(phpenv which php-config) --extension-dir` From 2b956f5484f7ceddfe9dd6968ec62bd6c52f0424 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 29 Apr 2018 11:12:17 +0300 Subject: [PATCH 35/40] Removed redundant Z_ADDREF (see c807fe7) --- kernels/ZendEngine3/object.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernels/ZendEngine3/object.c b/kernels/ZendEngine3/object.c index c2b5e0848b..16841ae0de 100644 --- a/kernels/ZendEngine3/object.c +++ b/kernels/ZendEngine3/object.c @@ -632,7 +632,6 @@ int zephir_update_property_array(zval *object, const char *property, zend_uint p ZVAL_DUP(&new_zv, &tmp); ZVAL_COPY_VALUE(&tmp, &new_zv); Z_TRY_DELREF(new_zv); - Z_ADDREF(tmp); separated = 1; } From ab12c074f127c4c7962fb7f1606167fa0924f0b9 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 29 Apr 2018 11:59:45 +0300 Subject: [PATCH 36/40] Amended build matrix [skip appveyor] --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index 291f9e22a5..9feb564c9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,6 +50,14 @@ matrix: - env: CC="clang" php: nightly compiler: clang + - env: CPPFLAGS=-DZEPHIR_RELEASE CC=gcc + php: 7.1 + - env: CPPFLAGS=-DZEPHIR_RELEASE CC=clang + php: 7.1 + - env: CPPFLAGS=-DZEPHIR_RELEASE CC=gcc + php: 7.2 + - env: CPPFLAGS=-DZEPHIR_RELEASE CC=clang + php: 7.2 cache: apt: true From 2605c3eb62008dd2fad0c5fec1a39c561d3304ca Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 29 Apr 2018 12:37:23 +0300 Subject: [PATCH 37/40] Cleaned .travis.yml [skip appveyor] --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9feb564c9f..e50a66b189 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,7 +64,6 @@ cache: ccache: true timeout: 604800 directories: - - $HOME/.composer/cache - $HOME/.ccache - $HOME/.composer/cache - $HOME/.local/opt/re2c From 13287da96baa831b37b29dca12ba0ffef3f2f417 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 29 Apr 2018 13:17:10 +0300 Subject: [PATCH 38/40] Bump parser version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e50a66b189..ee7c58897f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ env: - REPORT_EXIT_STATUS=1 - PATH="${HOME}/bin:${PATH}" - RE2C_VERSION="1.0.3" - - ZEPHIR_PARSER_VERSION="v1.1.1" + - ZEPHIR_PARSER_VERSION="v1.1.2" matrix: - CC="gcc" - CC="clang" From 815d5f2e9ee2ec87eb04e7b5fa53e3986d6a6d18 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 29 Apr 2018 22:18:55 +0300 Subject: [PATCH 39/40] UpdatedfFcall tests --- test/fcall.zep | 26 +++++++++---- unit-tests/Extension/FcallTest.php | 61 ++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/test/fcall.zep b/test/fcall.zep index d29dadbe18..772e875cb8 100644 --- a/test/fcall.zep +++ b/test/fcall.zep @@ -20,6 +20,8 @@ function zephir_global_method_with_type_casting(<\stdClass> variable) namespace Test; +use Test\Oo\PropertyAccess; + /** * Test function declaration in namespace */ @@ -28,19 +30,29 @@ function zephir_namespaced_method_test(var str) return new Fcall()->testCall5(str, 5); } +function test_call_relative_object_hint( a) -> boolean +{ + return true; +} + function zephir_namespaced_method_with_type_casting(<\stdClass> variable) { return variable; } +function test_call_object_hint(<\Test\Oo\PropertyAccess> a) -> boolean +{ + return true; +} + class Fcall { - public function testCall1() + public function testCall1() -> int { return strpos("hello", "h"); } - public function testCall2() + public function testCall2() -> int { loop { return mt_rand(0, 100); @@ -111,24 +123,24 @@ class Fcall return x; } - public function testCall1FromVar() + public function testCall1FromVar() -> int { var funcName; let funcName = "strpos"; return {funcName}("hello", "l"); } - public function testStrtokFalse() + public function testStrtokFalse() -> bool { return strtok("/"); } - public function testStrtokVarBySlash(var value) + public function testStrtokVarBySlash(var value) -> string { return strtok(value, "/"); } - public function testFunctionGetArgs(var param1, var param2) + public function testFunctionGetArgs(var param1, var param2) -> array { return func_get_args(); } @@ -138,7 +150,7 @@ class Fcall return [func_get_arg(0), func_get_arg(1)]; } - public function testArrayFill() + public function testArrayFill() -> array { var v1, v2; let v1 = array_fill(0, 5, "?"); diff --git a/unit-tests/Extension/FcallTest.php b/unit-tests/Extension/FcallTest.php index 28b15633a5..9779b72c97 100644 --- a/unit-tests/Extension/FcallTest.php +++ b/unit-tests/Extension/FcallTest.php @@ -7,51 +7,72 @@ | | | This source file is subject the MIT license, that is bundled with this | | package in the file LICENSE, and is available through the world-wide-web | - | at the following url: http://zephir-lang.com/license.html | + | at the following url: https://zephir-lang.com/license.html | +--------------------------------------------------------------------------+ */ namespace Extension; -class FcallTest extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\TestCase; +use Test\Fcall; +use Test\Oo\PropertyAccess; + +class FcallTest extends TestCase { public function testCall() { - $t = new \Test\Fcall(); - $this->assertSame($t->testCall1(), 0); - $this->assertLessThan($t->testCall2(), -1); - $this->assertSame($t->testCall1FromVar(), 2); + $t = new Fcall(); + $this->assertSame(0, $t->testCall1()); + $this->assertGreaterThan(-1, $t->testCall2()); + $this->assertSame(2, $t->testCall1FromVar()); } public function testStrtok() { - $t = new \Test\Fcall(); + $t = new Fcall(); $this->assertFalse($t->testStrtokFalse()); - $this->assertSame($t->testStrtokVarBySlash('test'), 'test'); + $this->assertSame('test', $t->testStrtokVarBySlash('test')); } - public function testFunctionGetArgs() + /** + * @dataProvider getArgsDataProvider + * @param mixed $param1 + * @param mixed $param2 + */ + public function testFunctionGetArgs($param1, $param2) { - $t = new \Test\Fcall(); - $this->assertSame($t->testFunctionGetArgs(true, false), array(true, false)); - $this->assertSame($t->testFunctionGetArgs(1025, false), array(1025, false)); - $this->assertSame($t->testFunctionGetArgs(false, 1234), array(false, 1234)); - $this->assertSame($t->testFunctionGetArgs(array(1, 2, 3), false), array(array(1, 2, 3), false)); - - $this->assertSame($t->testFunctionGetArg(true, false), array(true, false)); - $this->assertSame($t->testFunctionGetArg(1025, false), array(1025, false)); - $this->assertSame($t->testFunctionGetArg(false, 1234), array(false, 1234)); + $t = new Fcall(); + $this->assertSame([$param1, $param2], $t->testFunctionGetArgs($param1, $param2)); + } + + public function getArgsDataProvider() + { + return [ + [true, false], + [1025, false], + [false, 1234], + [[1, 2, 3], false], + [true, false], + [1025, false], + [false, 1234], + ]; } public function testArrayFill() { - $t = new \Test\Fcall(); - $this->assertSame($t->testArrayFill(), array(array_fill(0, 5, '?'), array_fill(0, 6, '?'))); + $t = new Fcall(); + $this->assertSame( + [array_fill(0, 5, '?'), array_fill(0, 6, '?')], + $t->testArrayFill() + ); } public function testFunctionDeclaration() { $this->assertSame("aaaaa", \Test\zephir_namespaced_method_test("a")); + $this->assertTrue(\Test\test_call_relative_object_hint(new PropertyAccess())); + $this->assertTrue(\Test\test_call_object_hint(new PropertyAccess())); + $this->assertSame("ab", zephir_global_method_test("ab/c")); $this->assertInstanceOf(\stdClass::class, \Test\zephir_namespaced_method_with_type_casting(new \stdClass())); From a9589700c9ca4afca8605ccbd47b27a8595829bb Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 29 Apr 2018 22:30:54 +0300 Subject: [PATCH 40/40] Bump version [ci skip] --- Library/Compiler.php | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/Compiler.php b/Library/Compiler.php index cced1f3bfc..b8e38b7dcd 100644 --- a/Library/Compiler.php +++ b/Library/Compiler.php @@ -31,7 +31,7 @@ */ class Compiler { - const VERSION = '0.10.8'; + const VERSION = '0.10.9'; public $parserCompiled = false; diff --git a/appveyor.yml b/appveyor.yml index 746a5e6cea..401a61f1ca 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.10.8-{build} +version: 0.10.9-{build} environment: matrix: