Skip to content

Commit 3d93d42

Browse files
committed
Try to parameterrize DOMAttr
1 parent 7b00257 commit 3d93d42

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

stubs/dom.stub

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ class DOMNode
3131
{
3232
/**
3333
* @readonly
34-
* @var DOMNamedNodeMap<DOMAttr>|null
34+
* @var DOMNamedNodeMap<DOMAttr<string>>|null
3535
*/
3636
public $attributes;
37+
38+
/** @phpstan-assert-if-true !null $this->attributes */
39+
public function hasAttributes(): bool
3740
}
3841

3942
class DOMElement extends DOMNode
@@ -42,6 +45,13 @@ class DOMElement extends DOMNode
4245
/** @var DOMDocument */
4346
public $ownerDocument;
4447

48+
/**
49+
* @readonly
50+
* @inherited
51+
* @var DOMNamedNodeMap<DOMAttr<string>>|null
52+
*/
53+
public $attributes;
54+
4555
/**
4656
* @param string $name
4757
* @return DOMNodeList<DOMElement>
@@ -55,6 +65,23 @@ class DOMElement extends DOMNode
5565
*/
5666
public function getElementsByTagNameNS ($namespaceURI, $localName) {}
5767

68+
/**
69+
* @template T of string
70+
* @param T $qualifiedName
71+
* @return bool
72+
* @phpstan-assert-if-true (T is 'xml:id' ? DOMNameSpaceNode : DOMAttr<T>) $this->hasAttribute($qualifiedName)
73+
* @phpstan-assert-if-true DOMNameSpaceNode<DOMAttr<T>|DOMAttr<string>> $this->$attributes
74+
*/
75+
public function hasAttribute(string $qualifiedName): bool
76+
77+
public function hasAttributeNS(?string $namespace, string $localName): bool
78+
79+
/**
80+
* @template T of string
81+
* @param T $qualifiedName
82+
* @return (T is 'xml:id' ? DOMNameSpaceNode|false : DOMAttr|false)
83+
*/
84+
public function getAttributeNode(string $qualifiedName): DOMAttr<T>|DOMNameSpaceNode|false
5885
}
5986

6087
/**
@@ -86,12 +113,20 @@ class DOMXPath
86113

87114
}
88115

116+
/**
117+
* @template Name as string
118+
*/
89119
class DOMAttr extends DOMNode
90120
{
91-
92121
/** @var DOMDocument */
93122
public $ownerDocument;
94123

124+
/**
125+
* @var Name
126+
* @readonly
127+
*/
128+
public $name;
129+
95130
}
96131

97132
class DOMCharacterData extends DOMNode

tests/PHPStan/Rules/Properties/data/dom-legacy-ext-template-nodes.php

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,24 @@
33
use function PHPStan\Testing\assertType;
44

55
function basic_node(\DOMNode $node): void {
6-
assertType(DOMNamedNodeMap::class . '<' . DOMAttr::class . '>', $node->attributes);
6+
if ($node->hasAttributes()) {
7+
assertType(DOMNamedNodeMap::class . '<' . DOMAttr::class . '>', $node->attributes);
8+
} else {
9+
assertType('null', $node->attributes);
10+
}
711
};
812

9-
function element_node(\DOMElement $node): void
13+
function element_node(\DOMElement $element): void
1014
{
11-
assertType(DOMNamedNodeMap::class . '<' . DOMAttr::class . '>', $node->attributes);
12-
$attribute = $node->attributes->getNamedItem('class');
13-
if ($attribute === null) {
14-
return;
15+
if ($element->hasAttribute('class')) {
16+
assertType(DOMNamedNodeMap::class . '<' . DOMAttr::class . '>', $element->attributes);
17+
$attribute = $element->attributes->getNamedItem('class');
18+
if ($attribute === null) {
19+
return;
20+
}
21+
assertType(DOMAttr::class, $attribute);
22+
assertType('string', $attribute->value);
23+
} else {
24+
assertType('null', $element->attributes);
1525
}
16-
assertType(DOMAttr::class, $attribute);
17-
assertType('string', $attribute->value);
1826
}

0 commit comments

Comments
 (0)