Skip to content

Commit

Permalink
Merge pull request #308 from elliotchance/2.0.2/308-update-assertions
Browse files Browse the repository at this point in the history
Update assertions when running concise
  • Loading branch information
elliotchance committed Oct 21, 2015
2 parents 3ec6f51 + f87cdc9 commit d8267b1
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 129 deletions.
198 changes: 198 additions & 0 deletions bin/concise-init
@@ -0,0 +1,198 @@
#!/usr/bin/env php
<?php

require_once('vendor/autoload.php');

// Load the bootstrap from the XML configuration. This will contain any extra
// custom modules that also need to be compiled.
if (!file_exists('phpunit.xml')) {
echo "You need to have setup phpunit.xml with a bootstrap file.\n\n";
exit(1);
}

$xml = simplexml_load_file('phpunit.xml');
$bootstrapFile = (string)$xml['bootstrap'];
if (!$bootstrapFile) {
echo "Your phpunit.xml configuration must have a bootstrap file.\n\n";
exit(1);
}

require_once($bootstrapFile);

use Concise\Core\ModuleManager;
use Concise\Core\TestCase;

// Simulate starting a test case which will cause the default ModuleManager
// to load all the modules.
$testCase = new TestCase();
$testCase->setUpBeforeClass();

updateBuilders();

function getShortName($trait)
{
static $shortNames = [];
static $c = 0;
if (!array_key_exists($trait, $shortNames)) {
if ($c < 26) {
$shortNames[$trait] = chr(ord('A') + $c);
} else {
$shortNames[$trait] =
chr(ord('A') + ($c / 26)) .
chr(ord('a') + ($c % 26));
}

if ($shortNames[$trait] == 'Do' || $shortNames[$trait] == 'If') {
unset($shortNames[$trait]);
++$c;
return getShortName($trait);
}
}

++$c;
return $shortNames[$trait];
}

function updateBuilders()
{
$syntaxTree = array();
foreach (ModuleManager::getInstance()->getModules() as $module) {
foreach ($module->getSyntaxes() as $syntax) {
$parts = explode('?', $syntax->getRawSyntax());
$temp = &$syntaxTree;
foreach ($parts as $part) {
$part = trim($part);
$temp = &$temp[$part];
}
$temp = null;
}
}

$php = array();
$header = "/**";
foreach ($syntaxTree as $k => $v) {
foreach (array(
'assert' => false,
'verify' => true
) as $method => $verify) {
$header .= "\n * @method ";

$types = '';
if (null !== $v) {
foreach ($v as $words => $s) {
$types .=
'|' .
getShortName(str_replace(' ', '', ucwords($words)));
}
}
$header .= ltrim($types, '|');

$header .= " $method" . ucfirst($k) .
"(\$valueOrFailureMessage, \$value = null)";

if (null !== $v) {
$php = a($v, $php);
}
}
}

$out =
$header .
"\n */\nabstract class BaseAssertions extends PHPUnit_Framework_TestCase\n{" .
"\n}\n\n";
ksort($php);
foreach ($php as $trait => $methods) {
$out .= "/**$methods */\nclass " . getShortName($trait) . "\n{\n}\n\n";
}

// Assume concise has been deployed through composer and we do not want to
// modify the repository itself; so we load it into a temp folder somewhere
// on the system. This will be loaded manually when they run concise.
$assertionsFile = Concise\Core\getBaseAssertionsPath();

if (strpos(__DIR__, 'vendor/') === false) {
// Lets also remove the temp file since it has higher precedence than
// the file we are about to load. Make sure this happens before
// $assertionsFile gets reassined below.
if (file_exists($assertionsFile)) {
unlink($assertionsFile);
}

// This means the script has been run when it wasn't deployed through
// composer. Which means someone is has downloaded the library manually
// or we are working on the composer package itself (dev). In either
// case we update the BaseAssertions.php in this repository.
$assertionsFile = __DIR__ . '/../src/Concise/Core/BaseAssertions.php';
}

file_put_contents(
$assertionsFile,
"<?php\n\nnamespace Concise\\Core;\n\nuse PHPUnit_Framework_TestCase;\n\n" .
str_replace("\t", ' ', $out)
);
}

/**
* @return string
*/
function getTempBaseAssertionsPath()
{
return sys_get_temp_dir() . '/BaseAssertions.php';
}

/**
* @param $v
* @param $php
* @return array
*/
function a($v, $php)
{
foreach ($v as $words => $s) {
$trait2 = str_replace(' ', '', ucwords($words));
$php[$trait2] = "\n * $trait2";
if (is_array($s)) {
$php[$trait2] .= "\n * @method null";
foreach ($s as $words2 => $s2) {
if ($words2) {
$php[$trait2] .=
'|' .
getShortName(str_replace(' ', '', ucwords($words2)));
}
}

unset($s['']);
if (count($s) > 0) {
$php = a($s, $php);
}
} else {
$php[$trait2] = "\n * @property null";
}
$php[$trait2] .= " ";
$php[$trait2] .= lcfirst($trait2);

if (is_array($s)) {
$php[$trait2] .= "(\$value)";
}
$php[$trait2] .= "\n";
}
return $php;
}

