<commit_before>////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2005 by Andrei Alexandrescu
// Permission to use, copy, modify, distribute, and sell this software for any
//     purpose is hereby granted without fee, provided that the above copyright
//     notice appear in all copies and that both that copyright notice and this
//     permission notice appear in supporting documentation.
// The author makes no representations about the suitability of this software
//     for any purpose. It is provided "as is" without express or implied
//     warranty.
////////////////////////////////////////////////////////////////////////////////

#include <loki/SafeFormat.h>
#include <iostream>
#include <cassert>
#include <utility>

#include "../SmallObj/timer.h"

using namespace std;

template <class Integral1, class Integral2>
Integral2 RandomInt(Integral1 low, Integral2 up)
{
    // From ``Accelerated C++'', page 135:
    // random integer in the range [0, n)
    // We adjust to generate in the range [0, n]
    const Integral2
    low2 = low,
           n = up - low;

    assert(n > 0);

    const unsigned int bucket_size = RAND_MAX / n;
    assert(bucket_size > 0);

    Integral2 r;
    do
        r = Integral2(rand() / bucket_size);
    while (r > n);

    r += low2;
    assert(r >= low2 && r <= up);
    return r;
}

string RandomString(unsigned int maxSize)
{
    string result(RandomInt(0, maxSize), '\0');
    unsigned int i = 0;
    for (; i != result.size(); ++i)
    {
        result[i] = RandomInt('a', 'z');
    }
    return result;
}

template <class T>
void TestCase(const string& fmt, T value)
{
    char buf[4096];
    std::string s;
    const int i1 = SPrintf(s, fmt.c_str())(value);

#ifdef _MSC_VER
    const int i2 = _snprintf(buf, sizeof(buf), fmt.c_str(), value);
#else
    const int i2 = snprintf(buf, sizeof(buf), fmt.c_str(), value);
#endif

    if (i1 != i2 || s != buf)
    {
        cout << endl
        << "Reference: " << i2 << "; Actual: " << i1 << ",  Difference = " << i2-i1 << endl
        << "V: [" << value << "]" << endl
        << "F: [" << fmt << "]" << endl
        << "R: [" << buf << "]" << endl
        << "A: [" << s.c_str() << "]" << endl;
        assert(false);
    }
}

template <class T, class U>
void TestCase2(const string& fmt, T value, U value2)
{
    char buf[4096];
    std::string s;
    const int i1 = SPrintf(s, fmt.c_str())(value)(value2);
    const int i2 = snprintf(buf, sizeof(buf), fmt.c_str(), value, value2);
    assert(i1 == i2);
    assert(s == buf);
}

int main(int argc, char** argv)
{
	if(sizeof(size_t) > 4)
	{
		std::cout << "\n\nSPrintf does not work for negative \n";
		std::cout << "integer values on 64 bit systems !!! \n\n";
	}

    if (argc == 2)
    {
        // test speed

        Timer t;

        int loop = atoi(argv[1]);

        if(loop < 100)
            loop = 100;

        t.start();
        for (int i=loop; i > 0; --i)
            printf("Hey, %u frobnicators and %u twiddlicators\n",i, i);
        t.stop();
        t.t100 = t.t();
        int t_printf = t.t();

        t.start();
        for (int i=loop; i > 0; --i)
            Printf("Hey, %u frobnicators and %u twiddlicators\n")(i)(i);
        t.stop();
        int t_Printf = t.t();

        t.start();
        for (int i=loop; i > 0; --i)
            cout << "Hey, " << i << " frobnicators and " << i <<" twiddlicators\n";
        t.stop();
        int t_cout = t.t();

        Printf("\n\nElapsed time for %i outputs\n\n")(loop);
        t.print(t_printf,"printf   : ");
        t.print(t_Printf,"Printf   : ");
        t.print(t_cout,  "std::cout: ");
    }
    else
    {
        //srand(time(0));
        srand(0);
        printf("\nNumber of tests:\n");
        for (unsigned i = 0; ; ++i)
        {
            printf("%u\r", i);

            // Generate a random string for the head
            string lead = RandomString(100);
            // This string will hold a random format specification
            string formatSpec(lead + "|%");
            // Generate a random set of flags
            static const string flags("-+0 #");
            unsigned int maxFlags = RandomInt(0u, flags.length() - 1);
            for (unsigned int i = 0; i != maxFlags; ++i)
            {
                formatSpec += flags[RandomInt(0u, flags.length() - 1)];
            }
            // Generate an optional random width
            if (RandomInt(0, 1))
            {
                const unsigned int width = RandomInt(0, 100);
                char buf[4];
                sprintf(buf, "%u", width);
                formatSpec += buf;
            }
            // Generate an optional random precision
            if (RandomInt(0, 1))
            {
                const unsigned int prec = RandomInt(0, 100);
                char buf[4];
                sprintf(buf, "%u", prec);
                formatSpec += '.';
                formatSpec += buf;
            }

            // Generate a random type character
            /* disable %p tests
            static const string type("cdeEfgGinopsuxX");*/
            static const string type("cdeEfgGinosuxX");

            const char typeSpec = type[RandomInt(0, type.size() - 1)];
            // Generate an optional type prefix
            static const string prefix("hl");
            if (typeSpec != 's' && RandomInt(0, 1))
            {
                formatSpec += prefix[RandomInt(0, prefix.size() - 1)];
            }
            formatSpec += typeSpec;
            formatSpec += '|';
            formatSpec += RandomString(100);

            switch (typeSpec)
            {
            case 'c':
                TestCase(formatSpec, RandomInt(1, 127));
                break;
            case 'd':
            case 'i':
            case 'o':
            case 'u':
            case 'x':
            case 'X':
                //TestCase(formatSpec, RandomInt(-10000, 10000));
				// don't test negative values on 64bit systems
				TestCase(formatSpec, RandomInt( -10000 * (sizeof(size_t)>4 ? 0 : 1) , 10000));
                break;
            case 'e':
            case 'E':
            case 'f':
            case 'g':
            case 'G':
                TestCase(formatSpec,
                         RandomInt(-10000, 10000) / double(RandomInt(1, 100)));
                break;
            case 'n':
                break;
            case 'p':
                {
                    void * p = malloc(RandomInt(1, 1000));
                    TestCase(formatSpec, p);
                    free(p);
                }
                break;
            case 's':
                TestCase(formatSpec, RandomString(100).c_str());
                break;
            default:
                assert(false);
                break;
            }
        }
    }
}
<commit_msg>test fails because snprintf does not support 64bit values, therefore tests on negative integer values is disabled<commit_after>////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2005 by Andrei Alexandrescu
// Permission to use, copy, modify, distribute, and sell this software for any
//     purpose is hereby granted without fee, provided that the above copyright
//     notice appear in all copies and that both that copyright notice and this
//     permission notice appear in supporting documentation.
// The author makes no representations about the suitability of this software
//     for any purpose. It is provided "as is" without express or implied
//     warranty.
////////////////////////////////////////////////////////////////////////////////

#include <loki/SafeFormat.h>
#include <iostream>
#include <cassert>
#include <utility>

#include "../SmallObj/timer.h"

using namespace std;

template <class Integral1, class Integral2>
Integral2 RandomInt(Integral1 low, Integral2 up)
{
    // From ``Accelerated C++'', page 135:
    // random integer in the range [0, n)
    // We adjust to generate in the range [0, n]
    const Integral2
    low2 = low,
           n = up - low;

    assert(n > 0);

    const unsigned int bucket_size = RAND_MAX / n;
    assert(bucket_size > 0);

    Integral2 r;
    do
        r = Integral2(rand() / bucket_size);
    while (r > n);

    r += low2;
    assert(r >= low2 && r <= up);
    return r;
}

string RandomString(unsigned int maxSize)
{
    string result(RandomInt(0, maxSize), '\0');
    unsigned int i = 0;
    for (; i != result.size(); ++i)
    {
        result[i] = RandomInt('a', 'z');
    }
    return result;
}

template <class T>
void TestCase(const string& fmt, T value)
{
    char buf[4096];
    std::string s;
    const int i1 = SPrintf(s, fmt.c_str())(value);

#ifdef _MSC_VER
    const int i2 = _snprintf(buf, sizeof(buf), fmt.c_str(), value);
#else
    const int i2 = snprintf(buf, sizeof(buf), fmt.c_str(), value);
#endif

    if (i1 != i2 || s != buf)
    {
        cout << endl
        << "Reference: " << i2 << "; Actual: " << i1 << ",  Difference = " << i2-i1 << endl
        << "V: [" << value << "]" << endl
        << "F: [" << fmt << "]" << endl
        << "R: [" << buf << "]" << endl
        << "A: [" << s.c_str() << "]" << endl;
        assert(false);
    }
}

