offapi/UnoApi_offapi.mk                        |    1 
 offapi/org/libreoffice/embindtest/Template.idl |   21 +++
 offapi/org/libreoffice/embindtest/XTest.idl    |    2 
 static/source/embindmaker/embindmaker.cxx      |  171 +++++++++++++++++++++++--
 unotest/source/embindtest/embindtest.cxx       |   19 ++
 unotest/source/embindtest/embindtest.js        |   10 +
 6 files changed, 214 insertions(+), 10 deletions(-)

New commits:
commit f504bd1ac99fe9464d6a5e41febbdcab08af1c97
Author:     Stephan Bergmann <stephan.bergm...@allotropia.de>
AuthorDate: Tue Jul 30 09:13:35 2024 +0200
Commit:     Stephan Bergmann <stephan.bergm...@allotropia.de>
CommitDate: Tue Jul 30 11:00:49 2024 +0200

    Embind: Missing support for UNO polymorphic struct types
    
    Change-Id: I6bb29a951e6e5a3ed7d825172ba7b92ef95a5619
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171228
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de>

diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index b3c1c4e52ddf..9613a54eb27a 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -4448,6 +4448,7 @@ $(eval $(call 
gb_UnoApi_add_idlfiles,offapi,org/libreoffice/embindtest, \
     Struct \
     StructLong \
     StructString \
+    Template \
     XAttributes \
     XTest \
 ))
diff --git a/offapi/org/libreoffice/embindtest/Template.idl 
b/offapi/org/libreoffice/embindtest/Template.idl
new file mode 100644
index 000000000000..73e94a491307
--- /dev/null
+++ b/offapi/org/libreoffice/embindtest/Template.idl
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+module org { module libreoffice { module embindtest {
+
+struct Template<T1, T2> {
+    T2 m1;
+    long m2;
+    T1 m3;
+    T2 m4;
+};
+
+}; }; };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/offapi/org/libreoffice/embindtest/XTest.idl 
b/offapi/org/libreoffice/embindtest/XTest.idl
index 370363cf9a09..8d46c9e71d5a 100644
--- a/offapi/org/libreoffice/embindtest/XTest.idl
+++ b/offapi/org/libreoffice/embindtest/XTest.idl
@@ -44,6 +44,8 @@ interface XTest {
     boolean isStructLong([in] StructLong value);
     StructString getStructString();
     boolean isStructString([in] StructString value);
+    Template<any, StructString> getTemplate();
+    boolean isTemplate([in] Template<any, StructString> value);
     any getAnyVoid();
     boolean isAnyVoid([in] any value);
     any getAnyBoolean();
diff --git a/static/source/embindmaker/embindmaker.cxx 
b/static/source/embindmaker/embindmaker.cxx
index 9953512a8bf0..4956376bed16 100644
--- a/static/source/embindmaker/embindmaker.cxx
+++ b/static/source/embindmaker/embindmaker.cxx
@@ -262,7 +262,100 @@ void scan(rtl::Reference<unoidl::MapCursor> const& 
cursor, std::u16string_view p
     }
 }
 
-OUString cppName(OUString const& name) { return "::" + name.replaceAll(u".", 
u"::"); }
+OUString cppName(OUString const& name)
+{
+    sal_Int32 k;
+    std::vector<OString> args;
+    OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k, &args)));
+    OUStringBuffer buf;
+    for (sal_Int32 i = 0; i != k; ++i)
+    {
+        buf.append("::com::sun::star::uno::Sequence<");
+    }
+    if (n == "boolean")
+    {
+        buf.append("::sal_Bool");
+    }
+    else if (n == "byte")
+    {
+        buf.append("::sal_Int8");
+    }
+    else if (n == "short")
+    {
+        buf.append("::sal_Int16");
+    }
+    else if (n == "unsigned short")
+    {
+        buf.append("::sal_uInt16");
+    }
+    else if (n == "long")
+    {
+        buf.append("::sal_Int32");
+    }
+    else if (n == "unsigned long")
+    {
+        buf.append("::sal_uInt32");
+    }
+    else if (n == "hyper")
+    {
+        buf.append("::sal_Int64");
+    }
+    else if (n == "unsigned hyper")
+    {
+        buf.append("::sal_uInt64");
+    }
+    else if (n == "float")
+    {
+        buf.append("float");
+    }
+    else if (n == "double")
+    {
+        buf.append("double");
+    }
+    else if (n == "char")
+    {
+        buf.append("::sal_Unicode");
+    }
+    else if (n == "string")
+    {
+        buf.append("::rtl::OUString");
+    }
+    else if (n == "type")
+    {
+        buf.append("::com::sun::star::uno::Type");
+    }
+    else if (n == "any")
+    {
+        buf.append("::com::sun::star::uno::Any");
+    }
+    else
+    {
+        buf.append("::" + n.replaceAll(u".", u"::"));
+    }
+    if (!args.empty())
+    {
+        buf.append('<');
+        bool first = true;
+        for (auto const& i : args)
+        {
+            if (first)
+            {
+                first = false;
+            }
+            else
+            {
+                buf.append(", ");
+            }
+            buf.append(cppName(b2u(i)));
+        }
+        buf.append('>');
+    }
+    for (sal_Int32 i = 0; i != k; ++i)
+    {
+        buf.append('>');
+    }
+    return buf.makeStringAndClear();
+}
 
 OUString resolveOuterTypedefs(rtl::Reference<TypeManager> const& manager, 
OUString const& name)
 {
@@ -453,6 +546,16 @@ void dumpStructMembers(std::ostream& out, 
rtl::Reference<TypeManager> const& man
     }
 }
 
