Skip to content

Commit 37a3c9b

Browse files
committed
Declare tentative return types for ext/simplexml
Closes GH-7003
1 parent 312b729 commit 37a3c9b

File tree

8 files changed

+159
-73
lines changed

8 files changed

+159
-73
lines changed

ext/simplexml/simplexml.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,7 +2005,8 @@ PHP_METHOD(SimpleXMLElement, current)
20052005
}
20062006

20072007
if (Z_ISUNDEF(sxe->iter.data)) {
2008-
return; /* return NULL */
2008+
zend_throw_error(NULL, "Iterator not initialized or already consumed");
2009+
RETURN_THROWS();
20092010
}
20102011

20112012
data = &sxe->iter.data;
@@ -2025,16 +2026,18 @@ PHP_METHOD(SimpleXMLElement, key)
20252026
}
20262027

20272028
if (Z_ISUNDEF(sxe->iter.data)) {
2028-
RETURN_FALSE;
2029+
zend_throw_error(NULL, "Iterator not initialized or already consumed");
2030+
RETURN_THROWS();
20292031
}
20302032

20312033
intern = Z_SXEOBJ_P(&sxe->iter.data);
2032-
if (intern != NULL && intern->node != NULL) {
2033-
curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
2034-
RETURN_STRINGL((char*)curnode->name, xmlStrlen(curnode->name));
2034+
if (intern == NULL || intern->node == NULL) {
2035+
zend_throw_error(NULL, "Iterator not initialized or already consumed");
2036+
RETURN_THROWS();
20352037
}
20362038

2037-
RETURN_FALSE;
2039+
curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
2040+
RETURN_STRINGL((char*)curnode->name, xmlStrlen(curnode->name));
20382041
}
20392042
/* }}} */
20402043

