Rémi Bernon : widl: Support WinRT parameterized delegate type.

Alexandre Julliard julliard at winehq.org
Thu Feb 18 16:06:07 CST 2021


Module: wine
Branch: master
Commit: fecfd245a15b60d44a17c1b7411a282b5e954858
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=fecfd245a15b60d44a17c1b7411a282b5e954858

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Thu Feb 18 10:39:00 2021 +0100

widl: Support WinRT parameterized delegate type.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Jacek Caban<jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 include/windows.foundation.idl |  6 ++++
 tools/widl/parser.y            |  6 ++++
 tools/widl/typetree.c          | 76 +++++++++++++++++++++++++++++++++++++-----
 tools/widl/typetree.h          |  2 ++
 4 files changed, 82 insertions(+), 8 deletions(-)

diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
index 5f7a49c38e4..bb0fafcab77 100644
--- a/include/windows.foundation.idl
+++ b/include/windows.foundation.idl
@@ -113,6 +113,12 @@ namespace Windows {
         }
 
 #ifdef __WIDL__
+        [
+            contract(Windows.Foundation.FoundationContract, 1.0),
+            uuid(9de1c535-6ae1-11e0-84e1-18a905bcc53f)
+        ]
+        delegate HRESULT EventHandler<T>([in] IInspectable *sender, [in] T args);
+
         namespace Collections
         {
             [
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 16d2e0023b7..57e7809fc1a 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1038,6 +1038,12 @@ delegatedef: m_attributes tDELEGATE type ident '(' m_args ')' semicolon_opt
 						{ $$ = type_delegate_declare($4->name, current_namespace);
 						  $$ = type_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $6)));
 						}
+	| m_attributes tDELEGATE type ident
+	  '<' { push_parameters_namespace($4->name); } type_parameters '>'
+	  '(' m_args ')' { pop_parameters_namespace($4->name); } semicolon_opt
+						{ $$ = type_parameterized_delegate_declare($4->name, current_namespace, $7);
+						  $$ = type_parameterized_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $10)));
+						}
 	;
 
 required_types:
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 468b81d450d..0a63b7ebf7f 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -142,15 +142,15 @@ static char const *parameterized_type_shorthands[][2] = {
     {"Windows_CFoundation_C", "__F"},
 };
 
-static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *params)
+static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *params, const char *prefix)
 {
     size_t len = 0, pos = 0;
     char *buf = NULL, *tmp;
     int i, count = params ? list_count(params) : 0;
     typeref_t *ref;
 
-    pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL);
-    pos += strappend(&buf, &len, pos, "_%d", count);
+    pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", "", use_abi_namespace ? "ABI" : NULL);
+    pos += strappend(&buf, &len, pos, "%s%s_%d", prefix, type->name, count);
     if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
     {
         for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
@@ -664,12 +664,13 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs)
     return apicontract;
 }
 
-static void compute_delegate_iface_names(type_t *delegate)
+static void compute_delegate_iface_names(type_t *delegate, type_t *type, typeref_list_t *params)
 {
     type_t *iface = delegate->details.delegate.iface;
     iface->namespace = delegate->namespace;
     iface->name = strmake("I%s", delegate->name);
-    iface->c_name = format_namespace(delegate->namespace, "__x_", "_C", iface->name, use_abi_namespace ? "ABI" : NULL);
+    if (type) iface->c_name = format_parameterized_type_c_name(type, params, "I");
+    else iface->c_name = format_namespace(delegate->namespace, "__x_", "_C", iface->name, use_abi_namespace ? "ABI" : NULL);
 }
 
 type_t *type_delegate_declare(char *name, struct namespace *namespace)
@@ -707,7 +708,7 @@ type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_lis
 
     delegate->details.delegate.iface = iface;
     delegate->defined = TRUE;
-    compute_delegate_iface_names(delegate);
+    compute_delegate_iface_names(delegate, NULL, NULL);
 
     return delegate;
 }
@@ -751,6 +752,46 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty
     return type;
 }
 