+void dumpInstantiationMembers(std::ostream& out, OUString const& name,
+                              
rtl::Reference<unoidl::PolymorphicStructTypeTemplateEntity> poly)
+{
+    for (auto const& mem : poly->getMembers())
+    {
+        out << "
        .field(\"" << mem.name << "\", &" << cppName(name) << "::" << mem.name
+            << ")";
+    }
+}
+
 void dumpExceptionMembers(std::ostream& out, rtl::Reference<TypeManager> 
const& manager,
                           OUString const& name,
                           rtl::Reference<unoidl::ExceptionTypeEntity> 
exception)
@@ -845,13 +948,32 @@ void dumpRegisterFunctionEpilog(std::ostream& out, 
unsigned long long& counter)
     }
 }
 
-void recordSequenceTypes(rtl::Reference<TypeManager> const& manager, OUString 
const& type,
-                         std::set<OUString>& sequences)
+void recordGenericTypes(rtl::Reference<TypeManager> const& manager, OUString 
const& type,
+                        std::set<OUString>& sequences, std::set<OUString>& 
instantiations)
 {
     auto const res = resolveAllTypedefs(manager, type);
-    if (manager->getSort(res) == codemaker::UnoType::Sort::Sequence)
+    switch (manager->getSort(res))
     {
-        sequences.insert(res);
+        case codemaker::UnoType::Sort::Sequence:
+            if (sequences.insert(res).second)
+            {
+                assert(res.startsWith("[]"));
+                recordGenericTypes(manager, res.copy(2), sequences, 
instantiations);
+            }
+            break;
+        case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+            if (instantiations.insert(res).second)
+            {
+                std::vector<OString> args;
+                codemaker::UnoType::decompose(u2b(res), nullptr, &args);
+                for (auto const& i : args)
+                {
+                    recordGenericTypes(manager, b2u(i), sequences, 
instantiations);
+                }
+            }
+            break;
+        default:
+            break;
     }
 }
 
@@ -995,6 +1117,7 @@ SAL_IMPLEMENT_MAIN()
             dumpRegisterFunctionEpilog(cppOut, n);
         }
         std::set<OUString> sequences;
+        std::set<OUString> instantiations;
         for (auto const& str : structs)
         {
             auto const ent = mgr->getManager()->findEntity(str);
@@ -1010,7 +1133,7 @@ SAL_IMPLEMENT_MAIN()
             dumpRegisterFunctionEpilog(cppOut, n);
             for (auto const& mem : strEnt->getDirectMembers())
             {
-                recordSequenceTypes(mgr, mem.type, sequences);
+                recordGenericTypes(mgr, mem.type, sequences, instantiations);
             }
         }
         for (auto const& exc : exceptions)
@@ -1028,7 +1151,7 @@ SAL_IMPLEMENT_MAIN()
             dumpRegisterFunctionEpilog(cppOut, n);
             for (auto const& mem : excEnt->getDirectMembers())
             {
-                recordSequenceTypes(mgr, mem.type, sequences);
+                recordGenericTypes(mgr, mem.type, sequences, instantiations);
             }
         }
         std::set<OUString> inOutParams;
