diff options
author | Olly Betts <olly@survex.com> | 2021-12-23 18:34:11 +1300 |
---|---|---|
committer | Olly Betts <olly@survex.com> | 2021-12-23 18:34:11 +1300 |
commit | 152a24a841e9dfba52cae105cddc09ab40d3e7ac (patch) | |
tree | 007daaa9181a3513fc286962f0aeb50c1b0dc1a5 | |
parent | b18bd0815f0689d15680dcb8b86afd100676567c (diff) | |
download | swig-152a24a841e9dfba52cae105cddc09ab40d3e7ac.tar.gz |
Allow control of PHP type declaration generation
This can be controlled with %feature("php:type"), which being a SWIG
feature can be specified globally, per class, per method, etc.
If unset or set to "0" then no type declarations are generated.
If set to "1" then type declarations are generated for both
parameters and return types.
Setting it to "compat" is the same as "1" except no return type
declarations are generated for virtual methods for which directors
are enabled. This provides better compatibility for PHP subclasses
of wrapped virtual methods in existing SWIG-generated bindings
-rw-r--r-- | Lib/php/php.swg | 5 | ||||
-rw-r--r-- | Source/Modules/php.cxx | 43 |
2 files changed, 35 insertions, 13 deletions
diff --git a/Lib/php/php.swg b/Lib/php/php.swg index aca8f6825..1120f226e 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -4,6 +4,11 @@ * PHP configuration file * ----------------------------------------------------------------------------- */ +// Default to generating PHP type declarations (for PHP >= 8) except for +// cases which are liable to cause compatibility issues with existing +// bindings. +%feature("php:type", "compat"); + %runtime "swigrun.swg" // Common C API type-checking code %runtime "swigerrors.swg" // SWIG errors %runtime "phprun.swg" // PHP runtime functions diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index d99db2fb8..dc9cc4dd8 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -671,24 +671,38 @@ public: // We generate the arginfo we want (taking care to normalise, e.g. the // lists of types are unique and in sorted order), then use the // arginfo_used Hash to see if we've already generated it. - String *arginfo_code = NewStringEmpty(); // Don't add a return type declaration for a constructor (because there - // is no return type as far as PHP is concerned) or a directed method - // (because if we do then user code has to add the same type declaration - // which would break compatibility with bindings generated by older - // SWIG versions). - // - // directorNode being present seems to indicate if this method or one it - // inherits from is directed, which is what we care about here. Using - // (!is_member_director(n)) would get it wrong for testcase director_frob. + // is no return type as far as PHP is concerned). String *out_phptype = NULL; String *out_phpclasses = NewStringEmpty(); - if (!Equal(fname, "__construct") && !Getattr(n, "directorNode")) { - out_phptype = phptypes.get_phptype(0, out_phpclasses); + if (!Equal(fname, "__construct")) { + String *php_type_flag = GetFlagAttr(n, "feature:php:type"); + if (Equal(php_type_flag, "1") || + (php_type_flag && !Getattr(n, "directorNode"))) { + // We provide a simple way to generate PHP return type declarations + // except for directed methods. The point of directors is to allow + // subclassing in the target language, and if the wrapped method has + // a return type declaration then an overriding method in user code + // needs to have a compatible declaration. + // + // The upshot of this is that enabling return type declarations for + // existing bindings would break compatibility with user code written + // for an older version. For parameters however the situation is + // different because if the parent class declares types for parameters + // a subclass overriding the function will be compatible whether it + // declares them or not. + // + // directorNode being present seems to indicate if this method or one + // it inherits from is directed, which is what we care about here. + // Using (!is_member_director(n)) would get it wrong for testcase + // director_frob. + out_phptype = phptypes.get_phptype(0, out_phpclasses); + } } - // ### will be replaced with the id once that is known. + // ### in arginfo_code will be replaced with the id once that is known. + String *arginfo_code = NewStringEmpty(); if (out_phptype) { if (Len(out_phpclasses)) { Replace(out_phpclasses, "\\", "\\\\", DOH_REPLACE_ANY); @@ -712,7 +726,10 @@ public: ++param_count; String *phpclasses = NewStringEmpty(); - String *phptype = phptypes.get_phptype(param_count, phpclasses); + String *phptype = NULL; + if (GetFlag(n, "feature:php:type")) { + phptypes.get_phptype(param_count, phpclasses); + } int byref = GetFlag(p, "tmap:in:byref"); #if 0 // FIXME: do this still |