NEW Show file path on PHP parser exceptions

This commit is contained in:
Ingo Schommer 2018-09-27 17:28:56 +12:00
parent 2f67be61c1
commit 25759ffc5f
3 changed files with 58 additions and 2 deletions

View File

@ -8,6 +8,7 @@ use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\Parser;
use PhpParser\ParserFactory;
use PhpParser\ErrorHandler\ErrorHandler;
use Psr\SimpleCache\CacheInterface;
use SilverStripe\Core\Cache\CacheFactory;
use SilverStripe\Dev\TestOnly;
@ -490,11 +491,13 @@ class ClassManifest
$changed = true;
// Build from php file parser
$fileContents = ClassContentRemover::remove_class_content($pathname);
// Not injectable, error handling is an implementation detail.
$errorHandler = new ClassManifestErrorHandler($pathname);
try {
$stmts = $this->getParser()->parse($fileContents);
$stmts = $this->getParser()->parse($fileContents, $errorHandler);
} catch (Error $e) {
// if our mangled contents breaks, try again with the proper file contents
$stmts = $this->getParser()->parse(file_get_contents($pathname));
$stmts = $this->getParser()->parse(file_get_contents($pathname), $errorHandler);
}
$this->getTraverser()->traverse($stmts);

View File

@ -0,0 +1,33 @@
<?php
namespace SilverStripe\Core\Manifest;
use PhpParser\Error;
use PhpParser\ErrorHandler;
/**
* Error handler which throws, but retains the original path context.
* For parsing errors, this is essential information to identify the issue.
*/
class ClassManifestErrorHandler implements ErrorHandler
{
/**
* @var String
*/
protected $pathname;
/**
* @param String $pathname
*/
public function __construct($pathname)
{
$this->pathname = $pathname;
}
public function handleError(Error $error)
{
$newMessage = sprintf('%s in %s', $error->getRawMessage(), $this->pathname);
$error->setRawMessage($newMessage);
throw $error;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace SilverStripe\Core\Tests\Manifest;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Core\Manifest\ClassManifestErrorHandler;
use PhpParser\Error;
class ClassManifestErrorHandlerTest extends SapphireTest
{
/**
* @expectedException \PhpParser\Error
* @expectedExceptionMessage my error in /my/path
*/
public function testIncludesPathname()
{
$h = new ClassManifestErrorHandler('/my/path');
$e = new Error('my error');
$h->handleError($e);
}
}