@@ -1097,20 +1220,48 @@ SAL_IMPLEMENT_MAIN()
             dumpRegisterFunctionEpilog(cppOut, n);
             for (auto const& attr : ifcEnt->getDirectAttributes())
             {
-                recordSequenceTypes(mgr, attr.type, sequences);
+                recordGenericTypes(mgr, attr.type, sequences, instantiations);
             }
             for (auto const& meth : ifcEnt->getDirectMethods())
             {
                 for (auto const& param : meth.parameters)
                 {
-                    recordSequenceTypes(mgr, param.type, sequences);
+                    recordGenericTypes(mgr, param.type, sequences, 
instantiations);
                     if (param.direction
                         != 
unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
                     {
                         recordInOutParameterType(mgr, param.type, inOutParams);
                     }
                 }
-                recordSequenceTypes(mgr, meth.returnType, sequences);
+                recordGenericTypes(mgr, meth.returnType, sequences, 
instantiations);
+            }
+        }
+        for (auto const& ins : instantiations)
+        {
+            std::vector<OString> templArgs;
+            auto const templ = b2u(codemaker::UnoType::decompose(u2b(ins), 
nullptr, &templArgs));
+            auto const ent = mgr->getManager()->findEntity(templ);
+            assert(ent.is());
+            assert(ent->getSort() == 
unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE);
+            rtl::Reference const polEnt(
+                
static_cast<unoidl::PolymorphicStructTypeTemplateEntity*>(ent.get()));
+            dumpRegisterFunctionProlog(cppOut, n);
+            cppOut << "    ::emscripten::value_object<" << cppName(ins) << 
">(\"uno_Type_"
+                   << jsName(ins) << "\")";
+            dumpInstantiationMembers(cppOut, ins, polEnt);
+            cppOut << ";
";
+            cppOut << "    ::unoembindhelpers::registerUnoType<" << 
cppName(ins) << ">();
";
+            dumpRegisterFunctionEpilog(cppOut, n);
+            for (auto const& arg : templArgs)
+            {
+                recordGenericTypes(mgr, b2u(arg), sequences, instantiations);
+            }
+            for (auto const& mem : polEnt->getMembers())
+            {
+                if (!mem.parameterized)
+                {
+                    recordGenericTypes(mgr, mem.type, sequences, 
instantiations);
+                }
             }
         }
         for (auto const& srv : services)
diff --git a/unotest/source/embindtest/embindtest.cxx 
b/unotest/source/embindtest/embindtest.cxx
index 166fa9650b8a..3883c031755c 100644
--- a/unotest/source/embindtest/embindtest.cxx
+++ b/unotest/source/embindtest/embindtest.cxx
@@ -30,6 +30,7 @@
 #include <org/libreoffice/embindtest/Struct.hpp>
 #include <org/libreoffice/embindtest/StructLong.hpp>
 #include <org/libreoffice/embindtest/StructString.hpp>
+#include <org/libreoffice/embindtest/Template.hpp>
 #include <org/libreoffice/embindtest/Test.hpp>
 #include <org/libreoffice/embindtest/XTest.hpp>
 #include <rtl/ustring.hxx>
@@ -146,6 +147,24 @@ class Test : public 
cppu::WeakImplHelper<org::libreoffice::embindtest::XTest>
         return value.m == u"hä";
     }
 
+    org::libreoffice::embindtest::Template<css::uno::Any,
+                                           
org::libreoffice::embindtest::StructString>
+        SAL_CALL getTemplate() override
+    {
+        return { { u"foo"_ustr }, -123456, css::uno::Any(sal_Int32(-123456)), 
{ u"barr"_ustr } };
+    }
+
+    sal_Bool SAL_CALL
+    isTemplate(org::libreoffice::embindtest::Template<
+               css::uno::Any, org::libreoffice::embindtest::StructString> 
const& value) override
+    {
+        return value
+               == org::libreoffice::embindtest::Template<
+                      css::uno::Any, 
org::libreoffice::embindtest::StructString>{
+                      { u"foo"_ustr }, -123456, 
css::uno::Any(sal_Int32(-123456)), { u"barr"_ustr }
+                  };
+    }
+
     css::uno::Any SAL_CALL getAnyVoid() override { return {}; }
 
     sal_Bool SAL_CALL isAnyVoid(css::uno::Any const& value) override
diff --git a/unotest/source/embindtest/embindtest.js 
b/unotest/source/embindtest/embindtest.js
index 42da2ee51b4e..57720b6baaa6 100644
--- a/unotest/source/embindtest/embindtest.js
+++ b/unotest/source/embindtest/embindtest.js
@@ -109,6 +109,16 @@ Module.uno_init.then(function() {
         console.assert(test.isStruct(v));
         v.m4.delete();
     }
+    {
+        let v = test.getTemplate();
+        console.log(v);
+        console.assert(v.m1.m === 'foo');
+        console.assert(v.m2 === -123456);
+        console.assert(v.m3.get() === -123456);
+        console.assert(v.m4.m === 'barr');
+        console.assert(test.isTemplate(v));
+        v.m3.delete();
+    }
     {
         let v = test.getAnyVoid();
         console.log(v);

Reply via email to