diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /codemaker/source/cppumaker | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'codemaker/source/cppumaker')
-rw-r--r-- | codemaker/source/cppumaker/cppumaker.cxx | 110 | ||||
-rw-r--r-- | codemaker/source/cppumaker/cppuoptions.cxx | 325 | ||||
-rw-r--r-- | codemaker/source/cppumaker/cppuoptions.hxx | 41 | ||||
-rw-r--r-- | codemaker/source/cppumaker/cpputype.cxx | 4105 | ||||
-rw-r--r-- | codemaker/source/cppumaker/cpputype.hxx | 35 | ||||
-rw-r--r-- | codemaker/source/cppumaker/dependencies.cxx | 296 | ||||
-rw-r--r-- | codemaker/source/cppumaker/dependencies.hxx | 126 | ||||
-rw-r--r-- | codemaker/source/cppumaker/dumputils.cxx | 79 | ||||
-rw-r--r-- | codemaker/source/cppumaker/dumputils.hxx | 40 | ||||
-rw-r--r-- | codemaker/source/cppumaker/includes.cxx | 273 | ||||
-rw-r--r-- | codemaker/source/cppumaker/includes.hxx | 100 |
11 files changed, 5530 insertions, 0 deletions
diff --git a/codemaker/source/cppumaker/cppumaker.cxx b/codemaker/source/cppumaker/cppumaker.cxx new file mode 100644 index 000000000..b2556655b --- /dev/null +++ b/codemaker/source/cppumaker/cppumaker.cxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <vector> + +#include <codemaker/generatedtypeset.hxx> +#include <codemaker/typemanager.hxx> +#include <rtl/ref.hxx> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <sal/main.h> +#include <sal/types.h> +#include <unoidl/unoidl.hxx> +#include <o3tl/string_view.hxx> + +#include "cppuoptions.hxx" +#include "cpputype.hxx" + +// coverity[tainted_data] - this is a build time tool +SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) { + CppuOptions options; + try { + if (!options.initOptions(argc, argv)) { + return EXIT_FAILURE; + } + + rtl::Reference typeMgr(new TypeManager); + for (const OString& f :options.getExtraInputFiles()) + { + typeMgr->loadProvider(convertToFileUrl(f), false); + } + for (const OString& f : options.getInputFiles()) + { + typeMgr->loadProvider(convertToFileUrl(f), true); + } + codemaker::GeneratedTypeSet generated; + if (options.isValid("-T")) { + OUString names(b2u(options.getOption("-T"))); + for (sal_Int32 i = 0; i != -1;) { + std::u16string_view name(o3tl::getToken(names, 0, ';', i)); + if (!name.empty()) { + produce( + OUString(name == u"*" + ? u"" + : o3tl::ends_with(name, u".*") + ? name.substr(0, name.size() - std::strlen(".*")) + : name), + typeMgr, generated, options); + } + } + } else { + produce("", typeMgr, generated, options); + } + if (!options.isValid("-nD")) { + // C++ header files generated for the following UNO types are + // included in header files in cppu/inc/com/sun/star/uno (Any.hxx, + // Reference.hxx, Type.h), so it seems best to always generate those + // C++ header files: + produce( + "com.sun.star.uno.RuntimeException", typeMgr, generated, + options); + produce( + "com.sun.star.uno.TypeClass", typeMgr, generated, options); + produce( + "com.sun.star.uno.XInterface", typeMgr, generated, options); + } + } catch (CannotDumpException & e) { + std::cerr << "ERROR: " << e.getMessage() << '\n'; + return EXIT_FAILURE; + } catch (unoidl::NoSuchFileException & e) { + std::cerr << "ERROR: No such file <" << e.getUri() << ">\n"; + return EXIT_FAILURE; + } catch (unoidl::FileFormatException & e) { + std::cerr + << "ERROR: Bad format of <" << e.getUri() << ">, \"" + << e.getDetail() << "\"\n"; + return EXIT_FAILURE; + } catch (IllegalArgument& e) { + std::cerr << "Illegal option " << e.m_message << '\n'; + return EXIT_FAILURE; + } catch (std::exception& e) { + std::cerr << "Failure " << e.what() << '\n'; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/cppuoptions.cxx b/codemaker/source/cppumaker/cppuoptions.cxx new file mode 100644 index 000000000..0a2ad9623 --- /dev/null +++ b/codemaker/source/cppumaker/cppuoptions.cxx @@ -0,0 +1,325 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <stdio.h> +#include <string.h> + +#include "cppuoptions.hxx" + +#ifdef SAL_UNX +#define SEPARATOR '/' +#else +#define SEPARATOR '\\' +#endif + +bool CppuOptions::initOptions(int ac, char* av[], bool bCmdFile) +{ + bool ret = true; + int i=0; + + if (!bCmdFile) + { + bCmdFile = true; + + OString name(av[0]); + sal_Int32 index = name.lastIndexOf(SEPARATOR); + m_program = name.copy(index > 0 ? index+1 : 0); + + if (ac < 2) + { + fprintf(stderr, "%s", prepareHelp().getStr()); + ret = false; + } + + i = 1; + } + else + { + i = 0; + } + + char *s=nullptr; + for( ; i < ac; i++) + { + if (av[i][0] == '-') + { + switch (av[i][1]) + { + case 'O': + if (av[i][2] == '\0') + { + if (i < ac - 1 && av[i+1][0] != '-') + { + i++; + s = av[i]; + } + else + { + OString tmp("'-O', please check"); + if (i <= ac - 1) + { + tmp += OString::Concat(" your input '") + av[i+1] + "'"; + } + + throw IllegalArgument(tmp); + } + } + else + { + s = av[i] + 2; + } + + m_options["-O"] = OString(s); + break; + case 'n': + if (av[i][2] != 'D' || av[i][3] != '\0') + { + OString tmp = OString::Concat("'-nD', please check your input '") + av[i] + "'"; + throw IllegalArgument(tmp); + } + + m_options["-nD"] = OString(); + break; + case 'T': + if (av[i][2] == '\0') + { + if (i < ac - 1 && av[i+1][0] != '-') + { + i++; + s = av[i]; + } + else + { + OString tmp("'-T', please check"); + if (i <= ac - 1) + { + tmp += OString::Concat(" your input '") + av[i+1] + "'"; + } + + throw IllegalArgument(tmp); + } + } + else + { + s = av[i] + 2; + } + + if (m_options.count("-T") > 0) + { + OString tmp = m_options["-T"] + ";" + s; + m_options["-T"] = tmp; + } + else + { + m_options["-T"] = OString(s); + } + break; + case 'L': + if (av[i][2] != '\0') + { + OString tmp("'-L', please check"); + if (i <= ac - 1) + { + tmp += OString::Concat(" your input '") + av[i] + "'"; + } + + throw IllegalArgument(tmp); + } + + if (isValid("-C") || isValid("-CS")) + { + throw IllegalArgument("'-L' could not be combined with '-C' or '-CS' option"); + } + m_options["-L"] = OString(); + break; + case 'C': + if (av[i][2] == 'S') + { + if (av[i][3] != '\0') + { + OString tmp("'-CS', please check"); + if (i <= ac - 1) + { + tmp += OString::Concat(" your input '") + av[i] + "'"; + } + + throw IllegalArgument(tmp); + } + + if (isValid("-L") || isValid("-C")) + { + throw IllegalArgument("'-CS' could not be combined with '-L' or '-C' option"); + } + m_options["-CS"] = OString(); + break; + } + else if (av[i][2] != '\0') + { + OString tmp("'-C', please check"); + if (i <= ac - 1) + { + tmp += OString::Concat(" your input '") + av[i] + "'"; + } + + throw IllegalArgument(tmp); + } + + if (isValid("-L") || isValid("-CS")) + { + throw IllegalArgument("'-C' could not be combined with '-L' or '-CS' option"); + } + m_options["-C"] = OString(); + break; + case 'G': + if (av[i][2] == 'c') + { + if (av[i][3] != '\0') + { + OString tmp("'-Gc', please check"); + if (i <= ac - 1) + { + tmp += OString::Concat(" your input '") + av[i] + "'"; + } + + throw IllegalArgument(tmp); + } + + m_options["-Gc"] = OString(); + break; + } + else if (av[i][2] != '\0') + { + OString tmp("'-G', please check"); + if (i <= ac - 1) + { + tmp += OString::Concat(" your input '") + av[i] + "'"; + } + + throw IllegalArgument(tmp); + } + + m_options["-G"] = OString(); + break; + case 'X': // support for eXtra type rdbs + { + if (av[i][2] == '\0') + { + if (i < ac - 1 && av[i+1][0] != '-') + { + i++; + s = av[i]; + } + else + { + OString tmp("'-X', please check"); + if (i <= ac - 1) + { + tmp += OString::Concat(" your input '") + av[i+1] + "'"; + } + + throw IllegalArgument(tmp); + } + } + else + { + s = av[i] + 2; + } + + m_extra_input_files.emplace_back(s ); + break; + } + + default: + throw IllegalArgument(OString::Concat("the option is unknown") + av[i]); + } + } else + { + if (av[i][0] == '@') + { + FILE* cmdFile = fopen(av[i]+1, "r"); + if( cmdFile == nullptr ) + { + fprintf(stderr, "%s", prepareHelp().getStr()); + ret = false; + } + else + { + int rargc=0; + char* rargv[512]; + char buffer[512]; + + while (fscanf(cmdFile, "%511s", buffer) != EOF && rargc < 512) + { + rargv[rargc]= strdup(buffer); + rargc++; + } + fclose(cmdFile); + + ret = initOptions(rargc, rargv, bCmdFile); + + for (int j=0; j < rargc; j++) + { + free(rargv[j]); + } + } + } + else + { + m_inputFiles.emplace_back(av[i]); + } + } + } + + return ret; +} + +OString CppuOptions::prepareHelp() +{ + OString help = "\nusing: " + + m_program + " [-options] file_1 ... file_n\nOptions:\n" + " -O<path> = path describes the root directory for the generated output.\n" + " The output directory tree is generated under this directory.\n" + " -T<name> = name specifies a type or a list of types. The output for this\n" + " [t1;...] type is generated. If no '-T' option is specified,\n" + " then output for all types is generated.\n" + " Example: 'com.sun.star.uno.XInterface' is a valid type.\n" + " -L = UNO type functions are generated lightweight, that means only\n" + " the name and typeclass are given and everything else is retrieved\n" + " from the type library dynamically. The default is that UNO type\n" + " functions provides enough type information for bootstrapping C++.\n" + " '-L' should be the default for external components.\n" + " -C = UNO type functions are generated comprehensive that means all\n" + " necessary information is available for bridging the type in UNO.\n" + " -nD = no dependent types are generated.\n" + " -G = generate only target files which does not exists.\n" + " -Gc = generate only target files which content will be changed.\n" + " -X<file> = extra types which will not be taken into account for generation.\n\n" + + prepareVersion(); + + return help; +} + +OString CppuOptions::prepareVersion() const +{ + OString version = m_program + " Version 2.0\n\n"; + return version; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/cppuoptions.hxx b/codemaker/source/cppumaker/cppuoptions.hxx new file mode 100644 index 000000000..f3d65e4fa --- /dev/null +++ b/codemaker/source/cppumaker/cppuoptions.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <codemaker/options.hxx> + +class CppuOptions : public Options +{ +public: + CppuOptions() + : Options() + { + } + + bool initOptions(int ac, char* av[], bool bCmdFile = false) override; + + OString prepareHelp() override; + + OString prepareVersion() const; + +protected: +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/cpputype.cxx b/codemaker/source/cppumaker/cpputype.cxx new file mode 100644 index 000000000..03fcd033b --- /dev/null +++ b/codemaker/source/cppumaker/cpputype.cxx @@ -0,0 +1,4105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. +* + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <sal/log.hxx> + +#include <algorithm> +#include <cassert> +#include <cstdlib> +#include <map> +#include <set> +#include <string_view> +#include <memory> +#include <utility> +#include <vector> +#include <iostream> + +#include <rtl/alloc.h> +#include <rtl/ref.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> +#include <rtl/strbuf.hxx> +#include <unoidl/unoidl.hxx> + +#include <codemaker/commoncpp.hxx> +#include <codemaker/exceptiontree.hxx> +#include <codemaker/generatedtypeset.hxx> +#include <codemaker/typemanager.hxx> +#include <codemaker/unotype.hxx> + +#include "cpputype.hxx" +#include "cppuoptions.hxx" +#include "dependencies.hxx" +#include "dumputils.hxx" +#include "includes.hxx" + +namespace +{ + +bool isBootstrapType(OUString const & name) +{ + static char const * const names[] = { + "com.sun.star.beans.Property", + "com.sun.star.beans.PropertyAttribute", + "com.sun.star.beans.PropertyChangeEvent", + "com.sun.star.beans.PropertyState", + "com.sun.star.beans.PropertyValue", + "com.sun.star.beans.XFastPropertySet", + "com.sun.star.beans.XMultiPropertySet", + "com.sun.star.beans.XPropertiesChangeListener", + "com.sun.star.beans.XPropertyAccess", + "com.sun.star.beans.XPropertyChangeListener", + "com.sun.star.beans.XPropertySet", + "com.sun.star.beans.XPropertySetInfo", + "com.sun.star.beans.XPropertySetOption", + "com.sun.star.beans.XVetoableChangeListener", + "com.sun.star.bridge.UnoUrlResolver", + "com.sun.star.bridge.XUnoUrlResolver", + "com.sun.star.connection.SocketPermission", + "com.sun.star.container.XElementAccess", + "com.sun.star.container.XEnumeration", + "com.sun.star.container.XEnumerationAccess", + "com.sun.star.container.XHierarchicalNameAccess", + "com.sun.star.container.XNameAccess", + "com.sun.star.container.XNameContainer", + "com.sun.star.container.XNameReplace", + "com.sun.star.container.XSet", + "com.sun.star.io.FilePermission", + "com.sun.star.io.IOException", + "com.sun.star.lang.DisposedException", + "com.sun.star.lang.EventObject", + "com.sun.star.lang.WrappedTargetRuntimeException", + "com.sun.star.lang.XComponent", + "com.sun.star.lang.XEventListener", + "com.sun.star.lang.XInitialization", + "com.sun.star.lang.XMultiComponentFactory", + "com.sun.star.lang.XMultiServiceFactory", + "com.sun.star.lang.XServiceInfo", + "com.sun.star.lang.XSingleComponentFactory", + "com.sun.star.lang.XSingleServiceFactory", + "com.sun.star.lang.XTypeProvider", + "com.sun.star.loader.XImplementationLoader", + "com.sun.star.reflection.FieldAccessMode", + "com.sun.star.reflection.MethodMode", + "com.sun.star.reflection.ParamInfo", + "com.sun.star.reflection.ParamMode", + "com.sun.star.reflection.TypeDescriptionSearchDepth", + "com.sun.star.reflection.XCompoundTypeDescription", + "com.sun.star.reflection.XEnumTypeDescription", + "com.sun.star.reflection.XIdlArray", + "com.sun.star.reflection.XIdlClass", + "com.sun.star.reflection.XIdlField", + "com.sun.star.reflection.XIdlField2", + "com.sun.star.reflection.XIdlMethod", + "com.sun.star.reflection.XIdlReflection", + "com.sun.star.reflection.XIndirectTypeDescription", + "com.sun.star.reflection.XInterfaceAttributeTypeDescription", + "com.sun.star.reflection.XInterfaceAttributeTypeDescription2", + "com.sun.star.reflection.XInterfaceMemberTypeDescription", + "com.sun.star.reflection.XInterfaceMethodTypeDescription", + "com.sun.star.reflection.XInterfaceTypeDescription", + "com.sun.star.reflection.XInterfaceTypeDescription2", + "com.sun.star.reflection.XMethodParameter", + "com.sun.star.reflection.XStructTypeDescription", + "com.sun.star.reflection.XTypeDescription", + "com.sun.star.reflection.XTypeDescriptionEnumeration", + "com.sun.star.reflection.XTypeDescriptionEnumerationAccess", + "com.sun.star.registry.RegistryKeyType", + "com.sun.star.registry.RegistryValueType", + "com.sun.star.registry.XImplementationRegistration", + "com.sun.star.registry.XRegistryKey", + "com.sun.star.registry.XSimpleRegistry", + "com.sun.star.security.RuntimePermission", + "com.sun.star.security.XAccessControlContext", + "com.sun.star.security.XAccessController", + "com.sun.star.security.XAction", + "com.sun.star.uno.DeploymentException", + "com.sun.star.uno.RuntimeException", + "com.sun.star.uno.TypeClass", + "com.sun.star.uno.Uik", + "com.sun.star.uno.XAdapter", + "com.sun.star.uno.XAggregation", + "com.sun.star.uno.XComponentContext", + "com.sun.star.uno.XCurrentContext", + "com.sun.star.uno.XInterface", + "com.sun.star.uno.XReference", + "com.sun.star.uno.XUnloadingPreference", + "com.sun.star.uno.XWeak", + "com.sun.star.util.XMacroExpander" }; + // cf. cppuhelper/unotypes/Makefile UNOTYPES (plus missing dependencies) + auto const pred = [&name](const char* aName) { + return name.equalsAscii(aName); + }; + return std::any_of(std::begin(names), std::end(names), pred); +} + +class CppuType +{ +public: + CppuType(OUString name, rtl::Reference< TypeManager > const & typeMgr); + + virtual ~CppuType() {} + + CppuType(const CppuType&) = delete; + const CppuType& operator=(const CppuType&) = delete; + + void dump(CppuOptions const & options); + + void dumpFile( + std::u16string_view uri, std::u16string_view name, bool hpp, + CppuOptions const & options); + + void dumpDependedTypes( + codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const; + + virtual void dumpHdlFile( + FileStream & out, codemaker::cppumaker::Includes & includes) { + dumpHFileContent(out, includes); + } + + virtual void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) = 0; + + OUString dumpHeaderDefine(FileStream& o, std::u16string_view extension) const; + + void dumpGetCppuType(FileStream & out); + + virtual void dumpLightGetCppuType(FileStream & out); + + virtual void dumpNormalGetCppuType(FileStream &) { + assert(false); // this cannot happen + } + + virtual void dumpComprehensiveGetCppuType(FileStream &) { + assert(false); // this cannot happen + } + + void dumpType( + FileStream & out, std::u16string_view name, bool isConst = false, + bool isRef = false, bool native = false, bool cppuUnoType = false) + const; + + OUString getTypeClass(OUString const & name, bool cStyle = false); + + void dumpCppuGetType( + FileStream & out, std::u16string_view name, OUString const * ownName = nullptr) const; + + sal_uInt32 getInheritedMemberCount(); + + void inc(sal_Int32 num=4); + void dec(sal_Int32 num=4); + OUString indent() const; +protected: + virtual sal_uInt32 checkInheritedMemberCount() const { + assert(false); // this cannot happen + return 0; + } + + bool passByReference(OUString const & name) const; + + bool canBeWarnUnused(OUString const & name) const; + bool canBeWarnUnused(OUString const & name, int depth) const; + + OUString resolveOuterTypedefs(OUString const & name) const; + + OUString resolveAllTypedefs(std::u16string_view name) const; + + codemaker::cpp::IdentifierTranslationMode isGlobal() const; + + virtual void dumpDeclaration(FileStream &) { + assert(false); // this cannot happen + } + + virtual void dumpFiles(OUString const & uri, CppuOptions const & options); + + virtual void addLightGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const; + + virtual void addNormalGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const; + + virtual void addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const; + + virtual bool isPolymorphic() const; + + virtual void dumpTemplateHead(FileStream &) const {} + + virtual void dumpTemplateParameters(FileStream &) const {} + + void dumpGetCppuTypePreamble(FileStream & out); + + void dumpGetCppuTypePostamble(FileStream & out); + + void addDefaultHIncludes(codemaker::cppumaker::Includes & includes) const; + void addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes) const; + + void dumpInitializer( + FileStream & out, bool parameterized, std::u16string_view name) const; + + void dumpHFileContent( + FileStream & out, codemaker::cppumaker::Includes & includes); + +protected: + sal_uInt32 m_inheritedMemberCount; + + bool m_cppuTypeLeak; + bool m_cppuTypeDynamic; + sal_Int32 m_indentLength; + OUString name_; + OUString id_; + rtl::Reference< TypeManager > m_typeMgr; + codemaker::cppumaker::Dependencies m_dependencies; + +private: + void addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes) + const; +}; + +CppuType::CppuType( + OUString name, rtl::Reference< TypeManager > const & typeMgr): + m_inheritedMemberCount(0) + , m_cppuTypeLeak(false) + , m_cppuTypeDynamic(true) + , m_indentLength(0) + , name_(std::move(name)) + , id_(name_.copy(name_.lastIndexOf('.') + 1)) + , m_typeMgr(typeMgr) + , m_dependencies(typeMgr, name_) +{} + +void CppuType::addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes) +const +{ + if (name_ == "com.sun.star.uno.XInterface" + || name_ == "com.sun.star.uno.Exception") { + includes.addType(); + includes.addCppuUnotypeHxx(); + includes.addSalTypesH(); + includes.addTypelibTypeclassH(); + includes.addTypelibTypedescriptionH(); + } else if (m_cppuTypeLeak) { + addLightGetCppuTypeIncludes(includes); + } else if (m_cppuTypeDynamic) { + addNormalGetCppuTypeIncludes(includes); + } else { + addComprehensiveGetCppuTypeIncludes(includes); + } +} + +void CppuType::dumpFiles(OUString const & uri, CppuOptions const & options) +{ + dumpFile(uri, name_, false, options); + dumpFile(uri, name_, true, options); +} + +void CppuType::addLightGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + //TODO: Determine what is really needed, instead of relying on + // addDefaultHxxIncludes + includes.addCppuUnotypeHxx(); +} + +void CppuType::addNormalGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + //TODO: Determine what is really needed, instead of relying on + // addDefaultHxxIncludes + includes.addCppuUnotypeHxx(); +} + +void CppuType::addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + //TODO: Determine what is really needed, instead of relying on + // addDefaultHxxIncludes + includes.addCppuUnotypeHxx(); +} + +bool CppuType::isPolymorphic() const +{ + return false; +} + +void CppuType::dumpGetCppuTypePreamble(FileStream & out) +{ + if (isPolymorphic()) { + out << "namespace cppu {\n\n"; + dumpTemplateHead(out); + out << "class UnoType< "; + dumpType(out, name_); + dumpTemplateParameters(out); + out << " > {\npublic:\n"; + inc(); + out << indent() + << "static inline ::css::uno::Type const & get() {\n"; + } else { + if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) { + out << "\n\n"; + } + out << ("inline ::css::uno::Type const &" + " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER "); + dumpType(out, name_, false, false, true); + out << " const *) {\n"; + } + inc(); +} + +void CppuType::dumpGetCppuTypePostamble(FileStream & out) +{ + dec(); + if (isPolymorphic()) { + out << indent() << "}\n\nprivate:\n" + << indent() << "UnoType(UnoType &); // not defined\n" + << indent() << "~UnoType(); // not defined\n" + << indent() + << "void operator =(UnoType); // not defined\n};\n\n}\n\n"; + } else { + out << "}\n\n"; + if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) { + out << "\n\n"; + } + } + dumpTemplateHead(out); + out << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL" + " getCppuType(SAL_UNUSED_PARAMETER "); + dumpType(out, name_); + dumpTemplateParameters(out); + out << " const *) {\n"; + inc(); + out << indent() << "return ::cppu::UnoType< "; + dumpType(out, name_); + dumpTemplateParameters(out); + out << " >::get();\n"; + dec(); + out << indent() << "}\n"; +} + +void CppuType::dump(CppuOptions const & options) +{ + if (isBootstrapType(name_)) { + m_cppuTypeDynamic = false; + } else { + // -CS was used as an undocumented option to generate static getCppuType + // functions; since the introduction of cppu::UnoType this no longer is + // meaningful (getCppuType is just a forward to cppu::UnoType::get now), + // and -CS is handled the same way as -C now: + if (options.isValid("-L")) + m_cppuTypeLeak = true; + if (options.isValid("-C") || options.isValid("-CS")) + m_cppuTypeDynamic = false; + } + dumpFiles( + options.isValid("-O") ? b2u(options.getOption("-O")) : "", options); +} + +void CppuType::dumpFile( + std::u16string_view uri, std::u16string_view name, bool hpp, + CppuOptions const & options) +{ + OUString fileUri( + b2u(createFileNameFromType( + u2b(uri), u2b(name), hpp ? ".hpp" : ".hdl"))); + if (fileUri.isEmpty()) { + throw CannotDumpException(OUString::Concat("empty target URI for entity ") + name); + } + bool exists = fileExists(u2b(fileUri)); + if (exists && options.isValid("-G")) { + return; + } + FileStream out; + out.createTempFile(getTempDir(u2b(fileUri))); + OUString tmpUri(b2u(out.getName())); + if(!out.isValid()) { + throw CannotDumpException("cannot open " + tmpUri + " for writing"); + } + codemaker::cppumaker::Includes includes(m_typeMgr, m_dependencies, hpp); + try { + if (hpp) { + addGetCppuTypeIncludes(includes); + dumpHppFile(out, includes); + } else { + dumpHdlFile(out, includes); + } + } catch (...) { + out.close(); + // Remove existing type file if something goes wrong to ensure + // consistency: + if (fileExists(u2b(fileUri))) { + removeTypeFile(u2b(fileUri)); + } + removeTypeFile(u2b(tmpUri)); + throw; + } + out.close(); + (void)makeValidTypeFile( + u2b(fileUri), u2b(tmpUri), exists && options.isValid("-Gc")); +} + +void CppuType::dumpDependedTypes( + codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const +{ + if (!options.isValid("-nD")) { + codemaker::cppumaker::Dependencies::Map const & map + = m_dependencies.getMap(); + for (const auto& entry : map) { + produce(entry.first, m_typeMgr, generated, options); + } + } +} + +OUString CppuType::dumpHeaderDefine( + FileStream & out, std::u16string_view extension) const +{ + OUString def( + "INCLUDED_" + name_.replace('.', '_').toAsciiUpperCase() + "_" + + extension); + out << "#ifndef " << def << "\n#define " << def << "\n"; + return def; +} + +void CppuType::addDefaultHIncludes(codemaker::cppumaker::Includes & includes) +const +{ + //TODO: Only include what is really needed + includes.addCppuMacrosHxx(); + if (m_typeMgr->getSort(name_) + == codemaker::UnoType::Sort::Interface) { + includes.addReference(); + } +} + +void CppuType::addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes) +const +{ + //TODO: Only include what is really needed + includes.addType(); + if (m_typeMgr->getSort(name_) + == codemaker::UnoType::Sort::Interface) { + includes.addReference(); + } +} + +void CppuType::dumpInitializer( + FileStream & out, bool parameterized, std::u16string_view name) const +{ + out << "("; + if (!parameterized) { + sal_Int32 k; + std::vector< OString > args; + OUString n( + b2u(codemaker::UnoType::decompose( + u2b(resolveAllTypedefs(name)), &k, &args))); + if (k == 0) { + rtl::Reference< unoidl::Entity > ent; + switch (m_typeMgr->getSort(n, &ent)) { + case codemaker::UnoType::Sort::Boolean: + out << "false"; + break; + case codemaker::UnoType::Sort::Byte: + case codemaker::UnoType::Sort::Short: + case codemaker::UnoType::Sort::UnsignedShort: + case codemaker::UnoType::Sort::Long: + case codemaker::UnoType::Sort::UnsignedLong: + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + case codemaker::UnoType::Sort::Float: + case codemaker::UnoType::Sort::Double: + case codemaker::UnoType::Sort::Char: + out << "0"; + break; + case codemaker::UnoType::Sort::Enum: + out << codemaker::cpp::scopedCppName(u2b(n)) << "_" + << (dynamic_cast<unoidl::EnumTypeEntity&>(*ent). + getMembers()[0].name); + break; + case codemaker::UnoType::Sort::String: + case codemaker::UnoType::Sort::Type: + case codemaker::UnoType::Sort::Any: + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::PolymorphicStructTemplate: + case codemaker::UnoType::Sort::Interface: + break; + default: + throw CannotDumpException( + OUString::Concat("unexpected entity \"") + name + + "\" in call to CppuType::dumpInitializer"); + } + } + } + out << ")"; +} + +void CppuType::dumpHFileContent( + FileStream & out, codemaker::cppumaker::Includes & includes) +{ + addDefaultHIncludes(includes); + dumpHeaderDefine(out, u"HDL"); + out << "\n"; + includes.dump(out, nullptr, false); + // 'exceptions = false' would be wrong for services/singletons, but + // those don't dump .hdl files anyway + out << ("\nnamespace com { namespace sun { namespace star { namespace uno" + " { class Type; } } } }\n\n"); + if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) { + out << "\n"; + } + dumpDeclaration(out); + if (!(name_ == "com.sun.star.uno.XInterface" + || name_ == "com.sun.star.uno.Exception" + || isPolymorphic())) { + out << "\n" << indent() + << ("inline ::css::uno::Type const &" + " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER "); + dumpType(out, name_, false, false, true); + out << " const *);\n"; + } + if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) { + out << "\n"; + } + out << "\n"; + dumpTemplateHead(out); + out << "SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL getCppuType("; + dumpType(out, name_, true); + dumpTemplateParameters(out); + out << " *);\n\n#endif\n"; +} + +void CppuType::dumpGetCppuType(FileStream & out) +{ + if (name_ == "com.sun.star.uno.XInterface") { + out << indent() + << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL" + " getCppuType(SAL_UNUSED_PARAMETER "); + dumpType(out, name_, true); + out << " *) {\n"; + inc(); + out << indent() + << ("return ::cppu::UnoType< ::css::uno::XInterface" + " >::get();\n"); + dec(); + out << indent() << "}\n"; + } else if (name_ == "com.sun.star.uno.Exception") { + out << indent() + << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL" + " getCppuType(SAL_UNUSED_PARAMETER "); + dumpType(out, name_, true); + out << " *) {\n"; + inc(); + out << indent() + << ("return ::cppu::UnoType< ::css::uno::Exception" + " >::get();\n"); + dec(); + out << indent() << "}\n"; + } else if (m_cppuTypeLeak) { + dumpLightGetCppuType(out); + } else if (m_cppuTypeDynamic) { + dumpNormalGetCppuType(out); + } else { + dumpComprehensiveGetCppuType(out); + } +} + +void CppuType::dumpLightGetCppuType(FileStream & out) +{ + dumpGetCppuTypePreamble(out); + out << indent() + << "static typelib_TypeDescriptionReference * the_type = 0;\n" + << indent() << "if ( !the_type )\n" << indent() << "{\n"; + inc(); + out << indent() << "typelib_static_type_init( &the_type, " + << getTypeClass(name_, true) << ", \"" << name_ << "\" );\n"; + dec(); + out << indent() << "}\n" << indent() + << ("return * reinterpret_cast< ::css::uno::Type * >(" + " &the_type );\n"); + dumpGetCppuTypePostamble(out); +} + +codemaker::cpp::IdentifierTranslationMode CppuType::isGlobal() const +{ + return name_.indexOf('.') == -1 + ? codemaker::cpp::IdentifierTranslationMode::Global : codemaker::cpp::IdentifierTranslationMode::NonGlobal; +} + +sal_uInt32 CppuType::getInheritedMemberCount() +{ + if (m_inheritedMemberCount == 0) { + m_inheritedMemberCount = checkInheritedMemberCount(); + } + + return m_inheritedMemberCount; +} + +OUString CppuType::getTypeClass(OUString const & name, bool cStyle) +{ + rtl::Reference< unoidl::Entity > ent; + switch (m_typeMgr->getSort(name, &ent)) { + case codemaker::UnoType::Sort::Void: + return cStyle + ? OUString("typelib_TypeClass_VOID") + : OUString("::css::uno::TypeClass_VOID"); + case codemaker::UnoType::Sort::Boolean: + return cStyle + ? OUString("typelib_TypeClass_BOOLEAN") + : OUString("::css::uno::TypeClass_BOOLEAN"); + case codemaker::UnoType::Sort::Byte: + return cStyle + ? OUString("typelib_TypeClass_BYTE") + : OUString("::css::uno::TypeClass_BYTE"); + case codemaker::UnoType::Sort::Short: + return cStyle + ? OUString("typelib_TypeClass_SHORT") + : OUString("::css::uno::TypeClass_SHORT"); + case codemaker::UnoType::Sort::UnsignedShort: + return cStyle + ? OUString("typelib_TypeClass_UNSIGNED_SHORT") + : OUString("::css::uno::TypeClass_UNSIGNED_SHORT"); + case codemaker::UnoType::Sort::Long: + return cStyle + ? OUString("typelib_TypeClass_LONG") + : OUString("::css::uno::TypeClass_LONG"); + case codemaker::UnoType::Sort::UnsignedLong: + return cStyle + ? OUString("typelib_TypeClass_UNSIGNED_LONG") + : OUString("::css::uno::TypeClass_UNSIGNED_LONG"); + case codemaker::UnoType::Sort::Hyper: + return cStyle + ? OUString("typelib_TypeClass_HYPER") + : OUString("::css::uno::TypeClass_HYPER"); + case codemaker::UnoType::Sort::UnsignedHyper: + return cStyle + ? OUString("typelib_TypeClass_UNSIGNED_HYPER") + : OUString("::css::uno::TypeClass_UNSIGNED_HYPER"); + case codemaker::UnoType::Sort::Float: + return cStyle + ? OUString("typelib_TypeClass_FLOAT") + : OUString("::css::uno::TypeClass_FLOAT"); + case codemaker::UnoType::Sort::Double: + return cStyle + ? OUString("typelib_TypeClass_DOUBLE") + : OUString("::css::uno::TypeClass_DOUBLE"); + case codemaker::UnoType::Sort::Char: + return cStyle + ? OUString("typelib_TypeClass_CHAR") + : OUString("::css::uno::TypeClass_CHAR"); + case codemaker::UnoType::Sort::String: + return cStyle + ? OUString("typelib_TypeClass_STRING") + : OUString("::css::uno::TypeClass_STRING"); + case codemaker::UnoType::Sort::Type: + return cStyle + ? OUString("typelib_TypeClass_TYPE") + : OUString("::css::uno::TypeClass_TYPE"); + case codemaker::UnoType::Sort::Any: + return cStyle + ? OUString("typelib_TypeClass_ANY") + : OUString("::css::uno::TypeClass_ANY"); + case codemaker::UnoType::Sort::Sequence: + return cStyle + ? OUString("typelib_TypeClass_SEQUENCE") + : OUString("::css::uno::TypeClass_SEQUENCE"); + case codemaker::UnoType::Sort::Enum: + return cStyle + ? OUString("typelib_TypeClass_ENUM") + : OUString("::css::uno::TypeClass_ENUM"); + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::PolymorphicStructTemplate: + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + return cStyle + ? OUString("typelib_TypeClass_STRUCT") + : OUString("::css::uno::TypeClass_STRUCT"); + case codemaker::UnoType::Sort::Exception: + return cStyle + ? OUString("typelib_TypeClass_EXCEPTION") + : OUString("::css::uno::TypeClass_EXCEPTION"); + case codemaker::UnoType::Sort::Interface: + return cStyle + ? OUString("typelib_TypeClass_INTERFACE") + : OUString("::css::uno::TypeClass_INTERFACE"); + case codemaker::UnoType::Sort::Typedef: + return getTypeClass(dynamic_cast<unoidl::TypedefEntity&>(*ent).getType(), cStyle); + default: + for (;;) { + std::abort(); + } + } +} + +void CppuType::dumpType( + FileStream & out, std::u16string_view name, bool isConst, bool isRef, + bool native, bool cppuUnoType) const +{ + sal_Int32 k; + std::vector< OString > args; + OUString n( + b2u(codemaker::UnoType::decompose( + u2b(resolveAllTypedefs(name)), &k, &args))); + if (isConst) { + out << "const "; + } + for (sal_Int32 i = 0; i != k; ++i) { + out << (cppuUnoType + ? "::cppu::UnoSequenceType" : "::css::uno::Sequence") + << "< "; + } + switch (m_typeMgr->getSort(n)) { + case codemaker::UnoType::Sort::Void: + out << "void"; + break; + case codemaker::UnoType::Sort::Boolean: + out << "::sal_Bool"; + break; + case codemaker::UnoType::Sort::Byte: + out << "::sal_Int8"; + break; + case codemaker::UnoType::Sort::Short: + out << "::sal_Int16"; + break; + case codemaker::UnoType::Sort::UnsignedShort: + out << (cppuUnoType ? "::cppu::UnoUnsignedShortType" : "::sal_uInt16"); + break; + case codemaker::UnoType::Sort::Long: + out << "::sal_Int32"; + break; + case codemaker::UnoType::Sort::UnsignedLong: + out << "::sal_uInt32"; + break; + case codemaker::UnoType::Sort::Hyper: + out << "::sal_Int64"; + break; + case codemaker::UnoType::Sort::UnsignedHyper: + out << "::sal_uInt64"; + break; + case codemaker::UnoType::Sort::Float: + out << "float"; + break; + case codemaker::UnoType::Sort::Double: + out << "double"; + break; + case codemaker::UnoType::Sort::Char: + out << (cppuUnoType ? "::cppu::UnoCharType" : "::sal_Unicode"); + break; + case codemaker::UnoType::Sort::String: + out << "::rtl::OUString"; + break; + case codemaker::UnoType::Sort::Type: + out << "::css::uno::Type"; + break; + case codemaker::UnoType::Sort::Any: + out << "::css::uno::Any"; + break; + case codemaker::UnoType::Sort::Enum: + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::Exception: + out << codemaker::cpp::scopedCppName(u2b(n)); + break; + case codemaker::UnoType::Sort::PolymorphicStructTemplate: + out << codemaker::cpp::scopedCppName(u2b(n)); + if (!args.empty()) { + out << "< "; + for (std::vector< OString >::iterator i(args.begin()); + i != args.end(); ++i) { + if (i != args.begin()) { + out << ", "; + } + dumpType(out, b2u(*i)); + } + out << " >"; + } + break; + case codemaker::UnoType::Sort::Interface: + if (!native) { + out << "::css::uno::Reference< "; + } + out << codemaker::cpp::scopedCppName(u2b(n)); + if (!native) { + out << " >"; + } + break; + default: + throw CannotDumpException( + OUString::Concat("unexpected entity \"") + name + "\" in call to CppuType::dumpType"); + } + for (sal_Int32 i = 0; i != k; ++i) { + out << " >"; + } + if (isRef) { + out << "&"; + } +} + +void CppuType::dumpCppuGetType( + FileStream & out, std::u16string_view name, OUString const * ownName) const +{ + //TODO: What are these calls good for? + OUString nucleus; + sal_Int32 rank; + codemaker::UnoType::Sort sort = m_typeMgr->decompose( + name, true, &nucleus, &rank, nullptr, nullptr); + switch (rank == 0 ? sort : codemaker::UnoType::Sort::Sequence) { + case codemaker::UnoType::Sort::Void: + case codemaker::UnoType::Sort::Boolean: + case codemaker::UnoType::Sort::Byte: + case codemaker::UnoType::Sort::Short: + case codemaker::UnoType::Sort::UnsignedShort: + case codemaker::UnoType::Sort::Long: + case codemaker::UnoType::Sort::UnsignedLong: + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + case codemaker::UnoType::Sort::Float: + case codemaker::UnoType::Sort::Double: + case codemaker::UnoType::Sort::Char: + case codemaker::UnoType::Sort::String: + case codemaker::UnoType::Sort::Type: + case codemaker::UnoType::Sort::Any: + break; + case codemaker::UnoType::Sort::Sequence: + case codemaker::UnoType::Sort::Enum: + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + case codemaker::UnoType::Sort::Exception: + case codemaker::UnoType::Sort::Interface: + // Take care of recursion like struct S { sequence<S> x; }: + if (ownName == nullptr || nucleus != *ownName) { + out << indent() << "::cppu::UnoType< "; + dumpType(out, name, false, false, false, true); + out << " >::get();\n"; + } + break; + case codemaker::UnoType::Sort::Typedef: + for (;;) std::abort(); // this cannot happen + default: + throw CannotDumpException( + OUString::Concat("unexpected entity \"") + name + + "\" in call to CppuType::dumpCppuGetType"); + } +} + +bool CppuType::passByReference(OUString const & name) const +{ + switch (m_typeMgr->getSort(resolveOuterTypedefs(name))) { + case codemaker::UnoType::Sort::Boolean: + case codemaker::UnoType::Sort::Byte: + case codemaker::UnoType::Sort::Short: + case codemaker::UnoType::Sort::UnsignedShort: + case codemaker::UnoType::Sort::Long: + case codemaker::UnoType::Sort::UnsignedLong: + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + case codemaker::UnoType::Sort::Float: + case codemaker::UnoType::Sort::Double: + case codemaker::UnoType::Sort::Char: + case codemaker::UnoType::Sort::Enum: + return false; + case codemaker::UnoType::Sort::String: + case codemaker::UnoType::Sort::Type: + case codemaker::UnoType::Sort::Any: + case codemaker::UnoType::Sort::Sequence: + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + case codemaker::UnoType::Sort::Interface: + return true; + default: + throw CannotDumpException( + "unexpected entity \"" + name + + "\" in call to CppuType::passByReference"); + } +} + +bool CppuType::canBeWarnUnused(OUString const & name) const +{ + return canBeWarnUnused(name, 0); +} +bool CppuType::canBeWarnUnused(OUString const & name, int depth) const +{ + // prevent infinite recursion and blowing the stack + if (depth > 10) + return false; + OUString aResolvedName = resolveOuterTypedefs(name); + switch (m_typeMgr->getSort(aResolvedName)) { + case codemaker::UnoType::Sort::Boolean: + case codemaker::UnoType::Sort::Byte: + case codemaker::UnoType::Sort::Short: + case codemaker::UnoType::Sort::UnsignedShort: + case codemaker::UnoType::Sort::Long: + case codemaker::UnoType::Sort::UnsignedLong: + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + case codemaker::UnoType::Sort::Float: + case codemaker::UnoType::Sort::Double: + case codemaker::UnoType::Sort::Char: + case codemaker::UnoType::Sort::Enum: + case codemaker::UnoType::Sort::String: + case codemaker::UnoType::Sort::Type: + return true; + case codemaker::UnoType::Sort::PlainStruct: { + rtl::Reference< unoidl::Entity > ent; + m_typeMgr->getSort(aResolvedName, &ent); + rtl::Reference< unoidl::PlainStructTypeEntity > ent2( + dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get())); + if (!ent2->getDirectBase().isEmpty() && !canBeWarnUnused(ent2->getDirectBase(), depth+1)) + return false; + for ( const unoidl::PlainStructTypeEntity::Member& rMember : ent2->getDirectMembers()) { + if (!canBeWarnUnused(rMember.type, depth+1)) + return false; + } + return true; + } + case codemaker::UnoType::Sort::Sequence: { + OUString aInnerType = aResolvedName.copy(2); + return canBeWarnUnused(aInnerType, depth+1); + } + case codemaker::UnoType::Sort::Any: + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + case codemaker::UnoType::Sort::Interface: + return false; + default: + throw CannotDumpException( + "unexpected entity \"" + name + + "\" in call to CppuType::canBeWarnUnused"); + } +} + +OUString CppuType::resolveOuterTypedefs(OUString const & name) const +{ + for (OUString n(name);;) { + rtl::Reference< unoidl::Entity > ent; + if (m_typeMgr->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) { + return n; + } + n = dynamic_cast<unoidl::TypedefEntity&>(*ent).getType(); + } +} + +OUString CppuType::resolveAllTypedefs(std::u16string_view name) const +{ + sal_Int32 k1; + OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k1))); + for (;;) { + rtl::Reference< unoidl::Entity > ent; + if (m_typeMgr->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) { + break; + } + sal_Int32 k2; + n = b2u(codemaker::UnoType::decompose( + u2b(dynamic_cast<unoidl::TypedefEntity&>(*ent).getType()), &k2)); + k1 += k2; //TODO: overflow + } + OUStringBuffer b(k1*2 + n.getLength()); + for (sal_Int32 i = 0; i != k1; ++i) { + b.append("[]"); + } + b.append(n); + return b.makeStringAndClear(); +} + +void CppuType::inc(sal_Int32 num) +{ + m_indentLength += num; +} + +void CppuType::dec(sal_Int32 num) +{ + m_indentLength = std::max< sal_Int32 >(m_indentLength - num, 0); +} + +OUString CppuType::indent() const +{ + OUStringBuffer buf(m_indentLength); + for (sal_Int32 i = 0; i != m_indentLength; ++i) { + buf.append(' '); + } + return buf.makeStringAndClear(); +} + +bool isDeprecated(std::vector< OUString > const & annotations) +{ + for (const OUString& r : annotations) { + if (r == "deprecated") { + return true; + } + } + return false; +} + +void dumpDeprecation(FileStream & out, bool deprecated) +{ + if (deprecated) { + out << "SAL_DEPRECATED_INTERNAL(\"marked @deprecated in UNOIDL\") "; + } +} + +class BaseOffset +{ +public: + BaseOffset( + rtl::Reference< TypeManager > manager, + rtl::Reference< unoidl::InterfaceTypeEntity > const & entity): + manager_(std::move(manager)), offset_(0) { + calculateBases(entity); + } + BaseOffset(const BaseOffset&) = delete; + const BaseOffset& operator=(const BaseOffset&) = delete; + + sal_Int32 get() const { + return offset_; + } + +private: + void calculateBases( + rtl::Reference< unoidl::InterfaceTypeEntity > const & entity); + + rtl::Reference< TypeManager > manager_; + std::set< OUString > set_; + sal_Int32 offset_; +}; + +void BaseOffset::calculateBases( + rtl::Reference< unoidl::InterfaceTypeEntity > const & entity) +{ + assert(entity.is()); + for (const unoidl::AnnotatedReference& ar : entity->getDirectMandatoryBases()) { + if (set_.insert(ar.name).second) { + rtl::Reference< unoidl::Entity > ent; + codemaker::UnoType::Sort sort = manager_->getSort(ar.name, &ent); + if (sort != codemaker::UnoType::Sort::Interface) { + throw CannotDumpException( + "interface type base " + ar.name + + " is not an interface type"); + } + rtl::Reference< unoidl::InterfaceTypeEntity > ent2( + dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get())); + assert(ent2.is()); + calculateBases(ent2); + offset_ += ent2->getDirectAttributes().size() + + ent2->getDirectMethods().size(); //TODO: overflow + } + } +} + +class InterfaceType: public CppuType +{ +public: + InterfaceType( + rtl::Reference< unoidl::InterfaceTypeEntity > const & entity, + OUString const & name, rtl::Reference< TypeManager > const & typeMgr); + + virtual void dumpDeclaration(FileStream& o) override; + void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override; + + void dumpAttributes(FileStream& o) const; + void dumpMethods(FileStream& o) const; + void dumpNormalGetCppuType(FileStream& o) override; + void dumpComprehensiveGetCppuType(FileStream& o) override; + void dumpCppuAttributeRefs(FileStream& o, sal_uInt32& index); + void dumpCppuMethodRefs(FileStream& o, sal_uInt32& index); + void dumpCppuAttributes(FileStream& o, sal_uInt32& index); + void dumpCppuMethods(FileStream& o, sal_uInt32& index); + void dumpAttributesCppuDecl(FileStream & out, std::set< OUString > * seen) const; + void dumpMethodsCppuDecl(FileStream & out, std::set< OUString > * seen) const; + +private: + virtual void addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + virtual sal_uInt32 checkInheritedMemberCount() const override { + return BaseOffset(m_typeMgr, entity_).get(); + } + + void dumpExceptionTypeName( + FileStream & out, std::u16string_view prefix, sal_uInt32 index, + std::u16string_view name) const; + + sal_Int32 dumpExceptionTypeNames( + FileStream & out, std::u16string_view prefix, + std::vector< OUString > const & exceptions, bool runtimeException) const; + + rtl::Reference< unoidl::InterfaceTypeEntity > entity_; + bool m_isDeprecated; +}; + +InterfaceType::InterfaceType( + rtl::Reference< unoidl::InterfaceTypeEntity > const & entity, + OUString const & name, rtl::Reference< TypeManager > const & typeMgr): + CppuType(name, typeMgr), entity_(entity), + m_isDeprecated(isDeprecated(entity->getAnnotations())) +{ + assert(entity.is()); +} + +void InterfaceType::dumpDeclaration(FileStream & out) +{ + out << "\nclass SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI " << id_; + for (std::vector< unoidl::AnnotatedReference >::const_iterator i( + entity_->getDirectMandatoryBases().begin()); + i != entity_->getDirectMandatoryBases().end(); ++i) { + out << (i == entity_->getDirectMandatoryBases().begin() ? " :" : ",") + << " public " << codemaker::cpp::scopedCppName(u2b(i->name)); + } + out << "\n{\npublic:\n"; + inc(); + out << "#if defined LIBO_INTERNAL_ONLY\n" + << indent() << id_ << "() = default;\n" + << indent() << id_ << "(" << id_ << " const &) = default;\n" + << indent() << id_ << "(" << id_ << " &&) = default;\n" + << indent() << id_ << " & operator =(" << id_ << " const &) = default;\n" + << indent() << id_ << " & operator =(" << id_ << " &&) = default;\n#endif\n\n"; + dumpAttributes(out); + dumpMethods(out); + out << "\n" << indent() + << ("static inline ::css::uno::Type const & SAL_CALL" + " static_type(void * = 0);\n\n"); + dec(); + out << "protected:\n"; + inc(); + out << indent() << "~" << id_ + << ("() SAL_NOEXCEPT {} // avoid warnings about virtual members and" + " non-virtual dtor\n"); + dec(); + out << "};\n\n"; +} + +void InterfaceType::dumpHppFile( + FileStream & out, codemaker::cppumaker::Includes & includes) +{ + OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + out << "\n"; + addDefaultHxxIncludes(includes); + includes.dump(out, &name_, !(m_cppuTypeLeak || m_cppuTypeDynamic)); + out << "\n"; + dumpGetCppuType(out); + out << "\n::css::uno::Type const & " + << codemaker::cpp::scopedCppName(u2b(name_)) + << "::static_type(SAL_UNUSED_PARAMETER void *) {\n"; + inc(); + out << indent() << "return ::cppu::UnoType< "; + dumpType(out, name_, false, false, true); + out << " >::get();\n"; + dec(); + out << "}\n\n#endif // "<< headerDefine << "\n"; +} + +void InterfaceType::dumpAttributes(FileStream & out) const +{ + if (!entity_->getDirectAttributes().empty()) { + out << "\n" << indent() << "// Attributes\n"; + } + for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) { + bool depr = m_isDeprecated || isDeprecated(attr.annotations); + out << indent(); + dumpDeprecation(out, depr); + out << "virtual "; + dumpType(out, attr.type); + out << " SAL_CALL get" << attr.name << "() = 0;\n"; + if (!attr.readOnly) { + bool byRef = passByReference(attr.type); + out << indent(); + dumpDeprecation(out, depr); + out << "virtual void SAL_CALL set" << attr.name << "( "; + dumpType(out, attr.type, byRef, byRef); + out << " _" << attr.name.toAsciiLowerCase() << " ) = 0;\n"; + } + } +} + +void InterfaceType::dumpMethods(FileStream & out) const +{ + if (!entity_->getDirectMethods().empty()) { + out << "\n" << indent() << "// Methods\n"; + } + for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) { + out << indent(); + dumpDeprecation(out, m_isDeprecated || isDeprecated(method.annotations)); + out << "virtual "; + dumpType(out, method.returnType); + out << " SAL_CALL " << method.name << "("; + if (!method.parameters.empty()) { + out << " "; + for (std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >:: + const_iterator j(method.parameters.begin()); + j != method.parameters.end();) { + bool isConst; + bool isRef; + if (j->direction + == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN) + { + isConst = passByReference(j->type); + isRef = isConst; + } else { + isConst = false; + isRef = true; + } + dumpType(out, j->type, isConst, isRef); + out << " " << j->name; + ++j; + if (j != method.parameters.end()) { + out << ", "; + } + } + out << " "; + } + out << ") = 0;\n"; + } +} + +void InterfaceType::dumpNormalGetCppuType(FileStream & out) +{ + dumpGetCppuTypePreamble(out); + out << indent() + << "static typelib_TypeDescriptionReference * the_type = 0;\n" + << indent() << "if ( !the_type )\n" << indent() << "{\n"; + inc(); + std::vector< unoidl::AnnotatedReference >::size_type bases( + entity_->getDirectMandatoryBases().size()); + if (bases == 1 + && (entity_->getDirectMandatoryBases()[0].name + == "com.sun.star.uno.XInterface")) { + bases = 0; + } + if (bases != 0) { + out << indent() << "typelib_TypeDescriptionReference * aSuperTypes[" + << entity_->getDirectMandatoryBases().size() << "];\n"; + std::vector< unoidl::AnnotatedReference >::size_type n = 0; + for (const unoidl::AnnotatedReference& ar : entity_->getDirectMandatoryBases()) { + out << indent() << "aSuperTypes[" << n++ << "] = ::cppu::UnoType< "; + dumpType(out, ar.name, true, false, false, true); + out << " >::get().getTypeLibType();\n"; + } + } + out << indent() << "typelib_static_mi_interface_type_init( &the_type, \"" + << name_ << "\", " << bases << ", " + << (bases == 0 ? "0" : "aSuperTypes") << " );\n"; + dec(); + out << indent() << "}\n" << indent() + << ("return * reinterpret_cast< ::css::uno::Type * >(" + " &the_type );\n"); + dumpGetCppuTypePostamble(out); +} + +void InterfaceType::dumpComprehensiveGetCppuType(FileStream & out) +{ + codemaker::cppumaker::dumpNamespaceOpen(out, name_, false); + OUString staticTypeClass("the" + id_ + "Type"); + out << " namespace detail {\n\n" << indent() << "struct " << staticTypeClass + << " : public rtl::StaticWithInit< ::css::uno::Type *, " + << staticTypeClass << " >\n" << indent() << "{\n"; + inc(); + out << indent() << "::css::uno::Type * operator()() const\n" + << indent() << "{\n"; + inc(); + out << indent() << "::rtl::OUString sTypeName( \"" << name_ << "\" );\n\n" + << indent() << "// Start inline typedescription generation\n" + << indent() << "typelib_InterfaceTypeDescription * pTD = 0;\n\n"; + out << indent() << "typelib_TypeDescriptionReference * aSuperTypes[" + << entity_->getDirectMandatoryBases().size() << "];\n"; + std::vector< unoidl::AnnotatedReference >::size_type n = 0; + for (const unoidl::AnnotatedReference& ar : entity_->getDirectMandatoryBases()) { + out << indent() << "aSuperTypes[" << n++ << "] = ::cppu::UnoType< "; + dumpType(out, ar.name, false, false, false, true); + out << " >::get().getTypeLibType();\n"; + } + std::size_t count = entity_->getDirectAttributes().size() + + entity_->getDirectMethods().size(); //TODO: overflow + if (count != 0) { + out << indent() << "typelib_TypeDescriptionReference * pMembers[" + << count << "] = { "; + for (std::size_t i = 0; i != count; ++i) { + out << "0"; + if (i + 1 != count) { + out << ","; + } + } + out << " };\n"; + sal_uInt32 index = 0; + dumpCppuAttributeRefs(out, index); + dumpCppuMethodRefs(out, index); + } + out << "\n" << indent() << "typelib_typedescription_newMIInterface(\n"; + inc(); + out << indent() << "&pTD,\n" << indent() + << "sTypeName.pData, 0, 0, 0, 0, 0,\n" << indent() + << entity_->getDirectMandatoryBases().size() << ", aSuperTypes,\n" + << indent() << count << ",\n" << indent() + << (count == 0 ? "0" : "pMembers") << " );\n\n"; + dec(); + out << indent() + << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD" + " );\n"); + for (std::size_t i = 0; i != count; ++i) { + out << indent() << "typelib_typedescriptionreference_release( pMembers[" + << i << "] );\n"; + } + out << indent() + << ("typelib_typedescription_release( (typelib_TypeDescription*)pTD" + " );\n\n") + << indent() << "return new ::css::uno::Type( " + << getTypeClass(name_) << ", sTypeName ); // leaked\n"; + dec(); + out << indent() << "}\n"; + dec(); + out << indent() << "};\n\n"; + codemaker::cppumaker::dumpNamespaceClose(out, name_, false); + out << " }\n\n"; + dumpGetCppuTypePreamble(out); + out << indent() << "const ::css::uno::Type &rRet = *detail::" + << staticTypeClass << "::get();\n" << indent() + << "// End inline typedescription generation\n" << indent() + << "static bool bInitStarted = false;\n" << indent() + << "if (!bInitStarted)\n" << indent() << "{\n"; + inc(); + out << indent() + << "::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );\n" + << indent() << "if (!bInitStarted)\n" << indent() << "{\n"; + inc(); + out << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n" + << indent() << "bInitStarted = true;\n"; + std::set< OUString > seen; + // Type for RuntimeException is always needed: + seen.insert("com.sun.star.uno.RuntimeException"); + dumpCppuGetType(out, u"com.sun.star.uno.RuntimeException"); + dumpAttributesCppuDecl(out, &seen); + dumpMethodsCppuDecl(out, &seen); + if (count != 0) { + sal_uInt32 index = getInheritedMemberCount(); + dumpCppuAttributes(out, index); + dumpCppuMethods(out, index); + } + dec(); + out << indent() << "}\n"; + dec(); + out << indent() << "}\n" << indent() << "else\n" << indent() << "{\n"; + inc(); + out << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n"; + dec(); + out << indent() << "}\n" << indent() << "return rRet;\n"; + dumpGetCppuTypePostamble(out); +} + +void InterfaceType::dumpCppuAttributeRefs(FileStream & out, sal_uInt32 & index) +{ + std::vector< unoidl::InterfaceTypeEntity::Attribute >::size_type n = 0; + for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) { + out << indent() << "::rtl::OUString sAttributeName" << n << "( \"" + << name_ << "::" << attr.name << "\" );\n" << indent() + << "typelib_typedescriptionreference_new( &pMembers[" << index++ + << "],\n"; + inc(38); + out << indent() + << "(typelib_TypeClass)::css::uno::TypeClass_INTERFACE_ATTRIBUTE,\n" + << indent() << "sAttributeName" << n << ".pData );\n"; + dec(38); + ++n; + } +} + +void InterfaceType::dumpCppuMethodRefs(FileStream & out, sal_uInt32 & index) +{ + std::vector< unoidl::InterfaceTypeEntity::Method >::size_type n = 0; + for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) { + out << indent() << "::rtl::OUString sMethodName" << n << "( \"" << name_ + << "::" << method.name << "\" );\n" << indent() + << "typelib_typedescriptionreference_new( &pMembers[" << index++ + << "],\n"; + inc(38); + out << indent() + << "(typelib_TypeClass)::css::uno::TypeClass_INTERFACE_METHOD,\n" + << indent() << "sMethodName" << n << ".pData );\n"; + dec(38); + ++n; + } +} + +void InterfaceType::addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + // The comprehensive getCppuType method always includes a line + // "getCppuType( (const ::css::uno::RuntimeException*)0 );": + includes.addCppuUnotypeHxx(); + includes.addRtlInstanceHxx(); // using rtl::StaticWithInit + includes.addOslMutexHxx(); + includes.add("com.sun.star.uno.RuntimeException"); +} + +void InterfaceType::dumpCppuAttributes(FileStream & out, sal_uInt32 & index) +{ + if (entity_->getDirectAttributes().empty()) + return; + + out << "\n" << indent() + << "typelib_InterfaceAttributeTypeDescription * pAttribute = 0;\n"; + std::vector< unoidl::InterfaceTypeEntity::Attribute >::size_type n = 0; + for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) { + OUString type(resolveAllTypedefs(attr.type)); + out << indent() << "{\n"; + inc(); + out << indent() << "::rtl::OUString sAttributeType" << n << "( \"" + << type << "\" );\n" << indent() + << "::rtl::OUString sAttributeName" << n << "( \"" << name_ + << "::" << attr.name << "\" );\n"; + sal_Int32 getExcn = dumpExceptionTypeNames( + out, u"get", attr.getExceptions, false); + sal_Int32 setExcn = dumpExceptionTypeNames( + out, u"set", attr.setExceptions, false); + out << indent() + << ("typelib_typedescription_newExtendedInterfaceAttribute(" + " &pAttribute,\n"); + inc(); + out << indent() << index++ << ", sAttributeName" << n + << ".pData,\n" << indent() << "(typelib_TypeClass)" + << getTypeClass(type) << ", sAttributeType" << n << ".pData,\n" + << indent() << "sal_" << (attr.readOnly ? "True" : "False") + << ", " << getExcn << ", " + << (getExcn == 0 ? "0" : "the_getExceptions") << ", " << setExcn + << ", " << (setExcn == 0 ? "0" : "the_setExceptions") + << " );\n"; + dec(); + out << indent() + << ("typelib_typedescription_register(" + " (typelib_TypeDescription**)&pAttribute );\n"); + dec(); + out << indent() << "}\n"; + ++n; + } + out << indent() + << ("typelib_typedescription_release(" + " (typelib_TypeDescription*)pAttribute );\n"); +} + +void InterfaceType::dumpCppuMethods(FileStream & out, sal_uInt32 & index) +{ + if (entity_->getDirectMethods().empty()) + return; + + out << "\n" << indent() + << "typelib_InterfaceMethodTypeDescription * pMethod = 0;\n"; + std::vector< unoidl::InterfaceTypeEntity::Method >::size_type n = 0; + for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) { + OUString returnType(resolveAllTypedefs(method.returnType)); + out << indent() << "{\n"; + inc(); + if (!method.parameters.empty()) { + out << indent() << "typelib_Parameter_Init aParameters[" + << method.parameters.size() << "];\n"; + } + std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >:: + size_type m = 0; + for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters) { + OUString type(resolveAllTypedefs(param.type)); + out << indent() << "::rtl::OUString sParamName" << m << "( \"" + << param.name << "\" );\n" << indent() + << "::rtl::OUString sParamType" << m << "( \"" << type + << "\" );\n" << indent() << "aParameters[" << m + << "].pParamName = sParamName" << m << ".pData;\n" + << indent() << "aParameters[" << m + << "].eTypeClass = (typelib_TypeClass)" + << getTypeClass(type) << ";\n" << indent() << "aParameters[" + << m << "].pTypeName = sParamType" << m << ".pData;\n" + << indent() << "aParameters[" << m << "].bIn = " + << ((param.direction + == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT) + ? "sal_False" : "sal_True") + << ";\n" << indent() << "aParameters[" << m << "].bOut = " + << ((param.direction + == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN) + ? "sal_False" : "sal_True") + << ";\n"; + ++m; + } + sal_Int32 excn = dumpExceptionTypeNames( + out, u"", method.exceptions, + method.name != "acquire" && method.name != "release"); + out << indent() << "::rtl::OUString sReturnType" << n << "( \"" + << returnType << "\" );\n" << indent() + << "::rtl::OUString sMethodName" << n << "( \"" << name_ << "::" + << method.name << "\" );\n" << indent() + << "typelib_typedescription_newInterfaceMethod( &pMethod,\n"; + inc(); + out << indent() << index++ << ", sal_False,\n" << indent() + << "sMethodName" << n << ".pData,\n" << indent() + << "(typelib_TypeClass)" << getTypeClass(returnType) + << ", sReturnType" << n << ".pData,\n" << indent() + << method.parameters.size() << ", " + << (method.parameters.empty() ? "0" : "aParameters") << ",\n" + << indent() << excn << ", " + << (excn == 0 ? "0" : "the_Exceptions") << " );\n"; + dec(); + out << indent() + << ("typelib_typedescription_register(" + " (typelib_TypeDescription**)&pMethod );\n"); + dec(); + out << indent() << "}\n"; + ++n; + } + out << indent() + << ("typelib_typedescription_release(" + " (typelib_TypeDescription*)pMethod );\n"); +} + +void InterfaceType::dumpAttributesCppuDecl( + FileStream & out, std::set< OUString > * seen) const +{ + assert(seen != nullptr); + for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) { + if (seen->insert(attr.type).second) { + dumpCppuGetType(out, attr.type); + } + for (const OUString& exc : attr.getExceptions) { + if (seen->insert(exc).second) { + dumpCppuGetType(out, exc); + } + } + for (const OUString& exc : attr.setExceptions) { + if (seen->insert(exc).second) { + dumpCppuGetType(out, exc); + } + } + } +} + +void InterfaceType::dumpMethodsCppuDecl( + FileStream & out, std::set< OUString > * seen) const +{ + assert(seen != nullptr); + for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) { + for (const OUString& ex : method.exceptions) { + if (seen->insert(ex).second) { + dumpCppuGetType(out, ex); + } + } + } +} + +void InterfaceType::dumpExceptionTypeName( + FileStream & out, std::u16string_view prefix, sal_uInt32 index, + std::u16string_view name) const +{ + out << indent() << "::rtl::OUString the_" << prefix << "ExceptionName" + << index << "( \"" << name << "\" );\n"; +} + +sal_Int32 InterfaceType::dumpExceptionTypeNames( + FileStream & out, std::u16string_view prefix, + std::vector< OUString > const & exceptions, bool runtimeException) const +{ + sal_Int32 count = 0; + for (const OUString& ex : exceptions) { + if (ex != "com.sun.star.uno.RuntimeException") { + dumpExceptionTypeName(out, prefix, count++, ex); + } + } + if (runtimeException) { + dumpExceptionTypeName( + out, prefix, count++, u"com.sun.star.uno.RuntimeException"); + } + if (count != 0) { + out << indent() << "rtl_uString * the_" << prefix << "Exceptions[] = {"; + for (sal_Int32 i = 0; i != count; ++i) { + out << (i == 0 ? " " : ", ") << "the_" << prefix << "ExceptionName" + << i << ".pData"; + } + out << " };\n"; + } + return count; +} + +class ConstantGroup: public CppuType +{ +public: + ConstantGroup( + rtl::Reference< unoidl::ConstantGroupEntity > const & entity, + OUString const & name, rtl::Reference< TypeManager > const & typeMgr): + CppuType(name, typeMgr), entity_(entity) { + assert(entity.is()); + } + + bool hasConstants() const { + return !entity_->getMembers().empty(); + } + +private: + virtual void dumpHdlFile( + FileStream & out, codemaker::cppumaker::Includes & includes) override; + + virtual void dumpHppFile( + FileStream & out, codemaker::cppumaker::Includes & includes) override; + + virtual void dumpDeclaration(FileStream & out) override; + + rtl::Reference< unoidl::ConstantGroupEntity > entity_; +}; + +void ConstantGroup::dumpHdlFile( + FileStream & out, codemaker::cppumaker::Includes & includes) +{ + OUString headerDefine(dumpHeaderDefine(out, u"HDL")); + out << "\n"; + addDefaultHIncludes(includes); + includes.dump(out, nullptr, true); + out << "\n"; + if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, true)) { + out << "\n"; + } + out << "\n"; + dumpDeclaration(out); + out << "\n"; + if (codemaker::cppumaker::dumpNamespaceClose(out, name_, true)) { + out << "\n"; + } + out << "\n#endif // "<< headerDefine << "\n"; +} + +void ConstantGroup::dumpHppFile( + FileStream & out, codemaker::cppumaker::Includes &) +{ + OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + out << "\n"; + codemaker::cppumaker::Includes::dumpInclude(out, u2b(name_), false); + out << "\n#endif // "<< headerDefine << "\n"; +} + +void ConstantGroup::dumpDeclaration(FileStream & out) +{ + for (const unoidl::ConstantGroupEntity::Member& member : entity_->getMembers()) { + out << "static const "; + switch (member.value.type) { + case unoidl::ConstantValue::TYPE_BOOLEAN: + out << "::sal_Bool"; + break; + case unoidl::ConstantValue::TYPE_BYTE: + out << "::sal_Int8"; + break; + case unoidl::ConstantValue::TYPE_SHORT: + out << "::sal_Int16"; + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT: + out << "::sal_uInt16"; + break; + case unoidl::ConstantValue::TYPE_LONG: + out << "::sal_Int32"; + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_LONG: + out << "::sal_uInt32"; + break; + case unoidl::ConstantValue::TYPE_HYPER: + out << "::sal_Int64"; + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER: + out << "::sal_uInt64"; + break; + case unoidl::ConstantValue::TYPE_FLOAT: + out << "float"; + break; + case unoidl::ConstantValue::TYPE_DOUBLE: + out << "double"; + break; + } + out << " " << member.name << " = "; + switch (member.value.type) { + case unoidl::ConstantValue::TYPE_BOOLEAN: + out << (member.value.booleanValue ? "sal_True" : "sal_False"); + break; + case unoidl::ConstantValue::TYPE_BYTE: + out << "(sal_Int8)" << OUString::number(member.value.byteValue); + break; + case unoidl::ConstantValue::TYPE_SHORT: + out << "(sal_Int16)" << OUString::number(member.value.shortValue); + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT: + out << "(sal_uInt16)" + << OUString::number(member.value.unsignedShortValue); + break; + case unoidl::ConstantValue::TYPE_LONG: + // Avoid C++ compiler warnings about (un)signedness of literal + // -2^31: + if (member.value.longValue == SAL_MIN_INT32) { + out << "SAL_MIN_INT32"; + } else { + out << "(sal_Int32)" << OUString::number(member.value.longValue); + } + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_LONG: + out << "(sal_uInt32)" + << OUString::number(member.value.unsignedLongValue) << "U"; + break; + case unoidl::ConstantValue::TYPE_HYPER: + // Avoid C++ compiler warnings about (un)signedness of literal + // -2^63: + if (member.value.hyperValue == SAL_MIN_INT64) { + out << "SAL_MIN_INT64"; + } else { + out << "(sal_Int64) SAL_CONST_INT64(" + << OUString::number(member.value.hyperValue) << ")"; + } + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER: + out << "SAL_CONST_UINT64(" + << OUString::number(member.value.unsignedHyperValue) << ")"; + break; + case unoidl::ConstantValue::TYPE_FLOAT: + out << "(float)" << OUString::number(member.value.floatValue); + break; + case unoidl::ConstantValue::TYPE_DOUBLE: + out << "(double)" << OUString::number(member.value.doubleValue); + break; + } + out << ";\n"; + } +} + +void dumpTypeParameterName(FileStream & out, std::u16string_view name) +{ + // Prefix all type parameters with "typeparam_" to avoid problems when a + // struct member has the same name as a type parameter, as in + // struct<T> { T T; }; + out << "typeparam_" << name; +} + +class PlainStructType: public CppuType +{ +public: + PlainStructType( + rtl::Reference< unoidl::PlainStructTypeEntity > const & entity, + OUString const & name, rtl::Reference< TypeManager > const & typeMgr): + CppuType(name, typeMgr), entity_(entity) { + assert(entity.is()); + } + +private: + virtual sal_uInt32 checkInheritedMemberCount() const override { + return getTotalMemberCount(entity_->getDirectBase()); + } + + virtual void dumpDeclaration(FileStream& o) override; + + void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override; + + virtual void dumpLightGetCppuType(FileStream & out) override; + + virtual void dumpNormalGetCppuType(FileStream & out) override; + + virtual void dumpComprehensiveGetCppuType(FileStream & out) override; + + virtual void addLightGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + virtual void addNormalGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + virtual void addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + bool dumpBaseMembers( + FileStream & out, OUString const & base, bool withType); + + sal_uInt32 getTotalMemberCount(OUString const & base) const; + + rtl::Reference< unoidl::PlainStructTypeEntity > entity_; +}; + +void PlainStructType::dumpDeclaration(FileStream & out) +{ + out << "\n#ifdef _WIN32\n# pragma pack(push, 8)\n#endif\n\n" << indent(); + out << "struct SAL_DLLPUBLIC_RTTI "; + if (canBeWarnUnused(name_)) + out << "SAL_WARN_UNUSED "; + out << id_; + OUString base(entity_->getDirectBase()); + if (!base.isEmpty()) { + out << ": public " << codemaker::cpp::scopedCppName(u2b(base)); + } + out << " {\n"; + inc(); + out << indent() << "inline " << id_ << "();\n"; + if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) { + out << "\n" << indent() << "inline " << id_ << "("; + bool bFirst = !dumpBaseMembers(out, base, true); + for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) { + if (!bFirst) { + out << ", "; + } + dumpType(out, member.type, true, true); + out << " " << member.name << "_"; + bFirst = false; + } + out << ");\n"; + } + if (!entity_->getDirectMembers().empty()) { + out << "\n"; + for (std::vector< unoidl::PlainStructTypeEntity::Member >:: + const_iterator i(entity_->getDirectMembers().begin()); + i != entity_->getDirectMembers().end(); ++i) { + out << indent(); + dumpType(out, i->type); + out << " " << i->name; + if (i == entity_->getDirectMembers().begin() && !base.isEmpty() + && i->type != "hyper" && i->type != "unsigned hyper" + && i->type != "double") { + out << " CPPU_GCC3_ALIGN(" + << codemaker::cpp::scopedCppName(u2b(base)) << ")"; + } + out << ";\n"; + } + } + dec(); + out << "};\n\n#ifdef _WIN32\n# pragma pack(pop)\n#endif\n\n"; +} + +void PlainStructType::dumpHppFile( + FileStream & out, codemaker::cppumaker::Includes & includes) +{ + OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + out << "\n"; + includes.dump(out, &name_, true); + out << "\n"; + if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) { + out << "\n"; + } + out << "\ninline " << id_ << "::" << id_ << "()\n"; + inc(); + OUString base(entity_->getDirectBase()); + bool bFirst = true; + if (!base.isEmpty()) { + out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base)) + << "()\n"; + bFirst = false; + } + for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) { + out << indent() << (bFirst ? ":" : ",") << " " << member.name; + dumpInitializer(out, false, member.type); + out << "\n"; + bFirst = false; + } + dec(); + out << "{\n}\n\n"; + if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) { + out << "inline " << id_; + out << "::" << id_ << "("; + bFirst = !dumpBaseMembers(out, base, true); + for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) { + if (!bFirst) { + out << ", "; + } + dumpType(out, member.type, true, true); + out << " " << member.name << "_"; + bFirst = false; + } + out << ")\n"; + inc(); + bFirst = true; + if (!base.isEmpty()) { + out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base)) + << "("; + dumpBaseMembers(out, base, false); + out << ")\n"; + bFirst = false; + } + for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) { + out << indent() << (bFirst ? ":" : ",") << " " << member.name << "(" + << member.name << "_)\n"; + bFirst = false; + } + dec(); + out << "{\n}\n\n"; + } + // print the operator== + out << "\ninline bool operator==(const " << id_ << "& the_lhs, const " << id_ << "& the_rhs)\n"; + out << "{\n"; + inc(); + out << indent() << "return "; + bFirst = true; + if (!base.isEmpty()) { + out << "operator==( static_cast< " << codemaker::cpp::scopedCppName(u2b(base)) + << ">(the_lhs), static_cast< " << codemaker::cpp::scopedCppName(u2b(base)) << ">(the_rhs) )\n"; + bFirst = false; + } + for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) { + if (!bFirst) + out << "\n" << indent() << indent() << "&& "; + out << "the_lhs." << member.name << " == the_rhs." << member.name; + bFirst = false; + } + out << ";\n"; + dec(); + out << "}\n"; + // print the operator!= + out << "\ninline bool operator!=(const " << id_ << "& the_lhs, const " << id_ << "& the_rhs)\n"; + out << "{\n"; + out << indent() << "return !operator==(the_lhs, the_rhs);\n"; + out << "}\n"; + // close namespace + if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) { + out << "\n"; + } + out << "\n"; + dumpGetCppuType(out); + out << "\n#endif // "<< headerDefine << "\n"; +} + +void PlainStructType::dumpLightGetCppuType(FileStream & out) +{ + dumpGetCppuTypePreamble(out); + out << indent() + << ("//TODO: On certain platforms with weak memory models, the" + " following code can result in some threads observing that the_type" + " points to garbage\n") + << indent() + << "static ::typelib_TypeDescriptionReference * the_type = 0;\n" + << indent() << "if (the_type == 0) {\n"; + inc(); + out << indent() << "::typelib_static_type_init(&the_type, " + << getTypeClass(name_, true) << ", \"" << name_ << "\");\n"; + dec(); + out << indent() << "}\n" << indent() + << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n"; + dumpGetCppuTypePostamble(out); +} + +void PlainStructType::dumpNormalGetCppuType(FileStream & out) +{ + dumpGetCppuTypePreamble(out); + out << indent() + << ("//TODO: On certain platforms with weak memory models, the" + " following code can result in some threads observing that the_type" + " points to garbage\n") + << indent() + << "static ::typelib_TypeDescriptionReference * the_type = 0;\n" + << indent() << "if (the_type == 0) {\n"; + inc(); + out << indent() + << "::typelib_TypeDescriptionReference * the_members[] = {\n"; + inc(); + for (std::vector< unoidl::PlainStructTypeEntity::Member >::const_iterator i( + entity_->getDirectMembers().begin()); + i != entity_->getDirectMembers().end();) { + out << indent() << "::cppu::UnoType< "; + dumpType(out, i->type, false, false, false, true); + ++i; + out << " >::get().getTypeLibType()" + << (i == entity_->getDirectMembers().end() ? " };" : ",") << "\n"; + } + dec(); + out << indent() << "::typelib_static_struct_type_init(&the_type, \"" + << name_ << "\", "; + if (entity_->getDirectBase().isEmpty()) { + out << "0"; + } else { + out << "::cppu::UnoType< "; + dumpType(out, entity_->getDirectBase(), false, false, false, true); + out << " >::get().getTypeLibType()"; + } + out << ", " << entity_->getDirectMembers().size() << ", the_members, 0);\n"; + dec(); + out << indent() << "}\n" << indent() + << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n"; + dumpGetCppuTypePostamble(out); +} + +void PlainStructType::dumpComprehensiveGetCppuType(FileStream & out) +{ + OUString staticTypeClass("the" + id_ + "Type"); + codemaker::cppumaker::dumpNamespaceOpen(out, name_, false); + out << " namespace detail {\n\n" << indent() << "struct " + << staticTypeClass + << " : public rtl::StaticWithInit< ::css::uno::Type *, " + << staticTypeClass << " >\n" << indent() << "{\n"; + inc(); + out << indent() << "::css::uno::Type * operator()() const\n" + << indent() << "{\n"; + inc(); + out << indent() << "::rtl::OUString the_name( \"" << name_ << "\" );\n"; + std::map< OUString, sal_uInt32 > types; + std::vector< unoidl::PlainStructTypeEntity::Member >::size_type n = 0; + for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) { + if (types.emplace( + member.type, static_cast< sal_uInt32 >(types.size())). + second) { + dumpCppuGetType(out, member.type, &name_); + // For typedefs, use the resolved type name, as there will be no + // information available about the typedef itself at runtime (the + // above getCppuType call will make available information about the + // resolved type); no extra #include for the resolved type is + // needed, as the header for the typedef includes it already: + out << indent() << "::rtl::OUString the_tname" + << static_cast< sal_uInt32 >(types.size() - 1) << "( \"" + << resolveAllTypedefs(member.type) << "\" );\n"; + } + out << indent() << "::rtl::OUString the_name" << n++ << "( \"" + << member.name << "\" );\n"; + } + out << indent() << "::typelib_StructMember_Init the_members[] = {\n"; + inc(); + n = 0; + for (std::vector< unoidl::PlainStructTypeEntity::Member >::const_iterator i( + entity_->getDirectMembers().begin()); + i != entity_->getDirectMembers().end();) { + out << indent() << "{ { " << getTypeClass(i->type, true) + << ", the_tname" << types.find(i->type)->second + << ".pData, the_name" << n++ << ".pData }, false }"; + ++i; + out << (i == entity_->getDirectMembers().end() ? " };" : ",") << "\n"; + } + dec(); + out << indent() << "::typelib_TypeDescription * the_newType = 0;\n" + << indent() + << "::typelib_typedescription_newStruct(&the_newType, the_name.pData, "; + if (entity_->getDirectBase().isEmpty()) { + out << "0"; + } else { + out << "::cppu::UnoType< "; + dumpType(out, entity_->getDirectBase(), false, false, false, true); + out << " >::get().getTypeLibType()"; + } + out << ", " << entity_->getDirectMembers().size() << ", the_members);\n" + << indent() << "::typelib_typedescription_register(&the_newType);\n" + << indent() << "::typelib_typedescription_release(the_newType);\n" + << indent() << "return new ::css::uno::Type(" + << getTypeClass(name_) << ", the_name); // leaked\n"; + dec(); + out << indent() << "}\n"; + dec(); + out << indent() << "};\n"; + codemaker::cppumaker::dumpNamespaceClose(out, name_, false); + out << " }\n\n"; + dumpGetCppuTypePreamble(out); + out << indent() << "return *detail::" << staticTypeClass << "::get();\n"; + dumpGetCppuTypePostamble(out); +} + +bool PlainStructType::dumpBaseMembers( + FileStream & out, OUString const & base, bool withType) +{ + if (base.isEmpty()) + return false; + + rtl::Reference< unoidl::Entity > ent; + codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent); + if (sort != codemaker::UnoType::Sort::PlainStruct) { + throw CannotDumpException( + "plain struct type base " + base + + " is not a plain struct type"); + } + rtl::Reference< unoidl::PlainStructTypeEntity > ent2( + dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get())); + assert(ent2.is()); + if (!ent2.is()) { + return false; + } + bool hasMember = dumpBaseMembers(out, ent2->getDirectBase(), withType); + for (const unoidl::PlainStructTypeEntity::Member& member : ent2->getDirectMembers()) { + if (hasMember) { + out << ", "; + } + if (withType) { + dumpType(out, member.type, true, true); + out << " "; + } + out << member.name << "_"; + hasMember = true; + } + return hasMember; +} + +void PlainStructType::addLightGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + includes.addType(); + includes.addCppuUnotypeHxx(); + includes.addSalTypesH(); + includes.addTypelibTypeclassH(); + includes.addTypelibTypedescriptionH(); +} + +void PlainStructType::addNormalGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + includes.addType(); + includes.addCppuUnotypeHxx(); + includes.addSalTypesH(); + includes.addTypelibTypeclassH(); + includes.addTypelibTypedescriptionH(); +} + +void PlainStructType::addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + includes.addType(); + includes.addCppuUnotypeHxx(); + includes.addRtlInstanceHxx(); + includes.addRtlUstringH(); + includes.addRtlUstringHxx(); + includes.addSalTypesH(); + includes.addTypelibTypeclassH(); + includes.addTypelibTypedescriptionH(); +} + +sal_uInt32 PlainStructType::getTotalMemberCount(OUString const & base) const +{ + if (base.isEmpty()) { + return 0; + } + rtl::Reference< unoidl::Entity > ent; + codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent); + if (sort != codemaker::UnoType::Sort::PlainStruct) { + throw CannotDumpException( + "plain struct type base " + base + " is not a plain struct type"); + } + rtl::Reference< unoidl::PlainStructTypeEntity > ent2( + dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get())); + assert(ent2.is()); + if (!ent2.is()) { + return 0; + } + return getTotalMemberCount(ent2->getDirectBase()) + + ent2->getDirectMembers().size(); //TODO: overflow +} + +class PolyStructType: public CppuType +{ +public: + PolyStructType( + rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const & + entity, + OUString const & name, rtl::Reference< TypeManager > const & typeMgr): + CppuType(name, typeMgr), entity_(entity) { + assert(entity.is()); + } + +private: + virtual void dumpDeclaration(FileStream& o) override; + + void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override; + + virtual void dumpLightGetCppuType(FileStream & out) override; + + virtual void dumpNormalGetCppuType(FileStream & out) override; + + virtual void dumpComprehensiveGetCppuType(FileStream & out) override; + + virtual void addLightGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + virtual void addNormalGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + virtual void addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + virtual bool isPolymorphic() const override { + return true; + } + + virtual void dumpTemplateHead(FileStream & out) const override; + + virtual void dumpTemplateParameters(FileStream & out) const override; + + rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > entity_; +}; + +void PolyStructType::dumpDeclaration(FileStream & out) +{ + out << "\n#ifdef _WIN32\n# pragma pack(push, 8)\n#endif\n\n" << indent(); + dumpTemplateHead(out); + out << "struct SAL_DLLPUBLIC_RTTI " << id_ << " {\n"; + inc(); + out << indent() << "inline " << id_ << "();\n"; + if (!entity_->getMembers().empty()) { + out << "\n" << indent() << "inline " << id_ << "("; + for (std::vector< + unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end(); ++i) { + if (i != entity_->getMembers().begin()) { + out << ", "; + } + if (i->parameterized) { + dumpTypeParameterName(out, i->type); + out << " const &"; + } else { + dumpType(out, i->type, true, true); + } + out << " " << i->name << "_"; + } + out << ");\n\n"; + // print the member fields + for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : + entity_->getMembers()) { + out << indent(); + if (member.parameterized) { + dumpTypeParameterName(out, member.type); + } else { + dumpType(out, member.type); + } + out << " " << member.name << ";\n"; + } + } + dec(); + out << "};\n\n#ifdef _WIN32\n# pragma pack(pop)\n#endif\n\n"; +} + +void PolyStructType::dumpHppFile( + FileStream & out, codemaker::cppumaker::Includes & includes) +{ + OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + out << "\n"; + includes.dump(out, &name_, true); + out << "\n"; + if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) { + out << "\n"; + } + out << "\n"; + // dump default (no-arg) constructor + dumpTemplateHead(out); + out << "inline " << id_; + dumpTemplateParameters(out); + out << "::" << id_ << "()\n"; + inc(); + for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end(); ++i) { + out << indent() << (i == entity_->getMembers().begin() ? ":" : ",") + << " " << i->name; + dumpInitializer(out, i->parameterized, i->type); + out << "\n"; + } + dec(); + out << "{\n}\n\n"; + if (!entity_->getMembers().empty()) { + // dump takes-all-fields constructor + dumpTemplateHead(out); + out << "inline " << id_; + dumpTemplateParameters(out); + out << "::" << id_ << "("; + for (std::vector< + unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end(); ++i) { + if (i != entity_->getMembers().begin()) { + out << ", "; + } + if (i->parameterized) { + dumpTypeParameterName(out, i->type); + out << " const &"; + } else { + dumpType(out, i->type, true, true); + } + out << " " << i->name << "_"; + } + out << ")\n"; + inc(); + for (std::vector< + unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end(); ++i) { + out << indent() << (i == entity_->getMembers().begin() ? ":" : ",") + << " " << i->name << "(" << i->name << "_)\n"; + } + dec(); + out << "{\n}\n\n" << indent(); + // dump make_T method + dumpTemplateHead(out); + out << "\n" << indent() << "inline " << id_; + dumpTemplateParameters(out); + out << "\n" << indent() << "make_" << id_ << "("; + for (std::vector< + unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end(); ++i) { + if (i != entity_->getMembers().begin()) { + out << ", "; + } + if (i->parameterized) { + dumpTypeParameterName(out, i->type); + out << " const &"; + } else { + dumpType(out, i->type, true, true); + } + out << " " << i->name << "_"; + } + out << ")\n" << indent() << "{\n"; + inc(); + out << indent() << "return " << id_; + dumpTemplateParameters(out); + out << "("; + for (std::vector< + unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end(); ++i) { + if (i != entity_->getMembers().begin()) { + out << ", "; + } + out << i->name << "_"; + } + out << ");\n"; + dec(); + out << indent() << "}\n\n"; + } + // print the operator== + dumpTemplateHead(out); + out << " inline bool operator==(const " << id_; + dumpTemplateParameters(out); + out << "& the_lhs, const " << id_; + dumpTemplateParameters(out); + out << "& the_rhs)\n"; + out << "{\n"; + inc(); + out << indent() << "return "; + bool bFirst = true; + for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity_->getMembers()) { + if (!bFirst) + out << "\n" << indent() << indent() << "&& "; + out << "the_lhs." << member.name << " == the_rhs." << member.name; + bFirst = false; + } + out << ";\n"; + dec(); + out << "}\n"; + // print the operator!= + dumpTemplateHead(out); + out << " inline bool operator!=(const " << id_; + dumpTemplateParameters(out); + out << "& the_lhs, const " << id_; + dumpTemplateParameters(out); + out << "& the_rhs)\n"; + out << "{\n"; + out << indent() << "return !operator==(the_lhs, the_rhs);\n"; + out << "}\n"; + // close namespace + if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) { + out << "\n"; + } + out << "\n"; + dumpGetCppuType(out); + out << "\n#endif // "<< headerDefine << "\n"; +} + +void PolyStructType::dumpLightGetCppuType(FileStream & out) +{ + dumpGetCppuTypePreamble(out); + out << indent() + << ("//TODO: On certain platforms with weak memory models, the" + " following code can result in some threads observing that the_type" + " points to garbage\n") + << indent() + << "static ::typelib_TypeDescriptionReference * the_type = 0;\n" + << indent() << "if (the_type == 0) {\n"; + inc(); + + out << "#ifdef LIBO_INTERNAL_ONLY\n"; + + out << indent() << "::rtl::OString the_buffer = \"" << name_ + << "<\" +\n"; + for (std::vector< OUString >::const_iterator i( + entity_->getTypeParameters().begin()); + i != entity_->getTypeParameters().end();) { + out << indent() + << ("::rtl::OUStringToOString(" + "::cppu::getTypeFavourChar(static_cast< "); + dumpTypeParameterName(out, *i); + out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8) +\n"; + ++i; + if (i != entity_->getTypeParameters().end()) { + out << indent() << "\",\" +\n"; + } + } + out << indent() << "\">\";\n"; + + out << "#else\n"; + + out << indent() << "::rtl::OStringBuffer the_buffer(\"" << name_ + << "<\");\n"; + for (std::vector< OUString >::const_iterator i( + entity_->getTypeParameters().begin()); + i != entity_->getTypeParameters().end();) { + out << indent() + << ("the_buffer.append(::rtl::OUStringToOString(" + "::cppu::getTypeFavourChar(static_cast< "); + dumpTypeParameterName(out, *i); + out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n"; + ++i; + if (i != entity_->getTypeParameters().end()) { + out << indent() << "the_buffer.append(',');\n"; + } + } + out << indent() << "the_buffer.append('>');\n"; + + out << "#endif\n"; + + out << indent() + << "::typelib_static_type_init(&the_type, " << getTypeClass(name_, true) + << ", the_buffer.getStr());\n"; + + dec(); + out << indent() << "}\n" << indent() + << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n"; + dumpGetCppuTypePostamble(out); +} + +void PolyStructType::dumpNormalGetCppuType(FileStream & out) +{ + dumpGetCppuTypePreamble(out); + out << indent() + << ("//TODO: On certain platforms with weak memory models, the" + " following code can result in some threads observing that the_type" + " points to garbage\n") + << indent() + << "static ::typelib_TypeDescriptionReference * the_type = 0;\n" + << indent() << "if (the_type == 0) {\n"; + inc(); + out << indent() << "::rtl::OStringBuffer the_buffer(\"" << name_ + << "<\");\n"; + for (std::vector< OUString >::const_iterator i( + entity_->getTypeParameters().begin()); + i != entity_->getTypeParameters().end();) { + out << indent() + << ("the_buffer.append(::rtl::OUStringToOString(" + "::cppu::getTypeFavourChar(static_cast< "); + dumpTypeParameterName(out, *i); + out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n"; + ++i; + if (i != entity_->getTypeParameters().end()) { + out << indent() << "the_buffer.append(',');\n"; + } + } + out << indent() << "the_buffer.append('>');\n" << indent() + << "::typelib_TypeDescriptionReference * the_members[] = {\n"; + inc(); + for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end();) { + out << indent(); + if (i->parameterized) { + out << "::cppu::getTypeFavourChar(static_cast< "; + dumpTypeParameterName(out, i->type); + out << " * >(0))"; + } else { + out << "::cppu::UnoType< "; + dumpType(out, i->type, false, false, false, true); + out << " >::get()"; + } + ++i; + out << ".getTypeLibType()" + << (i == entity_->getMembers().end() ? " };" : ",") << "\n"; + } + dec(); + out << indent() << "static ::sal_Bool const the_parameterizedTypes[] = { "; + for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end(); ++i) { + if (i != entity_->getMembers().begin()) { + out << ", "; + } + out << (i->parameterized ? "true" : "false"); + } + out << " };\n" << indent() + << ("::typelib_static_struct_type_init(&the_type, the_buffer.getStr()," + " 0, ") + << entity_->getMembers().size() + << ", the_members, the_parameterizedTypes);\n"; + dec(); + out << indent() << "}\n" << indent() + << ("return *reinterpret_cast< ::css::uno::Type * >(" + "&the_type);\n"); + dumpGetCppuTypePostamble(out); +} + +void PolyStructType::dumpComprehensiveGetCppuType(FileStream & out) +{ + out << "namespace cppu { namespace detail {\n\n" << indent(); + dumpTemplateHead(out); + OUString staticTypeClass("the" + id_ + "Type"); + out << "struct " << staticTypeClass + << " : public rtl::StaticWithInit< ::css::uno::Type *, " + << staticTypeClass; + dumpTemplateParameters(out); + out << " >\n" << indent() << "{\n"; + inc(); + out << indent() << "::css::uno::Type * operator()() const\n" + << indent() << "{\n"; + inc(); + + out << "#ifdef LIBO_INTERNAL_ONLY\n"; + out << indent() + << "::rtl::OUString the_name =\n"; + out << indent() << "\"" << name_ << "<\" +\n"; + for (std::vector< OUString >::const_iterator i( + entity_->getTypeParameters().begin()); + i != entity_->getTypeParameters().end();) { + out << indent() + << "::cppu::getTypeFavourChar(static_cast< "; + dumpTypeParameterName(out, *i); + out << " * >(0)).getTypeName() +\n"; + ++i; + if (i != entity_->getTypeParameters().end()) { + out << indent() + << "\",\" +\n"; + } + } + out << indent() + << "\">\";\n"; + out << "#else\n"; + out << indent() << "::rtl::OUStringBuffer the_buffer;\n" << indent() + << "the_buffer.append(\"" << name_ << "<\");\n"; + for (std::vector< OUString >::const_iterator i( + entity_->getTypeParameters().begin()); + i != entity_->getTypeParameters().end();) { + out << indent() + << "the_buffer.append(::cppu::getTypeFavourChar(static_cast< "; + dumpTypeParameterName(out, *i); + out << " * >(0)).getTypeName());\n"; + ++i; + if (i != entity_->getTypeParameters().end()) { + out << indent() + << ("the_buffer.append(" + "static_cast< ::sal_Unicode >(','));\n"); + } + } + out << indent() << "the_buffer.append(static_cast< ::sal_Unicode >('>'));\n"; + out << indent() + << "::rtl::OUString the_name(the_buffer.makeStringAndClear());\n"; + out << "#endif\n"; + std::map< OUString, sal_uInt32 > parameters; + std::map< OUString, sal_uInt32 > types; + std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + size_type n = 0; + for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity_->getMembers()) { + if (member.parameterized) { + if (parameters.emplace( + member.type, static_cast< sal_uInt32 >(parameters.size())). + second) { + sal_uInt32 k = static_cast< sal_uInt32 >(parameters.size() - 1); + out << indent() + << "::css::uno::Type const & the_ptype" << k + << " = ::cppu::getTypeFavourChar(static_cast< "; + dumpTypeParameterName(out, member.type); + out << " * >(0));\n" << indent() + << "::typelib_TypeClass the_pclass" << k + << " = (::typelib_TypeClass) the_ptype" << k + << ".getTypeClass();\n" << indent() + << "::rtl::OUString the_pname" << k << "(the_ptype" << k + << ".getTypeName());\n"; + } + } else if (types.emplace(member.type, static_cast< sal_uInt32 >(types.size())). + second) { + dumpCppuGetType(out, member.type, &name_); + // For typedefs, use the resolved type name, as there will be no + // information available about the typedef itself at runtime (the + // above getCppuType call will make available information about the + // resolved type); no extra #include for the resolved type is + // needed, as the header for the typedef includes it already: + out << indent() << "::rtl::OUString the_tname" + << static_cast< sal_uInt32 >(types.size() - 1) << "( \"" + << resolveAllTypedefs(member.type) << "\" );\n"; + } + out << indent() << "::rtl::OUString the_name" << n++ << "( \"" + << member.name << "\" );\n"; + } + out << indent() << "::typelib_StructMember_Init the_members[] = {\n"; + inc(); + n = 0; + for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >:: + const_iterator i(entity_->getMembers().begin()); + i != entity_->getMembers().end();) { + out << indent() << "{ { "; + if (i->parameterized) { + sal_uInt32 k = parameters.find(i->type)->second; + out << "the_pclass" << k << ", the_pname" << k << ".pData"; + } else { + out << getTypeClass(i->type, true) << ", the_tname" + << types.find(i->type)->second << ".pData"; + } + out << ", the_name" << n++ << ".pData }, " + << (i->parameterized ? "true" : "false") << " }"; + ++i; + out << (i == entity_->getMembers().end() ? " };" : ",") << "\n"; + } + dec(); + out << indent() << "::typelib_TypeDescription * the_newType = 0;\n"; + out << indent() + << ("::typelib_typedescription_newStruct(&the_newType, the_name.pData," + " 0, ") + << entity_->getMembers().size() << ", the_members);\n" << indent() + << "::typelib_typedescription_register(&the_newType);\n" << indent() + << "::typelib_typedescription_release(the_newType);\n" << indent() + << "return new ::css::uno::Type(" << getTypeClass(name_) + << ", the_name); // leaked\n"; + dec(); + out << indent() << "}\n"; + dec(); + out << indent() << "};\n } }\n\n"; + dumpGetCppuTypePreamble(out); + out << indent() << "return *detail::" << staticTypeClass; + dumpTemplateParameters(out); + out << "::get();\n"; + dumpGetCppuTypePostamble(out); +} + +void PolyStructType::addLightGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + includes.addType(); + includes.addCppuUnotypeHxx(); + includes.addSalTypesH(); + includes.addTypelibTypeclassH(); + includes.addTypelibTypedescriptionH(); + includes.addRtlStrbufHxx(); + includes.addRtlTextencH(); + includes.addRtlUstringHxx(); +} + +void PolyStructType::addNormalGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + includes.addType(); + includes.addCppuUnotypeHxx(); + includes.addSalTypesH(); + includes.addTypelibTypeclassH(); + includes.addTypelibTypedescriptionH(); + includes.addRtlStrbufHxx(); + includes.addRtlTextencH(); + includes.addRtlUstringHxx(); +} + +void PolyStructType::addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + includes.addType(); + includes.addCppuUnotypeHxx(); + includes.addRtlInstanceHxx(); + includes.addRtlUstringH(); + includes.addRtlUstringHxx(); + includes.addSalTypesH(); + includes.addTypelibTypeclassH(); + includes.addTypelibTypedescriptionH(); + includes.addRtlStringH(); + includes.addRtlUstrbufHxx(); +} + +void PolyStructType::dumpTemplateHead(FileStream & out) const +{ + out << "template< "; + for (std::vector< OUString >::const_iterator i( + entity_->getTypeParameters().begin()); + i != entity_->getTypeParameters().end(); ++i) { + if (i != entity_->getTypeParameters().begin()) { + out << ", "; + } + out << "typename "; + dumpTypeParameterName(out, *i); + } + out << " > "; +} + +void PolyStructType::dumpTemplateParameters(FileStream & out) const +{ + out << "< "; + for (std::vector< OUString >::const_iterator i( + entity_->getTypeParameters().begin()); + i != entity_->getTypeParameters().end(); ++i) { + if (i != entity_->getTypeParameters().begin()) { + out << ", "; + } + dumpTypeParameterName(out, *i); + } + out << " >"; +} + +OUString typeToIdentifier(std::u16string_view name) +{ + sal_Int32 k; + OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k))); + OUStringBuffer b(4*k + n.getLength()); + for (sal_Int32 i = 0; i != k; ++i) { + b.append("seq_"); + } + b.append(n); + b.replace(' ', '_'); + b.replace(',', '_'); + b.replace('.', '_'); + b.replace('<', '_'); + b.replace('>', '_'); + return b.makeStringAndClear(); +} + +class ExceptionType: public CppuType +{ +public: + ExceptionType( + rtl::Reference< unoidl::ExceptionTypeEntity > const & entity, + OUString const & name, rtl::Reference< TypeManager > const & typeMgr): + CppuType(name, typeMgr), entity_(entity) { + assert(entity.is()); + } + +private: + virtual void dumpHdlFile( + FileStream & out, codemaker::cppumaker::Includes & includes) override; + + virtual void dumpHppFile( + FileStream & out, codemaker::cppumaker::Includes & includes) override; + + virtual void addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + virtual void dumpLightGetCppuType(FileStream & out) override; + + virtual void dumpNormalGetCppuType(FileStream & out) override; + + virtual void dumpComprehensiveGetCppuType(FileStream & out) override; + + virtual sal_uInt32 checkInheritedMemberCount() const override { + return getTotalMemberCount(entity_->getDirectBase()); + } + + virtual void dumpDeclaration(FileStream & out) override; + + bool dumpBaseMembers( + FileStream & out, OUString const & base, bool withType, + bool eligibleForDefaults); + + sal_uInt32 getTotalMemberCount(OUString const & base) const; + + rtl::Reference< unoidl::ExceptionTypeEntity > entity_; +}; + +void ExceptionType::dumpHdlFile( + FileStream & out, codemaker::cppumaker::Includes & includes) +{ + if (name_ == "com.sun.star.uno.Exception") + { + // LIBO_INTERNAL_ONLY implies GCC >= 7, which we need for this + // Merely checking __has_include is not enough because some systems have the header, + // but do not have a new enough Clang 9 supporting __builtin_FILE/LINE/FUNCTION as used by + // that libstdc++ header. + includes.addCustom("#if defined LIBO_INTERNAL_ONLY && ((defined __GNUC__ && !defined __clang__) || (defined __clang__ && __clang_major__ >= 9)) && __has_include(<experimental/source_location>)"); + includes.addCustom("#define LIBO_USE_SOURCE_LOCATION"); + includes.addCustom("#endif"); + includes.addCustom("#if defined LIBO_USE_SOURCE_LOCATION"); + includes.addCustom("#include <experimental/source_location>"); + includes.addCustom("#include <o3tl/runtimetooustring.hxx>"); + includes.addCustom("#endif"); + } + dumpHFileContent(out, includes); +} + +void ExceptionType::addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + includes.addCppuUnotypeHxx(); + includes.addRtlInstanceHxx(); // using rtl::StaticWithInit +} + +void ExceptionType::dumpHppFile( + FileStream & out, codemaker::cppumaker::Includes & includes) +{ + OUString headerDefine(dumpHeaderDefine(out, u"HPP")); + out << "\n"; + addDefaultHxxIncludes(includes); + includes.dump(out, &name_, true); + + // for the output operator below + if (name_ == "com.sun.star.uno.Exception") + { + out << "#if defined LIBO_INTERNAL_ONLY\n"; + out << "#include <ostream>\n"; + out << "#include <typeinfo>\n"; + out << "#endif\n"; + } + + out << "\n"; + + if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) { + out << "\n"; + } + + // default constructor + out << "\ninline " << id_ << "::" << id_ << "(\n"; + out << "#if defined LIBO_USE_SOURCE_LOCATION\n"; + out << " std::experimental::source_location location\n"; + out << "#endif\n"; + out << " )\n"; + inc(); + OUString base(entity_->getDirectBase()); + bool bFirst = true; + if (!base.isEmpty()) { + out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base)) + << "(\n"; + out << "#if defined LIBO_USE_SOURCE_LOCATION\n"; + out << " location\n"; + out << "#endif\n"; + out << ")\n"; + bFirst = false; + } + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + out << indent() << (bFirst ? ":" : ",") << " "; + out << member.name; + dumpInitializer(out, false, member.type); + out << "\n"; + bFirst = false; + } + dec(); + out << "{"; + if (!m_cppuTypeDynamic) { + out << "\n"; + inc(); + dumpCppuGetType(out, name_); + dec(); + } else { + out << " "; + } + if (name_ == "com.sun.star.uno.Exception") + { + out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n"; + out << " if (!Message.isEmpty())\n"; + out << " Message += \" \";\n"; + out << " Message += \"at \" + o3tl::runtimeToOUString(location.file_name()) + \":\" + OUString::number(location.line());\n"; + out << "#endif\n"; + } + out << "}\n\n"; + + // fields constructor + if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) { + out << indent() << "inline " << id_ << "::" << id_ << "("; + bFirst = !dumpBaseMembers(out, base, true, false); + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + if (!bFirst) { + out << ", "; + } + dumpType(out, member.type, true, true); + out << " " << member.name << "_"; + bFirst = false; + } + out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n"; + out << " " << (bFirst ? "" : ", ") << "std::experimental::source_location location\n"; + out << "#endif\n"; + out << ")\n"; + inc(); + bFirst = true; + if (!base.isEmpty()) { + out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base)) + << "("; + dumpBaseMembers(out, base, false, false); + out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n"; + out << " , location\n"; + out << "#endif\n"; + out << ")\n"; + bFirst = false; + } + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + out << indent() << (bFirst ? ":" : ",") << " " << member.name << "(" + << member.name << "_)\n"; + bFirst = false; + } + dec(); + out << "{"; + if (!m_cppuTypeDynamic) { + out << "\n"; + inc(); + dumpCppuGetType(out, name_); + dec(); + } else { + out << " "; + } + if (name_ == "com.sun.star.uno.Exception") + { + out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n"; + out << " if (!Message.isEmpty())\n"; + out << " Message += \" \";\n"; + out << " Message += \"at \" + o3tl::runtimeToOUString(location.file_name()) + \":\" + OUString::number(location.line());\n"; + out << "#endif\n"; + } + out << "}\n\n"; + } + out << "#if !defined LIBO_INTERNAL_ONLY\n" << indent() << id_ << "::" << id_ + << "(" << id_ << " const & the_other)"; + bFirst = true; + if (!base.isEmpty()) { + out << ": " << codemaker::cpp::scopedCppName(u2b(base)) + << "(the_other)"; + bFirst = false; + } + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + out << (bFirst ? ":" : ",") << " " << member.name << "(the_other." << member.name + << ")"; + bFirst = false; + } + out << indent() << " {}\n\n" << indent() << id_ << "::~" << id_ + << "() {}\n\n" << indent() << id_ << " & " << id_ << "::operator =(" + << id_ << " const & the_other) {\n"; + inc(); + out << indent() + << ("//TODO: Just like its implicitly-defined counterpart, this" + " function definition is not exception-safe\n"); + if (!base.isEmpty()) { + out << indent() << codemaker::cpp::scopedCppName(u2b(base)) + << "::operator =(the_other);\n"; + } + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + out << indent() << member.name << " = the_other." << member.name << ";\n"; + } + out << indent() << "return *this;\n"; + dec(); + out << indent() << "}\n#endif\n\n"; + + // Provide an output operator for printing Exception information to SAL_WARN/SAL_INFO. + if (name_ == "com.sun.star.uno.Exception") + { + out << "#if defined LIBO_INTERNAL_ONLY\n"; + out << "template< typename charT, typename traits >\n"; + out << "inline ::std::basic_ostream<charT, traits> & operator<<(\n"; + out << " ::std::basic_ostream<charT, traits> & os, ::com::sun::star::uno::Exception const & exception)\n"; + out << "{\n"; + out << " // the class name is useful because exception throwing code does not always pass in a useful message\n"; + out << " os << typeid(exception).name();\n"; + out << " if (!exception.Message.isEmpty())\n"; + out << " os << \" msg: \" << exception.Message;\n"; + out << " return os;\n"; + out << "}\n"; + out << "#endif\n"; + out << "\n"; + } + + if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) { + out << "\n"; + } + out << "\n"; + + dumpGetCppuType(out); + out << "\n#endif // "<< headerDefine << "\n"; +} + +void ExceptionType::dumpLightGetCppuType(FileStream & out) +{ + dumpGetCppuTypePreamble(out); + out << indent() + << "static typelib_TypeDescriptionReference * the_type = 0;\n" + << indent() << "if ( !the_type )\n" << indent() << "{\n"; + inc(); + out << indent() << "typelib_static_type_init( &the_type, " + << getTypeClass(name_, true) << ", \"" << name_ << "\" );\n"; + dec(); + out << indent() << "}\n" << indent() + << ("return * reinterpret_cast< ::css::uno::Type * >(" + " &the_type );\n"); + dumpGetCppuTypePostamble(out); +} + +void ExceptionType::dumpNormalGetCppuType(FileStream & out) +{ + dumpGetCppuTypePreamble(out); + out << indent() + << "static typelib_TypeDescriptionReference * the_type = 0;\n" + << indent() << "if ( !the_type )\n" << indent() << "{\n"; + inc(); + OUString base(entity_->getDirectBase()); + bool baseException = false; + if (!base.isEmpty()) { + if (base == "com.sun.star.uno.Exception") { + baseException = true; + } else { + out << indent() + << ("const ::css::uno::Type& rBaseType =" + " ::cppu::UnoType< "); + dumpType(out, base, true, false, false, true); + out << " >::get();\n\n"; + } + } + if (!entity_->getDirectMembers().empty()) { + out << indent() << "typelib_TypeDescriptionReference * aMemberRefs[" + << entity_->getDirectMembers().size() << "];\n"; + std::set< OUString > seen; + std::vector< unoidl::ExceptionTypeEntity::Member >::size_type n = 0; + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + OUString type(resolveAllTypedefs(member.type)); + OUString modType(typeToIdentifier(type)); + if (seen.insert(type).second) { + out << indent() + << "const ::css::uno::Type& rMemberType_" + << modType << " = ::cppu::UnoType< "; + dumpType(out, type, false, false, false, true); + out << " >::get();\n"; + } + out << indent() << "aMemberRefs[" << n++ << "] = rMemberType_" + << modType << ".getTypeLibType();\n"; + } + out << "\n"; + } + out << indent() << "typelib_static_compound_type_init( &the_type, " + << getTypeClass(name_, true) << ", \"" << name_ << "\", "; + if (baseException) { + out << ("* ::typelib_static_type_getByTypeClass(" + " typelib_TypeClass_EXCEPTION )"); + } else if (base.isEmpty()) { + out << "0"; + } else { + out << "rBaseType.getTypeLibType()"; + } + out << ", " << entity_->getDirectMembers().size() << ", " + << (entity_->getDirectMembers().empty() ? "0" : "aMemberRefs") + << " );\n"; + dec(); + out << indent() << "}\n" << indent() + << ("return * reinterpret_cast< const ::css::uno::Type * >(" + " &the_type );\n"); + dumpGetCppuTypePostamble(out); +} + +void ExceptionType::dumpComprehensiveGetCppuType(FileStream & out) +{ + codemaker::cppumaker::dumpNamespaceOpen(out, name_, false); + out << " namespace detail {\n\n"; + OUString staticTypeClass("the" + id_ + "Type"); + out << indent() << "struct " << staticTypeClass + << " : public rtl::StaticWithInit< ::css::uno::Type *, " + << staticTypeClass << " >\n" << indent() << "{\n"; + inc(); + out << indent() << "::css::uno::Type * operator()() const\n" + << indent() << "{\n"; + inc(); + out << indent() << "::rtl::OUString sTypeName( \"" << name_ << "\" );\n\n" + << indent() << "// Start inline typedescription generation\n" + << indent() << "typelib_TypeDescription * pTD = 0;\n"; + OUString base(entity_->getDirectBase()); + if (!base.isEmpty()) { + out << indent() + << ("const ::css::uno::Type& rSuperType =" + " ::cppu::UnoType< "); + dumpType(out, base, false, false, false, true); + out << " >::get();\n"; + } + std::set< OUString > seen; + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + if (seen.insert(member.type).second) { + dumpCppuGetType(out, member.type); + } + } + if (!entity_->getDirectMembers().empty()) { + out << "\n" << indent() << "typelib_CompoundMember_Init aMembers[" + << entity_->getDirectMembers().size() << "];\n"; + std::vector< unoidl::ExceptionTypeEntity::Member >::size_type n = 0; + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + OUString type(resolveAllTypedefs(member.type)); + out << indent() << "::rtl::OUString sMemberType" << n << "( \"" + << type << "\" );\n" << indent() + << "::rtl::OUString sMemberName" << n << "( \"" << member.name + << "\" );\n" << indent() << "aMembers[" << n + << "].eTypeClass = (typelib_TypeClass)" << getTypeClass(type) + << ";\n" << indent() << "aMembers[" << n + << "].pTypeName = sMemberType" << n << ".pData;\n" << indent() + << "aMembers[" << n << "].pMemberName = sMemberName" << n + << ".pData;\n"; + ++n; + } + } + out << "\n" << indent() << "typelib_typedescription_new(\n"; + inc(); + out << indent() << "&pTD,\n" << indent() << "(typelib_TypeClass)" + << getTypeClass(name_) << ", sTypeName.pData,\n" << indent() + << (base.isEmpty() ? "0" : "rSuperType.getTypeLibType()") << ",\n" + << indent() << entity_->getDirectMembers().size() << ",\n" << indent() + << (entity_->getDirectMembers().empty() ? "0" : "aMembers") + << " );\n\n"; + dec(); + out << indent() + << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD" + " );\n\n") + << indent() << "typelib_typedescription_release( pTD );\n" << indent() + << "// End inline typedescription generation\n\n" << indent() + << "return new ::css::uno::Type( " << getTypeClass(name_) + << ", sTypeName ); // leaked\n"; + dec(); + out << indent() << "}\n"; + dec(); + out << indent() << "};\n\n"; + codemaker::cppumaker::dumpNamespaceClose(out, name_, false); + out << " }\n\n"; + dumpGetCppuTypePreamble(out); + out << indent() << "return *detail::" << staticTypeClass << "::get();\n"; + dumpGetCppuTypePostamble(out); +} + +void ExceptionType::dumpDeclaration(FileStream & out) +{ + out << "\nclass CPPU_GCC_DLLPUBLIC_EXPORT SAL_WARN_UNUSED " << id_; + OUString base(entity_->getDirectBase()); + if (!base.isEmpty()) { + out << " : public " << codemaker::cpp::scopedCppName(u2b(base)); + } + out << "\n{\npublic:\n"; + inc(); + + // default constructor + out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(\n"; + out << "#if defined LIBO_USE_SOURCE_LOCATION\n"; + out << " std::experimental::source_location location = std::experimental::source_location::current()\n"; + out << "#endif\n\n"; + out << " );\n"; + + // constructor that initializes data members + if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) { + out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "("; + bool eligibleForDefaults = entity_->getDirectMembers().empty(); + bool bFirst = !dumpBaseMembers(out, base, true, eligibleForDefaults); + for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) { + if (!bFirst) { + out << ", "; + } + dumpType(out, member.type, true, true); + out << " " << member.name << "_"; + bFirst = false; + } + out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n"; + out << ", std::experimental::source_location location = std::experimental::source_location::current()\n"; + out << "#endif\n"; + out << " );\n\n"; + } + out << "#if !defined LIBO_INTERNAL_ONLY\n" << indent() + << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(" << id_ + << " const &);\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE ~" + << id_ << "();\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ + << " & operator =(" << id_ << " const &);\n#endif\n\n"; + for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i( + entity_->getDirectMembers().begin()); + i != entity_->getDirectMembers().end(); ++i) { + out << indent(); + dumpType(out, i->type); + out << " " << i->name; + if (i == entity_->getDirectMembers().begin() && !base.isEmpty() + && i->type != "hyper" && i->type != "unsigned hyper" + && i->type != "double") { + out << " CPPU_GCC3_ALIGN( " + << codemaker::cpp::scopedCppName(u2b(base)) << " )"; + } + out << ";\n"; + } + dec(); + out << "};\n\n"; +} + +bool ExceptionType::dumpBaseMembers( + FileStream & out, OUString const & base, bool withType, bool eligibleForDefaults) +{ + if (base.isEmpty()) + return false; + + bool hasMember = false; + rtl::Reference< unoidl::Entity > ent; + codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent); + if (sort != codemaker::UnoType::Sort::Exception) { + throw CannotDumpException( + "exception type base " + base + " is not an exception type"); + } + rtl::Reference< unoidl::ExceptionTypeEntity > ent2( + dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get())); + assert(ent2.is()); + if (!ent2.is()) { + return false; + } + hasMember = dumpBaseMembers( out, ent2->getDirectBase(), withType, + eligibleForDefaults && ent2->getDirectMembers().empty() ); + int memberCount = 0; + for (const unoidl::ExceptionTypeEntity::Member& member : ent2->getDirectMembers()) { + if (hasMember) { + out << ", "; + } + if (withType) { + dumpType(out, member.type, true, true); + out << " "; + } + out << member.name << "_"; + // We want to provide a default parameter value for uno::Exception subtype + // constructors, since most of the time we don't pass a Context object in to the exception + // throw sites. + if (eligibleForDefaults + && base == "com.sun.star.uno.Exception" + && memberCount == 1 + && member.name == "Context" + && member.type == "com.sun.star.uno.XInterface") { + out << " = ::css::uno::Reference< ::css::uno::XInterface >()"; + } + hasMember = true; + ++memberCount; + } + return hasMember; +} + +sal_uInt32 ExceptionType::getTotalMemberCount(OUString const & base) const +{ + if (base.isEmpty()) { + return 0; + } + rtl::Reference< unoidl::Entity > ent; + codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent); + if (sort != codemaker::UnoType::Sort::Exception) { + throw CannotDumpException( + "exception type base " + base + " is not an exception type"); + } + unoidl::ExceptionTypeEntity& ent2(dynamic_cast<unoidl::ExceptionTypeEntity&>(*ent)); + return getTotalMemberCount(ent2.getDirectBase()) + + ent2.getDirectMembers().size(); //TODO: overflow +} + +class EnumType: public CppuType +{ +public: + EnumType( + rtl::Reference< unoidl::EnumTypeEntity > const & entity, + OUString const & name, rtl::Reference< TypeManager > const & typeMgr): + CppuType(name, typeMgr), entity_(entity) { + assert(entity.is()); + } + +private: + virtual void dumpDeclaration(FileStream& o) override; + + virtual void addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const override; + + void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override; + + void dumpNormalGetCppuType(FileStream& o) override; + void dumpComprehensiveGetCppuType(FileStream& o) override; + + rtl::Reference< unoidl::EnumTypeEntity > entity_; +}; + +void EnumType::addComprehensiveGetCppuTypeIncludes( + codemaker::cppumaker::Includes & includes) const +{ + includes.addCppuUnotypeHxx(); + includes.addRtlInstanceHxx(); // using rtl::StaticWithInit +} + +void EnumType::dumpDeclaration(FileStream& o) +{ + o << "\n#if defined LIBO_INTERNAL_ONLY\n"; + o << "\nenum class SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n"; + o << "\n#else\n"; + o << "\nenum SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n"; + o << "\n#endif\n"; + inc(); + + for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) { + o << indent() << id_ << "_" << u2b(member.name) << " = " << member.value + << ",\n"; + } + + o << indent() << id_ << "_MAKE_FIXED_SIZE = SAL_MAX_ENUM\n"; + + dec(); + o << "};\n\n"; + + // use constexpr to create a kind of type-alias so we don't have to modify existing code + o << "#if defined LIBO_INTERNAL_ONLY\n"; + for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) { + o << "constexpr auto " << id_ << "_" << u2b(member.name) + << " = " + << id_ << "::" << id_ << "_" << u2b(member.name) + << ";\n"; + } + o << "#endif\n"; +} + +void EnumType::dumpHppFile( + FileStream& o, codemaker::cppumaker::Includes & includes) +{ + OUString headerDefine(dumpHeaderDefine(o, u"HPP")); + o << "\n"; + + addDefaultHxxIncludes(includes); + includes.dump(o, &name_, true); + o << "\n"; + + dumpGetCppuType(o); + + o << "\n#endif // "<< headerDefine << "\n"; +} + +void EnumType::dumpNormalGetCppuType(FileStream& o) +{ + dumpGetCppuTypePreamble(o); + + o << indent() + << "static typelib_TypeDescriptionReference * the_type = 0;\n"; + + o << indent() << "if ( !the_type )\n" << indent() << "{\n"; + inc(); + + o << indent() << "typelib_static_enum_type_init( &the_type,\n"; + inc(31); + o << indent() << "\"" << name_ << "\",\n" + << indent() << codemaker::cpp::scopedCppName(u2b(name_)) << "_" + << u2b(entity_->getMembers()[0].name) << " );\n"; + dec(31); + dec(); + o << indent() << "}\n"; + o << indent() + << ("return * reinterpret_cast< ::css::uno::Type * >(" + " &the_type );\n"); + dumpGetCppuTypePostamble(o); +} + +void EnumType::dumpComprehensiveGetCppuType(FileStream& o) +{ + if (!isPolymorphic()) + codemaker::cppumaker::dumpNamespaceOpen(o, name_, false); + else + o << "namespace cppu { "; + o << " namespace detail {\n\n"; + + OUString sStaticTypeClass("the" + id_ + "Type"); + o << indent() << "struct " << sStaticTypeClass << " : public rtl::StaticWithInit< ::css::uno::Type *, " << sStaticTypeClass << " >\n"; + o << indent() << "{\n"; + inc(); + o << indent() << "::css::uno::Type * operator()() const\n"; + o << indent() << "{\n"; + + inc(); + o << indent() << "::rtl::OUString sTypeName( \"" << name_ + << "\" );\n\n"; + + o << indent() << "// Start inline typedescription generation\n" + << indent() << "typelib_TypeDescription * pTD = 0;\n\n"; + + o << indent() << "rtl_uString* enumValueNames[" + << entity_->getMembers().size() << "];\n"; + std::vector< unoidl::EnumTypeEntity::Member >::size_type n = 0; + for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) { + o << indent() << "::rtl::OUString sEnumValue" << n << "( \"" + << u2b(member.name) << "\" );\n"; + o << indent() << "enumValueNames[" << n << "] = sEnumValue" << n + << ".pData;\n"; + ++n; + } + + o << "\n" << indent() << "sal_Int32 enumValues[" + << entity_->getMembers().size() << "];\n"; + n = 0; + for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) { + o << indent() << "enumValues[" << n++ << "] = " << member.value << ";\n"; + } + + o << "\n" << indent() << "typelib_typedescription_newEnum( &pTD,\n"; + inc(); + o << indent() << "sTypeName.pData,\n" + << indent() << "(sal_Int32)" + << codemaker::cpp::scopedCppName(u2b(name_), false) << "_" + << u2b(entity_->getMembers()[0].name) << ",\n" + << indent() << entity_->getMembers().size() + << ", enumValueNames, enumValues );\n\n"; + dec(); + + o << indent() + << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD" + " );\n"); + o << indent() << "typelib_typedescription_release( pTD );\n" + << indent() << "// End inline typedescription generation\n\n"; + + o << indent() << "return new ::css::uno::Type( " + << getTypeClass(name_) << ", sTypeName ); // leaked\n"; + + dec(); + o << indent() << "}\n"; + dec(); + o << indent() << "};\n\n"; + + if (!isPolymorphic()) + codemaker::cppumaker::dumpNamespaceClose(o, name_, false); + else + o << " }"; + o << " }\n\n"; + + dumpGetCppuTypePreamble(o); + o << indent() << "return *detail::" << sStaticTypeClass << "::get();\n"; + dumpGetCppuTypePostamble(o); +} + +class Typedef: public CppuType +{ +public: + Typedef( + rtl::Reference< unoidl::TypedefEntity > const & entity, + OUString const & name, rtl::Reference< TypeManager > const & typeMgr): + CppuType(name, typeMgr), entity_(entity) { + assert(entity.is()); + } + +private: + virtual void dumpDeclaration(FileStream& o) override; + + void dumpHdlFile(FileStream& o, codemaker::cppumaker::Includes & includes) override; + + void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override; + + rtl::Reference< unoidl::TypedefEntity > entity_; +}; + +void Typedef::dumpHdlFile( + FileStream& o, codemaker::cppumaker::Includes & includes) +{ + OUString headerDefine(dumpHeaderDefine(o, u"HDL")); + o << "\n"; + + addDefaultHIncludes(includes); + includes.dump(o, nullptr, true); + o << "\n"; + + if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) { + o << "\n"; + } + + dumpDeclaration(o); + + if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) { + o << "\n"; + } + + o << "#endif // "<< headerDefine << "\n"; +} + +void Typedef::dumpDeclaration(FileStream& o) +{ + o << "\ntypedef "; + dumpType(o, entity_->getType()); + o << " " << id_ << ";\n\n"; +} + +void Typedef::dumpHppFile( + FileStream& o, codemaker::cppumaker::Includes & includes) +{ + OUString headerDefine(dumpHeaderDefine(o, u"HPP")); + o << "\n"; + + addDefaultHxxIncludes(includes); + includes.dump(o, &name_, true); + o << "\n"; + + o << "\n#endif // "<< headerDefine << "\n"; +} + +class ConstructiveType: public CppuType +{ +public: + ConstructiveType( + OUString const & name, rtl::Reference< TypeManager > const & manager): + CppuType(name, manager) {} + +private: + virtual void dumpHdlFile(FileStream &, codemaker::cppumaker::Includes &) override { + assert(false); // this cannot happen + } + + virtual void dumpFiles(OUString const & uri, CppuOptions const & options) override { + dumpFile(uri, name_, true, options); + } +}; + +bool hasRestParameter( + unoidl::SingleInterfaceBasedServiceEntity::Constructor const & constructor) +{ + return !constructor.parameters.empty() + && constructor.parameters.back().rest; +} + +void includeExceptions( + codemaker::cppumaker::Includes & includes, + codemaker::ExceptionTreeNode const * node) +{ + if (node->present) { + includes.add(node->name); + } else { + for (std::unique_ptr<codemaker::ExceptionTreeNode> const & pChild : node->children) { + includeExceptions(includes, pChild.get()); + } + } +} + +class ServiceType: public ConstructiveType +{ +public: + ServiceType( + rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const & + entity, + OUString const & name, rtl::Reference< TypeManager > const & manager): + ConstructiveType(name, manager), entity_(entity) { + assert(entity.is()); + } + +private: + virtual void dumpHppFile( + FileStream & o, codemaker::cppumaker::Includes & includes) override; + + void dumpCatchClauses( + FileStream & out, codemaker::ExceptionTreeNode const * node); + + rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > entity_; +}; + +void failsToSupply( + FileStream & o, std::u16string_view service, OString const & type) +{ + o << "::rtl::OUString(\"component context fails to supply service \") + \"" + << service << "\" + \" of type \" + \"" << type << "\""; +} + +void ServiceType::dumpHppFile( + FileStream & o, codemaker::cppumaker::Includes & includes) +{ + if (!entity_->getConstructors().empty()) { + //TODO: Decide whether the types added to includes should rather be + // added to m_dependencies (and thus be generated during + // dumpDependedTypes): + includes.addCassert(); + includes.addReference(); + includes.addRtlUstringH(); + includes.addRtlUstringHxx(); + includes.add("com.sun.star.uno.DeploymentException"); + includes.add("com.sun.star.uno.XComponentContext"); + for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons : entity_->getConstructors()) { + if (cons.defaultConstructor) { + includes.add("com.sun.star.uno.Exception"); + includes.add("com.sun.star.uno.RuntimeException"); + } else { + if (!hasRestParameter(cons)) { + includes.addAny(); + includes.addSequence(); + for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param : + cons.parameters) { + if (m_typeMgr->getSort( + b2u(codemaker::UnoType::decompose( + u2b(param.type)))) + == codemaker::UnoType::Sort::Char) { + includes.addCppuUnotypeHxx(); + break; + } + } + } + codemaker::ExceptionTree tree; + for (const OUString& ex : cons.exceptions) { + tree.add(u2b(ex), m_typeMgr); + } + if (!tree.getRoot().present) { + includes.add("com.sun.star.uno.Exception"); + includes.add("com.sun.star.uno.RuntimeException"); + includeExceptions(includes, &tree.getRoot()); + } + } + } + } + OString cppName( + codemaker::cpp::translateUnoToCppIdentifier( + u2b(id_), "service", isGlobal())); + OUString headerDefine(dumpHeaderDefine(o, u"HPP")); + o << "\n"; + includes.dump(o, nullptr, true); + if (!entity_->getConstructors().empty()) { + o << ("\n#if defined ANDROID || defined IOS //TODO\n" + "#include <com/sun/star/lang/XInitialization.hpp>\n" + "#include <osl/detail/component-defines.h>\n#endif\n\n" + "#if defined LO_URE_CURRENT_ENV && defined LO_URE_CTOR_ENV_") + << name_.replaceAll(".", "_dot_") + << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_" + << name_.replaceAll(".", "_dot_") << ") && defined LO_URE_CTOR_FUN_" + << name_.replaceAll(".", "_dot_") + << "\nextern \"C\" ::css::uno::XInterface * SAL_CALL LO_URE_CTOR_FUN_" + << name_.replaceAll(".", "_dot_") + << "(::css::uno::XComponentContext *, ::css::uno::Sequence< " + "::css::uno::Any > const &);\n#endif\n"; + } + o << "\n"; + if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) { + o << "\n"; + } + o << "\nclass " << cppName << " {\n"; + inc(); + if (!entity_->getConstructors().empty()) { + OString baseName(u2b(entity_->getBase())); + OString scopedBaseName(codemaker::cpp::scopedCppName(baseName)); + o << "public:\n"; + for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons : + entity_->getConstructors()) { + if (cons.defaultConstructor) { + o << indent() << "static ::css::uno::Reference< " + << scopedBaseName << " > " + << codemaker::cpp::translateUnoToCppIdentifier( + "create", "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal, + &cppName) + << ("(::css::uno::Reference< ::css::uno::XComponentContext > const &" + " the_context) {\n"); + inc(); + o << indent() << "assert(the_context.is());\n" << indent() + << "::css::uno::Reference< " << scopedBaseName + << " > the_instance;\n" << indent() << "try {\n"; + inc(); + o << ("#if defined LO_URE_CURRENT_ENV && defined " + "LO_URE_CTOR_ENV_") + << name_.replaceAll(".", "_dot_") + << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_" + << name_.replaceAll(".", "_dot_") + << ") && defined LO_URE_CTOR_FUN_" + << name_.replaceAll(".", "_dot_") << "\n" << indent() + << "the_instance = ::css::uno::Reference< " << scopedBaseName + << (" >(::css::uno::Reference< ::css::uno::XInterface >(" + "static_cast< ::css::uno::XInterface * >((*" + "LO_URE_CTOR_FUN_") + << name_.replaceAll(".", "_dot_") + << (")(the_context.get(), ::css::uno::Sequence<" + " ::css::uno::Any >())), ::SAL_NO_ACQUIRE)," + " ::css::uno::UNO_QUERY);\n#else\n") + << indent() << "the_instance = ::css::uno::Reference< " + << scopedBaseName + << (" >(the_context->getServiceManager()->" + "createInstanceWithContext(" + " \"") + << name_ + << "\", the_context), ::css::uno::UNO_QUERY);\n#endif\n"; + dec(); + o << indent() + << "} catch (const ::css::uno::RuntimeException &) {\n"; + inc(); + o << indent() << "throw;\n"; + dec(); + o << indent() + << "} catch (const ::css::uno::Exception & the_exception) {\n"; + inc(); + o << indent() << "throw ::css::uno::DeploymentException("; + failsToSupply(o, name_, baseName); + o << " + \": \" + the_exception.Message, the_context);\n"; + dec(); + o << indent() << "}\n" << indent() + << "if (!the_instance.is()) {\n"; + inc(); + o << indent() << "throw ::css::uno::DeploymentException("; + failsToSupply(o, name_, baseName); + o << ", the_context);\n"; + dec(); + o << indent() << "}\n" << indent() << "return the_instance;\n"; + dec(); + o << indent() << "}\n\n"; + } else { + o << indent() << "static ::css::uno::Reference< " + << scopedBaseName << " > " + << codemaker::cpp::translateUnoToCppIdentifier( + u2b(cons.name), "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal, + &cppName) + << ("(::css::uno::Reference< ::css::uno::XComponentContext > const &" + " the_context"); + bool rest = hasRestParameter(cons); + for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param : + cons.parameters) { + o << ", "; + OUStringBuffer buf(2 + param.type.getLength()); + if (param.rest) { + buf.append("[]"); + } + buf.append(param.type); + OUString type(buf.makeStringAndClear()); + bool byRef = passByReference(type); + dumpType(o, type, byRef, byRef); + o << " " + << codemaker::cpp::translateUnoToCppIdentifier( + u2b(param.name), "param", codemaker::cpp::IdentifierTranslationMode::NonGlobal); + } + o << ") {\n"; + inc(); + o << indent() << "assert(the_context.is());\n"; + if (!rest && !cons.parameters.empty()) { + o << indent() + << "::css::uno::Sequence< ::css::uno::Any > the_arguments(" + << cons.parameters.size() << ");\n"; + o << indent() + << "::css::uno::Any* the_arguments_array = the_arguments.getArray();\n"; + + std::vector< + unoidl::SingleInterfaceBasedServiceEntity::Constructor:: + Parameter >::size_type n = 0; + for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& j : + cons.parameters) { + o << indent() << "the_arguments_array[" << n++ << "] "; + OString param( + codemaker::cpp::translateUnoToCppIdentifier( + u2b(j.name), "param", + codemaker::cpp::IdentifierTranslationMode::NonGlobal)); + sal_Int32 rank; + if (resolveOuterTypedefs(j.type) == "any") { + o << "= " << param; + } else if (m_typeMgr->getSort( + b2u(codemaker::UnoType::decompose( + u2b(j.type), &rank))) + == codemaker::UnoType::Sort::Char) { + o << "= ::css::uno::Any(&" << param + << ", ::cppu::UnoType< "; + for (sal_Int32 k = 0; k < rank; ++k) { + o << "::cppu::UnoSequenceType< "; + } + o << "::cppu::UnoCharType"; + for (sal_Int32 k = 0; k < rank; ++k) { + o << " >"; + } + o << " >::get())"; + } else { + o << "<<= " << param; + } + o << ";\n"; + } + } + o << indent() << "::css::uno::Reference< " + << scopedBaseName << " > the_instance;\n"; + codemaker::ExceptionTree tree; + for (const OUString& ex : cons.exceptions) { + tree.add(u2b(ex), m_typeMgr); + } + if (!tree.getRoot().present) { + o << indent() << "try {\n"; + inc(); + } + o << ("#if defined LO_URE_CURRENT_ENV && defined " + "LO_URE_CTOR_ENV_") + << name_.replaceAll(".", "_dot_") + << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_" + << name_.replaceAll(".", "_dot_") + << ") && defined LO_URE_CTOR_FUN_" + << name_.replaceAll(".", "_dot_") << "\n" << indent() + << "the_instance = ::css::uno::Reference< " << scopedBaseName + << (" >(::css::uno::Reference< ::css::uno::XInterface >(" + "static_cast< ::css::uno::XInterface * >((*" + "LO_URE_CTOR_FUN_") + << name_.replaceAll(".", "_dot_") + << ")(the_context.get(), "; + if (rest) { + o << codemaker::cpp::translateUnoToCppIdentifier( + u2b(cons.parameters.back().name), "param", + codemaker::cpp::IdentifierTranslationMode::NonGlobal); + } else if (cons.parameters.empty()) { + o << "::css::uno::Sequence< ::css::uno::Any >()"; + } else { + o << "the_arguments"; + } + o << ")), ::SAL_NO_ACQUIRE), ::css::uno::UNO_QUERY);\n" << indent() + << ("::css::uno::Reference< ::css::lang::XInitialization > " + "init(the_instance, ::css::uno::UNO_QUERY);\n") + << indent() << "if (init.is()) {\n" + << indent() << " init->initialize("; + if (cons.parameters.empty()) { + o << "::css::uno::Sequence< ::css::uno::Any >()"; + } else { + o << "the_arguments"; + } + o << ");\n" << indent() << "}\n"; + o << "#else\n" + << indent() << "the_instance = ::css::uno::Reference< " + << scopedBaseName + << (" >(the_context->getServiceManager()->" + "createInstanceWithArgumentsAndContext(" + " \"") + << name_ << "\", "; + if (rest) { + o << codemaker::cpp::translateUnoToCppIdentifier( + u2b(cons.parameters.back().name), "param", + codemaker::cpp::IdentifierTranslationMode::NonGlobal); + } else if (cons.parameters.empty()) { + o << "::css::uno::Sequence< ::css::uno::Any >()"; + } else { + o << "the_arguments"; + } + o << ", the_context), ::css::uno::UNO_QUERY);\n#endif\n"; + if (!tree.getRoot().present) { + dec(); + o << indent() + << "} catch (const ::css::uno::RuntimeException &) {\n"; + inc(); + o << indent() << "throw;\n"; + dec(); + dumpCatchClauses(o, &tree.getRoot()); + o << indent() + << ("} catch (const ::css::uno::Exception &" + " the_exception) {\n"); + inc(); + o << indent() << "throw ::css::uno::DeploymentException("; + failsToSupply(o, name_, baseName); + o << " + \": \" + the_exception.Message, the_context);\n"; + dec(); + o << indent() << "}\n"; + } + o << indent() << "if (!the_instance.is()) {\n"; + inc(); + o << indent() << "throw ::css::uno::DeploymentException("; + failsToSupply(o, name_, baseName); + o << ", the_context);\n"; + dec(); + o << indent() << "}\n" << indent() << "return the_instance;\n"; + dec(); + o << indent() << "}\n\n"; + } + } + } + o << "private:\n"; + o << indent() << cppName << "(); // not implemented\n" + << indent() << cppName << "(" << cppName << " &); // not implemented\n" + << indent() << "~" << cppName << "(); // not implemented\n" + << indent() << "void operator =(" << cppName << "); // not implemented\n"; + dec(); + o << "};\n\n"; + if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) { + o << "\n"; + } + o << "\n#endif // "<< headerDefine << "\n"; +} + +void ServiceType::dumpCatchClauses( + FileStream & out, codemaker::ExceptionTreeNode const * node) +{ + if (node->present) { + out << indent() << "} catch (const "; + dumpType(out, b2u(node->name)); + out << " &) {\n"; + inc(); + out << indent() << "throw;\n"; + dec(); + } else { + for (std::unique_ptr<codemaker::ExceptionTreeNode> const & pChild : node->children) { + dumpCatchClauses(out, pChild.get()); + } + } +} + +class SingletonType: public ConstructiveType +{ +public: + SingletonType( + rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity, + OUString const & name, rtl::Reference< TypeManager > const & manager): + ConstructiveType(name, manager), entity_(entity) { + assert(entity.is()); + } + +private: + virtual void dumpHppFile( + FileStream & o, codemaker::cppumaker::Includes & includes) override; + + rtl::Reference< unoidl::InterfaceBasedSingletonEntity > entity_; +}; + +void SingletonType::dumpHppFile( + FileStream & o, codemaker::cppumaker::Includes & includes) +{ + OString cppName( + codemaker::cpp::translateUnoToCppIdentifier( + u2b(id_), "singleton", isGlobal())); + OString baseName(u2b(entity_->getBase())); + OString scopedBaseName(codemaker::cpp::scopedCppName(baseName)); + OUString headerDefine(dumpHeaderDefine(o, u"HPP")); + o << "\n"; + //TODO: Decide whether the types added to includes should rather be added to + // m_dependencies (and thus be generated during dumpDependedTypes): + includes.add("com.sun.star.uno.DeploymentException"); + includes.add("com.sun.star.uno.XComponentContext"); + includes.addCassert(); + includes.addAny(); + includes.addReference(); + includes.addRtlUstringH(); + includes.addRtlUstringHxx(); + includes.dump(o, nullptr, true); + o << ("\n#if defined ANDROID || defined IOS //TODO\n" + "#include <com/sun/star/lang/XInitialization.hpp>\n" + "#include <osl/detail/component-defines.h>\n#endif\n\n" + "#if defined LO_URE_CURRENT_ENV && defined LO_URE_CTOR_ENV_") + << name_.replaceAll(".", "_dot_") + << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_" + << name_.replaceAll(".", "_dot_") << ") && defined LO_URE_CTOR_FUN_" + << name_.replaceAll(".", "_dot_") + << "\nextern \"C\" ::css::uno::XInterface * SAL_CALL LO_URE_CTOR_FUN_" + << name_.replaceAll(".", "_dot_") + << "(::css::uno::XComponentContext *, ::css::uno::Sequence< " + "::css::uno::Any > const &);\n#endif\n"; + o << "\n"; + if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) { + o << "\n"; + } + o << "\nclass " << cppName << " {\npublic:\n"; + inc(); + o << indent() << "static ::css::uno::Reference< " + << scopedBaseName << " > " + << codemaker::cpp::translateUnoToCppIdentifier( + "get", "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal, &cppName) + << ("(::css::uno::Reference<" + " ::css::uno::XComponentContext > const & the_context)" + " {\n"); + inc(); + o << indent() << "assert(the_context.is());\n" << indent() + << "::css::uno::Reference< " << scopedBaseName + << (" > instance;\n#if defined LO_URE_CURRENT_ENV && defined " + "LO_URE_CTOR_ENV_") + << name_.replaceAll(".", "_dot_") + << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_" + << name_.replaceAll(".", "_dot_") + << ") && defined LO_URE_CTOR_FUN_" + << name_.replaceAll(".", "_dot_") << "\n" << indent() + << "instance = ::css::uno::Reference< " << scopedBaseName + << (" >(::css::uno::Reference< ::css::uno::XInterface >(" + "static_cast< ::css::uno::XInterface * >((*" + "LO_URE_CTOR_FUN_") + << name_.replaceAll(".", "_dot_") + << (")(the_context.get(), ::css::uno::Sequence<" + " ::css::uno::Any >())), ::SAL_NO_ACQUIRE)," + " ::css::uno::UNO_QUERY);\n#else\n") + << indent() << ("the_context->getValueByName(" + "::rtl::OUString( \"/singletons/") + << name_ << "\" )) >>= instance;\n#endif\n" + << indent() << "if (!instance.is()) {\n"; + inc(); + o << indent() + << ("throw ::css::uno::DeploymentException(" + "::rtl::OUString( \"component context" + " fails to supply singleton ") + << name_ << " of type " << baseName << "\" ), the_context);\n"; + dec(); + o << indent() << "}\n" << indent() << "return instance;\n"; + dec(); + o << indent() << "}\n\n"; + o << "private:\n"; + o << indent() << cppName << "(); // not implemented\n" + << indent() << cppName << "(" << cppName << " &); // not implemented\n" + << indent() << "~" << cppName << "(); // not implemented\n" + << indent() << "void operator =(" << cppName << "); // not implemented\n"; + dec(); + o << "};\n\n"; + if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) { + o << "\n"; + } + o << "\n#endif // "<< headerDefine << "\n"; +} + +} + +void produce( + OUString const & name, rtl::Reference< TypeManager > const & manager, + codemaker::GeneratedTypeSet & generated, CppuOptions const & options) +{ + if (generated.contains(u2b(name))) { + return; + } + generated.add(u2b(name)); + if (!manager->foundAtPrimaryProvider(name)) { + return; + } + rtl::Reference< unoidl::Entity > ent; + rtl::Reference< unoidl::MapCursor > cur; + switch (manager->getSort(name, &ent, &cur)) { + case codemaker::UnoType::Sort::Module: { + OUString prefix; + if (!name.isEmpty()) { + prefix = name + "."; + } + for (;;) { + OUString mem; + if (!cur->getNext(&mem).is()) { + break; + } + produce(prefix + mem, manager, generated, options); + } + break; + } + case codemaker::UnoType::Sort::Enum: { + EnumType t( + dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()), name, + manager); + t.dump(options); + t.dumpDependedTypes(generated, options); + break; + } + case codemaker::UnoType::Sort::PlainStruct: { + PlainStructType t( + dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()), + name, manager); + t.dump(options); + t.dumpDependedTypes(generated, options); + break; + } + case codemaker::UnoType::Sort::PolymorphicStructTemplate: { + PolyStructType t( + dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >( + ent.get()), + name, manager); + t.dump(options); + t.dumpDependedTypes(generated, options); + break; + } + case codemaker::UnoType::Sort::Exception: { + ExceptionType t( + dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()), name, + manager); + t.dump(options); + t.dumpDependedTypes(generated, options); + break; + } + case codemaker::UnoType::Sort::Interface: { + InterfaceType t( + dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()), name, + manager); + t.dump(options); + t.dumpDependedTypes(generated, options); + break; + } + case codemaker::UnoType::Sort::Typedef: { + Typedef t( + dynamic_cast< unoidl::TypedefEntity * >(ent.get()), name, + manager); + t.dump(options); + t.dumpDependedTypes(generated, options); + break; + } + case codemaker::UnoType::Sort::ConstantGroup: { + ConstantGroup t( + dynamic_cast< unoidl::ConstantGroupEntity * >(ent.get()), name, + manager); + if (t.hasConstants()) { + t.dump(options); + } + break; + } + case codemaker::UnoType::Sort::SingleInterfaceBasedService: { + ServiceType t( + dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >( + ent.get()), + name, manager); + t.dump(options); + t.dumpDependedTypes(generated, options); + break; + } + case codemaker::UnoType::Sort::InterfaceBasedSingleton: { + SingletonType t( + dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >( + ent.get()), + name, manager); + t.dump(options); + t.dumpDependedTypes(generated, options); + break; + } + case codemaker::UnoType::Sort::AccumulationBasedService: + case codemaker::UnoType::Sort::ServiceBasedSingleton: + break; + default: + throw CannotDumpException( + "unexpected entity \"" + name + "\" in call to produce"); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/cpputype.hxx b/codemaker/source/cppumaker/cpputype.hxx new file mode 100644 index 000000000..40fc94f26 --- /dev/null +++ b/codemaker/source/cppumaker/cpputype.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <rtl/ref.hxx> + +namespace codemaker { class GeneratedTypeSet; } +namespace rtl { class OUString; } +class CppuOptions; +class TypeManager; + +void produce( + OUString const & name, rtl::Reference< TypeManager > const & manager, + codemaker::GeneratedTypeSet & generated, CppuOptions const & options); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/dependencies.cxx b/codemaker/source/cppumaker/dependencies.cxx new file mode 100644 index 000000000..1af6b9d46 --- /dev/null +++ b/codemaker/source/cppumaker/dependencies.cxx @@ -0,0 +1,296 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cassert> +#include <utility> +#include <vector> + +#include <codemaker/global.hxx> +#include <codemaker/typemanager.hxx> +#include <codemaker/unotype.hxx> + +#include <rtl/ref.hxx> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> +#include <unoidl/unoidl.hxx> + +#include "dependencies.hxx" + +namespace codemaker::cppumaker { + +Dependencies::Dependencies( + rtl::Reference< TypeManager > const & manager, OUString const & name): + m_manager(manager), m_voidDependency(false), m_booleanDependency(false), + m_byteDependency(false), m_shortDependency(false), + m_unsignedShortDependency(false), m_longDependency(false), + m_unsignedLongDependency(false), m_hyperDependency(false), + m_unsignedHyperDependency(false), m_charDependency(false), + m_stringDependency(false), m_typeDependency(false), m_anyDependency(false), + m_sequenceDependency(false) +{ + assert(manager.is()); + rtl::Reference< unoidl::Entity > ent; + switch (m_manager->getSort(name, &ent)) { + case UnoType::Sort::Enum: + break; + case UnoType::Sort::PlainStruct: + { + rtl::Reference< unoidl::PlainStructTypeEntity > ent2( + static_cast< unoidl::PlainStructTypeEntity * >(ent.get())); + if (!ent2->getDirectBase().isEmpty()) { + insert(ent2->getDirectBase(), KIND_NORMAL); + } + for (const unoidl::PlainStructTypeEntity::Member& member : ent2->getDirectMembers()) + { + insert(member.type, KIND_NORMAL); + } + break; + } + case UnoType::Sort::PolymorphicStructTemplate: + { + rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > ent2( + static_cast< unoidl::PolymorphicStructTypeTemplateEntity * >( + ent.get())); + for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : ent2->getMembers()) + { + if (!member.parameterized) { + insert(member.type, KIND_NORMAL); + } + } + break; + } + case UnoType::Sort::Exception: + { + rtl::Reference< unoidl::ExceptionTypeEntity > ent2( + static_cast< unoidl::ExceptionTypeEntity * >(ent.get())); + if (!ent2->getDirectBase().isEmpty()) { + insert(ent2->getDirectBase(), KIND_NORMAL); + } + for (const unoidl::ExceptionTypeEntity::Member& member : ent2->getDirectMembers()) + { + insert(member.type, KIND_NORMAL); + } + break; + } + case UnoType::Sort::Interface: + { + rtl::Reference< unoidl::InterfaceTypeEntity > ent2( + static_cast< unoidl::InterfaceTypeEntity * >(ent.get())); + for (const unoidl::AnnotatedReference& ar : ent2->getDirectMandatoryBases()) + { + insert(ar.name, KIND_BASE); + } + if (!(ent2->getDirectAttributes().empty() + && ent2->getDirectMethods().empty())) + { + insert(u"com.sun.star.uno.RuntimeException", KIND_EXCEPTION); + } + for (const unoidl::InterfaceTypeEntity::Attribute& attr : ent2->getDirectAttributes()) + { + insert(attr.type, KIND_NORMAL); + for (const OUString& ex : attr.getExceptions) + { + insert(ex, KIND_EXCEPTION); + } + for (const OUString& ex : attr.setExceptions) + { + insert(ex, KIND_EXCEPTION); + } + } + for (const unoidl::InterfaceTypeEntity::Method& method : ent2->getDirectMethods()) + { + insert(method.returnType, KIND_NORMAL); + for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters) + { + insert(param.type, KIND_NORMAL); + } + for (const OUString& ex : method.exceptions) + { + insert(ex, KIND_EXCEPTION); + } + } + break; + } + case UnoType::Sort::Typedef: + insert( + static_cast< unoidl::TypedefEntity * >(ent.get())->getType(), + KIND_NORMAL); + break; + case UnoType::Sort::ConstantGroup: + { + rtl::Reference< unoidl::ConstantGroupEntity > ent2( + static_cast< unoidl::ConstantGroupEntity * >(ent.get())); + for (const unoidl::ConstantGroupEntity::Member& member : ent2->getMembers()) + { + switch (member.value.type) { + case unoidl::ConstantValue::TYPE_BOOLEAN: + m_booleanDependency = true; + break; + case unoidl::ConstantValue::TYPE_BYTE: + m_byteDependency = true; + break; + case unoidl::ConstantValue::TYPE_SHORT: + m_shortDependency = true; + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT: + m_unsignedShortDependency = true; + break; + case unoidl::ConstantValue::TYPE_LONG: + m_longDependency = true; + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_LONG: + m_unsignedLongDependency = true; + break; + case unoidl::ConstantValue::TYPE_HYPER: + m_hyperDependency = true; + break; + case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER: + m_unsignedHyperDependency = true; + break; + case unoidl::ConstantValue::TYPE_FLOAT: + break; + case unoidl::ConstantValue::TYPE_DOUBLE: + break; + } + } + break; + } + case UnoType::Sort::SingleInterfaceBasedService: + { + rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > ent2( + static_cast< unoidl::SingleInterfaceBasedServiceEntity * >( + ent.get())); + if (!ent2->getConstructors().empty()) { + insert(ent2->getBase(), KIND_NORMAL); + } + for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons : ent2->getConstructors()) + { + for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param + : cons.parameters) + { + insert(param.type, KIND_NORMAL); + if (param.rest) { + m_sequenceDependency = true; + } + } + for (const OUString& ex : cons.exceptions) + { + insert(ex, KIND_EXCEPTION); + } + } + break; + } + case UnoType::Sort::InterfaceBasedSingleton: + insert( + static_cast< unoidl::InterfaceBasedSingletonEntity * >(ent.get())-> + getBase(), + KIND_NORMAL); + break; + default: + assert(false); // this cannot happen + } +} + +Dependencies::~Dependencies() {} + +void Dependencies::insert(std::u16string_view name, Kind kind) { + sal_Int32 k; + std::vector< OString > args; + OUString n(b2u(UnoType::decompose(u2b(name), &k, &args))); + if (k != 0) { + m_sequenceDependency = true; + } + switch (m_manager->getSort(n)) { + case UnoType::Sort::Void: + m_voidDependency = true; + break; + case UnoType::Sort::Boolean: + m_booleanDependency = true; + break; + case UnoType::Sort::Byte: + m_byteDependency = true; + break; + case UnoType::Sort::Short: + m_shortDependency = true; + break; + case UnoType::Sort::UnsignedShort: + m_unsignedShortDependency = true; + break; + case UnoType::Sort::Long: + m_longDependency = true; + break; + case UnoType::Sort::UnsignedLong: + m_unsignedLongDependency = true; + break; + case UnoType::Sort::Hyper: + m_hyperDependency = true; + break; + case UnoType::Sort::UnsignedHyper: + m_unsignedHyperDependency = true; + break; + case UnoType::Sort::Float: + break; + case UnoType::Sort::Double: + break; + case UnoType::Sort::Char: + m_charDependency = true; + break; + case UnoType::Sort::String: + m_stringDependency = true; + break; + case UnoType::Sort::Type: + m_typeDependency = true; + break; + case UnoType::Sort::Any: + m_anyDependency = true; + break; + case UnoType::Sort::PolymorphicStructTemplate: + for (const OString& arg : args) + { + insert(b2u(arg), KIND_NORMAL); + } + [[fallthrough]]; + case UnoType::Sort::Sequence: + case UnoType::Sort::Enum: + case UnoType::Sort::PlainStruct: + case UnoType::Sort::Exception: + case UnoType::Sort::Interface: + case UnoType::Sort::Typedef: + { + std::pair< Map::iterator, bool > i( + m_map.emplace(n, kind)); + if (!i.second && kind == KIND_BASE) { + assert(i.first->second != KIND_EXCEPTION); + i.first->second = KIND_BASE; + } + break; + } + default: + throw CannotDumpException( + OUString::Concat("unexpected type \"") + name + + "\" in call to codemaker::cppumaker::Dependencies::Dependencies"); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/dependencies.hxx b/codemaker/source/cppumaker/dependencies.hxx new file mode 100644 index 000000000..0071397aa --- /dev/null +++ b/codemaker/source/cppumaker/dependencies.hxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <map> +#include <string_view> + +#include <rtl/ref.hxx> + +namespace rtl { class OUString; } +class TypeManager; + +/// @HTML + +namespace codemaker::cppumaker { + +/** + A simple class to track which other entities a given entity depends on. + + <p>This class is not multi-thread–safe.</p> + */ +class Dependencies { +public: + /** + Flags to distinguish whether one entity depends on another entity because + the second is a direct base of the first or an exception thrown by the + first. + */ + enum Kind { KIND_NORMAL, KIND_BASE, KIND_EXCEPTION }; + + typedef std::map< OUString, Kind > Map; + + /** + Constructs the dependencies for a given entity. + + @param manager a type manager, to obtain information about the given + entity; must not be null + + @param name the UNOIDL name of an enum type, plain struct type, + polymorphic struct type template, exception type, interface type, + typedef, constant group, single-interface--based service, or + interface-based singleton entity + */ + Dependencies( + rtl::Reference< TypeManager > const & manager, + OUString const & name); + + ~Dependencies(); + + Dependencies(const Dependencies&) = delete; + const Dependencies& operator=(const Dependencies&) = delete; + + Map const & getMap() const { return m_map; } + + bool hasBooleanDependency() const { return m_booleanDependency; } + + bool hasByteDependency() const { return m_byteDependency; } + + bool hasShortDependency() const { return m_shortDependency; } + + bool hasUnsignedShortDependency() const + { return m_unsignedShortDependency; } + + bool hasLongDependency() const { return m_longDependency; } + + bool hasUnsignedLongDependency() const + { return m_unsignedLongDependency; } + + bool hasHyperDependency() const { return m_hyperDependency; } + + bool hasUnsignedHyperDependency() const + { return m_unsignedHyperDependency; } + + bool hasCharDependency() const { return m_charDependency; } + + bool hasStringDependency() const { return m_stringDependency; } + + bool hasTypeDependency() const { return m_typeDependency; } + + bool hasAnyDependency() const { return m_anyDependency; } + + bool hasSequenceDependency() const { return m_sequenceDependency; } + +private: + void insert(std::u16string_view name, Kind kind); + + rtl::Reference< TypeManager > m_manager; + Map m_map; + bool m_voidDependency; + bool m_booleanDependency; + bool m_byteDependency; + bool m_shortDependency; + bool m_unsignedShortDependency; + bool m_longDependency; + bool m_unsignedLongDependency; + bool m_hyperDependency; + bool m_unsignedHyperDependency; + bool m_charDependency; + bool m_stringDependency; + bool m_typeDependency; + bool m_anyDependency; + bool m_sequenceDependency; +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/dumputils.cxx b/codemaker/source/cppumaker/dumputils.cxx new file mode 100644 index 000000000..2a3e809e7 --- /dev/null +++ b/codemaker/source/cppumaker/dumputils.cxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "dumputils.hxx" + +#include <codemaker/global.hxx> + +#include <rtl/ustring.hxx> +#include <sal/types.h> +#include <o3tl/string_view.hxx> + + +namespace codemaker::cppumaker { + +bool dumpNamespaceOpen( + FileStream & out, std::u16string_view entityName, bool fullModuleType) +{ + bool bOutput = false; + bool bFirst = true; + for (sal_Int32 i = 0; i >= 0;) { + std::u16string_view id(o3tl::getToken(entityName, 0, '.', i)); + if (fullModuleType || i >= 0) { + if (!bFirst) { + out << " "; + } + out << "namespace " << id << " {"; + bFirst = false; + bOutput = true; + } + } + return bOutput; +} + +bool dumpNamespaceClose( + FileStream & out, std::u16string_view entityName, bool fullModuleType) +{ + bool bOutput = false; + bool bFirst = true; + for (size_t i = 0; i != std::u16string_view::npos;) { + i = entityName.find('.', i); + if (i != std::u16string_view::npos) { + ++i; + } + if (fullModuleType || i != std::u16string_view::npos) { + if (!bFirst) { + out << " "; + } + out << "}"; + bFirst = false; + bOutput = true; + } + } + return bOutput; +} + +void dumpTypeIdentifier(FileStream & out, std::u16string_view entityName) { + out << entityName.substr(entityName.rfind('.') + 1); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/dumputils.hxx b/codemaker/source/cppumaker/dumputils.hxx new file mode 100644 index 000000000..24e5bae3b --- /dev/null +++ b/codemaker/source/cppumaker/dumputils.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> +#include <string_view> + +namespace rtl +{ +class OUString; +} +class FileStream; + +namespace codemaker::cppumaker +{ +bool dumpNamespaceOpen(FileStream& out, std::u16string_view entityName, bool fullModuleType); + +bool dumpNamespaceClose(FileStream& out, std::u16string_view entityName, bool fullModuleType); + +void dumpTypeIdentifier(FileStream& out, std::u16string_view entityName); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/includes.cxx b/codemaker/source/cppumaker/includes.cxx new file mode 100644 index 000000000..9dacdf268 --- /dev/null +++ b/codemaker/source/cppumaker/includes.cxx @@ -0,0 +1,273 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "includes.hxx" + +#include "dependencies.hxx" +#include "dumputils.hxx" + +#include <codemaker/global.hxx> +#include <codemaker/typemanager.hxx> +#include <codemaker/unotype.hxx> + +#include <osl/diagnose.h> +#include <rtl/ref.hxx> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> + +#include <utility> +#include <vector> + +using codemaker::cppumaker::Includes; + +Includes::Includes( + rtl::Reference< TypeManager > manager, + codemaker::cppumaker::Dependencies const & dependencies, bool hpp): + m_manager(std::move(manager)), m_map(dependencies.getMap()), m_hpp(hpp), + m_includeCassert(false), + m_includeAny(dependencies.hasAnyDependency()), m_includeReference(false), + m_includeSequence(dependencies.hasSequenceDependency()), + m_includeType(dependencies.hasTypeDependency()), + m_includeCppuMacrosHxx(false), m_includeCppuUnotypeHxx(false), + m_includeOslMutexHxx(false), + m_includeRtlStrbufHxx(false), m_includeRtlStringH(false), + m_includeRtlTextencH(false), m_includeRtlUstrbufHxx(false), + m_includeRtlUstringH(false), + m_includeRtlUstringHxx(dependencies.hasStringDependency()), + m_includeRtlInstanceHxx(false), + m_includeSalTypesH( + dependencies.hasBooleanDependency() || dependencies.hasByteDependency() + || dependencies.hasShortDependency() + || dependencies.hasUnsignedShortDependency() + || dependencies.hasLongDependency() + || dependencies.hasUnsignedLongDependency() + || dependencies.hasHyperDependency() + || dependencies.hasUnsignedHyperDependency() + || dependencies.hasCharDependency()), + m_includeTypelibTypeclassH(false), + m_includeTypelibTypedescriptionH(false) +{} + +Includes::~Includes() +{} + +void Includes::add(OString const & entityName) { + sal_Int32 k; + std::vector< OString > args; + OUString n(b2u(codemaker::UnoType::decompose(entityName, &k, &args))); + if (k != 0) { + m_includeSequence = true; + } + switch (m_manager->getSort(n)) { + case codemaker::UnoType::Sort::Boolean: + case codemaker::UnoType::Sort::Byte: + case codemaker::UnoType::Sort::Short: + case codemaker::UnoType::Sort::UnsignedShort: + case codemaker::UnoType::Sort::Long: + case codemaker::UnoType::Sort::UnsignedLong: + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + case codemaker::UnoType::Sort::Char: + m_includeSalTypesH = true; + break; + case codemaker::UnoType::Sort::Float: + case codemaker::UnoType::Sort::Double: + break; + case codemaker::UnoType::Sort::String: + m_includeRtlUstringHxx = true; + break; + case codemaker::UnoType::Sort::Type: + m_includeType = true; + break; + case codemaker::UnoType::Sort::Any: + m_includeAny = true; + break; + case codemaker::UnoType::Sort::PolymorphicStructTemplate: + for (const OString& arg : args) + { + add(arg); + } + [[fallthrough]]; + case codemaker::UnoType::Sort::Sequence: + case codemaker::UnoType::Sort::Enum: + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::Exception: + case codemaker::UnoType::Sort::Interface: + case codemaker::UnoType::Sort::Typedef: + m_map.emplace(n, Dependencies::KIND_NORMAL); + break; + default: + throw CannotDumpException( + "unexpected type \"" + b2u(entityName) + + "\" in call to codemaker::cppumaker::Includes::add"); + } +} + +namespace { + +void dumpEmptyLineBeforeFirst(FileStream & out, bool * first) { + OSL_ASSERT(first != nullptr); + if (*first) { + out << "\n"; + *first = false; + } +} + +} + +void Includes::dump( + FileStream & out, OUString const * companionHdl, bool exceptions) +{ + OSL_ASSERT(companionHdl == nullptr || m_hpp); + if (!m_includeReference) { + for (const auto& pair : m_map) + { + if (isInterfaceType(u2b(pair.first))) { + m_includeReference = true; + break; + } + } + } + out << "#include \"sal/config.h\"\n"; + if (m_includeCassert) { + out << "\n#include <cassert>\n"; + } + if (companionHdl) { + out << "\n"; + dumpInclude(out, u2b(*companionHdl), false); + } + bool first = true; + for (const auto& pair : m_map) + { + if (exceptions || pair.second != Dependencies::KIND_EXCEPTION) { + dumpEmptyLineBeforeFirst(out, &first); + if (m_hpp || pair.second == Dependencies::KIND_BASE + || !isInterfaceType(u2b(pair.first))) + { + // If we know our name, then avoid including ourselves. + if (!companionHdl || *companionHdl != pair.first) { + dumpInclude(out, u2b(pair.first), m_hpp); + } + } else { + bool ns = dumpNamespaceOpen(out, pair.first, false); + if (ns) { + out << " "; + } + out << "class "; + dumpTypeIdentifier(out, pair.first); + out << ";"; + if (ns) { + out << " "; + } + dumpNamespaceClose(out, pair.first, false); + out << "\n"; + } + } + } + static char const * hxxExtension[2] = { "h", "hxx" }; + if (m_includeAny) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"com/sun/star/uno/Any." << hxxExtension[m_hpp] + << "\"\n"; + } + if (m_includeReference) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"com/sun/star/uno/Reference." << hxxExtension[m_hpp] + << "\"\n"; + } + if (m_includeSequence) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"com/sun/star/uno/Sequence." << hxxExtension[m_hpp] + << "\"\n"; + } + if (m_includeType) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"com/sun/star/uno/Type." << hxxExtension[m_hpp] + << "\"\n"; + } + if (m_includeCppuMacrosHxx) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"cppu/macros.hxx\"\n"; + } + if (m_includeCppuUnotypeHxx) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"cppu/unotype.hxx\"\n"; + } + if (m_includeOslMutexHxx) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"osl/mutex.hxx\"\n"; + } + if (m_includeRtlStrbufHxx) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"rtl/strbuf.hxx\"\n"; + } + if (m_includeRtlStringH) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"rtl/string.h\"\n"; + } + if (m_includeRtlTextencH) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"rtl/textenc.h\"\n"; + } + if (m_includeRtlUstrbufHxx) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"rtl/ustrbuf.hxx\"\n"; + } + if (m_includeRtlUstringH) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"rtl/ustring.h\"\n"; + } + if (m_includeRtlUstringHxx) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"rtl/ustring.hxx\"\n"; + } + if (m_includeRtlInstanceHxx) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"rtl/instance.hxx\"\n"; + } + if (m_includeSalTypesH) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"sal/types.h\"\n"; + } + if (m_includeTypelibTypeclassH) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"typelib/typeclass.h\"\n"; + } + if (m_includeTypelibTypedescriptionH) { + dumpEmptyLineBeforeFirst(out, &first); + out << "#include \"typelib/typedescription.h\"\n"; + } + for (OUString const & s : m_custom) + out << s << "\n"; +} + +void Includes::dumpInclude( + FileStream & out, OString const & entityName, bool hpp) +{ + out << "#include \"" << entityName.replace('.', '/') << "." + << (hpp ? "hpp" : "hdl") << "\"\n"; +} + +bool Includes::isInterfaceType(std::string_view entityName) const { + return m_manager->getSort(b2u(entityName)) == UnoType::Sort::Interface; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/codemaker/source/cppumaker/includes.hxx b/codemaker/source/cppumaker/includes.hxx new file mode 100644 index 000000000..8cd830b4a --- /dev/null +++ b/codemaker/source/cppumaker/includes.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <rtl/ref.hxx> +#include <rtl/ustring.hxx> +#include <string_view> +#include <vector> +#include "dependencies.hxx" + +class FileStream; +class TypeManager; + +namespace codemaker::cppumaker { + +class Includes { +public: + Includes( + rtl::Reference< TypeManager > manager, + Dependencies const & dependencies, bool hpp); + + ~Includes(); + + void add(OString const & entityName); + void addCassert() { m_includeCassert = true; } + void addAny() { m_includeAny = true; } + void addReference() { m_includeReference = true; } + void addSequence() { m_includeSequence = true; } + void addType() { m_includeType = true; } + void addCppuMacrosHxx() { m_includeCppuMacrosHxx = true; } + void addCppuUnotypeHxx() { m_includeCppuUnotypeHxx = true; } + void addOslMutexHxx() { m_includeOslMutexHxx = true; } + void addRtlStrbufHxx() { m_includeRtlStrbufHxx = true; } + void addRtlStringH() { m_includeRtlStringH = true; } + void addRtlTextencH() { m_includeRtlTextencH = true; } + void addRtlUstrbufHxx() { m_includeRtlUstrbufHxx = true; } + void addRtlUstringH() { m_includeRtlUstringH = true; } + void addRtlUstringHxx() { m_includeRtlUstringHxx = true; } + void addRtlInstanceHxx() { m_includeRtlInstanceHxx = true; } + void addSalTypesH() { m_includeSalTypesH = true; } + void addTypelibTypeclassH() { m_includeTypelibTypeclassH = true; } + void addTypelibTypedescriptionH() + { m_includeTypelibTypedescriptionH = true; } + void addCustom(const OUString& s) { m_custom.push_back(s); } + void dump( + FileStream & out, OUString const * companionHdl, bool exceptions); + + static void dumpInclude( + FileStream & out, OString const & entityName, bool hpp); + +private: + Includes(Includes const &) = delete; + Includes& operator =(const Includes&) = delete; + + bool isInterfaceType(std::string_view entityName) const; + + rtl::Reference< TypeManager > m_manager; + Dependencies::Map m_map; + bool m_hpp; + bool m_includeCassert; + bool m_includeAny; + bool m_includeReference; + bool m_includeSequence; + bool m_includeType; + bool m_includeCppuMacrosHxx; + bool m_includeCppuUnotypeHxx; + bool m_includeOslMutexHxx; + bool m_includeRtlStrbufHxx; + bool m_includeRtlStringH; + bool m_includeRtlTextencH; + bool m_includeRtlUstrbufHxx; + bool m_includeRtlUstringH; + bool m_includeRtlUstringHxx; + bool m_includeRtlInstanceHxx; + bool m_includeSalTypesH; + bool m_includeTypelibTypeclassH; + bool m_includeTypelibTypedescriptionH; + std::vector<OUString> m_custom; +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |