Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/unodevtools/source/skeletonmaker/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 20 kB image not shown  

Quelle  skeletoncommon.cxx   Sprache: C

 
/* -*- 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 <codemaker/commoncpp.hxx>
#include <codemaker/generatedtypeset.hxx>
#include <codemaker/global.hxx>
#include <unoidl/unoidl.hxx>

#include "skeletoncommon.hxx"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <string_view>

using namespace ::codemaker::cpp;

namespace skeletonmaker {

void printLicenseHeader(std::ostream& o)
{
    o << "/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n"
         "/*\n"
         " * This file is part of the LibreOffice project.\n"
         " *\n"
         " * This Source Code Form is subject to the terms of the Mozilla Public\n"
         " * License, v. 2.0. If a copy of the MPL was not distributed with this\n"
         " * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n"
         " */\n\n";
}

bool getOutputStream(ProgramOptions const & options,
                     OString const & extension,
                     std::ostream** ppOutputStream,
                     OString & targetSourceFileName,
                     OString & tmpSourceFileName)
{
    bool bStandardout = false;
    if ( options.outputpath == "stdout" )
    {
        bStandardout = true;
        *ppOutputStream = &std::cout;
        return bStandardout;
    }

    targetSourceFileName = createFileNameFromType(
        options.outputpath, options.implname.replace('.','/'), extension);

    OString tmpDir = getTempDir(targetSourceFileName);
    FileStream file;
    file.createTempFile(tmpDir);

    if( !file.isValid() )
    {
        throw CannotDumpException(
            "cannot open " + b2u(targetSourceFileName) + " for writing");
    }
    tmpSourceFileName = file.getName();
    file.close();
    *ppOutputStream = new std::ofstream(tmpSourceFileName.getStr(),
                                        std::ios_base::binary);

    return bStandardout;
}

static bool containsAttribute(AttributeInfo& attributes, OUString const & attrname)
{
    return std::any_of(attributes.begin(), attributes.end(),
        [&attrname](const unoidl::AccumulationBasedServiceEntity::Property&&nbsp;rAttr) {
            return rAttr.name == attrname; });
}

// collect attributes including inherited attributes
static void checkAttributes(rtl::Reference< TypeManager > const & manager,
                     OUString const & name,
                     AttributeInfo& attributes,
                     std::set< OUString >& propinterfaces)
{
    if ( name == "com.sun.star.beans.XPropertySet" ||
         name == "com.sun.star.beans.XFastPropertySet" ||
         name == "com.sun.star.beans.XPropertyAccess" )
    {
        propinterfaces.insert(name);
    }
    rtl::Reference< unoidl::Entity > ent;
    switch (manager->getSort(name, &ent)) {
    case codemaker::UnoType::Sort::Interface:
        {
            rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
                dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
            assert(ent2.is());
            for (const auto& rBase : ent2->getDirectMandatoryBases())
            {
                checkAttributes(manager, rBase.name, attributes, propinterfaces);
            }
            for (const auto& rAttr : ent2->getDirectAttributes())
            {
                if (!containsAttribute(attributes, rAttr.name)) {
                    attributes.emplace_back(
                        rAttr.name, rAttr.type,
                        (unoidl::AccumulationBasedServiceEntity::Property::
                         Attributes(
                             ((rAttr.bound
                               ? unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_BOUND
                               : 0)
                              | (rAttr.readOnly
                                 ? unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_READ_ONLY
                                 : 0)))),
                        std::vector< OUString >());
                }
            }
            break;
        }
    case codemaker::UnoType::Sort::AccumulationBasedService:
        {
            rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
                dynamic_cast< unoidl::AccumulationBasedServiceEntity * >(
                    ent.get()));
            assert(ent2.is());
            for (const auto& rService : ent2->getDirectMandatoryBaseServices())
            {
                checkAttributes(manager, rService.name, attributes, propinterfaces);
            }
            for (const auto& rIface : ent2->getDirectMandatoryBaseInterfaces())
            {
                checkAttributes(manager, rIface.name, attributes, propinterfaces);
            }
            for (const auto& rProp : ent2->getDirectProperties())
            {
                if (!containsAttribute(attributes, rProp.name)) {
                    attributes.push_back(rProp);
                }
            }
            break;
        }
    default:
        throw CannotDumpException(
            "unexpected entity \"" + name
            + "\" in call to skeletonmaker::checkAttributes");
    }
}