function renderSyntax($syntax)
{
return preg_replace_callback(
"/\\?:?([a-zA-Z_,]+)?/",
function ($m) {
if ($m[0] == '?') {
return "`mixed`_";
}
$types = explode(",", $m[1]);
$r = array();
foreach ($types as $type) {
$r[] = "`$type`_";
}
return implode("\\|\\ ", $r);
},
$syntax
);
}
31 changes: 30 additions & 1 deletion doc/modules.rst
Expand Up @@ -61,7 +61,6 @@ Some things to note:
appropriate test cases is fine too.



Testing Modules
---------------

Expand Down Expand Up @@ -90,3 +89,33 @@ Use the ``Concise\Module\AbstractModuleTestCase`` when testing modules:
$this->assert(123.0)->isAnInteger;
}
}
IDE and Code Completion
-----------------------

Once modules are loaded in (as described in *Loading a Module*) all
functionailty will work as expected. However, to get code completion in your
favourite IDE you will need to refresh the BaseAssertions that the IDE has used
to pick up the known modules.

Bundled with concise is a command called ``concise-init`` that will do just
that. It is safe to run this as frequently as you need.

**Note:** Modules must be loaded in your `bootstrap file`_ defined in the XML
configuration.

.. _bootstrap file: https://phpunit.de/manual/current/en/appendixes.configuration.html

By default the original ``BaseAssertions.php`` is modified. However, there are
some cases where you want this file to be located somewhere else. To allow this
you can set the environment variable ``CONCISE_BASEASSERTIONS`` to another file.

.. code-block:: bash
export CONCISE_BASEASSERTIONS=/tmp/BaseAssertions.php
**Note:** You will need to put this file somewhere your IDE will index but
should not be committed to your application repository. A temporary build
directory containing other generated content that is ignored by your version
control is common.
113 changes: 1 addition & 112 deletions scripts/UpdateDocs.php
@@ -1,6 +1,6 @@
<?php

require_once __DIR__ . '/../vendor/autoload.php';
require_once('vendor/autoload.php');

use Concise\Core\ModuleManager;
use Concise\Core\Syntax;
Expand All @@ -13,117 +13,6 @@
$testCase->setUpBeforeClass();

updateReadme();
updateBuilders();

function getShortName($trait)
{
static $shortNames = [];
static $c = 0;
if (!array_key_exists($trait, $shortNames)) {
if ($c < 26) {
$shortNames[$trait] = chr(ord('A') + $c);
} else {
$shortNames[$trait] = chr(ord('A') + ($c / 26)) . chr(ord('a') + ($c % 26));
}

if ($shortNames[$trait] == 'Do' || $shortNames[$trait] == 'If') {
unset($shortNames[$trait]);
++$c;
return getShortName($trait);
}
}

++$c;
return $shortNames[$trait];
}

function updateBuilders()
{
$syntaxTree = array();
foreach (ModuleManager::getInstance()->getModules() as $module) {
foreach ($module->getSyntaxes() as $syntax) {
$parts = explode('?', $syntax->getRawSyntax());
$temp = &$syntaxTree;
foreach ($parts as $part) {
$part = trim($part);
$temp = &$temp[$part];
}
$temp = null;
}
}

$php = array();
$header = "/**";
foreach ($syntaxTree as $k => $v) {
foreach (array('assert' => false, 'verify' => true) as $method => $verify) {
$header .= "\n * @method AssertionBuilder";
if (null !== $v) {
foreach ($v as $words => $s) {
$header .=
'|' .
getShortName(str_replace(' ', '', ucwords($words)));
}
}
$header .= " $method" . ucfirst($k) .
"(\$valueOrFailureMessage, \$value = null)";

if (null !== $v) {
$php = a($v, $php);
}
}
}

$out = $header .
"\n */\nabstract class BaseAssertions extends PHPUnit_Framework_TestCase\n{" .
"\n}\n\n";
ksort($php);
foreach ($php as $trait => $methods) {
$out .= "/**$methods */\nclass " . getShortName($trait) . "\n{\n}\n\n";
}

file_put_contents(
__DIR__ . '/../src/Concise/Core/BaseAssertions.php',
"<?php\n\nnamespace Concise\\Core;\n\nuse PHPUnit_Framework_TestCase;\n\n" . str_replace("\t", ' ', $out)
);
}

/**
* @param $v
* @param $php
* @return array
*/
function a($v, $php)
{
foreach ($v as $words => $s) {
$trait2 = str_replace(' ', '', ucwords($words));
$php[$trait2] = "\n * $trait2";
if (is_array($s)) {
$php[$trait2] .= "\n * @method null";
foreach ($s as $words2 => $s2) {
if ($words2) {
$php[$trait2] .=
'|' .
getShortName(str_replace(' ', '', ucwords($words2)));
}
}

unset($s['']);
if (count($s) > 0) {
$php = a($s, $php);
}
} else {
$php[$trait2] = "\n * @property null";
}
$php[$trait2] .= " ";
$php[$trait2] .= lcfirst($trait2);

if (is_array($s)) {
$php[$trait2] .= "(\$value)";
}
$php[$trait2] .= "\n";
}
return $php;
}

function renderSyntax($syntax)
{
Expand Down

0 comments on commit d8267b1

Please sign in to comment.