Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Zend/tests/scalar_methods/args.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
Scalar methods: extra arguments are forwarded after the receiver
--FILE--
<?php
// "xxhixx"->trim("x") desugars to Str::trim("xxhixx", "x").
var_dump("xxhixx"->trim("x"));
// Argument plus chaining.
var_dump("--Hi--"->trim("-")->upper());
?>
--EXPECT--
string(2) "hi"
string(2) "HI"
13 changes: 13 additions & 0 deletions Zend/tests/scalar_methods/cast_receiver.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--TEST--
Scalar methods: a (string) cast is a valid scalar-method receiver
--FILE--
<?php
$n = 42;
var_dump(((string)$n)->upper());
// Chaining also works off a (string) cast receiver.
$s = " Mixed ";
var_dump(((string)$s)->trim()->lower());
?>
--EXPECT--
string(2) "42"
string(5) "mixed"
12 changes: 12 additions & 0 deletions Zend/tests/scalar_methods/chain.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
Scalar methods: chained dispatch on string-returning Str methods
--FILE--
<?php
// The demo: trim then upper, each level desugars to Str::<method>(...).
var_dump(" Hello World "->trim()->upper());
// Triple chain: trim -> upper -> lower.
var_dump(" abc "->trim()->upper()->lower());
?>
--EXPECT--
string(11) "HELLO WORLD"
string(3) "abc"
14 changes: 14 additions & 0 deletions Zend/tests/scalar_methods/direct_call.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
Scalar methods: the Str backing class can still be called directly
--FILE--
<?php
var_dump(Str::trim(" x "));
var_dump(Str::upper("abc"));
var_dump(Str::lower("ABC"));
var_dump(Str::length("hello"));
?>
--EXPECT--
string(1) "x"
string(3) "ABC"
string(3) "abc"
int(5)
20 changes: 20 additions & 0 deletions Zend/tests/scalar_methods/length_no_chain.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Scalar methods: length() returns int and is not treated as a chainable string
--FILE--
<?php
// length() desugars to Str::length() and returns an int.
var_dump("hello"->length());

// Because length() returns int (not string), it is NOT a chainable string
// receiver: the OUTER call is left as a normal method call on an int, which
// fails at runtime with "member function on int" -- proving the outer call was
// not desugared to a Str:: dispatch.
"hi"->length()->upper();
?>
--EXPECTF--
int(5)

Fatal error: Uncaught Error: Call to a member function upper() on int in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
32 changes: 32 additions & 0 deletions Zend/tests/scalar_methods/not_desugared.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
Scalar methods: only static-string receivers desugar; vars/objects/nullsafe unaffected
--FILE--
<?php
// An untyped variable holding a string is NOT a compile-time static string,
// so its method call is left untouched and fails as before.
try {
$s = "hi";
$s->trim();
} catch (\Error $e) {
echo $e->getMessage(), "\n";
}

// A genuine object's method call works normally.
class C {
public function trim() { return "object-trim"; }
}
$o = new C();
var_dump($o->trim());

// Nullsafe on a string literal is deliberately excluded from desugaring and
// behaves exactly as before.
try {
var_dump("x"?->trim());
} catch (\Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Call to a member function trim() on string
string(11) "object-trim"
Call to a member function trim() on string
12 changes: 12 additions & 0 deletions Zend/tests/scalar_methods/single.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
Scalar methods: single method calls on a string-literal receiver
--FILE--
<?php
var_dump(" hi "->trim());
var_dump("AB"->lower());
var_dump("hello"->length());
?>
--EXPECT--
string(2) "hi"
string(2) "ab"
int(5)
11 changes: 11 additions & 0 deletions Zend/tests/scalar_methods/undefined_method.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
Scalar methods: unknown method on a string literal errors as undefined Str method
--FILE--
<?php
"x"->nope();
?>
--EXPECTF--
Fatal error: Uncaught Error: Call to undefined method Str::nope() in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
14 changes: 11 additions & 3 deletions Zend/tests/varSyntax/method_call_on_string_literal.phpt
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
--TEST--
Method call on string literal
Method call on string literal dispatches to the Str backing class (scalar methods)
--FILE--
<?php
"string"->length();
var_dump(" string "->trim());
var_dump("string"->length());
var_dump("ABC"->lower());
// An unknown method errors as an undefined method on Str, not "member function on string".
"string"->noSuchMethod();
?>
--EXPECTF--
Fatal error: Uncaught Error: Call to a member function length() on string in %s:%d
string(6) "string"
int(6)
string(3) "abc"

Fatal error: Uncaught Error: Call to undefined method Str::noSuchMethod() in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
1 change: 1 addition & 0 deletions Zend/zend_ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ enum _zend_ast_kind {
ZEND_AST_PROP_GROUP,
ZEND_AST_CONST_ELEM,
ZEND_AST_CLASS_CONST_GROUP,
ZEND_AST_TYPED_VAR_DECL,

/* 4 child nodes */
ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT,
Expand Down
Loading
Loading