aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qtsupport/qscxmlcgenerator.cpp
blob: 8aa1c0198fd5527817251cd6f4dc1ca211b138c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#include "qscxmlcgenerator.h"

#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitaspect.h>

#include <projectexplorer/extracompiler.h>
#include <projectexplorer/target.h>

#include <utils/qtcassert.h>
#include <utils/temporarydirectory.h>

#include <QDateTime>
#include <QLoggingCategory>

using namespace ProjectExplorer;
using namespace Utils;

namespace QtSupport::Internal {

static QLoggingCategory log("qtc.qscxmlcgenerator", QtWarningMsg);

const char TaskCategory[] = "Task.Category.ExtraCompiler.QScxmlc";

class QScxmlcGenerator final : public ProcessExtraCompiler
{
public:
    QScxmlcGenerator(const Project *project, const FilePath &source,
                     const FilePaths &targets, QObject *parent)
        : ProcessExtraCompiler(project, source, targets, parent)
        , m_tmpdir("qscxmlgenerator")
    {
        QTC_ASSERT(targets.count() == 2, return);
        m_header = m_tmpdir.filePath(targets[0].fileName()).toString();
        QTC_ASSERT(!m_header.isEmpty(), return);
        m_impl = m_tmpdir.filePath(targets[1].fileName()).toString();
    }

private:
    FilePath command() const override;

    QStringList arguments() const override
    {
        return {"--header", m_header, "--impl", m_impl, tmpFile().fileName()};
    }

    FilePath workingDirectory() const override
    {
        return m_tmpdir.path();
    }

    FilePath tmpFile() const
    {
        return workingDirectory().pathAppended(source().fileName());
    }

    FileNameToContentsHash handleProcessFinished(Process *process) override;
    bool prepareToRun(const QByteArray &sourceContents) override;
    Tasks parseIssues(const QByteArray &processStderr) override;

    TemporaryDirectory m_tmpdir;
    QString m_header;
    QString m_impl;
};

Tasks QScxmlcGenerator::parseIssues(const QByteArray &processStderr)
{
    Tasks issues;
    const QList<QByteArray> lines = processStderr.split('\n');
    for (const QByteArray &line : lines) {
        QByteArrayList tokens = line.split(':');

        if (tokens.length() > 4) {
            FilePath file = FilePath::fromUtf8(tokens[0]);
            int line = tokens[1].toInt();
            // int column = tokens[2].toInt(); <- nice, but not needed for now.
            Task::TaskType type = tokens[3].trimmed() == "error" ?
                        Task::Error : Task::Warning;
            QString message = QString::fromUtf8(tokens.mid(4).join(':').trimmed());
            issues.append(Task(type, message, file, line, TaskCategory));
        }
    }
    return issues;
}

FilePath QScxmlcGenerator::command() const
{
    Target *target = project()->activeTarget();
    Kit *kit = target ? target->kit() : KitManager::defaultKit();
    QtVersion *version = QtKitAspect::qtVersion(kit);

    if (!version)
        return {};

    return version->qscxmlcFilePath();
}

bool QScxmlcGenerator::prepareToRun(const QByteArray &sourceContents)
{
    const FilePath fn = tmpFile();
    QFile input(fn.toString());
    if (!input.open(QIODevice::WriteOnly))
        return false;
    input.write(sourceContents);
    input.close();

    return true;
}

FileNameToContentsHash QScxmlcGenerator::handleProcessFinished(Process *process)
{
    Q_UNUSED(process)
    const FilePath wd = workingDirectory();
    FileNameToContentsHash result;
    forEachTarget([&](const FilePath &target) {
        const FilePath file = wd.pathAppended(target.fileName());
        QFile generated(file.toString());
        if (!generated.open(QIODevice::ReadOnly))
            return;
        result[target] = generated.readAll();
    });
    return result;
}

// QScxmlcGeneratorFactory

class QScxmlcGeneratorFactory final : public ExtraCompilerFactory
{
public:
    QScxmlcGeneratorFactory() = default;

    FileType sourceType() const final { return FileType::StateChart; }

    QString sourceTag() const final { return QStringLiteral("scxml"); }

    ExtraCompiler *create(const Project *project,
                          const FilePath &source,
                          const FilePaths &targets) final
    {
        return new QScxmlcGenerator(project, source, targets, this);
    }
};

void setupQScxmlcGenerator()
{
    static QScxmlcGeneratorFactory theQScxmlcGeneratorFactory;
}

} // QtSupport::Internal