template <class T, class U>
void TestCase2(const string& fmt, T value, U value2)
{
    char buf[4096];
    std::string s;
    const int i1 = SPrintf(s, fmt.c_str())(value)(value2);
    const int i2 = snprintf(buf, sizeof(buf), fmt.c_str(), value, value2);
    assert(i1 == i2);
    assert(s == buf);
}

int main(int argc, char** argv)
{

    if (argc == 2)
    {
        // test speed

        Timer t;

        int loop = atoi(argv[1]);

        if(loop < 100)
            loop = 100;

        t.start();
        for (int i=loop; i > 0; --i)
            printf("Hey, %u frobnicators and %u twiddlicators\n",i, i);
        t.stop();
        t.t100 = t.t();
        int t_printf = t.t();

        t.start();
        for (int i=loop; i > 0; --i)
            Printf("Hey, %u frobnicators and %u twiddlicators\n")(i)(i);
        t.stop();
        int t_Printf = t.t();

        t.start();
        for (int i=loop; i > 0; --i)
            cout << "Hey, " << i << " frobnicators and " << i <<" twiddlicators\n";
        t.stop();
        int t_cout = t.t();

        Printf("\n\nElapsed time for %i outputs\n\n")(loop);
        t.print(t_printf,"printf   : ");
        t.print(t_Printf,"Printf   : ");
        t.print(t_cout,  "std::cout: ");
    }
    else
    {
        //srand(time(0));
        srand(0);
        printf("\nNumber of tests:\n");
        for (unsigned i = 0; ; ++i)
        {
            printf("%u\r", i);

            // Generate a random string for the head
            string lead = RandomString(100);
            // This string will hold a random format specification
            string formatSpec(lead + "|%");
            // Generate a random set of flags
            static const string flags("-+0 #");
            unsigned int maxFlags = RandomInt(0u, flags.length() - 1);
            for (unsigned int i = 0; i != maxFlags; ++i)
            {
                formatSpec += flags[RandomInt(0u, flags.length() - 1)];
            }
            // Generate an optional random width
            if (RandomInt(0, 1))
            {
                const unsigned int width = RandomInt(0, 100);
                char buf[4];
                sprintf(buf, "%u", width);
                formatSpec += buf;
            }
            // Generate an optional random precision
            if (RandomInt(0, 1))
            {
                const unsigned int prec = RandomInt(0, 100);
                char buf[4];
                sprintf(buf, "%u", prec);
                formatSpec += '.';
                formatSpec += buf;
            }

            // Generate a random type character
            /* disable %p tests
            static const string type("cdeEfgGinopsuxX");*/
            static const string type("cdeEfgGinosuxX");

            const char typeSpec = type[RandomInt(0, type.size() - 1)];
            // Generate an optional type prefix
            static const string prefix("hl");
            if (typeSpec != 's' && RandomInt(0, 1))
            {
                formatSpec += prefix[RandomInt(0, prefix.size() - 1)];
            }
            formatSpec += typeSpec;
            formatSpec += '|';
            formatSpec += RandomString(100);

            switch (typeSpec)
            {
            case 'c':
                TestCase(formatSpec, RandomInt(1, 127));
                break;
            case 'd':
            case 'i':
            case 'o':
            case 'u':
            case 'x':
            case 'X':
                //TestCase(formatSpec, RandomInt(-10000, 10000));
                // don't test negative values on 64bit systems, because
                // snprintf does not support 64 Bit values
                TestCase(formatSpec, RandomInt( -10000 * (sizeof(size_t)>4 ? 0 : 1) , 10000));
                break;
            case 'e':
            case 'E':
            case 'f':
            case 'g':
            case 'G':
                TestCase(formatSpec,
                         RandomInt(-10000, 10000) / double(RandomInt(1, 100)));
                break;
            case 'n':
                break;
            case 'p':
                {
                    void * p = malloc(RandomInt(1, 1000));
                    TestCase(formatSpec, p);
                    free(p);
                }
                break;
            case 's':
                TestCase(formatSpec, RandomString(100).c_str());
                break;
            default:
                assert(false);
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

//project
#include "service-settings-widget.h"
#include "abstract-service-setup-context.h"
#include "settings-page.h"
#include "service-helper.h"

//M
#include <MContentItem>
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <MGridLayoutPolicy>
#include <MLabel>
#include <MButton>
#include <MLocale>
#include <MImageWidget>

//Qt
#include <QDebug>
#include <QDomElement>

namespace AccountsUI {

class ServiceSettingsWidgetPrivate
{
public:
    ServiceSettingsWidgetPrivate()
        : context(0)
         ,enableServiceButton(0)
    {}

    ~ServiceSettingsWidgetPrivate()
    {}

    AbstractServiceSetupContext *context;
    MButton *enableServiceButton;
};

ServiceSettingsWidget::ServiceSettingsWidget(AbstractServiceSetupContext *context,
                                             QGraphicsItem *parent,
                                             int settingsConf,
                                             bool enabled)
    : MWidget(parent),
    d_ptr(new ServiceSettingsWidgetPrivate())
{
    Q_D(ServiceSettingsWidget);

    d->context = context;
    QString catalog = d->context->service()->trCatalog();
    if (!catalog.isEmpty()) {
         MLocale locale;
         locale.installTrCatalog(catalog);
         MLocale::setDefault(locale);
    }

    MLayout *containerMainLayout = new MLayout(this);
    MLinearLayoutPolicy *mainPolicy = new MLinearLayoutPolicy(containerMainLayout, Qt::Vertical);
    mainPolicy->setSpacing(0);
    mainPolicy->setContentsMargins(0,0,0,0);

    MWidget *upperWidget = new MWidget(this);
    MLayout *upperLayout = new MLayout(upperWidget);
    MLinearLayoutPolicy *containerMainPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Horizontal);
    containerMainPolicy->setSpacing(0);
    containerMainPolicy->setContentsMargins(0,0,0,0);

    MContentItem *serviceInfo = 0;

    if (settingsConf & EnableButton) {
        if (context) {
            d->enableServiceButton = new MButton(this);
            d->enableServiceButton->setViewType(MButton::switchType);
            d->enableServiceButton->setCheckable(true);

            ServiceHelper *serviceHepler =
                new ServiceHelper(const_cast<Accounts::Service*>(context->service()), this);

            serviceInfo = new MContentItem(MContentItem::TwoTextLabels);
            serviceInfo->setTitle(serviceHepler->prettyName());
            serviceInfo->setSubtitle(serviceHepler->description());

            /*
             * no signals during widget creation
             * */
            d->context->enable(enabled);
            d->enableServiceButton->setChecked(enabled);
            connect(d->enableServiceButton, SIGNAL(toggled(bool)), this, SLOT(enabled(bool)));

            containerMainPolicy->addItem(d->enableServiceButton, Qt::AlignRight | Qt::AlignVCenter);
            containerMainPolicy->addItem(serviceInfo, Qt::AlignLeft | Qt::AlignVCenter);

            mainPolicy->addItem(upperWidget);
        }
    }

    if (context && serviceInfo) {
        MWidget *widget = context->widget(0, (settingsConf & NonMandatorySettings));

        if (widget) {
            MImageWidget *sideImage = new MImageWidget("icon-m-common-drilldown-arrow", upperWidget);
            sideImage->setStyleName("CommonDrillDownIcon");
            containerMainPolicy->addItem(sideImage, Qt::AlignRight | Qt::AlignVCenter);
            connect(serviceInfo, SIGNAL(clicked()),
                    this, SLOT(openSettingsPage()));

            if ((settingsConf & NonMandatorySettings) ||
                (settingsConf & MandatorySettings)) {
                    mainPolicy->addItem(widget);
            }
        } else {
            serviceInfo->setEnabled(false);
        }
    }
}

ServiceSettingsWidget::~ServiceSettingsWidget()
{
    delete d_ptr;
}

void ServiceSettingsWidget::enabled(bool enabled)
{
    Q_D(ServiceSettingsWidget);
    if (!d->context)
        return;

    d->context->enable(enabled);

    if (enabled &&
        d->context->service()) {
            emit serviceButtonEnabled(d->context->service()->serviceType());
            qDebug() << Q_FUNC_INFO << __LINE__ << d->context->service()->serviceType() << enabled;
    }
}

void ServiceSettingsWidget::setServiceButtonEnable(bool enable)
{
    Q_D(ServiceSettingsWidget);
    qDebug() << Q_FUNC_INFO << __LINE__;

    if (d->enableServiceButton->isChecked() != enable)
        d->enableServiceButton->setChecked(enable);
}

void ServiceSettingsWidget::openSettingsPage()
{
    Q_D(ServiceSettingsWidget);
    SettingsPage *settingsPage =
            new SettingsPage(d->context, d->enableServiceButton->model());
    settingsPage->appear();
}

}//end of namespace
<commit_msg>bugxif: 213774 - Account settings options for Other mail account is not shown in Account settings view<commit_after>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

//project
#include "service-settings-widget.h"
#include "abstract-service-setup-context.h"
#include "settings-page.h"
#include "service-helper.h"

//M
#include <MContentItem>
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <MGridLayoutPolicy>
#include <MLabel>
#include <MButton>
#include <MLocale>
#include <MImageWidget>

//Qt
#include <QDebug>
#include <QDomElement>

namespace AccountsUI {

class ServiceSettingsWidgetPrivate
{
public:
    ServiceSettingsWidgetPrivate()
        : context(0)
         ,enableServiceButton(0)
    {}

    ~ServiceSettingsWidgetPrivate()
    {}

    AbstractServiceSetupContext *context;
    MButton *enableServiceButton;
};

ServiceSettingsWidget::ServiceSettingsWidget(AbstractServiceSetupContext *context,
                                             QGraphicsItem *parent,
                                             int settingsConf,
                                             bool enabled)
    : MWidget(parent),
    d_ptr(new ServiceSettingsWidgetPrivate())
{
    Q_D(ServiceSettingsWidget);

    d->context = context;
    QString catalog = d->context->service()->trCatalog();
    if (!catalog.isEmpty()) {
         MLocale locale;
         locale.installTrCatalog(catalog);
         MLocale::setDefault(locale);
    }

    MLayout *containerMainLayout = new MLayout(this);
    MLinearLayoutPolicy *mainPolicy = new MLinearLayoutPolicy(containerMainLayout, Qt::Vertical);
    mainPolicy->setSpacing(0);
    mainPolicy->setContentsMargins(0,0,0,0);

    MWidget *upperWidget = new MWidget(this);
    MLayout *upperLayout = new MLayout(upperWidget);
    MLinearLayoutPolicy *containerMainPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Horizontal);
    containerMainPolicy->setSpacing(0);
    containerMainPolicy->setContentsMargins(0,0,0,0);

    MContentItem *serviceInfo = 0;

    if (settingsConf & EnableButton) {
        if (context) {
            d->enableServiceButton = new MButton(this);
            d->enableServiceButton->setViewType(MButton::switchType);
            d->enableServiceButton->setCheckable(true);

            ServiceHelper *serviceHepler =
                new ServiceHelper(const_cast<Accounts::Service*>(context->service()), this);

            serviceInfo = new MContentItem(MContentItem::TwoTextLabels);
            serviceInfo->setTitle(serviceHepler->prettyName());
            serviceInfo->setSubtitle(serviceHepler->description());

            /*
             * no signals during widget creation
             * */
            d->context->enable(enabled);
            d->enableServiceButton->setChecked(enabled);
            connect(d->enableServiceButton, SIGNAL(toggled(bool)), this, SLOT(enabled(bool)));

            containerMainPolicy->addItem(d->enableServiceButton, Qt::AlignRight | Qt::AlignVCenter);
            containerMainPolicy->addItem(serviceInfo, Qt::AlignLeft | Qt::AlignVCenter);

            mainPolicy->addItem(upperWidget);
        }
    }

    if (context) {
        MWidget *widget = context->widget(0, (settingsConf & NonMandatorySettings));

        if (widget) {
            MImageWidget *sideImage = new MImageWidget("icon-m-common-drilldown-arrow", upperWidget);
            sideImage->setStyleName("CommonDrillDownIcon");
            containerMainPolicy->addItem(sideImage, Qt::AlignRight | Qt::AlignVCenter);
            if (serviceInfo)
                connect(serviceInfo, SIGNAL(clicked()),
                        this, SLOT(openSettingsPage()));

            if ((settingsConf & NonMandatorySettings) ||
                (settingsConf & MandatorySettings)) {
                    mainPolicy->addItem(widget);
            }
        } else {
            if (serviceInfo)
                serviceInfo->setEnabled(false);
        }
    }
}

ServiceSettingsWidget::~ServiceSettingsWidget()
{
    delete d_ptr;
}

void ServiceSettingsWidget::enabled(bool enabled)
{
    Q_D(ServiceSettingsWidget);
    if (!d->context)
        return;

    d->context->enable(enabled);

    if (enabled &&
        d->context->service()) {
            emit serviceButtonEnabled(d->context->service()->serviceType());
            qDebug() << Q_FUNC_INFO << __LINE__ << d->context->service()->serviceType() << enabled;
    }
}

void ServiceSettingsWidget::setServiceButtonEnable(bool enable)
{
    Q_D(ServiceSettingsWidget);
    qDebug() << Q_FUNC_INFO << __LINE__;

    if (d->enableServiceButton->isChecked() != enable)
        d->enableServiceButton->setChecked(enable);
}

void ServiceSettingsWidget::openSettingsPage()
{
    Q_D(ServiceSettingsWidget);
    SettingsPage *settingsPage =
            new SettingsPage(d->context, d->enableServiceButton->model());
    settingsPage->appear();
}

}//end of namespace
<|endoftext|>


<commit_before>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

//project
#include "service-settings-widget.h"
#include "abstract-service-setup-context.h"
#include "settings-page.h"
#include "service-helper.h"

//M
#include <MBasicListItem>
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <MGridLayoutPolicy>
#include <MLabel>
#include <MButton>
#include <MLocale>
#include <MImageWidget>

//Qt
#include <QDebug>
#include <QDomElement>

namespace AccountsUI {

ServiceSettingsWidgetListItem::ServiceSettingsWidgetListItem(QGraphicsWidget *parent)
        : MBasicListItem(MBasicListItem::IconWithTitleAndSubtitle, parent)
{
    setStyleName("CommonBasicListItemInverted");
    setObjectName("wgServiceSettingsWidgetListItem");

    horizontalLayout = new MLayout(this);

    horizontalLayout->setContentsMargins(0, 0, 0, 0);
    MLinearLayoutPolicy *horizontalLayoutPolicy
            = new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
    horizontalLayoutPolicy->setSpacing(0);

    MLayout *titleSubtitleLayout = new MLayout(horizontalLayout);
    titleSubtitleLayout->setContentsMargins(0, 0, 0, 0);
    MLinearLayoutPolicy *titleSubtitleLayoutPolicy = new MLinearLayoutPolicy(titleSubtitleLayout, Qt::Vertical);
    titleSubtitleLayoutPolicy->setSpacing(0);

    titleSubtitleLayoutPolicy->addItem(titleLabelWidget(), Qt::AlignLeft | Qt::AlignTop);
    titleSubtitleLayoutPolicy->addItem(subtitleLabelWidget(), Qt::AlignLeft | Qt::AlignTop);

    horizontalLayoutPolicy->addItem(titleSubtitleLayout, Qt::AlignLeft | Qt::AlignCenter);
    horizontalLayoutPolicy->addItem(imageWidget(), Qt::AlignCenter);
}

ServiceSettingsWidgetListItem::~ServiceSettingsWidgetListItem()
{}

QGraphicsLayout *ServiceSettingsWidgetListItem::createLayout()
{
    return horizontalLayout;
}

void ServiceSettingsWidgetListItem::showDrillDownButton()
{
    imageWidget()->setImage("icon-m-common-drilldown-arrow-inverse");
    imageWidget()->setStyleName("CommonDrillDownIcon");
    imageWidget()->setObjectName("wgServiceSettingsWidgetDrillDownIcon");
}

class ServiceSettingsWidgetPrivate
{
public:
    ServiceSettingsWidgetPrivate()
        : context(0)
         ,enableServiceButton(0)
    {}

    ~ServiceSettingsWidgetPrivate()
    {}

    AbstractServiceSetupContext *context;
    MButton *enableServiceButton;
};

ServiceSettingsWidget::ServiceSettingsWidget(AbstractServiceSetupContext *context,
                                             QGraphicsItem *parent,
                                             int settingsConf,
                                             bool enabled)
    : MWidget(parent),
    d_ptr(new ServiceSettingsWidgetPrivate())
{
    Q_D(ServiceSettingsWidget);

    d->context = context;
    QString catalog = d->context->service()->trCatalog();
    if (!catalog.isEmpty()) {
         MLocale locale;
         locale.installTrCatalog(catalog);
         MLocale::setDefault(locale);
    }

    MLayout *containerMainLayout = new MLayout(this);
    MLinearLayoutPolicy *mainPolicy = new MLinearLayoutPolicy(containerMainLayout, Qt::Vertical);
    mainPolicy->setSpacing(0);
    mainPolicy->setContentsMargins(0,0,0,0);

    MWidget *upperWidget = new MWidget(this);
    MLayout *upperLayout = new MLayout(upperWidget);
    MLinearLayoutPolicy *containerMainPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Horizontal);
    containerMainPolicy->setSpacing(0);
    containerMainPolicy->setContentsMargins(0,0,0,0);

    ServiceSettingsWidgetListItem *serviceInfo = 0;

    if (settingsConf & EnableButton) {
        if (context) {
            d->enableServiceButton = new MButton(this);
            d->enableServiceButton->setViewType(MButton::switchType);
            d->enableServiceButton->setStyleName("CommonLeftSwitchInverted");
            d->enableServiceButton->setObjectName("wgServiceSettingsWidgetServiceButton");
            d->enableServiceButton->setCheckable(true);

            ServiceHelper *serviceHepler =
                new ServiceHelper(const_cast<Accounts::Service*>(context->service()), this);

            serviceInfo = new ServiceSettingsWidgetListItem();
            serviceInfo->setTitle(serviceHepler->prettyName());
            serviceInfo->setSubtitle(serviceHepler->description());

            /*
             * no signals during widget creation
             * */
            d->enableServiceButton->setChecked(enabled);
            connect(d->enableServiceButton, SIGNAL(toggled(bool)), this, SLOT(enabled(bool)));

            containerMainPolicy->addItem(d->enableServiceButton, Qt::AlignRight | Qt::AlignVCenter);
            containerMainPolicy->addItem(serviceInfo, Qt::AlignLeft | Qt::AlignVCenter);

            mainPolicy->addItem(upperWidget);
        }
    }

    if (context) {
        MWidget *widget = context->widget(0, (settingsConf & NonMandatorySettings));

        if (widget) {
            if (serviceInfo) {
                serviceInfo->showDrillDownButton();
                connect(serviceInfo, SIGNAL(clicked()),
                        this, SLOT(openSettingsPage()));
            }

            if ((settingsConf & NonMandatorySettings) ||
                (settingsConf & MandatorySettings)) {
                    mainPolicy->addItem(widget);
            }
        } else {
            if (serviceInfo)
                serviceInfo->setEnabled(false);
        }
    }
}

ServiceSettingsWidget::~ServiceSettingsWidget()
{
    delete d_ptr;
}

void ServiceSettingsWidget::enabled(bool enabled)
{
    Q_D(ServiceSettingsWidget);
    if (!d->context)
        return;

    emit serviceEnabled(d->context->service()->name(), enabled);
    if (enabled &&
        d->context->service()) {
            emit serviceButtonEnabled(d->context->service()->serviceType());
            qDebug() << Q_FUNC_INFO << __LINE__ << d->context->service()->serviceType() << enabled;
    }
}

void ServiceSettingsWidget::setServiceButtonEnable(bool enable)
{
    Q_D(ServiceSettingsWidget);
    qDebug() << Q_FUNC_INFO << __LINE__;

    if (d->enableServiceButton->isChecked() != enable)
        d->enableServiceButton->setChecked(enable);
}

void ServiceSettingsWidget::openSettingsPage()
{
    Q_D(ServiceSettingsWidget);
    SettingsPage *settingsPage =
            new SettingsPage(d->context, d->enableServiceButton->model());
    settingsPage->appear();
}

}//end of namespace
<commit_msg>bugfix #228509 - Layout is not proper for Account settings view and Service Selection view<commit_after>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

//project
#include "service-settings-widget.h"
#include "abstract-service-setup-context.h"
#include "settings-page.h"
#include "service-helper.h"

//M
#include <MBasicListItem>
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <MGridLayoutPolicy>
#include <MLabel>
#include <MButton>
#include <MLocale>
#include <MImageWidget>

//Qt
#include <QDebug>
#include <QDomElement>

namespace AccountsUI {

ServiceSettingsWidgetListItem::ServiceSettingsWidgetListItem(QGraphicsWidget *parent)
        : MBasicListItem(MBasicListItem::IconWithTitleAndSubtitle, parent)
{
    setStyleName("CommonBasicListItemInverted");
    setObjectName("wgServiceSettingsWidgetListItem");

    horizontalLayout = new MLayout(this);

    horizontalLayout->setContentsMargins(0, 0, 0, 0);
    MLinearLayoutPolicy *horizontalLayoutPolicy
            = new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
    horizontalLayoutPolicy->setSpacing(0);

    MLayout *titleSubtitleLayout = new MLayout(horizontalLayout);
    titleSubtitleLayout->setContentsMargins(0, 0, 0, 0);
    MLinearLayoutPolicy *titleSubtitleLayoutPolicy = new MLinearLayoutPolicy(titleSubtitleLayout, Qt::Vertical);
    titleSubtitleLayoutPolicy->setSpacing(0);

    titleSubtitleLayoutPolicy->addItem(titleLabelWidget(), Qt::AlignLeft | Qt::AlignTop);
    titleSubtitleLayoutPolicy->addItem(subtitleLabelWidget(), Qt::AlignLeft | Qt::AlignTop);

    horizontalLayoutPolicy->addItem(titleSubtitleLayout, Qt::AlignLeft | Qt::AlignCenter);

    MImageWidget *image = imageWidget();
    image->setImage("icon-m-common-drilldown-arrow-inverse");
    image->setStyleName("CommonDrillDownIcon");
    image->setObjectName("wgServiceSettingsWidgetDrillDownIcon");
    image->setVisible(false);
    horizontalLayoutPolicy->addItem(image, Qt::AlignCenter);
}

ServiceSettingsWidgetListItem::~ServiceSettingsWidgetListItem()
{}

QGraphicsLayout *ServiceSettingsWidgetListItem::createLayout()
{
    return horizontalLayout;
}

void ServiceSettingsWidgetListItem::showDrillDownButton()
{
    imageWidget()->setVisible(true);
}

class ServiceSettingsWidgetPrivate
{
public:
    ServiceSettingsWidgetPrivate()
        : context(0)
         ,enableServiceButton(0)
    {}

    ~ServiceSettingsWidgetPrivate()
    {}

    AbstractServiceSetupContext *context;
    MButton *enableServiceButton;
};

ServiceSettingsWidget::ServiceSettingsWidget(AbstractServiceSetupContext *context,
                                             QGraphicsItem *parent,
                                             int settingsConf,
                                             bool enabled)
    : MWidget(parent),
    d_ptr(new ServiceSettingsWidgetPrivate())
{
    Q_D(ServiceSettingsWidget);

    d->context = context;
    QString catalog = d->context->service()->trCatalog();
    if (!catalog.isEmpty()) {
         MLocale locale;
         locale.installTrCatalog(catalog);
         MLocale::setDefault(locale);
    }

    MLayout *containerMainLayout = new MLayout(this);
    MLinearLayoutPolicy *mainPolicy = new MLinearLayoutPolicy(containerMainLayout, Qt::Vertical);
    mainPolicy->setSpacing(0);
    mainPolicy->setContentsMargins(0,0,0,0);

    MWidget *upperWidget = new MWidget(this);
    MLayout *upperLayout = new MLayout(upperWidget);
    MLinearLayoutPolicy *containerMainPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Horizontal);
    containerMainPolicy->setSpacing(0);
    containerMainPolicy->setContentsMargins(0,0,0,0);

    ServiceSettingsWidgetListItem *serviceInfo = 0;

    if (settingsConf & EnableButton) {
        if (context) {
            d->enableServiceButton = new MButton(this);
            d->enableServiceButton->setViewType(MButton::switchType);
            d->enableServiceButton->setStyleName("CommonLeftSwitchInverted");
            d->enableServiceButton->setObjectName("wgServiceSettingsWidgetServiceButton");
            d->enableServiceButton->setCheckable(true);

            ServiceHelper *serviceHepler =
                new ServiceHelper(const_cast<Accounts::Service*>(context->service()), this);

            serviceInfo = new ServiceSettingsWidgetListItem();
            serviceInfo->setTitle(serviceHepler->prettyName());
            serviceInfo->setSubtitle(serviceHepler->description());

            /*
             * no signals during widget creation
             * */
            d->enableServiceButton->setChecked(enabled);
            connect(d->enableServiceButton, SIGNAL(toggled(bool)), this, SLOT(enabled(bool)));

            containerMainPolicy->addItem(d->enableServiceButton, Qt::AlignRight | Qt::AlignVCenter);
            containerMainPolicy->addItem(serviceInfo, Qt::AlignLeft | Qt::AlignVCenter);

            mainPolicy->addItem(upperWidget);
        }
    }

    if (context) {
        MWidget *widget = context->widget(0, (settingsConf & NonMandatorySettings));

        if (widget) {
            if (serviceInfo) {
                serviceInfo->showDrillDownButton();
                connect(serviceInfo, SIGNAL(clicked()),
                        this, SLOT(openSettingsPage()));
            }

            if ((settingsConf & NonMandatorySettings) ||
                (settingsConf & MandatorySettings)) {
                    mainPolicy->addItem(widget);
            }
        } else {
            if (serviceInfo)
                serviceInfo->setEnabled(false);
        }
    }
}

ServiceSettingsWidget::~ServiceSettingsWidget()
{
    delete d_ptr;
}

void ServiceSettingsWidget::enabled(bool enabled)
{
    Q_D(ServiceSettingsWidget);
    if (!d->context)
        return;

    emit serviceEnabled(d->context->service()->name(), enabled);
    if (enabled &&
        d->context->service()) {
            emit serviceButtonEnabled(d->context->service()->serviceType());
            qDebug() << Q_FUNC_INFO << __LINE__ << d->context->service()->serviceType() << enabled;
    }
}

void ServiceSettingsWidget::setServiceButtonEnable(bool enable)
{
    Q_D(ServiceSettingsWidget);
    qDebug() << Q_FUNC_INFO << __LINE__;

    if (d->enableServiceButton->isChecked() != enable)
        d->enableServiceButton->setChecked(enable);
}

void ServiceSettingsWidget::openSettingsPage()
{
    Q_D(ServiceSettingsWidget);
    SettingsPage *settingsPage =
            new SettingsPage(d->context, d->enableServiceButton->model());
    settingsPage->appear();
}

}//end of namespace
<|endoftext|>


