feat(compiler): 添加参数类型检查和对象类型验证功能

- 在ArgInfo类中新增class属性用于存储类型信息
- 修改parseParameterType方法以传递ArgInfo对象并设置类名
- 添加对stdClass和ArrayObject类型的测试用例
- 实现参数类型验证逻辑,确保对象类型匹配
- 增强类型转换过程中对对象类型的检测和错误提示
- 优化数组维度赋值的处理逻辑
pull/1/head
韩天峰 5 months ago
parent 932dc070d8
commit 68155d0793
  1. 1
      src/Php/ArgInfo.php
  2. 22
      src/Php/CompilerBase.php
  3. 37
      tests/aot/type_hits/001.phpt
  4. 23
      tests/aot/type_hits/002.phpt

@ -16,6 +16,7 @@ class ArgInfo
public string $type;
public string $default = '';
public ?Expr $defaultValue = null;
public string $class = '';
public bool $byRef = false;
public bool $variadic = false;
public bool $nullable = false;

@ -1064,13 +1064,13 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($this->method and $name == 'this_') {
$this->fatalError($param, 'Cannot use `$this` as parameter of class method');
}
$type = $this->parseParameterType($param, $name);
$argInfo = new ArgInfo();
$type = $this->parseParameterType($param, $argInfo, $name);
if ($param->variadic) {
$list[] = self::TYPE_ARRAY . ' ' . $name;
} else {
$list[] = $type . ' ' . $name;
}
$argInfo = new ArgInfo();
$argInfo->name = $name;
$argInfo->type = $type;
$argInfo->byRef = $param->byRef;
@ -1447,6 +1447,9 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->fatalError($left, 'Cannot use [] for strings');
}
}
if ($this->isScalar($right) or $this->isVarExpr($right)) {
return $this->parseAssignArrayDim($left, $right);
}
}
return $var . ' = ' . $this->convertExprType($expr, $this->detectExprType($left), $this->detectExprType($right));
@ -1980,7 +1983,7 @@ class CompilerBase extends \PhpAot\Core\Translator
'}';
}
protected function parseParameterType(Node\Param $param, string $var): string
protected function parseParameterType(Node\Param $param, ArgInfo $argInfo, string $var): string
{
if ($param->byRef) {
return self::TYPE_REF;
@ -1998,7 +2001,9 @@ class CompilerBase extends \PhpAot\Core\Translator
} elseif (isset($this->zendTypeMap[$typeName])) {
return $this->getTypeFromZendType($typeName);
} else {
$this->addObject($var, $this->getNamespacedClassName($typeName));
$class = $this->getNamespacedClassName($typeName);
$this->addObject($var, $class);
$argInfo->class = $class;
return self::TYPE_OBJECT;
}
}
@ -3257,7 +3262,7 @@ class CompilerBase extends \PhpAot\Core\Translator
return $this->functionDef->returnType;
}
protected function getTypeConvertedArg($arg, ArgInfo $argInfo): string
protected function getTypeConvertedArg(Node\Arg $arg, ArgInfo $argInfo): string
{
$expr = $this->parseArg($arg);
$type = $this->detectExprType($arg->value);
@ -3267,6 +3272,13 @@ class CompilerBase extends \PhpAot\Core\Translator
}
if ($argInfo->type === self::TYPE_OBJECT) {
$object = $this->parseVariable($arg->value);
if ($this->isVarExpr($arg->value) and $this->isTypedObject($object)) {
$class = $this->getObjectType($object);
if ($argInfo->class and $class != $argInfo->class) {
$this->fatalError($arg, "Argument `{$argInfo->name}` must be an instance of `{$argInfo->class}`, `{$class}` given");
}
}
return $this->convertObjectExpr($expr);
}

@ -0,0 +1,37 @@
--TEST--
type hits
--FILE--
<?php
function foo(object $data) {
var_dump($data);
}
function main()
{
$obj = new stdClass();
$obj->name = "John";
$obj->age = 20;
foo($obj);
$arr = new ArrayObject();
$name = "John";
$arr["name"] = $name;
$arr["age"] = 20;
foo($arr);
}
?>
--EXPECT--
object(stdClass)#1 (2) {
["name"]=>
string(4) "John"
["age"]=>
int(20)
}
object(ArrayObject)#2 (1) {
["storage":"ArrayObject":private]=>
array(2) {
["name"]=>
string(4) "John"
["age"]=>
int(20)
}
}

@ -0,0 +1,23 @@
--TEST--
type hits
--FILE--
<?php
function foo(stdClass $data) {
var_dump($data);
}
function main()
{
$obj = new stdClass();
$obj->name = "John";
$obj->age = 20;
foo($obj);
}
?>
--EXPECT--
object(stdClass)#1 (2) {
["name"]=>
string(4) "John"
["age"]=>
int(20)
}
Loading…
Cancel
Save