Strict type compliance

Were this library to be fully annotated with scalar types and
return types where possible and were strict types to be enabled
for all files, the test suite would now pass.
This commit is contained in:
Nikita Popov 2015-03-23 11:43:22 +01:00
parent edbf162e4c
commit dce19b074b
8 changed files with 26 additions and 21 deletions

View File

@ -48,13 +48,15 @@ class Lexer
* @throws Error on lexing errors (unterminated comment or unexpected character) * @throws Error on lexing errors (unterminated comment or unexpected character)
*/ */
public function startLexing($code) { public function startLexing($code) {
$scream = ini_set('xdebug.scream', 0); $scream = ini_set('xdebug.scream', '0');
$this->resetErrors(); $this->resetErrors();
$this->tokens = @token_get_all($code); $this->tokens = @token_get_all($code);
$this->handleErrors(); $this->handleErrors();
ini_set('xdebug.scream', $scream); if (false !== $scream) {
ini_set('xdebug.scream', $scream);
}
$this->code = $code; // keep the code around for __halt_compiler() handling $this->code = $code; // keep the code around for __halt_compiler() handling
$this->pos = -1; $this->pos = -1;
@ -76,7 +78,7 @@ class Lexer
'~^Unterminated comment starting line ([0-9]+)$~', '~^Unterminated comment starting line ([0-9]+)$~',
$error['message'], $matches $error['message'], $matches
)) { )) {
throw new Error('Unterminated comment', $matches[1]); throw new Error('Unterminated comment', (int) $matches[1]);
} }
if (preg_match( if (preg_match(

View File

@ -22,7 +22,7 @@ class Namespace_ extends Node\Stmt
* Constructs a namespace node. * Constructs a namespace node.
* *
* @param null|Node\Name $name Name * @param null|Node\Name $name Name
* @param Node[] $stmts Statements * @param null|Node[] $stmts Statements
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct(Node\Name $name = null, $stmts = array(), array $attributes = array()) { public function __construct(Node\Name $name = null, $stmts = array(), array $attributes = array()) {

View File

@ -140,7 +140,7 @@ class NameResolver extends NodeVisitorAbstract
protected function resolveClassName(Name $name) { protected function resolveClassName(Name $name) {
// don't resolve special class names // don't resolve special class names
if (in_array(strtolower($name), array('self', 'parent', 'static'))) { if (in_array(strtolower($name->toString()), array('self', 'parent', 'static'))) {
if (!$name->isUnqualified()) { if (!$name->isUnqualified()) {
throw new Error( throw new Error(
sprintf("'\\%s' is an invalid class name", $name->toString()), sprintf("'\\%s' is an invalid class name", $name->toString()),

View File

@ -57,7 +57,7 @@ class XML implements Serializer
} elseif ($node instanceof Comment) { } elseif ($node instanceof Comment) {
$this->writer->startElement('comment'); $this->writer->startElement('comment');
$this->writer->writeAttribute('isDocComment', $node instanceof Comment\Doc ? 'true' : 'false'); $this->writer->writeAttribute('isDocComment', $node instanceof Comment\Doc ? 'true' : 'false');
$this->writer->writeAttribute('line', $node->getLine()); $this->writer->writeAttribute('line', (string) $node->getLine());
$this->writer->text($node->getText()); $this->writer->text($node->getText());
$this->writer->endElement(); $this->writer->endElement();
} elseif (is_array($node)) { } elseif (is_array($node)) {
@ -69,9 +69,10 @@ class XML implements Serializer
} elseif (is_string($node)) { } elseif (is_string($node)) {
$this->writer->writeElement('scalar:string', $node); $this->writer->writeElement('scalar:string', $node);
} elseif (is_int($node)) { } elseif (is_int($node)) {
$this->writer->writeElement('scalar:int', $node); $this->writer->writeElement('scalar:int', (string) $node);
} elseif (is_float($node)) { } elseif (is_float($node)) {
$this->writer->writeElement('scalar:float', $node); // TODO Higher precision conversion?
$this->writer->writeElement('scalar:float', (string) $node);
} elseif (true === $node) { } elseif (true === $node) {
$this->writer->writeElement('scalar:true'); $this->writer->writeElement('scalar:true');
} elseif (false === $node) { } elseif (false === $node) {
@ -82,4 +83,4 @@ class XML implements Serializer
throw new \InvalidArgumentException('Unexpected node type'); throw new \InvalidArgumentException('Unexpected node type');
} }
} }
} }

View File

@ -9,7 +9,7 @@ interface Unserializer
* *
* @param string $string Serialized string * @param string $string Serialized string
* *
* @return array Statements * @return mixed Node tree
*/ */
public function unserialize($string); public function unserialize($string);
} }

View File

@ -102,11 +102,7 @@ class XML implements Unserializer
case 'string': case 'string':
return $this->reader->readString(); return $this->reader->readString();
case 'int': case 'int':
$text = $this->reader->readString(); return $this->parseInt($this->reader->readString());
if (false === $int = filter_var($text, FILTER_VALIDATE_INT)) {
throw new DomainException(sprintf('"%s" is not a valid integer', $text));
}
return $int;
case 'float': case 'float':
$text = $this->reader->readString(); $text = $this->reader->readString();
if (false === $float = filter_var($text, FILTER_VALIDATE_FLOAT)) { if (false === $float = filter_var($text, FILTER_VALIDATE_FLOAT)) {
@ -125,6 +121,13 @@ class XML implements Unserializer
} }
} }
private function parseInt($text) {
if (false === $int = filter_var($text, FILTER_VALIDATE_INT)) {
throw new DomainException(sprintf('"%s" is not a valid integer', $text));
}
return $int;
}
protected function readComment() { protected function readComment() {
$className = $this->reader->getAttribute('isDocComment') === 'true' $className = $this->reader->getAttribute('isDocComment') === 'true'
? 'PhpParser\Comment\Doc' ? 'PhpParser\Comment\Doc'
@ -132,7 +135,7 @@ class XML implements Unserializer
; ;
return new $className( return new $className(
$this->reader->readString(), $this->reader->readString(),
$this->reader->getAttribute('line') $this->parseInt($this->reader->getAttribute('line'))
); );
} }

View File

@ -47,10 +47,10 @@ class InterfaceTest extends \PHPUnit_Framework_TestCase
public function testAddConst() { public function testAddConst() {
$const = new Stmt\ClassConst(array( $const = new Stmt\ClassConst(array(
new Node\Const_('SPEED_OF_LIGHT', new DNumber(299792458)) new Node\Const_('SPEED_OF_LIGHT', new DNumber(299792458.0))
)); ));
$contract = $this->builder->addStmt($const)->getNode(); $contract = $this->builder->addStmt($const)->getNode();
$this->assertSame(299792458, $contract->stmts[0]->consts[0]->value->value); $this->assertSame(299792458.0, $contract->stmts[0]->consts[0]->value->value);
} }
public function testOrder() { public function testOrder() {

View File

@ -11,8 +11,8 @@ abstract class CodeTestAbstract extends \PHPUnit_Framework_TestCase
$tests = array(); $tests = array();
foreach ($it as $file) { foreach ($it as $file) {
// read file $fileName = realpath($file->getPathname());
$fileContents = file_get_contents($file); $fileContents = file_get_contents($fileName);
// evaluate @@{expr}@@ expressions // evaluate @@{expr}@@ expressions
$fileContents = preg_replace_callback( $fileContents = preg_replace_callback(
@ -25,7 +25,6 @@ abstract class CodeTestAbstract extends \PHPUnit_Framework_TestCase
$parts = array_map('trim', explode('-----', $fileContents)); $parts = array_map('trim', explode('-----', $fileContents));
// first part is the name // first part is the name
$fileName = realpath($file->getPathname());
$name = array_shift($parts) . ' (' . $fileName . ')'; $name = array_shift($parts) . ' (' . $fileName . ')';
// multiple sections possible with always two forming a pair // multiple sections possible with always two forming a pair