<commit_before>#pragma once

#ifndef __ASYNC_MAP_HPP__
#define __ASYNC_MAP_HPP__

#include <atomic>

namespace async {

// This value can be asserted to equal zero if there's no pending callbacks.  Otherwise,
// if it's non-zero after all callbacks have executed, we have a memory leak.
namespace priv {
std::atomic<int> map_state_count(0);
}

int get_map_state_count() {
  return priv::map_state_count;
}

template<typename T>
void map(std::vector<T> objects,
    std::function<void(T, TaskCallback<T>)> func,
    const TaskCompletionCallback<T> &final_callback=noop_task_final_callback<T>) {

  struct State {
    std::vector<T> results;
    std::shared_ptr<State> keep_alive;
    std::atomic<int> results_count;
    const TaskCompletionCallback<T> *final_callback;
    bool had_error = false;

    State() {
      priv::map_state_count++;
      printf("> STATE\n");
    }

    ~State() {
      priv::map_state_count--;
      printf("< STATE\n");
    }
  };

  auto state = std::make_shared<State>();
  state->results = std::vector<T>(objects.size());
  state->keep_alive = state;
  state->final_callback = &final_callback;
  state->results_count.store(0);

  for (int i = 0; i < objects.size(); i++) {
    auto object = objects[i];
    func(object, [i, state](ErrorCode error, T result) {
          if (state->had_error) {
            // There was an error code earlier, so work has finished.
            return;
          }

          state->results[i] = result;

          state->results_count++;

          if (error != OK) {
            state->had_error = true;
          }

          if (state->had_error || state->results_count == state->results.size()) {
            // All results have been collected.

            (*state->final_callback)(error, state->results);
            state->keep_alive.reset();
          }
        });
  }
}

}

#endif
<commit_msg>start task limit<commit_after>#pragma once

#ifndef __ASYNC_MAP_HPP__
#define __ASYNC_MAP_HPP__

#include <atomic>

namespace async {

// This value can be asserted to equal zero if there's no pending callbacks.  Otherwise,
// if it's non-zero after all callbacks have executed, we have a memory leak.
namespace priv {
std::atomic<int> map_state_count(0);
}

int get_map_state_count() {
  return priv::map_state_count;
}

template<typename T>
void map(std::vector<T> objects,
    std::function<void(T, TaskCallback<T>)> func,
    const TaskCompletionCallback<T> &final_callback=noop_task_final_callback<T>,
    unsigned int task_limit=0) {

  if (task_limit == 0 || task_limit > objects.size()) {
    task_limit = objects.size();
  }

  struct State {
    std::vector<T> results;
    std::shared_ptr<State> keep_alive;
    std::atomic<int> results_count;
    unsigned int task_limit;
    const TaskCompletionCallback<T> *final_callback;
    bool had_error = false;

    State() {
      priv::map_state_count++;
      printf("> STATE\n");
    }

    ~State() {
      priv::map_state_count--;
      printf("< STATE\n");
    }
  };

  auto state = std::make_shared<State>();
  state->results = std::vector<T>(objects.size());
  state->keep_alive = state;
  state->final_callback = &final_callback;
  state->results_count.store(0);
  state->task_limit = task_limit;

  for (int i = 0; i < objects.size(); i++) {
    auto object = objects[i];
    func(object, [i, state](ErrorCode error, T result) {
          if (state->had_error) {
            // There was an error code earlier, so work has finished.
            return;
          }

          state->results[i] = result;

          state->results_count++;

          if (error != OK) {
            state->had_error = true;
          }

          if (state->had_error || state->results_count == state->results.size()) {
            // All results have been collected.

            (*state->final_callback)(error, state->results);
            state->keep_alive.reset();
          }
        });
  }
}

}

