feat(compiler): 添加PHP语法错误处理和类常量重复定义检查

- 在编译器中引入SyntaxError异常类用于处理PHP语法错误
- 修改预处理器捕获PHP解析错误并转换为SyntaxError异常
- 实现类常量重复定义的检测逻辑并抛出致命错误
- 添加多个测试用例验证类常量相关错误场景
- 更新编译器跳过包含语法错误的文件处理流程
pull/1/head
韩天峰 7 months ago
parent d90bf8a5fd
commit a6826d5fd0
  1. 3
      bin/compiler.php
  2. 7
      src/Php/Preprocessor.php
  3. 8
      src/Php/SyntaxError.php
  4. 6
      src/Php/Translator.php
  5. 18
      tests/core/classes/constants_error_001.phpt
  6. 13
      tests/core/classes/constants_error_002.phpt
  7. 16
      tests/core/classes/constants_error_005.phpt

@ -3,6 +3,7 @@
require __DIR__ . '/bootstrap.php';
use PhpAot\Php\FileScanner;
use PhpAot\Php\SyntaxError;
use PhpAot\Php\Translator;
use PhpAot\Php\Unsupported;
@ -41,6 +42,8 @@ foreach ($list as $k => $file) {
echo " unsupported syntax: " . $e->getMessage() . "\n";
echo " skip: " . $file . "\n";
unset($list[$k]);
} catch (SyntaxError $e) {
unset($list[$k]);
}
}
}

@ -85,7 +85,12 @@ class Preprocessor extends CompilerBase
$phpCode = $this->loadFile($file);
$this->climate->info('prepare: ' . $this->file);
$ast = $this->parser->parse($phpCode);
try {
$ast = $this->parser->parse($phpCode);
} catch (\PhpParser\Error $e) {
$this->climate->red("Fatal error: {$e->getMessage()} in {$this->file}");
throw new SyntaxError($e->getMessage(), $e->getCode());
}
$traverser = new NodeTraverser();
$traverser->addVisitor(new Visitor());

@ -0,0 +1,8 @@
<?php
namespace PhpAot\Php;
class SyntaxError extends \RuntimeException
{
}

@ -769,7 +769,11 @@ class Translator extends Preprocessor
$flags = $v->flags;
$type = $v->type ? $this->getTypeFromZendType($this->parseIdentifier($v->type)) : self::TYPE_VAR;
foreach ($v->consts as $const) {
$constInfo = new ConstantDef($this->parseIdentifier($const->name), $flags, $type, $this->parseIdentifier($const->value));
$constName = $this->parseIdentifier($const->name);
if (isset($this->classDef->constants[$constName])) {
$this->fatalError($const, 'Cannot redefine class constant ' . $this->class . '::' . $constName);
}
$constInfo = new ConstantDef($constName, $flags, $type, $this->parseIdentifier($const->value));
$this->classDef->constants[$constInfo->name] = $constInfo;
}
}

@ -0,0 +1,18 @@
--TEST--
Error case: duplicate class constant definition
--SKIPIF--
<?php die('skip, failed at compile time'); ?>
--FILE--
<?php
class myclass
{
const myConst = "hello";
const myConst = "hello again";
}
function main() {
}
?>
--EXPECTF--
Fatal error: Cannot redefine class constant myclass::myConst in %s on line 5

@ -0,0 +1,13 @@
--TEST--
Error case: class constant as an array
--FILE--
<?php
class myclass
{
const myConst = array();
}
function main() {
}
?>
--EXPECT--

@ -0,0 +1,16 @@
--TEST--
Error case: class constant as an encapsed containing a variable
--SKIPIF--
<?php die('skip, failed at compile time'); ?>
--FILE--
<?php
class myclass
{
const myConst = "$myVar";
}
function main() {
}
?>
--EXPECTF--
Fatal error: Constant expression contains invalid operations in %s on line %d
Loading…
Cancel
Save