summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlly Betts <olly@survex.com>2021-12-23 18:34:11 +1300
committerOlly Betts <olly@survex.com>2021-12-23 18:34:11 +1300
commit152a24a841e9dfba52cae105cddc09ab40d3e7ac (patch)
tree007daaa9181a3513fc286962f0aeb50c1b0dc1a5
parentb18bd0815f0689d15680dcb8b86afd100676567c (diff)
downloadswig-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.swg5
-rw-r--r--Source/Modules/php.cxx43
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