<commit_before>/**************************************************************************
**
** This file is part of the Qt Build Suite
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (<EMAIL>)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file.
** Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**************************************************************************/

#include "automoc.h"
#include "scanresultcache.h"
#include <buildgraph/artifact.h>
#include <buildgraph/transformer.h>
#include <tools/error.h>
#include <tools/logger.h>
#include <tools/scannerpluginmanager.h>

namespace qbs {

AutoMoc::AutoMoc()
    : m_scanResultCache(0)
{
}

void AutoMoc::setScanResultCache(ScanResultCache *scanResultCache)
{
    m_scanResultCache = scanResultCache;
}

void AutoMoc::apply(BuildProduct::Ptr product)
{
    if (scanners().isEmpty())
        throw Error("C++ scanner cannot be loaded.");

    Artifact *pluginMetaDataFile = 0;
    QList<QPair<Artifact *, FileType> > artifactsToMoc;
    QSet<QString> includedMocCppFiles;
    ArtifactList::const_iterator it = product->artifacts.begin();
    for (; it != product->artifacts.end(); ++it) {
        Artifact *artifact = *it;
        if (!pluginMetaDataFile && artifact->fileTags.contains(QLatin1String("qt_plugin_metadata"))) {
            if (qbsLogLevel(LoggerDebug))
                qbsDebug() << "[AUTOMOC] found Qt plugin metadata file " << artifact->filePath();
            pluginMetaDataFile = artifact;
        }
        if (artifact->artifactType != Artifact::SourceFile)
            continue;
        const FileType fileType = AutoMoc::fileType(artifact);
        if (fileType == UnknownFileType)
            continue;
        QString mocFileTag;
        bool alreadyMocced = isVictimOfMoc(artifact, fileType, mocFileTag);
        bool hasQObjectMacro;
        scan(artifact, hasQObjectMacro, includedMocCppFiles);
        if (hasQObjectMacro && !alreadyMocced) {
            artifactsToMoc += qMakePair(artifact, fileType);
        } else if (!hasQObjectMacro && alreadyMocced) {
            unmoc(artifact, mocFileTag);
        }
    }

    Artifact *pluginHeaderFile = 0;
    QMap<QString, QSet<Artifact *> > artifactsPerFileTag;
    for (int i = artifactsToMoc.count(); --i >= 0;) {
        const QPair<Artifact *, FileType> &p = artifactsToMoc.at(i);
        Artifact * const artifact = p.first;
        FileType fileType = p.second;
        foreach (const QString &fileTag, artifact->fileTags) {
            if (fileTag == QLatin1String("moc_hpp")) {
                const QString mocFileName = generateMocFileName(artifact, fileType);
                if (includedMocCppFiles.contains(mocFileName)) {
                    QString newFileTag = QLatin1String("moc_hpp_inc");
                    artifact->fileTags -= fileTag;
                    artifact->fileTags += newFileTag;
                    artifactsPerFileTag[newFileTag].insert(artifact);
                    continue;
                }
            } else if (fileTag == QLatin1String("moc_plugin_hpp")) {
                if (qbsLogLevel(LoggerDebug))
                    qbsDebug() << "[AUTOMOC] found Qt plugin header file " << artifact->filePath();
                QString newFileTag = QLatin1String("moc_hpp");
                artifact->fileTags -= fileTag;
                artifact->fileTags += newFileTag;
                artifactsPerFileTag[newFileTag].insert(artifact);
                pluginHeaderFile = artifact;
            }
            artifactsPerFileTag[fileTag].insert(artifact);
        }
    }

    BuildGraph *buildGraph = product->project->buildGraph();
    if (!artifactsPerFileTag.isEmpty()) {
        qbsInfo() << DontPrintLogLevel << "Applying moc rules for '" << product->rProduct->name << "'.";
        buildGraph->applyRules(product.data(), artifactsPerFileTag);
    }
    if (pluginHeaderFile && pluginMetaDataFile) {
        // Make every artifact that is dependent of the header file also<commit_msg>fix pch dependencies for moc generated C++ files<commit_after>/**************************************************************************
**
** This file is part of the Qt Build Suite
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (<EMAIL>)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file.
** Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**************************************************************************/

#include "automoc.h"
#include "scanresultcache.h"
#include <buildgraph/artifact.h>
#include <buildgraph/transformer.h>
#include <tools/error.h>
#include <tools/logger.h>
#include <tools/scannerpluginmanager.h>

namespace qbs {

AutoMoc::AutoMoc()
    : m_scanResultCache(0)
{
}

void AutoMoc::setScanResultCache(ScanResultCache *scanResultCache)
{
    m_scanResultCache = scanResultCache;
}

void AutoMoc::apply(BuildProduct::Ptr product)
{
    if (scanners().isEmpty())
        throw Error("C++ scanner cannot be loaded.");

    Artifact *pluginMetaDataFile = 0;
    Artifact *pchFile = 0;
    QList<QPair<Artifact *, FileType> > artifactsToMoc;
    QSet<QString> includedMocCppFiles;
    ArtifactList::const_iterator it = product->artifacts.begin();
    for (; it != product->artifacts.end(); ++it) {
        Artifact *artifact = *it;
        if (!pchFile || !pluginMetaDataFile) {
            foreach (const QString &fileTag, artifact->fileTags) {
                if (fileTag == QLatin1String("c++_pch"))
                    pchFile = artifact;
                else if (fileTag == QLatin1String("qt_plugin_metadata"))
                    pluginMetaDataFile = artifact;
            }
        }

        if (!pluginMetaDataFile && artifact->fileTags.contains(QLatin1String("qt_plugin_metadata"))) {
            if (qbsLogLevel(LoggerDebug))
                qbsDebug() << "[AUTOMOC] found Qt plugin metadata file " << artifact->filePath();
            pluginMetaDataFile = artifact;
        }
        if (artifact->artifactType != Artifact::SourceFile)
            continue;
        const FileType fileType = AutoMoc::fileType(artifact);
        if (fileType == UnknownFileType)
            continue;
        QString mocFileTag;
        bool alreadyMocced = isVictimOfMoc(artifact, fileType, mocFileTag);
        bool hasQObjectMacro;
        scan(artifact, hasQObjectMacro, includedMocCppFiles);
        if (hasQObjectMacro && !alreadyMocced) {
            artifactsToMoc += qMakePair(artifact, fileType);
        } else if (!hasQObjectMacro && alreadyMocced) {
            unmoc(artifact, mocFileTag);
        }
    }

    Artifact *pluginHeaderFile = 0;
    QMap<QString, QSet<Artifact *> > artifactsPerFileTag;
    for (int i = artifactsToMoc.count(); --i >= 0;) {
        const QPair<Artifact *, FileType> &p = artifactsToMoc.at(i);
        Artifact * const artifact = p.first;
        FileType fileType = p.second;
        foreach (const QString &fileTag, artifact->fileTags) {
            if (fileTag == QLatin1String("moc_hpp")) {
                const QString mocFileName = generateMocFileName(artifact, fileType);
                if (includedMocCppFiles.contains(mocFileName)) {
                    QString newFileTag = QLatin1String("moc_hpp_inc");
                    artifact->fileTags -= fileTag;
                    artifact->fileTags += newFileTag;
                    artifactsPerFileTag[newFileTag].insert(artifact);
                    continue;
                }
            } else if (fileTag == QLatin1String("moc_plugin_hpp")) {
                if (qbsLogLevel(LoggerDebug))
                    qbsDebug() << "[AUTOMOC] found Qt plugin header file " << artifact->filePath();
                QString newFileTag = QLatin1String("moc_hpp");
                artifact->fileTags -= fileTag;
                artifact->fileTags += newFileTag;
                artifactsPerFileTag[newFileTag].insert(artifact);
                pluginHeaderFile = artifact;
            }
            artifactsPerFileTag[fileTag].insert(artifact);
        }
    }

    if (pchFile)
        artifactsPerFileTag[QLatin1String("c++_pch")] += pchFile;
    BuildGraph *buildGraph = product->project->buildGraph();
    if (!artifactsPerFileTag.isEmpty()) {
        qbsInfo() << DontPrintLogLevel << "Applying moc rules for '" << product->rProduct->name << "'.";
        buildGraph->applyRules(product.data(), artifactsPerFileTag);
    }
    if (pluginHeaderFile && pluginMetaDataFile) {
        // Make every artifact that is dependent of the header file also
{'fraction_non_alphanumeric': 0.13168724279835392, 'fraction_numerical': 0.0049382716049382715, 'mean_word_length': 3.0548757879124953, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5875911', 'n_tokens_mistral': 3100, 'n_tokens_neox': 2914, 'n_words': 848}