void checkType(rtl::Reference< TypeManager > const & manager,
               OUString const & name,
               std::set< OUString >& interfaceTypes,
               std::set< OUString >& serviceTypes,
               AttributeInfo& properties)
{
    rtl::Reference< unoidl::Entity > ent;
    switch (manager->getSort(name, &ent)) {
    case codemaker::UnoType::Sort::Interface:
        // com.sun.star.lang.XComponent should be also not in the list
        // but it will be used for checking the impl helper and will be
        // removed later if necessary.
        if ( name == "com.sun.star.lang.XTypeProvider" ||
             name == "com.sun.star.uno.XWeak" )
            return;
        interfaceTypes.insert(name);
        break;
    case codemaker::UnoType::Sort::SingleInterfaceBasedService:
        if (serviceTypes.insert(name).second) {
            rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > ent2(
                dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
                    ent.get()));
            assert(ent2.is());
            if (interfaceTypes.insert(ent2->getBase()).second) {
                // check if constructors are specified, if yes automatically
                // support of XInitialization. We will take care of the default
                // constructor because in this case XInitialization is not
                // called.
                if (ent2->getConstructors().size() > 1 ||
                    (ent2->getConstructors().size() == 1 &&
                     !ent2->getConstructors()[0].defaultConstructor))
                {
                    interfaceTypes.insert(u"com.sun.star.lang.XInitialization"_ustr);
                }
            }
        }
        break;
    case codemaker::UnoType::Sort::AccumulationBasedService:
        if ( serviceTypes.insert(name).second ) {
            rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
                dynamic_cast< unoidl::AccumulationBasedServiceEntity * >(
                    ent.get()));
            assert(ent2.is());
            for (const auto& rService : ent2->getDirectMandatoryBaseServices())
            {
                checkType(
                    manager, rService.name, interfaceTypes, serviceTypes, properties);
            }
            for (const auto& rIface : ent2->getDirectMandatoryBaseInterfaces())
            {
                checkType(
                    manager, rIface.name, interfaceTypes, serviceTypes, properties);
            }
            for (const auto& rProp : ent2->getDirectProperties())
            {
                properties.push_back(rProp);
            }
        }
        break;
    default:
        throw CannotDumpException(
            "unexpected entity \"" + name
            + "\" in call to skeletonmaker::checkType");
    }
}

void checkDefaultInterfaces(
    std::set< OUString >& interfaces,
    const std::set< OUString >& services,
    std::u16string_view propertyhelper)
{
    if ( services.empty() ) {
        interfaces.erase(u"com.sun.star.lang.XServiceInfo"_ustr);
    } else {
        interfaces.insert(u"com.sun.star.lang.XServiceInfo"_ustr);
    }

    if ( propertyhelper == u"_" ) {
        interfaces.erase(u"com.sun.star.beans.XPropertySet"_ustr);
        interfaces.erase(u"com.sun.star.beans.XFastPropertySet"_ustr);
        interfaces.erase(u"com.sun.star.beans.XPropertyAccess"_ustr);
    }
}

static bool checkServiceProperties(rtl::Reference< TypeManager > const & manager,
                            OUString const & name)
{
    rtl::Reference< unoidl::Entity > ent;
    if (manager->getSort(name, &ent)
        == codemaker::UnoType::Sort::AccumulationBasedService)
    {
        rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
            dynamic_cast< unoidl::AccumulationBasedServiceEntity * >(
                ent.get()));
        assert(ent2.is());
        if (!ent2->getDirectProperties().empty()) {
            return true;
        }
        return std::any_of(ent2->getDirectMandatoryBaseServices().begin(),
            ent2->getDirectMandatoryBaseServices().end(),
            [&manager](const unoidl::AnnotatedReference& rService) {
                return checkServiceProperties(manager, rService.name); });
    }
    return false;
}


OUString checkPropertyHelper(
    ProgramOptions const & options,
    rtl::Reference< TypeManager > const & manager,
    const std::set< OUString >& services,
    const std::set< OUString >& interfaces,
    AttributeInfo& attributes,
    std::set< OUString >& propinterfaces)
{
    std::set< OUString >::const_iterator iter;
    std::set< OUString >::const_iterator end;

    if ( !services.empty() ) {
        iter = services.begin();
        end = services.end();
    } else {
        iter = interfaces.begin();
        end = interfaces.end();
    }

    bool oldStyleWithProperties = false;
    while ( iter != end ) {
        rtl::Reference< unoidl::Entity > ent;
        codemaker::UnoType::Sort sort = manager->getSort(*iter, &ent);
        if ( !services.empty() ) {
            if (options.supportpropertysetmixin
                && (sort
                    == codemaker::UnoType::Sort::SingleInterfaceBasedService))
            {
                rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity >
                    ent2(
                        dynamic_cast<
                        unoidl::SingleInterfaceBasedServiceEntity * >(
                            ent.get()));
                assert(ent2.is());
                checkAttributes(
                    manager, ent2->getBase(), attributes, propinterfaces);
                if (!(attributes.empty() || propinterfaces.empty())) {
                    return ent2->getBase();
                }
            } else {
                oldStyleWithProperties = checkServiceProperties(manager, *iter);
            }
        } else {
            checkAttributes(manager, *iter, attributes, propinterfaces);
            if (!(attributes.empty() || propinterfaces.empty())) {
                return *iter;
            }
        }
        ++iter;
    }

    return oldStyleWithProperties ? u"_"_ustr : OUString();
}