ext/simplexml/simplexml.stub.php

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,69 +10,69 @@ function simplexml_import_dom(SimpleXMLElement|DOMNode $node, ?string $class_nam
1010

1111
class SimpleXMLElement implements Stringable, Countable, RecursiveIterator
1212
{
13-
/** @return array|null|false */
14-
public function xpath(string $expression) {}
13+
/** @tentative-return-type */
14+
public function xpath(string $expression): array|null|false {}
1515

16-
/** @return bool */
17-
public function registerXPathNamespace(string $prefix, string $namespace) {}
16+
/** @tentative-return-type */
17+
public function registerXPathNamespace(string $prefix, string $namespace): bool {}
1818

19-
/** @return string|bool */
20-
public function asXML(?string $filename = null) {}
19+
/** @tentative-return-type */
20+
public function asXML(?string $filename = null): string|bool {}
2121

2222
/**
23-
* @return string|bool
23+
* @tentative-return-type
2424
* @alias SimpleXMLElement::asXML
2525
*/
26-
public function saveXML(?string $filename = null) {}
26+
public function saveXML(?string $filename = null): string|bool {}
2727

28-
/** @return array */
29-
public function getNamespaces(bool $recursive = false) {}
28+
/** @tentative-return-type */
29+
public function getNamespaces(bool $recursive = false): array {}
3030

31-
/** @return array|false */
32-
public function getDocNamespaces(bool $recursive = false, bool $fromRoot = true) {}
31+
/** @tentative-return-type */
32+
public function getDocNamespaces(bool $recursive = false, bool $fromRoot = true): array|false {}
3333

34-
/** @return SimpleXMLElement|null */
35-
public function children(?string $namespaceOrPrefix = null, bool $isPrefix = false) {}
34+
/** @tentative-return-type */
35+
public function children(?string $namespaceOrPrefix = null, bool $isPrefix = false): ?SimpleXMLElement {}
3636

37-
/** @return SimpleXMLElement|null */
38-
public function attributes(?string $namespaceOrPrefix = null, bool $isPrefix = false) {}
37+
/** @tentative-return-type */
38+
public function attributes(?string $namespaceOrPrefix = null, bool $isPrefix = false): ?SimpleXMLElement {}
3939

4040
public function __construct(string $data, int $options = 0, bool $dataIsURL = false, string $namespaceOrPrefix = "", bool $isPrefix = false) {}
4141

42-
/** @return SimpleXMLElement|null */
43-
public function addChild(string $qualifiedName, ?string $value = null, ?string $namespace = null) {}
42+
/** @tentative-return-type */
43+
public function addChild(string $qualifiedName, ?string $value = null, ?string $namespace = null): ?SimpleXMLElement {}
4444

45-
/** @return void */
46-
public function addAttribute(string $qualifiedName, string $value, ?string $namespace = null) {}
45+
/** @tentative-return-type */
46+
public function addAttribute(string $qualifiedName, ?string $value = null, ?string $namespace = null): void {}
4747

48-
/** @return string */
49-
public function getName() {}
48+
/** @tentative-return-type */
49+
public function getName(): string {}
5050

5151
public function __toString(): string {}
5252

53-
/** @return int */
54-
public function count() {}
53+
/** @tentative-return-type */
54+
public function count(): int {}
5555

56-
/** @return void */
57-
public function rewind() {}
56+
/** @tentative-return-type */
57+
public function rewind(): void {}
5858

59-
/** @return bool */
60-
public function valid() {}
59+
/** @tentative-return-type */
60+
public function valid(): bool {}
6161

62-
/** @return SimpleXMLElement|null */
63-
public function current() {}
62+
/** @tentative-return-type */
63+
public function current(): SimpleXMLElement {}
6464

65-
/** @return string|false */
66-
public function key() {}
65+
/** @tentative-return-type */
66+
public function key(): string {}
6767

68-
/** @return void */
69-
public function next() {}
68+
/** @tentative-return-type */
69+
public function next(): void {}
7070

71-
/** @return bool */
72-
public function hasChildren() {}
71+
/** @tentative-return-type */
72+
public function hasChildren(): bool {}
7373

74-
/** @return SimpleXMLElement|null */
75-
public function getChildren() {}
74+
/** @tentative-return-type */
75+
public function getChildren(): ?SimpleXMLElement {}
7676
}
7777

7878
class SimpleXMLIterator extends SimpleXMLElement

ext/simplexml/simplexml_arginfo.h

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: a15b1397538882bf618a4963193a63be8d893842 */
2+
* Stub hash: 2adc13ce6717fe2255ea7d9a3df56eeb8838d61d */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_simplexml_load_file, 0, 1, SimpleXMLElement, MAY_BE_FALSE)
55
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
@@ -22,31 +22,31 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_simplexml_import_dom, 0, 1, Simpl
2222
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, class_name, IS_STRING, 1, "SimpleXMLElement::class")
2323
ZEND_END_ARG_INFO()
2424

25-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_xpath, 0, 0, 1)
25+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_SimpleXMLElement_xpath, 0, 1, MAY_BE_ARRAY|MAY_BE_NULL|MAY_BE_FALSE)
2626
ZEND_ARG_TYPE_INFO(0, expression, IS_STRING, 0)
2727
ZEND_END_ARG_INFO()
2828

29-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_registerXPathNamespace, 0, 0, 2)
29+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_registerXPathNamespace, 0, 2, _IS_BOOL, 0)
3030
ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 0)
3131
ZEND_ARG_TYPE_INFO(0, namespace, IS_STRING, 0)
3232
ZEND_END_ARG_INFO()
3333

34-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_asXML, 0, 0, 0)
34+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_SimpleXMLElement_asXML, 0, 0, MAY_BE_STRING|MAY_BE_BOOL)
3535
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, filename, IS_STRING, 1, "null")
3636
ZEND_END_ARG_INFO()
3737

3838
#define arginfo_class_SimpleXMLElement_saveXML arginfo_class_SimpleXMLElement_asXML
3939

40-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_getNamespaces, 0, 0, 0)
40+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_getNamespaces, 0, 0, IS_ARRAY, 0)
4141
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, recursive, _IS_BOOL, 0, "false")
4242
ZEND_END_ARG_INFO()
4343

44-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_getDocNamespaces, 0, 0, 0)
44+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_SimpleXMLElement_getDocNamespaces, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE)
4545
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, recursive, _IS_BOOL, 0, "false")
4646
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fromRoot, _IS_BOOL, 0, "true")
4747
ZEND_END_ARG_INFO()
4848

49-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_children, 0, 0, 0)
49+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_SimpleXMLElement_children, 0, 0, SimpleXMLElement, 1)
5050
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, namespaceOrPrefix, IS_STRING, 1, "null")
5151
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, isPrefix, _IS_BOOL, 0, "false")
5252
ZEND_END_ARG_INFO()
@@ -61,39 +61,44 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement___construct, 0, 0, 1)
6161
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, isPrefix, _IS_BOOL, 0, "false")
6262
ZEND_END_ARG_INFO()
6363

64-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_addChild, 0, 0, 1)
64+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_SimpleXMLElement_addChild, 0, 1, SimpleXMLElement, 1)
6565
ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0)
6666
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value, IS_STRING, 1, "null")
6767
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, namespace, IS_STRING, 1, "null")
6868
ZEND_END_ARG_INFO()
6969

70-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_addAttribute, 0, 0, 2)
70+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_addAttribute, 0, 1, IS_VOID, 0)
7171
ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0)
72-
ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0)
72+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value, IS_STRING, 1, "null")
7373
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, namespace, IS_STRING, 1, "null")
7474
ZEND_END_ARG_INFO()
7575

76-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimpleXMLElement_getName, 0, 0, 0)
76+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_getName, 0, 0, IS_STRING, 0)
7777
ZEND_END_ARG_INFO()
7878

7979
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement___toString, 0, 0, IS_STRING, 0)
8080
ZEND_END_ARG_INFO()
8181

82-
#define arginfo_class_SimpleXMLElement_count arginfo_class_SimpleXMLElement_getName
82+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_count, 0, 0, IS_LONG, 0)
83+
ZEND_END_ARG_INFO()
8384

84-
#define arginfo_class_SimpleXMLElement_rewind arginfo_class_SimpleXMLElement_getName
85+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_rewind, 0, 0, IS_VOID, 0)
86+
ZEND_END_ARG_INFO()
8587

86-
#define arginfo_class_SimpleXMLElement_valid arginfo_class_SimpleXMLElement_getName
88+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_valid, 0, 0, _IS_BOOL, 0)
89+
ZEND_END_ARG_INFO()
8790

88-
#define arginfo_class_SimpleXMLElement_current arginfo_class_SimpleXMLElement_getName
91+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_SimpleXMLElement_current, 0, 0, SimpleXMLElement, 0)
92+
ZEND_END_ARG_INFO()
8993

9094
#define arginfo_class_SimpleXMLElement_key arginfo_class_SimpleXMLElement_getName
9195

92-
#define arginfo_class_SimpleXMLElement_next arginfo_class_SimpleXMLElement_getName
96+
#define arginfo_class_SimpleXMLElement_next arginfo_class_SimpleXMLElement_rewind
9397

94-
#define arginfo_class_SimpleXMLElement_hasChildren arginfo_class_SimpleXMLElement_getName
98+
#define arginfo_class_SimpleXMLElement_hasChildren arginfo_class_SimpleXMLElement_valid
9599

96-
#define arginfo_class_SimpleXMLElement_getChildren arginfo_class_SimpleXMLElement_getName
100+
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_SimpleXMLElement_getChildren, 0, 0, SimpleXMLElement, 1)
101+
ZEND_END_ARG_INFO()
97102

98103

99104
ZEND_FUNCTION(simplexml_load_file);

