qbsnodetreebuilder.cpp 8.35 KB
Newer Older
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
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/

#include "qbsnodetreebuilder.h"

28
29
#include "qbsproject.h"

30
31
32
33
34
#include <utils/algorithm.h>
#include <utils/qtcassert.h>

namespace {

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
ProjectExplorer::FileType fileType(const qbs::ArtifactData &artifact)
{
    QTC_ASSERT(artifact.isValid(), return ProjectExplorer::FileType::Unknown);

    if (artifact.fileTags().contains("c")
            || artifact.fileTags().contains("cpp")
            || artifact.fileTags().contains("objc")
            || artifact.fileTags().contains("objcpp")) {
        return ProjectExplorer::FileType::Source;
    }
    if (artifact.fileTags().contains("hpp"))
        return ProjectExplorer::FileType::Header;
    if (artifact.fileTags().contains("qrc"))
        return ProjectExplorer::FileType::Resource;
    if (artifact.fileTags().contains("ui"))
        return ProjectExplorer::FileType::Form;
    if (artifact.fileTags().contains("scxml"))
        return ProjectExplorer::FileType::StateChart;
    return ProjectExplorer::FileType::Unknown;
}

56
57
void setupArtifacts(ProjectExplorer::FolderNode *root, const QList<qbs::ArtifactData> &artifacts)
{
Orgad Shaneh's avatar
Orgad Shaneh committed
58
    for (const qbs::ArtifactData &ad : artifacts) {
59
        const Utils::FileName path = Utils::FileName::fromString(ad.filePath());
60
        const ProjectExplorer::FileType type = fileType(ad);
61
        const bool isGenerated = ad.isGenerated();
Orgad Shaneh's avatar
Orgad Shaneh committed
62
63
        root->addNestedNode(new ProjectExplorer::FileNode(path, type, isGenerated));
    };
64
65
66
67

    root->compress();
}

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
QbsProjectManager::Internal::QbsGroupNode
*buildGroupNodeTree(const qbs::GroupData &grp, const QString &productPath, bool productIsEnabled)
{
    QTC_ASSERT(grp.isValid(), return nullptr);

    auto result = new QbsProjectManager::Internal::QbsGroupNode(grp, productPath);

    result->setEnabled(productIsEnabled && grp.isEnabled());
    result->setAbsoluteFilePathAndLine(
                Utils::FileName::fromString(grp.location().filePath()).parentDir(), -1);
    result->setDisplayName(grp.name());
    result->addNode(new QbsProjectManager::Internal::QbsFileNode(
                        Utils::FileName::fromString(grp.location().filePath()),
                        ProjectExplorer::FileType::Project, false,
                        grp.location().line()));

    ::setupArtifacts(result, grp.allSourceArtifacts());

    return result;
}

void setupQbsProductData(QbsProjectManager::Internal::QbsProductNode *node,
                         const qbs::ProductData &prd, const qbs::Project &project)
{
    using namespace QbsProjectManager::Internal;

    node->setEnabled(prd.isEnabled());

    node->setDisplayName(QbsProject::productDisplayName(project, prd));
    node->setAbsoluteFilePathAndLine(Utils::FileName::fromString(prd.location().filePath()).parentDir(), -1);
    const QString &productPath = QFileInfo(prd.location().filePath()).absolutePath();

    // Add QbsFileNode:
    node->addNode(new QbsFileNode(Utils::FileName::fromString(prd.location().filePath()),
                                  ProjectExplorer::FileType::Project, false,
                                  prd.location().line()));


    foreach (const qbs::GroupData &grp, prd.groups()) {
        if (grp.name() == prd.name() && grp.location() == prd.location()) {
            // Set implicit product group right onto this node:
            setupArtifacts(node, grp.allSourceArtifacts());
            continue;
        }
        node->addNode(buildGroupNodeTree(grp, productPath, prd.isEnabled()));
    }

    // Add "Generated Files" Node:
    auto genFiles
            = new ProjectExplorer::VirtualFolderNode(node->filePath(),
                                                     ProjectExplorer::Node::DefaultProjectFilePriority - 10);
    genFiles->setDisplayName(QCoreApplication::translate("QbsProductNode", "Generated files"));
    node->addNode(genFiles);
    setupArtifacts(genFiles, prd.generatedArtifacts());
}

124
125
126
127
128
129
130
131
132
QbsProjectManager::Internal::QbsProductNode *
buildProductNodeTree(const qbs::Project &project, const qbs::ProductData &prd)
{
    auto result = new QbsProjectManager::Internal::QbsProductNode(prd);

    setupQbsProductData(result, prd, project);
    return result;
}

133
134
void setupProjectNode(QbsProjectManager::Internal::QbsProjectNode *node, const qbs::ProjectData &prjData,
                      const qbs::Project &qbsProject)
135
{
136
137
138
139
    using namespace QbsProjectManager::Internal;
    node->addNode(new QbsFileNode(Utils::FileName::fromString(prjData.location().filePath()),
                                  ProjectExplorer::FileType::Project, false,
                                  prjData.location().line()));
140
141
    foreach (const qbs::ProjectData &subData, prjData.subProjects()) {
        auto subProject =
142
143
                new QbsProjectManager::Internal::QbsProjectNode(
                    Utils::FileName::fromString(subData.location().filePath()).parentDir());
144
145
146
147
148
149
150
151
152
153
154
        setupProjectNode(subProject, subData, qbsProject);
        node->addNode(subProject);
    }

    foreach (const qbs::ProductData &prd, prjData.products())
        node->addNode(buildProductNodeTree(qbsProject, prd));

    if (!prjData.name().isEmpty())
        node->setDisplayName(prjData.name());
    else
        node->setDisplayName(node->project()->displayName());
hjk's avatar
hjk committed
155
156

    node->setProjectData(prjData);
157
158
}

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
QSet<QString> referencedBuildSystemFiles(const qbs::ProjectData &data)
{
    QSet<QString> result;
    result.insert(data.location().filePath());
    foreach (const qbs::ProjectData &subProject, data.subProjects())
        result.unite(referencedBuildSystemFiles(subProject));
    foreach (const qbs::ProductData &product, data.products()) {
        result.insert(product.location().filePath());
        foreach (const qbs::GroupData &group, product.groups())
            result.insert(group.location().filePath());
    }

    return result;
}

QStringList unreferencedBuildSystemFiles(const qbs::Project &p)
{
Joerg Bornemann's avatar
Joerg Bornemann committed
176
177
178
179
180
    QStringList result;
    if (!p.isValid())
        return result;

    const std::set<QString> &available = p.buildSystemFiles();
181
182
    QList<QString> referenced = referencedBuildSystemFiles(p.projectData()).toList();
    Utils::sort(referenced);
Joerg Bornemann's avatar
Joerg Bornemann committed
183
184
185
    std::set_difference(available.begin(), available.end(), referenced.begin(), referenced.end(),
                        std::back_inserter(result));
    return result;
186
187
188
189
190
191
192
}

} // namespace

namespace QbsProjectManager {
namespace Internal {

193
QbsRootProjectNode *QbsNodeTreeBuilder::buildTree(QbsProject *project)
194
{
195
    auto root = new QbsRootProjectNode(project);
196
    setupProjectNode(root, project->qbsProjectData(), project->qbsProject());
197
198
199
200
201
202
203
204
205
    auto buildSystemFiles
            = new ProjectExplorer::FolderNode(project->projectDirectory(),
                                              ProjectExplorer::NodeType::Folder,
                                              QCoreApplication::translate("QbsRootProjectNode", "Qbs files"));

    Utils::FileName base = project->projectDirectory();
    for (const QString &f : unreferencedBuildSystemFiles(project->qbsProject())) {
        const Utils::FileName filePath = Utils::FileName::fromString(f);
        if (filePath.isChildOf(base))
206
            buildSystemFiles->addNestedNode(new ProjectExplorer::FileNode(filePath, ProjectExplorer::FileType::Project, false));
207
208
209
210
    }
    buildSystemFiles->compress();
    root->addNode(buildSystemFiles);

211
    return root;
212
213
}

214
215
} // namespace Internal
} // namespace QbsProjectManager