Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FFI stubs improvement #9368

Merged
merged 3 commits into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 49 additions & 2 deletions stubs/extensions/ffi.phpstub
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ namespace {
}

/**
* Note: Official docs say this could return `null`, but it throws exceptions instead.
* @param \FFI\CType|string $type
*/
public static function new($type, bool $owned = true, bool $persistent = false): ?\FFI\CData
public static function new($type, bool $owned = true, bool $persistent = false): \FFI\CData
{
}

Expand Down Expand Up @@ -106,6 +107,25 @@ namespace {
public static function isNull(\FFI\CData $ptr): bool
{
}

public function __call(...$values)
{
}

/**
* @param mixed $value
* @return mixed $value
*/
public function __set(string $key, $value)
{
}

/**
* @return string|int|float|\FFI\CData|null
*/
public function __get(string $key)
{
}
}

}
Expand All @@ -115,9 +135,36 @@ namespace FFI {
/**
* @since 7.4.0
*/
final class CData
final class CData implements \Countable, \ArrayAccess, \Countable, \Traversable
{
/**
* @return bool
*/
public function offsetExists($offset)
{
}

/**
* @return mixed|null
*/
public function offsetGet($offset)
{
}

/**
* @param mixed|null $value
* @return void
*/
public function offsetSet($offset, $value)
{
}

/**
* @return void
*/
public function offsetUnset($offset)
{
}
}

/**
Expand Down
87 changes: 87 additions & 0 deletions tests/FFITest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

namespace Psalm\Tests;

use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait;

/**
* tests for the handling of code using the PHP FFI extension
*
* https://www.php.net/manual/en/book.ffi.php
*/
class FFITest extends TestCase
{
use ValidCodeAnalysisTestTrait;

public function providerValidCodeParse(): iterable
{
return [
// Examples are from https://www.php.net/manual/en/ffi.examples-basic.php
// Some of them needed tweaks, e.g. due to unsafe use of var_dump().
'Example #1 Calling a function from shared library' => [
'code' => '<?php
$ffi = FFI::cdef(
"int printf(const char *format, ...);", // this is a regular C declaration
"libc.so.6"
);
$ffi->printf("Hello %s!\n", "world");
',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '7.4',
],
'Example #3 Accessing existing C variables' => [
'code' => '<?php
$ffi = FFI::cdef(
"int errno;", // this is a regular C declaration
"libc.so.6"
);
echo $ffi->errno;
',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '7.4',
],
'Example #5 Working with C arrays' => [
'code' => '<?php
// create C data structure
$a = FFI::new("long[1024]");
// work with it like with a regular PHP array
$size = count($a);
for ($i = 0; $i < $size; $i++) {
$a[$i] = $i;
}
$sum = 0;
/** @psalm-suppress MixedAssignment */
foreach ($a as $n) {
/** @psalm-suppress MixedOperand */
$sum += $n;
}
',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '7.4',
],
'Example #6 Working with C enums' => [
'code' => '<?php
$a = FFI::cdef(
"typedef enum _zend_ffi_symbol_kind {
ZEND_FFI_SYM_TYPE,
ZEND_FFI_SYM_CONST = 2,
ZEND_FFI_SYM_VAR,
ZEND_FFI_SYM_FUNC
} zend_ffi_symbol_kind;"
);
echo $a->ZEND_FFI_SYM_TYPE;
echo $a->ZEND_FFI_SYM_CONST;
echo $a->ZEND_FFI_SYM_VAR;
',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '7.4',
],
];
}
}