Skip to content

Commit 633f7c5

Browse files
committed
Fix #391: Allow making parameters nullable.
1 parent 5ea12c3 commit 633f7c5

File tree

8 files changed

+76
-13
lines changed

8 files changed

+76
-13
lines changed

exts/jphp-zend-ext/src/main/tests/resources/zend/classes/type_hinting_005b.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@
99
?>
1010
==DONE==
1111
--EXPECTF--
12-
Warning: Declaration of D::f($a) should be compatible with C::f(array $a) in %s on line 5 at pos %d
1312
No hint, should be array.
1413
==DONE==

jphp-core/src/org/develnext/jphp/core/syntax/generators/manually/SimpleExprGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,7 @@ else if (previous instanceof StaticAccessExprToken){
14431443
isFunc = true;
14441444
}
14451445

1446-
if (isFunc){
1446+
if (isFunc) {
14471447
CallExprToken call = processCall(previous, current, iterator);
14481448
if (call.getName() != null) {
14491449
current = call;

jphp-core/tests/org/develnext/jphp/core/compiler/jvm/ClassesTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ public void testBugs() {
146146
check("classes/bug123.php");
147147
check("classes/bug127.php");
148148
check("classes/bug130.php");
149+
check("classes/bug391.phpt", true);
149150
}
150151

151152
@Test
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Allow making parameters nullable
3+
--FILE--
4+
<?php
5+
interface a
6+
{
7+
public function test($a);
8+
}
9+
10+
class b implements a
11+
{
12+
public function test($a = null) {}
13+
}
14+
15+
var_dump(new b);
16+
?>
17+
--EXPECTF--
18+
object(b)#%d (0) {
19+
}

jphp-runtime/src/php/runtime/reflection/ClassEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ public SignatureResult addMethod(MethodEntity method, String realName) {
340340
//method.setModifier(Modifier.PUBLIC);
341341
}
342342

343-
if (!systemMethod.equalsBySignature(method, false)) {
343+
if (!method.isImplementableSignatureFor(systemMethod)) {
344344
addResult.add(InvalidMethod.error(InvalidMethod.Kind.INVALID_SIGNATURE, method));
345345
} else if (systemMethod.isStatic && !method.isStatic)
346346
addResult.add(InvalidMethod.warning(InvalidMethod.Kind.MUST_STATIC, method));

jphp-runtime/src/php/runtime/reflection/MethodEntity.java

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -440,17 +440,38 @@ public boolean isImplementableSignatureFor(MethodEntity parentMethod) {
440440
return false;
441441
}
442442

443-
if (getSignature().equals(parentMethod.getSignature())) {
444-
return true;
445-
} else {
446-
if (parentMethod.getReturnTypeChecker() == null && getReturnTypeChecker() != null) {
447-
return getSignature(true).equals(parentMethod.getSignature(true));
443+
for (int i = 0; i < p_count; i++) {
444+
ParameterEntity param = parameters[i];
445+
ParameterEntity parentParam = i > p_parent_count-1 ? null : parentMethod.parameters[i];
446+
447+
if (parentParam == null) {
448+
if (!param.hasDefaultValue()) {
449+
return false;
450+
} else {
451+
continue;
452+
}
448453
}
449454

450-
return false;
455+
if (!TypeChecker.identical(param.getTypeChecker(), parentParam.getTypeChecker())) {
456+
if (param.getTypeChecker() == null || TypeChecker.of(HintType.ANY).identical(param.getTypeChecker())) {
457+
continue; // skip any typehinting
458+
}
459+
460+
return false;
461+
}
451462
}
463+
464+
return true;
452465
}
453466

467+
468+
/**
469+
* Use isImplementableSignatureFor() method.
470+
* @param method
471+
* @param strong
472+
* @return
473+
*/
474+
@Deprecated
454475
public boolean equalsBySignature(MethodEntity method, boolean strong){
455476
if (strong)
456477
return getSignature().equals(method.getSignature());
@@ -462,6 +483,13 @@ public boolean equalsBySignature(MethodEntity method, boolean strong){
462483
}
463484
}
464485

486+
/**
487+
* Use isImplementableSignatureFor() method.
488+
* @param method
489+
* @param strong
490+
* @return
491+
*/
492+
@Deprecated
465493
public boolean equalsBySignature(MethodEntity method){
466494
return equalsBySignature(method, true);
467495
}
@@ -554,11 +582,15 @@ public void setTrait(ClassEntity trait) {
554582

555583
public int getRequiredParamCount() {
556584
int cnt = 0;
557-
if (parameters != null)
558-
for(ParameterEntity e : parameters) {
559-
if (e.getDefaultValue() != null)
560-
break;
585+
586+
if (parameters != null) {
587+
for (ParameterEntity e : parameters) {
588+
if (e.hasDefaultValue())
589+
break;
590+
cnt++;
591+
}
561592
}
593+
562594
return cnt;
563595
}
564596

jphp-runtime/src/php/runtime/reflection/ParameterEntity.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ public Memory getDefaultValue() {
5454
return defaultValue;
5555
}
5656

57+
public boolean hasDefaultValue() {
58+
return defaultValue != null || defaultValueConstName != null;
59+
}
60+
5761
public void setDefaultValue(Memory defaultValue) {
5862
this.defaultValue = defaultValue;
5963
}

jphp-runtime/src/php/runtime/reflection/support/TypeChecker.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ public boolean identical(TypeChecker typeChecker) {
2929
return this == typeChecker;
3030
}
3131

32+
public static boolean identical(TypeChecker tc1, TypeChecker tc2) {
33+
if (tc1 != null && tc2 != null) {
34+
return tc1.identical(tc2);
35+
} else {
36+
return tc1 == tc2;
37+
}
38+
}
39+
3240
public static TypeChecker of(HintType type) {
3341
return Simple.valueOf(type);
3442
}

0 commit comments

Comments
 (0)