#endif
<|endoftext|>


<commit_before>//===--- CodeSynthesisDistributedActor.cpp --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "TypeCheckDistributed.h"

#include "TypeChecker.h"
#include "TypeCheckType.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Availability.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Defer.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Sema/ConstraintSystem.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "DerivedConformances.h"
using namespace swift;

/******************************************************************************/
/******************************* RESOLVE FUNCTION *****************************/
/******************************************************************************/

/// Synthesizes the
///
/// \verbatim
/// static resolve(_ address: ActorAddress,
///                using transport: ActorTransport) throws -> Self {
///   <filled in by SILGenDistributed>
/// }
/// \endverbatim
///
/// factory function in the AST, with an empty body. Its body is
/// expected to be filled-in during SILGen.
static void addFactoryResolveFunction(ClassDecl *decl) {
  assert(decl->isDistributedActor());
  auto &C = decl->getASTContext();

  auto mkParam = [&](Identifier argName, Identifier paramName, Type ty) -> ParamDecl* {
    auto *param = new (C) ParamDecl(SourceLoc(),
                                    SourceLoc(), argName,
                                    SourceLoc(), paramName, decl);
    param->setImplicit();
    param->setSpecifier(ParamSpecifier::Default);
    param->setInterfaceType(ty);
    return param;
  };

  auto addressType = C.getAnyActorIdentityDecl()->getDeclaredInterfaceType();
  auto transportType = C.getActorTransportDecl()->getDeclaredInterfaceType();

  // (_ identity: AnyActorIdentity, using transport: ActorTransport)
  auto *params = ParameterList::create(
      C,
      /*LParenLoc=*/SourceLoc(),
      /*params=*/{  mkParam(Identifier(), C.Id_identity, addressType),
                    mkParam(C.Id_using, C.Id_transport, transportType)
                  },
      /*RParenLoc=*/SourceLoc()
      );

  // Func name: resolve(_:using:)
  DeclName name(C, C.Id_resolve, params);

  // Expected type: (Self) -> (AnyActorIdentity, ActorTransport) throws -> (Self)
  auto *factoryDecl =
      FuncDecl::createImplicit(C, StaticSpellingKind::KeywordStatic,
                               name, SourceLoc(),
                               /*async=*/false,
                               /*throws=*/true,
                               /*genericParams=*/nullptr,
                               params,
                               /*returnType*/decl->getDeclaredInterfaceType(),
                               decl);

  factoryDecl->setDistributedActorFactory(); // TODO(distributed): should we mark this specifically as the resolve factory?
  factoryDecl->copyFormalAccessFrom(decl, /*sourceIsParentContext=*/true);

  decl->addMember(factoryDecl);
}

/******************************************************************************/
/******************************** DEINIT **************************************/
/******************************************************************************/

/// A distributed actor's deinit MUST call `transport.resignIdentity` before it
/// is deallocated.
static void addImplicitResignIdentity(ClassDecl *decl) {
  auto &C = decl->getASTContext();

  DestructorDecl *existingDeinit = decl->getDestructor();
  assert(existingDeinit);

  DestructorDecl *deinitDecl = existingDeinit ? existingDeinit :
      new (C) DestructorDecl(SourceLoc(), decl);
//  DestructorDecl *deinitDecl = new (C) DestructorDecl(SourceLoc(), decl);

  BraceStmt *body = deinitDecl->getBody();

  // == Copy all existing statements to the new deinit
  SmallVector<ASTNode, 2> statements; // TODO: how to init at body statements count size?
  for (auto stmt : body->getElements())
    statements.push_back(stmt); // TODO: copy?

  // TODO: INJECT THIS AS FIRST THING IN A DEFER {}

  // == Inject the lifecycle 'resignIdentity' interaction
  // ==== self
  auto *selfRef = DerivedConformance::createSelfDeclRef(deinitDecl);

  // ==== `self.actorTransport`
  auto *varTransportExpr = UnresolvedDotExpr::createImplicit(C, selfRef,
                                                           C.Id_actorTransport);

  // ==== `self.id`
  auto *varIdExpr = UnresolvedDotExpr::createImplicit(C, selfRef, C.Id_id);

  // ==== `self.transport.resignIdentity(self.actorAddress)`
  //  auto resignIdentityRef = new (C) DeclRefExpr(varTransportExpr,
  //  DeclNameLoc(), /*implicit=*/true);
  //  resignIdentityRef->setThrows(false);
  auto resignFuncDecls =
      C.getActorTransportDecl()->lookupDirect(C.Id_resignIdentity);
  assert(resignFuncDecls.size() == 1);
  AbstractFunctionDecl *resignFuncDecl =
      dyn_cast<AbstractFunctionDecl>(resignFuncDecls.front());
  auto resignFuncRef = new (C) DeclRefExpr(resignFuncDecl, DeclNameLoc(),
                                           /*implicit=*/true);

  auto *idParam = new (C) ParamDecl(
      SourceLoc(), SourceLoc(), Identifier(),
      SourceLoc(), C.Id_id, decl);
  idParam->setInterfaceType(C.getActorIdentityDecl()->getInterfaceType());
  idParam->setSpecifier(ParamSpecifier::Default);
  idParam->setImplicit();
  auto *paramList = ParameterList::createWithoutLoc(idParam);

  auto *resignFuncRefRef = UnresolvedDotExpr::createImplicit(
      C, varTransportExpr, C.Id_resignIdentity, paramList);

  Expr *resignIdentityCall = CallExpr::createImplicit(C, resignFuncRefRef,
                                                     { varIdExpr },
                                                     { Identifier() });
  statements.push_back(resignIdentityCall);

  BraceStmt *newBody = BraceStmt::create(C, SourceLoc(), statements, SourceLoc(),
                                         /*implicit=*/true);

  deinitDecl->setBody(newBody, AbstractFunctionDecl::BodyKind::TypeChecked); // FIXME: no idea if Parsed is right, we are NOT type checked I guess?
}