ext/simplexml/tests/036.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ simplexml
55
--FILE--
66
<?php
77
class SXE extends SimpleXmlElement {
8-
public function count() {
8+
public function count(): int {
99
echo "Called Count!\n";
1010
return parent::count();
1111
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
SimpleXML: invoking current() after the iterator has already been consumed
3+
--EXTENSIONS--
4+
simplexml
5+
--FILE--
6+
<?php
7+
8+
$xml =<<<EOF
9+
<?xml version='1.0'?>
10+
<root>
11+
<elem/>
12+
</root>
13+
EOF;
14+
15+
$sxe = simplexml_load_string($xml);
16+
17+
try {
18+
$sxe->current();
19+
} catch (Error $exception) {
20+
echo $exception->getMessage() . "\n";
21+
}
22+
23+
for ($sxe->rewind(); $sxe->valid(); $sxe->next()) {
24+
var_dump($sxe->key(), $sxe->current());
25+
}
26+
27+
try {
28+
$sxe->current();
29+
} catch (Error $exception) {
30+
echo $exception->getMessage() . "\n";
31+
}
32+
33+
?>
34+
--EXPECT--
35+
Iterator not initialized or already consumed
36+
string(4) "elem"
37+
object(SimpleXMLElement)#3 (0) {
38+
}
39+
Iterator not initialized or already consumed

ext/simplexml/tests/key_error.phpt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
SimpleXML: invoking key() after the iterator has already been consumed
3+
--EXTENSIONS--
4+
simplexml
5+
--FILE--
6+
<?php
7+
8+
$xml =<<<EOF
9+
<?xml version='1.0'?>
10+
<root>
11+
<elem/>
12+
</root>
13+
EOF;
14+
15+
$sxe = simplexml_load_string($xml);
16+
17+
try {
18+
$sxe->key();
19+
} catch (Error $exception) {
20+
echo $exception->getMessage() . "\n";
21+
}
22+
23+
for ($sxe->rewind(); $sxe->valid(); $sxe->next()) {
24+
var_dump($sxe->key(), $sxe->current());
25+
}
26+
27+
try {
28+
$sxe->key();
29+
} catch (Error $exception) {
30+
echo $exception->getMessage() . "\n";
31+
}
32+
33+
?>
34+
--EXPECT--
35+
Iterator not initialized or already consumed
36+
string(4) "elem"
37+
object(SimpleXMLElement)#3 (0) {
38+
}
39+
Iterator not initialized or already consumed

ext/simplexml/tests/sxe_004.phpt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,37 +35,37 @@ EOF;
3535

3636
class SXETest extends SimpleXMLIterator
3737
{
38-
function rewind()
38+
function rewind(): void
3939
{
4040
echo __METHOD__ . "\n";
41-
return parent::rewind();
41+
parent::rewind();
4242
}
43-
function valid()
43+
function valid(): bool
4444
{
4545
echo __METHOD__ . "\n";
4646
return parent::valid();
4747
}
48-
function current()
48+
function current(): SimpleXMLElement
4949
{
5050
echo __METHOD__ . "\n";
5151
return parent::current();
5252
}
53-
function key()
53+
function key(): string
5454
{
5555
echo __METHOD__ . "\n";
5656
return parent::key();
5757
}
58-
function next()
58+
function next(): void
5959
{
6060
echo __METHOD__ . "\n";
61-
return parent::next();
61+
parent::next();
6262
}
63-
function hasChildren()
63+
function hasChildren(): bool
6464
{
6565
echo __METHOD__ . "\n";
6666
return parent::hasChildren();
6767
}
68-
function getChildren()
68+
function getChildren(): ?SimpleXMLIterator
6969
{
7070
echo __METHOD__ . "\n";
7171
return parent::getChildren();

ext/simplexml/tests/sxe_005.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ EOF;
1717

1818
class SXETest extends SimpleXMLIterator
1919
{
20-
function count()
20+
function count(): int
2121
{
2222
echo __METHOD__ . "\n";
2323
return parent::count();

0 commit comments

Comments
 (0)