Skip to content
This repository has been archived by the owner on Dec 6, 2022. It is now read-only.

Commit

Permalink
Implement Analysis\TolerantExpressionAnalyser and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TimeToogo committed Apr 7, 2015
1 parent c66ed83 commit fcf5b32
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ dev-master
==========
- Refactor `Analysis\PhpTypeSystem::getTypeFromValue` method logic into new static method `Analysis\TypeId::fromValue`
- Fix bug when attempting to parse function with a magic scope parameter type hint (eg `function (self $param) { ... }`.
- Implement `Analysis\TolerantExpressionAnalyser` which will convert analysis exceptions into the *mixed* type.

3.1.0 (29/3/15)
===============
Expand Down
11 changes: 11 additions & 0 deletions Source/Analysis/ExpressionAnalyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,26 @@ public function visitCast(O\CastExpression $expression)

public function visitConstant(O\ConstantExpression $expression)
{
$this->verifyConstantDefined($expression->getName());

$this->analysis[$expression] = $this->typeSystem->getTypeFromValue($expression->evaluate($this->analysisContext->getEvaluationContext()));
}

public function visitClassConstant(O\ClassConstantExpression $expression)
{
$this->validateStaticClassName($expression->getClass(), 'class constant');
$this->verifyConstantDefined($expression->getClass()->getValue() . '::' . $expression->getName());

$this->analysis[$expression] = $this->typeSystem->getTypeFromValue($expression->evaluate($this->analysisContext->getEvaluationContext()));
}

private function verifyConstantDefined($constantName)
{
if (!defined($constantName)) {
throw new TypeException('Cannot get type from constant %s: constant is not defined', $constantName);
}
}

public function visitEmpty(O\EmptyExpression $expression)
{
$this->walk($expression->getValue());
Expand Down
32 changes: 32 additions & 0 deletions Source/Analysis/TolerantExpressionAnalyser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Pinq\Analysis;

use Pinq\Expressions as O;

/**
* Implementation of the expression type analyser that will
* convert exceptions from not being able to be statically analysed
* into the mixed type.
*
* @author Elliot Levin <elliotlevin@hotmail.com>
*/
class TolerantExpressionAnalyser extends ExpressionAnalyser
{
protected function doWalk(O\Expression $expression)
{
$caught = false;
try {
return parent::doWalk($expression);
} catch (TypeException $exception) {
$caught = true;
} catch (\ReflectionException $exception) {
$caught = true;
}

if($caught) {
$this->analysis[$expression] = $this->typeSystem->getNativeType(INativeType::TYPE_MIXED);
return $expression;
}
}
}
10 changes: 7 additions & 3 deletions Tests/Integration/Analysis/ExpressionAnalysisTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,16 @@ protected function assertReturnsObjectType(callable $expression, $objectType, ar

protected function assertAnalysisFails(callable $expression, array $variableTypeMap = [], $message = '')
{
$failed = false;
try {
$this->getAnalysis($expression, $variableTypeMap);
$this->fail(
'Expecting analysis to fail with exception of type \\Pinq\\Analysis\\TypeException: no exception was thrown' . $message);
} catch (\Exception $exception) {
$failed = true;
} catch (\Exception $exception) {}

if($failed) {
$this->fail(
'Expecting analysis to fail with exception of type \\Pinq\\Analysis\\TypeException: no exception was thrown' . $message
);
}
}

Expand Down
49 changes: 49 additions & 0 deletions Tests/Integration/Analysis/TolerantExpressionAnalysisTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Pinq\Tests\Integration\Analysis;

use Pinq\Analysis\INativeType;
use Pinq\Analysis\TolerantExpressionAnalyser;
use Pinq\Expressions as O;

/**
* @author Elliot Levin <elliotlevin@hotmail.com>
*/
class WeakExpressionAnalysisTest extends ExpressionAnalysisTestCase
{
protected function setUpExpressionAnalyser()
{
return new TolerantExpressionAnalyser($this->typeSystem);
}

public function testThatUnknownVariableReturnsMixed()
{
$this->assertReturnsNativeType(function () { $var; }, INativeType::TYPE_MIXED);
}

public function testThatDynamicExpressionsReturnsMixed()
{
$this->assertReturnsNativeType(function () { $class::$field; }, INativeType::TYPE_MIXED);
$this->assertReturnsNativeType(function () { $class::method(); }, INativeType::TYPE_MIXED);
$this->assertReturnsNativeType(function () { Foo::$method(); }, INativeType::TYPE_MIXED);
$this->assertReturnsNativeType(function () { Foo::$$field; }, INativeType::TYPE_MIXED);
$this->assertReturnsNativeType(function () { $this->$foo; }, INativeType::TYPE_MIXED);
$this->assertReturnsNativeType(function () { $this->field; }, INativeType::TYPE_MIXED);
$this->assertReturnsNativeType(function () { $this->field[434]->{__NON_CONSTANT}->abc()[self::NON_CONSTANT]; }, INativeType::TYPE_MIXED);
}

public function testThatAllUnknownExpressionsAreMixedInTheTypeAnalysis()
{
$analysis = $this->getAnalysis(function () {
$this->field[434]->abc();
});

/** @var O\VariableExpression $variable */
$variable = $analysis
->getExpression()
->getValue()
->getValue();

$this->assertSame(INativeType::TYPE_MIXED, $analysis->getReturnTypeOf($variable)->getIdentifier());
}
}

0 comments on commit fcf5b32

Please sign in to comment.