/******************************************************************************/
/******************************** PROPERTIES **********************************/
/******************************************************************************/

// TODO: deduplicate with 'declareDerivedProperty' from DerivedConformance...
std::pair<VarDecl *, PatternBindingDecl *>
createStoredProperty(ClassDecl *classDecl, ASTContext &ctx,
                     VarDecl::Introducer introducer, Identifier name,
                     Type propertyInterfaceType, Type propertyContextType,
                     bool isStatic, bool isFinal) {
  auto parentDC = classDecl;

  VarDecl *propDecl = new (ctx)
      VarDecl(/*IsStatic*/ isStatic, introducer,
                           SourceLoc(), name, parentDC);
  propDecl->setImplicit();
  propDecl->setSynthesized();
  propDecl->copyFormalAccessFrom(classDecl, /*sourceIsParentContext*/ true);
  propDecl->setInterfaceType(propertyInterfaceType);

  Pattern *propPat = NamedPattern::createImplicit(ctx, propDecl);
  propPat->setType(propertyContextType);

  propPat = TypedPattern::createImplicit(ctx, propPat, propertyContextType);
  propPat->setType(propertyContextType);

  auto *pbDecl = PatternBindingDecl::createImplicit(
      ctx, StaticSpellingKind::None, propPat, /*InitExpr*/ nullptr,
      parentDC);
  return {propDecl, pbDecl};
}

/// Adds the following, fairly special, properties to each distributed actor:
/// - actorTransport
/// - id
static void addImplicitDistributedActorStoredProperties(ClassDecl *decl) {
  assert(decl->isDistributedActor());

  auto &C = decl->getASTContext();

  // ```
  // @_distributedActorIndependent
  // let id: AnyActorIdentity // TODO: move to `nonisolated var id {}` once we have the new allocation scheme
  // ```
  {
    auto propertyType = C.getAnyActorIdentityDecl()->getDeclaredInterfaceType();

    VarDecl *propDecl;
    PatternBindingDecl *pbDecl;
    std::tie(propDecl, pbDecl) = createStoredProperty(
        decl, C,
        VarDecl::Introducer::Let, C.Id_id,
        propertyType, propertyType,
        /*isStatic=*/false, /*isFinal=*/true);

    // mark as @_distributedActorIndependent, allowing access to it from everywhere
    propDecl->getAttrs().add(
        new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true)); // TODO: remove and move to nonisolated once new constructors land

    decl->addMember(propDecl);
    decl->addMember(pbDecl);
  }

  // ```
  // @_distributedActorIndependent
  // let actorTransport: ActorTransport
  // ```
  // (no need for @actorIndependent because it is an immutable let)
  {
    auto propertyType = C.getActorTransportDecl()->getDeclaredInterfaceType();

    VarDecl *propDecl;
    PatternBindingDecl *pbDecl;
    std::tie(propDecl, pbDecl) = createStoredProperty(
        decl, C,
        VarDecl::Introducer::Let, C.Id_actorTransport,
        propertyType, propertyType,
        /*isStatic=*/false, /*isFinal=*/true);

    // mark as @_distributedActorIndependent, allowing access to it from everywhere
    propDecl->getAttrs().add(
        new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true)); // TODO: remove and move to nonisolated once new constructors land

    decl->addMember(propDecl);
    decl->addMember(pbDecl);
  }
}

/******************************************************************************/
/*************************** _REMOTE_ FUNCTIONS *******************************/
/******************************************************************************/

/// Synthesizes the for `_remote_xxx` functions.
///
/// Create a stub body that emits a fatal error message.
static std::pair<BraceStmt *, bool>
synthesizeRemoteFuncStubBody(AbstractFunctionDecl *func, void *context) {
  auto distributedFunc = static_cast<AbstractFunctionDecl *>(context);
  auto classDecl = func->getDeclContext()->getSelfClassDecl();
  auto &ctx = func->getASTContext();
  auto &SM = ctx.SourceMgr;

  auto *staticStringDecl = ctx.getStaticStringDecl();
  auto staticStringType = staticStringDecl->getDeclaredInterfaceType();
  auto staticStringInit = ctx.getStringBuiltinInitDecl(staticStringDecl);

  auto *uintDecl = ctx.getUIntDecl();
  auto uintType = uintDecl->getDeclaredInterfaceType();
  auto uintInit = ctx.getIntBuiltinInitDecl(uintDecl);

  auto missingTransportDecl = ctx.getMissingDistributedActorTransport();
  assert(missingTransportDecl && "Could not locate '_missingDistributedActorTransport' function");

  // Create a call to _Distributed._missingDistributedActorTransport
  auto loc = func->getLoc();
  Expr *ref = new (ctx) DeclRefExpr(missingTransportDecl,
                                    DeclNameLoc(loc), /*Implicit=*/true);
  ref->setType(missingTransportDecl->getInterfaceType()
  ->removeArgumentLabels(1));

  llvm::SmallString<64> buffer;
  StringRef fullClassName = ctx.AllocateCopy(
      (classDecl->getModuleContext()->getName().str() +
      "." +
      classDecl->getName().str()).toStringRef(buffer));

  auto *className = new (ctx) StringLiteralExpr(fullClassName, loc,
                                                /*Implicit=*/true);
  className->setBuiltinInitializer(staticStringInit);
  assert(isa<ConstructorDecl>(className->getBuiltinInitializer().getDecl()));
  className->setType(staticStringType);

  auto *funcName = new (ctx) StringLiteralExpr(
      ctx.AllocateCopy(func->getName().getBaseName().getIdentifier().str()), loc,
      /*Implicit=*/true);
  funcName->setType(staticStringType);
  funcName->setBuiltinInitializer(staticStringInit);

  // Note: Sadly we cannot just rely on #function, #file, #line for the location
  // (MagicIdentifierLiteralExpr), of the call because the call is made from a thunk.
  // That thunk does not carry those info today although it could.
  //
  // Instead, we offer the location where the distributed func was declared.
  auto fileString = SM.getDisplayNameForLoc(distributedFunc->getStartLoc());
  auto *file = new (ctx) StringLiteralExpr(fileString, loc, /*Implicit=*/true);
  file->setType(staticStringType);
  file->setBuiltinInitializer(staticStringInit);

  auto startLineAndCol = SM.getPresumedLineAndColumnForLoc(distributedFunc->getStartLoc());
//  auto *line = new (ctx) MagicIdentifierLiteralExpr(
//      MagicIdentifierLiteralExpr::Line, loc, /*Implicit=*/true);
//  auto *line = new (ctx) IntegerLiteralExpr(startLineAndCol.first, loc,
//                                            /*implicit*/ true);
  auto *line = IntegerLiteralExpr::createFromUnsigned(ctx, startLineAndCol.first);
  line->setType(uintType);
  line->setBuiltinInitializer(uintInit);

//  auto *column = new (ctx) MagicIdentifierLiteralExpr(
//      MagicIdentifierLiteralExpr::Column, loc, /*Implicit=*/true);
  auto *column = IntegerLiteralExpr::createFromUnsigned(ctx, startLineAndCol.second);
  column->setType(uintType);
  column->setBuiltinInitializer(uintInit);

  auto *call = CallExpr::createImplicit(
      ctx, ref, { className, funcName, file, line, column }, {});
  call->setType(ctx.getNeverType());
  call->setThrows(false);

  SmallVector<ASTNode, 2> stmts;
  stmts.push_back(call); // something() -> Never
  // stmts.push_back(new (ctx) ReturnStmt(SourceLoc(), /*Result=*/nullptr)); // FIXME: this causes 'different types for return type: String vs. ()'
  auto body = BraceStmt::create(ctx, SourceLoc(), stmts, SourceLoc(),
                                /*implicit=*/true);
  return { body, /*isTypeChecked=*/true };
}

