@ -196,6 +196,7 @@ class CompilerBase implements PropertyAccessContext
public const string FUNC_MAP = 'func_map';
public const string PROP_MAP = 'property_map';
public const string NAMESPACE_SEPARATOR = '__';
public const string NAMESPACE_END_MARKER = 'NSE';
public const string PREFIX = 'php_';
protected const string MULTI_RETURN_NAMESPACE = 'typephp::detail';
@ -1018,7 +1019,14 @@ class CompilerBase implements PropertyAccessContext
protected function getFunctionName(FunctionLike $v): string
{
return $this->getNativeName($this->parseIdentifier($v->name), $this->namespace, $this->class);
if ($this->class !== '') {
return $this->getNativeClassMethodName(
$this->parseIdentifier($v->name),
$this->namespace,
$this->class,
);
}
return $this->getNativeFunctionName($this->parseIdentifier($v->name), $this->namespace);
}
protected function getFullClassName(): string
@ -1141,6 +1149,29 @@ class CompilerBase implements PropertyAccessContext
return implode(self::NAMESPACE_SEPARATOR, $names);
}
protected function getNativeFunctionName(string $function, string $namespace = ''): string
{
$names = [];
if ($namespace !== '') {
$names[] = $this->escapeNamespace($namespace);
$names[] = self::NAMESPACE_END_MARKER;
}
$names[] = $this->escapeName($function);
return implode(self::NAMESPACE_SEPARATOR, $names);
}
protected function getNativeClassMethodName(string $method, string $namespace, string $class): string
{
$names = [];
if ($namespace !== '') {
$names[] = $this->escapeNamespace($namespace);
}
$names[] = self::NAMESPACE_END_MARKER;
$names[] = $this->escapeClass($class);
$names[] = $this->escapeName($method);
return implode(self::NAMESPACE_SEPARATOR, $names);
}
protected function getClassId(string $className): int
{
if (isset($this->classMap[$className])) {
@ -2362,7 +2393,7 @@ class CompilerBase implements PropertyAccessContext
if ($checkArgs) {
$this->checkNativeCallArgs($expr, $methodDef->functionDef, $expr->args, $classDef->getNamespacedName() . '::' . $method);
}
return $this->getNativeName($method, $classDef->namespace, $classDef->name);
return $this->getNativeClassMethod Name($method, $classDef->namespace, $classDef->name);
}
protected function findNativeClassConst(NodeAbstract $expr, string $class, string $const): string|false
@ -2814,17 +2845,33 @@ class CompilerBase implements PropertyAccessContext
// 绝对命名空间的函数
if ($funcName[0] == '\\') {
$funcName = ltrim($funcName, '\\');
$possibleFunctionNames = [$this->escapeName($funcName)];
$separator = strrpos($funcName, '\\');
if ($separator === false) {
$possibleFunctionNames = [$this->getNativeFunctionName($funcName)];
} else {
$possibleFunctionNames = [$this->getNativeFunctionName(
substr($funcName, $separator + 1),
substr($funcName, 0, $separator),
)];
}
} else {
$possibleFunctionNames = [$this->escapeName($funcName)];
$possibleFunctionNames = [$this->getNativeFunction Name($funcName)];
if (isset($this->useAliases[$funcName])) {
$possibleFunctionNames[] = $this->escapeName($this->escapeNamespace($this->useAliases[$funcName]));
$alias = $this->useAliases[$funcName];
$separator = strrpos($alias, '\\');
$possibleFunctionNames[] = $separator === false
? $this->getNativeFunctionName($alias)
: $this->getNativeFunctionName(substr($alias, $separator + 1), substr($alias, 0, $separator));
}
if ($this->namespace) {
$possibleFunctionNames[] = $this->escapeNamespace($this->namespace) . self::NAMESPACE_SEPARATOR . $this->escapeName($funcName);
$possibleFunctionNames[] = $this->getNativeFunctionName($funcName, $this->namespac e);
}
if (isset($this->useFunctions[$funcName])) {
$possibleFunctionNames[] = $this->escapeNamespace($this->useFunctions[$funcName]);
$alias = $this->useFunctions[$funcName];
$separator = strrpos($alias, '\\');
$possibleFunctionNames[] = $separator === false
? $this->getNativeFunctionName($alias)
: $this->getNativeFunctionName(substr($alias, $separator + 1), substr($alias, 0, $separator));
}
// 复杂命名空间规则,组合命名空间
// 例子:use foo\bar; bar\fn();
@ -2834,7 +2881,12 @@ class CompilerBase implements PropertyAccessContext
if ($ns1[array_key_last($ns1)] === $ns2[array_key_first($ns2)]) {
$ns = array_merge($ns1, $ns2);
array_splice($ns, array_key_last($ns1) + 1);
$possibleFunctionNames[] = $this->escapeNamespace(implode('\\', $ns));
$fullName = implode('\\', $ns);
$separator = strrpos($fullName, '\\');
$possibleFunctionNames[] = $this->getNativeFunctionName(
substr($fullName, $separator + 1),
substr($fullName, 0, $separator),
);
break;
}
}