+type_t *type_parameterized_delegate_declare(char *name, struct namespace *namespace, typeref_list_t *params)
+{
+    type_t *type = get_type(TYPE_PARAMETERIZED_TYPE, name, namespace, 0);
+    if (type_get_type_detect_alias(type) != TYPE_PARAMETERIZED_TYPE)
+        error_loc("pdelegate %s previously not declared a pdelegate at %s:%d\n",
+                  type->name, type->loc_info.input_name, type->loc_info.line_number);
+    type->details.parameterized.type = make_type(TYPE_DELEGATE);
+    type->details.parameterized.params = params;
+    return type;
+}
+
+type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, statement_list_t *stmts)
+{
+    type_t *iface, *delegate;
+
+    if (type->defined)
+        error_loc("pdelegate %s already defined at %s:%d\n",
+                  type->name, type->loc_info.input_name, type->loc_info.line_number);
+
+    type->attrs = check_interface_attrs(type->name, attrs);
+
+    delegate = type->details.parameterized.type;
+    delegate->attrs = type->attrs;
+    delegate->details.delegate.iface = make_type(TYPE_INTERFACE);
+
+    iface = delegate->details.delegate.iface;
+    iface->details.iface = xmalloc(sizeof(*iface->details.iface));
+    iface->details.iface->disp_props = NULL;
+    iface->details.iface->disp_methods = NULL;
+    iface->details.iface->stmts = stmts;
+    iface->details.iface->inherit = find_type("IUnknown", NULL, 0);
+    if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n");
+    iface->details.iface->disp_inherit = NULL;
+    iface->details.iface->async_iface = NULL;
+    iface->details.iface->requires = NULL;
+
+    type->defined = TRUE;
+    return type;
+}
+
 type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params)
 {
     type_t *new_type = duptype(type, 0);
@@ -932,6 +973,11 @@ static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface,
     iface->details.iface->requires = NULL;
 }
 
+static void type_parameterized_delegate_specialize(type_t *tmpl, type_t *delegate, typeref_list_t *orig, typeref_list_t *repl)
+{
+    type_parameterized_interface_specialize(tmpl->details.delegate.iface, delegate->details.delegate.iface, orig, repl);
+}
+
 type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params)
 {
     type_t *tmpl = type->details.parameterized.type;
@@ -940,7 +986,13 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t
     new_type->namespace = type->namespace;
     new_type->name = format_parameterized_type_name(type, params);
     reg_type(new_type, new_type->name, new_type->namespace, 0);
-    new_type->c_name = format_parameterized_type_c_name(type, params);
+    new_type->c_name = format_parameterized_type_c_name(type, params, "");
+
+    if (new_type->type_type == TYPE_DELEGATE)
+    {
+        new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0);
+        compute_delegate_iface_names(new_type, type, params);
+    }
 
     return new_type;
 }
@@ -960,11 +1012,19 @@ type_t *type_parameterized_type_specialize_define(type_t *type)
     if (type_get_type_detect_alias(tmpl->details.parameterized.type) == TYPE_INTERFACE &&
         type_get_type_detect_alias(iface) == TYPE_INTERFACE)
         type_parameterized_interface_specialize(tmpl->details.parameterized.type, iface, orig, repl);
+    else if (type_get_type_detect_alias(tmpl->details.parameterized.type) == TYPE_DELEGATE &&
+             type_get_type_detect_alias(iface) == TYPE_DELEGATE)
+        type_parameterized_delegate_specialize(tmpl->details.parameterized.type, iface, orig, repl);
     else
-        error_loc("pinterface %s previously not declared a pinterface at %s:%d\n",
+        error_loc("pinterface/pdelegate %s previously not declared a pinterface/pdelegate at %s:%d\n",
                   iface->name, iface->loc_info.input_name, iface->loc_info.line_number);
 
     iface->defined = TRUE;
+    if (iface->type_type == TYPE_DELEGATE)
+    {
+        iface = iface->details.delegate.iface;
+        iface->defined = TRUE;
+    }
     compute_method_indexes(iface);
     return iface;
 }
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index c2b3b6c90c6..8130174fe2a 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -68,6 +68,8 @@ type_t *type_delegate_declare(char *name, struct namespace *namespace);
 type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts);
 type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, typeref_list_t *params);
 type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, typeref_list_t *requires);
+type_t *type_parameterized_delegate_declare(char *name, struct namespace *namespace, typeref_list_t *params);
+type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, statement_list_t *stmts);
 type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params);
 type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params);
 type_t *type_parameterized_type_specialize_define(type_t *type);




More information about the wine-cvs mailing list