static Identifier makeRemoteFuncIdentifier(FuncDecl* func) {
  auto &C = func->getASTContext();
  auto localFuncName = func->getBaseIdentifier().str().str();
  auto remoteFuncIdent = C.getIdentifier("_remote_" + localFuncName);
  return remoteFuncIdent;
}

/// Create a remote stub for the passed in \c func.
/// The remote stub function is not user accessible and mirrors the API of
/// the local function. It is always throwing, async, and user-inaccessible.
///
/// ```
/// // func greet(name: String) { ... }
/// dynamic <access> func _remote_greet(name: String) async throws {
///     fatalError(...)
/// }
/// ```
///
/// and is intended to be replaced by a transport library by providing an
/// appropriate @_dynamicReplacement function.
static void addImplicitRemoteActorFunction(ClassDecl *decl, FuncDecl *func) {
  auto &C = decl->getASTContext();
  auto parentDC = decl;

  auto remoteFuncIdent = makeRemoteFuncIdentifier(func);

  auto params = ParameterList::clone(C, func->getParameters());
  auto genericParams = func->getGenericParams(); // TODO: also clone those
  Type resultTy = func->getResultInterfaceType();

  DeclName name(C, remoteFuncIdent, params);
  auto *const remoteFuncDecl = FuncDecl::createImplicit(
      C, StaticSpellingKind::None, name, /*NameLoc=*/SourceLoc(),
      /*Async=*/true, /*Throws=*/true,
      /*GenericParams=*/genericParams, params,
      resultTy, parentDC);

  // *dynamic* because we'll be replacing it with specific transports
  remoteFuncDecl->getAttrs().add(
      new (C) DynamicAttr(/*implicit=*/true));

  // @_distributedActorIndependent
  remoteFuncDecl->getAttrs().add(
      new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true));

  // users should never have to access this function directly;
  // it is only invoked from our distributed function thunk if the actor is remote.
  remoteFuncDecl->setUserAccessible(false);
  remoteFuncDecl->setSynthesized();

  remoteFuncDecl->setBodySynthesizer(&synthesizeRemoteFuncStubBody, func);

  // same access control as the original function is fine
  remoteFuncDecl->copyFormalAccessFrom(func, /*sourceIsParentContext=*/false);

  decl->addMember(remoteFuncDecl);
}

/// Synthesize dynamic _remote stub functions for each encountered distributed function.
static void addImplicitRemoteActorFunctions(ClassDecl *decl) {
  assert(decl->isDistributedActor());

  for (auto member : decl->getMembers()) {
    auto func = dyn_cast<FuncDecl>(member);
    if (func && func->isDistributed()) {
      addImplicitRemoteActorFunction(decl, func);
    }
  }
}

/******************************************************************************/
/************************ SYNTHESIS ENTRY POINT *******************************/
/******************************************************************************/

/// Entry point for adding all computed members to a distributed actor decl.
void swift::addImplicitDistributedActorMembersToClass(ClassDecl *decl) {
  // Bail out if not a distributed actor definition.
  if (!decl->isDistributedActor())
    return;

  // If the _Distributed module is missing we cannot synthesize anything.
  if (!swift::ensureDistributedModuleLoaded(decl))
    return;

  addFactoryResolveFunction(decl);
  addImplicitDistributedActorStoredProperties(decl);
  addImplicitRemoteActorFunctions(decl);
//  addImplicitResignIdentity(decl);
}
<commit_msg>[Distributed] Remove deinit AST synthesis, now handled in SILGenDestructor<commit_after>//===--- CodeSynthesisDistributedActor.cpp --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "TypeCheckDistributed.h"

#include "TypeChecker.h"
#include "TypeCheckType.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Availability.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Defer.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Sema/ConstraintSystem.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "DerivedConformances.h"
using namespace swift;

/******************************************************************************/
/******************************* RESOLVE FUNCTION *****************************/
/******************************************************************************/

/// Synthesizes the
///
/// \verbatim
/// static resolve(_ address: ActorAddress,
///                using transport: ActorTransport) throws -> Self {
///   <filled in by SILGenDistributed>
/// }
/// \endverbatim
///
/// factory function in the AST, with an empty body. Its body is
/// expected to be filled-in during SILGen.
static void addFactoryResolveFunction(ClassDecl *decl) {
  assert(decl->isDistributedActor());
  auto &C = decl->getASTContext();

  auto mkParam = [&](Identifier argName, Identifier paramName, Type ty) -> ParamDecl* {
    auto *param = new (C) ParamDecl(SourceLoc(),
                                    SourceLoc(), argName,
                                    SourceLoc(), paramName, decl);
    param->setImplicit();
    param->setSpecifier(ParamSpecifier::Default);
    param->setInterfaceType(ty);
    return param;
  };

  auto addressType = C.getAnyActorIdentityDecl()->getDeclaredInterfaceType();
  auto transportType = C.getActorTransportDecl()->getDeclaredInterfaceType();

  // (_ identity: AnyActorIdentity, using transport: ActorTransport)
  auto *params = ParameterList::create(
      C,
      /*LParenLoc=*/SourceLoc(),
      /*params=*/{  mkParam(Identifier(), C.Id_identity, addressType),
                    mkParam(C.Id_using, C.Id_transport, transportType)
                  },
      /*RParenLoc=*/SourceLoc()
      );

  // Func name: resolve(_:using:)
  DeclName name(C, C.Id_resolve, params);

  // Expected type: (Self) -> (AnyActorIdentity, ActorTransport) throws -> (Self)
  auto *factoryDecl =
      FuncDecl::createImplicit(C, StaticSpellingKind::KeywordStatic,
                               name, SourceLoc(),
                               /*async=*/false,
                               /*throws=*/true,
                               /*genericParams=*/nullptr,
                               params,
                               /*returnType*/decl->getDeclaredInterfaceType(),
                               decl);

  factoryDecl->setDistributedActorFactory(); // TODO(distributed): should we mark this specifically as the resolve factory?
  factoryDecl->copyFormalAccessFrom(decl, /*sourceIsParentContext=*/true);

  decl->addMember(factoryDecl);
}

/******************************************************************************/
/******************************** PROPERTIES **********************************/
/******************************************************************************/

// TODO: deduplicate with 'declareDerivedProperty' from DerivedConformance...
std::pair<VarDecl *, PatternBindingDecl *>
createStoredProperty(ClassDecl *classDecl, ASTContext &ctx,
                     VarDecl::Introducer introducer, Identifier name,
                     Type propertyInterfaceType, Type propertyContextType,
                     bool isStatic, bool isFinal) {
  auto parentDC = classDecl;

  VarDecl *propDecl = new (ctx)
      VarDecl(/*IsStatic*/ isStatic, introducer,
                           SourceLoc(), name, parentDC);
  propDecl->setImplicit();
  propDecl->setSynthesized();
  propDecl->copyFormalAccessFrom(classDecl, /*sourceIsParentContext*/ true);
  propDecl->setInterfaceType(propertyInterfaceType);

  Pattern *propPat = NamedPattern::createImplicit(ctx, propDecl);
  propPat->setType(propertyContextType);

  propPat = TypedPattern::createImplicit(ctx, propPat, propertyContextType);
  propPat->setType(propertyContextType);

  auto *pbDecl = PatternBindingDecl::createImplicit(
      ctx, StaticSpellingKind::None, propPat, /*InitExpr*/ nullptr,
      parentDC);
  return {propDecl, pbDecl};
}