static bool checkXComponentSupport(
    rtl::Reference< TypeManager > const & manager, OUString const & name)
{
    assert(manager.is());
    if (name == "com.sun.star.lang.XComponent") {
        return true;
    }
    rtl::Reference< unoidl::Entity > ent;
    codemaker::UnoType::Sort sort = manager->getSort(name, &ent);
    if (sort != codemaker::UnoType::Sort::Interface) {
        throw CannotDumpException(
            "unexpected entity \"" + name
            + "\" in call to skeletonmaker::checkXComponentSupport");
    }
    rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
        dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
    assert(ent2.is());
    return std::any_of(ent2->getDirectMandatoryBases().begin(), ent2->getDirectMandatoryBases().end(),
        [&manager](const unoidl::AnnotatedReference& rBase) { return checkXComponentSupport(manager, rBase.name); });
}


// if XComponent is directly specified, return true and remove it from the
// supported interfaces list
bool checkXComponentSupport(rtl::Reference< TypeManager > const & manager,
                            std::set< OUString >& interfaces)
{
    if ( interfaces.empty() )
        return false;

    for ( const auto& rIface : interfaces ) {
        if ( rIface == "com.sun.star.lang.XComponent" ) {
            interfaces.erase(u"com.sun.star.lang.XComponent"_ustr);
            return true;
        }
        if ( checkXComponentSupport(manager, rIface) )
            return true;
    }

    return false;
}

unoidl::AccumulationBasedServiceEntity::Property::Attributes
checkAdditionalPropertyFlags(
    unoidl::InterfaceTypeEntity::Attribute const & attribute)
{
    int flags = 0;
    bool getterSupportsUnknown = false;
    for (const auto& rException : attribute.getExceptions)
    {
        if (rException == "com.sun.star.beans.UnknownPropertyException") {
            getterSupportsUnknown = true;
        }
    }
    for (const auto& rException : attribute.setExceptions)
    {
        if (rException == "com.sun.star.beans.PropertyVetoException") {
            flags |= unoidl::AccumulationBasedServiceEntity::Property::
                ATTRIBUTE_CONSTRAINED;
        } else if (getterSupportsUnknown
                   && rException == "com.sun.star.beans.UnknownPropertyException")
        {
            flags |= unoidl::AccumulationBasedServiceEntity::Property::
                ATTRIBUTE_OPTIONAL;
        }
    }
    return unoidl::AccumulationBasedServiceEntity::Property::Attributes(flags);
}

// This function checks if the specified types for parameters and return
// types are allowed add-in types, for more info see the com.sun.star.sheet.AddIn
// service description
static bool checkAddinType(rtl::Reference< TypeManager > const & manager,
                    std::u16string_view type, bool & bLastAny,
                    bool & bHasXPropertySet, bool bIsReturn)
{
    assert(manager.is());
    sal_Int32 rank;
    codemaker::UnoType::Sort sort = manager->decompose(
        type, true, nullptr, &rank, nullptr, nullptr);

    if ( sort == codemaker::UnoType::Sort::Long ||
         sort == codemaker::UnoType::Sort::Double ||
         sort == codemaker::UnoType::Sort::String )
    {
        if ( rank == 0 || rank ==2 )
            return true;
    }
    if ( sort == codemaker::UnoType::Sort::Any )
    {
        if ( rank <= 2 ) {
            if ( rank ==1 ) {
                if ( bIsReturn )
                    return false;
                bLastAny = true;
            }

            return true;
        }
    }
    if ( sort == codemaker::UnoType::Sort::Interface )
    {
        if ( bIsReturn && type == u"com.sun.star.sheet.XVolatileResult" )
            return true;
        if ( !bIsReturn && type == u"com.sun.star.table.XCellRange" )
            return true;
        if ( !bIsReturn && type == u"com.sun.star.beans.XPropertySet" )
        {
            if ( bHasXPropertySet ) {
                return false;
            } else {
                bHasXPropertySet = true;
                return true;
            }
        }
    }
    return false;
}