/// Adds the following, fairly special, properties to each distributed actor:
/// - actorTransport
/// - id
static void addImplicitDistributedActorStoredProperties(ClassDecl *decl) {
  assert(decl->isDistributedActor());

  auto &C = decl->getASTContext();

  // ```
  // @_distributedActorIndependent
  // let id: AnyActorIdentity // TODO: move to `nonisolated var id {}` once we have the new allocation scheme
  // ```
  {
    auto propertyType = C.getAnyActorIdentityDecl()->getDeclaredInterfaceType();

    VarDecl *propDecl;
    PatternBindingDecl *pbDecl;
    std::tie(propDecl, pbDecl) = createStoredProperty(
        decl, C,
        VarDecl::Introducer::Let, C.Id_id,
        propertyType, propertyType,
        /*isStatic=*/false, /*isFinal=*/true);

    // mark as @_distributedActorIndependent, allowing access to it from everywhere
    propDecl->getAttrs().add(
        new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true)); // TODO: remove and move to nonisolated once new constructors land

    decl->addMember(propDecl);
    decl->addMember(pbDecl);
  }

  // ```
  // @_distributedActorIndependent
  // let actorTransport: ActorTransport
  // ```
  // (no need for @actorIndependent because it is an immutable let)
  {
    auto propertyType = C.getActorTransportDecl()->getDeclaredInterfaceType();

    VarDecl *propDecl;
    PatternBindingDecl *pbDecl;
    std::tie(propDecl, pbDecl) = createStoredProperty(
        decl, C,
        VarDecl::Introducer::Let, C.Id_actorTransport,
        propertyType, propertyType,
        /*isStatic=*/false, /*isFinal=*/true);

    // mark as @_distributedActorIndependent, allowing access to it from everywhere
    propDecl->getAttrs().add(
        new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true)); // TODO: remove and move to nonisolated once new constructors land

    decl->addMember(propDecl);
    decl->addMember(pbDecl);
  }
}

/******************************************************************************/
/*************************** _REMOTE_ FUNCTIONS *******************************/
/******************************************************************************/

/// Synthesizes the for `_remote_xxx` functions.
///
/// Create a stub body that emits a fatal error message.
static std::pair<BraceStmt *, bool>
synthesizeRemoteFuncStubBody(AbstractFunctionDecl *func, void *context) {
  auto distributedFunc = static_cast<AbstractFunctionDecl *>(context);
  auto classDecl = func->getDeclContext()->getSelfClassDecl();
  auto &ctx = func->getASTContext();
  auto &SM = ctx.SourceMgr;

  auto *staticStringDecl = ctx.getStaticStringDecl();
  auto staticStringType = staticStringDecl->getDeclaredInterfaceType();
  auto staticStringInit = ctx.getStringBuiltinInitDecl(staticStringDecl);

  auto *uintDecl = ctx.getUIntDecl();
  auto uintType = uintDecl->getDeclaredInterfaceType();
  auto uintInit = ctx.getIntBuiltinInitDecl(uintDecl);

  auto missingTransportDecl = ctx.getMissingDistributedActorTransport();
  assert(missingTransportDecl && "Could not locate '_missingDistributedActorTransport' function");

  // Create a call to _Distributed._missingDistributedActorTransport
  auto loc = func->getLoc();
  Expr *ref = new (ctx) DeclRefExpr(missingTransportDecl,
                                    DeclNameLoc(loc), /*Implicit=*/true);
  ref->setType(missingTransportDecl->getInterfaceType()
  ->removeArgumentLabels(1));

  llvm::SmallString<64> buffer;
  StringRef fullClassName = ctx.AllocateCopy(
      (classDecl->getModuleContext()->getName().str() +
      "." +
      classDecl->getName().str()).toStringRef(buffer));

  auto *className = new (ctx) StringLiteralExpr(fullClassName, loc,
                                                /*Implicit=*/true);
  className->setBuiltinInitializer(staticStringInit);
  assert(isa<ConstructorDecl>(className->getBuiltinInitializer().getDecl()));
  className->setType(staticStringType);

  auto *funcName = new (ctx) StringLiteralExpr(
      ctx.AllocateCopy(func->getName().getBaseName().getIdentifier().str()), loc,
      /*Implicit=*/true);
  funcName->setType(staticStringType);
  funcName->setBuiltinInitializer(staticStringInit);

  // Note: Sadly we cannot just rely on #function, #file, #line for the location
  // (MagicIdentifierLiteralExpr), of the call because the call is made from a thunk.
  // That thunk does not carry those info today although it could.
  //
  // Instead, we offer the location where the distributed func was declared.
  auto fileString = SM.getDisplayNameForLoc(distributedFunc->getStartLoc());
  auto *file = new (ctx) StringLiteralExpr(fileString, loc, /*Implicit=*/true);
  file->setType(staticStringType);
  file->setBuiltinInitializer(staticStringInit);

  auto startLineAndCol = SM.getPresumedLineAndColumnForLoc(distributedFunc->getStartLoc());
//  auto *line = new (ctx) MagicIdentifierLiteralExpr(
//      MagicIdentifierLiteralExpr::Line, loc, /*Implicit=*/true);
//  auto *line = new (ctx) IntegerLiteralExpr(startLineAndCol.first, loc,
//                                            /*implicit*/ true);
  auto *line = IntegerLiteralExpr::createFromUnsigned(ctx, startLineAndCol.first);
  line->setType(uintType);
  line->setBuiltinInitializer(uintInit);

//  auto *column = new (ctx) MagicIdentifierLiteralExpr(
//      MagicIdentifierLiteralExpr::Column, loc, /*Implicit=*/true);
  auto *column = IntegerLiteralExpr::createFromUnsigned(ctx, startLineAndCol.second);
  column->setType(uintType);
  column->setBuiltinInitializer(uintInit);

  auto *call = CallExpr::createImplicit(
      ctx, ref, { className, funcName, file, line, column }, {});
  call->setType(ctx.getNeverType());
  call->setThrows(false);

  SmallVector<ASTNode, 2> stmts;
  stmts.push_back(call); // something() -> Never
  // stmts.push_back(new (ctx) ReturnStmt(SourceLoc(), /*Result=*/nullptr)); // FIXME: this causes 'different types for return type: String vs. ()'
  auto body = BraceStmt::create(ctx, SourceLoc(), stmts, SourceLoc(),
                                /*implicit=*/true);
  return { body, /*isTypeChecked=*/true };
}

static Identifier makeRemoteFuncIdentifier(FuncDecl* func) {
  auto &C = func->getASTContext();
  auto localFuncName = func->getBaseIdentifier().str().str();
  auto remoteFuncIdent = C.getIdentifier("_remote_" + localFuncName);
  return remoteFuncIdent;
}

/// Create a remote stub for the passed in \c func.
/// The remote stub function is not user accessible and mirrors the API of
/// the local function. It is always throwing, async, and user-inaccessible.
///
/// ```
/// // func greet(name: String) { ... }
/// dynamic <access> func _remote_greet(name: String) async throws {
///     fatalError(...)
/// }
/// ```
///
/// and is intended to be replaced by a transport library by providing an
/// appropriate @_dynamicReplacement function.
static void addImplicitRemoteActorFunction(ClassDecl *decl, FuncDecl *func) {
  auto &C = decl->getASTContext();
  auto parentDC = decl;

  auto remoteFuncIdent = makeRemoteFuncIdentifier(func);

  auto params = ParameterList::clone(C, func->getParameters());
  auto genericParams = func->getGenericParams(); // TODO: also clone those
  Type resultTy = func->getResultInterfaceType();

  DeclName name(C, remoteFuncIdent, params);
  auto *const remoteFuncDecl = FuncDecl::createImplicit(
      C, StaticSpellingKind::None, name, /*NameLoc=*/SourceLoc(),
      /*Async=*/true, /*Throws=*/true,
      /*GenericParams=*/genericParams, params,
      resultTy, parentDC);

  // *dynamic* because we'll be replacing it with specific transports
  remoteFuncDecl->getAttrs().add(
      new (C) DynamicAttr(/*implicit=*/true));

  // @_distributedActorIndependent
  remoteFuncDecl->getAttrs().add(
      new (C) DistributedActorIndependentAttr(/*IsImplicit=*/true));

  // users should never have to access this function directly;
  // it is only invoked from our distributed function thunk if the actor is remote.
  remoteFuncDecl->setUserAccessible(false);
  remoteFuncDecl->setSynthesized();

  remoteFuncDecl->setBodySynthesizer(&synthesizeRemoteFuncStubBody, func);

  // same access control as the original function is fine
  remoteFuncDecl->copyFormalAccessFrom(func, /*sourceIsParentContext=*/false);

  decl->addMember(remoteFuncDecl);
}

/// Synthesize dynamic _remote stub functions for each encountered distributed function.
static void addImplicitRemoteActorFunctions(ClassDecl *decl) {
  assert(decl->isDistributedActor());

  for (auto member : decl->getMembers()) {
    auto func = dyn_cast<FuncDecl>(member);
    if (func && func->isDistributed()) {
      addImplicitRemoteActorFunction(decl, func);
    }
  }
}

/******************************************************************************/
/************************ SYNTHESIS ENTRY POINT *******************************/
/******************************************************************************/

/// Entry point for adding all computed members to a distributed actor decl.
void swift::addImplicitDistributedActorMembersToClass(ClassDecl *decl) {
  // Bail out if not a distributed actor definition.
  if (!decl->isDistributedActor())
    return;

  // If the _Distributed module is missing we cannot synthesize anything.
  if (!swift::ensureDistributedModuleLoaded(decl))
    return;

  addFactoryResolveFunction(decl);
  addImplicitDistributedActorStoredProperties(decl);
  addImplicitRemoteActorFunctions(decl);
}
<|endoftext|>