static void checkAddInTypes(
    rtl::Reference< TypeManager > const & manager, std::u16string_view name,
    rtl::Reference< unoidl::InterfaceTypeEntity > const & entity)
{
    assert(entity.is());
    bool bLastAny = false;
    bool bHasXPropertySet = false;
    for (const auto& rMethod : entity->getDirectMethods())
    {
        if ( !checkAddinType(
                 manager, rMethod.returnType, bLastAny, bHasXPropertySet, true) )
        {
            throw CannotDumpException(
                OUString::Concat("the return type of the calc add-in function '") + name
                + ":" + rMethod.name
                + "' is invalid. Please check your IDL definition.");
        }

        bHasXPropertySet = false;
        for (const auto& rParam : rMethod.parameters)
        {
            bLastAny = false;
            if ( !checkAddinType(manager, rParam.type,
                                bLastAny, bHasXPropertySet, false) ||
                 bLastAny )
            {
                throw CannotDumpException(
                    "the type of the " + rParam.name
                    + " parameter of the calc add-in function '" + name
                    + ":" + rMethod.name + "' is invalid."
                    + (bLastAny
                       ? u" The type 'sequence' is allowed as last"
                           " parameter only."_ustr
                       : OUString())
                    + (bHasXPropertySet
                       ? u" The type 'XPropertySet' is allowed only once."_ustr
                       : OUString())
                    + " Please check your IDL definition.");
            }
        }
    }
}

static void generateFunctionParameterMap(std::ostream& o,
                                 ProgramOptions const & options,
                                 rtl::Reference< TypeManager > const & manager,
                                 OUString const & name,
                                 ::codemaker::GeneratedTypeSet & generated,
                                 bool& bFirst)
{
    if ( name == "com.sun.star.uno.XInterface" ||
         name == "com.sun.star.lang.XLocalizable" ||
         name == "com.sun.star.lang.XServiceInfo" ||
         // the next three checks becomes obsolete when configuration is used
         name == "com.sun.star.sheet.XAddIn" ||
         name == "com.sun.star.sheet.XCompatibilityNames" ||
         name == "com.sun.star.lang.XServiceName" )
    {
        return;
    }

    rtl::Reference< unoidl::Entity > ent;
    codemaker::UnoType::Sort sort = manager->getSort(name, &ent);
    if (sort != codemaker::UnoType::Sort::Interface) {
        throw CannotDumpException(
            "unexpected entity \"" + name
            + "\" in call to skeletonmaker::generateFunctionParameterMap");
    }
    rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
        dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
    assert(ent2.is());

    // check if the specified add-in functions supports valid types
    checkAddInTypes(manager, name, ent2);

    for (const auto& rBase : ent2->getDirectMandatoryBases())
    {
        generateFunctionParameterMap(
            o, options, manager, rBase.name, generated, bFirst);
    }

    if ( generated.contains(u2b(name)) )
        return;
    else
        generated.add(u2b(name));

    for (const auto& rMethod : ent2->getDirectMethods())
    {
        if ( bFirst ) {
            if (options.language == 2) {
                o << " ParamMap fpm;\n";
            }
            else {
                o << " java.util.Hashtable< Integer, String > fpm = "
                    "new java.util.Hashtable< Integer, String >();\n";
            }
            bFirst = false;
        } else
            if ( options.language == 2 ) {
                o << " fpm = ParamMap();\n";
            }
            else {
                o << " fpm = new java.util.Hashtable< "
                    "Integer, String >();\n";
            }

        std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::size_type
            n = 0;
        for (const auto& rParam : rMethod.parameters)
        {
            if ( options.language == 2 ) {
                o << " fpm[" << n
                  << "] = OUString(\""
                  << rParam.name
                  << "\");\n";
            }
            else {
                o << " fpm.put(" << n << ", \""
                  << rParam.name
                  << "\");\n";
            }
            ++n;
        }

        if ( options.language == 2 ) {
            o << " m_functionMap[OUString(\""
              << rMethod.name << "\")] = fpm;\n\n";
        }
        else {
            o << " m_functionMap.put(\"" << rMethod.name << "\", fpm);\n\n";
        }
    }
}

void generateFunctionParameterMap(std::ostream& o,
         ProgramOptions const & options,
         rtl::Reference< TypeManager > const & manager,
         const std::set< OUString >& interfaces)
{
    ::codemaker::GeneratedTypeSet generated;
    bool bFirst = true;
    for ( const auto& rIface : interfaces ) {
        generateFunctionParameterMap(o, options, manager, rIface, generated, bFirst);
    }
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

94%


¤ Dauer der Verarbeitung: 0.9 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.