void CppPreprocessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType type)
{
    typedef Document::DiagnosticMessage Message;
    if (fileName.isEmpty())
        return;

    QString absoluteFileName = resolveFile(fileName, type);
    absoluteFileName = QDir::cleanPath(absoluteFileName);
    if (m_currentDoc) {
        m_currentDoc->addIncludeFile(Document::Include(fileName, absoluteFileName, line, type));
        if (absoluteFileName.isEmpty()) {
            const QString text = QCoreApplication::translate(
                "CppPreprocessor", "%1: No such file or directory").arg(fileName);
            Message message(Message::Warning, m_currentDoc->fileName(), line, /*column =*/ 0, text);
            m_currentDoc->addDiagnosticMessage(message);
            return;
        }
    }
    if (m_included.contains(absoluteFileName))
        return; // we've already seen this file.
    if (absoluteFileName != modelManager()->configurationFileName())
        m_included.insert(absoluteFileName);

    // Already in snapshot? Use it!
    Document::Ptr doc = m_snapshot.document(absoluteFileName);
    if (doc) {
        mergeEnvironment(doc);
        return;
    }

    // Otherwise get file contents
    unsigned editorRevision = 0;
    QByteArray contents;
    const bool gotFileContents = getFileContents(absoluteFileName, &contents, &editorRevision);
    contents = convertToLatin1(contents);
    if (m_currentDoc && !gotFileContents) {
        const QString text = QCoreApplication::translate(
            "CppPreprocessor", "%1: Could not get file contents").arg(fileName);
        Message message(Message::Warning, m_currentDoc->fileName(), line, /*column =*/ 0, text);
        m_currentDoc->addDiagnosticMessage(message);
        return;
    }

    if (m_dumpFileNameWhileParsing) {
        qDebug() << "Parsing file:" << absoluteFileName
                 << "contents:" << contents.size() << "bytes";
    }

    doc = Document::create(absoluteFileName);
    doc->setRevision(m_revision);
    doc->setEditorRevision(editorRevision);

    const QFileInfo info(absoluteFileName);
    if (info.exists())
        doc->setLastModified(info.lastModified());

    const Document::Ptr previousDoc = switchDocument(doc);

    const QByteArray preprocessedCode = m_preprocess.run(absoluteFileName, contents);
//    {
//        QByteArray b(preprocessedCode);
//        b.replace("\n", "<<<\n");
//        qDebug("Preprocessed code for \"%s\": [[%s]]", fileName.toUtf8().constData(),
//               b.constData());
//    }

    QCryptographicHash hash(QCryptographicHash::Sha1);
    hash.addData(preprocessedCode);
    foreach (const Macro &macro, doc->definedMacros()) {
        if (macro.isHidden()) {
            static const QByteArray undef("#undef ");
            hash.addData(undef);
            hash.addData(macro.name());
        } else {
            static const QByteArray def("#define ");
            hash.addData(macro.name());
            hash.addData(" ", 1);
            hash.addData(def);
            hash.addData(macro.definitionText());
        }
        hash.addData("\n", 1);
    }
    doc->setFingerprint(hash.result());

    Document::Ptr anotherDoc = m_globalSnapshot.document(absoluteFileName);
    if (anotherDoc && anotherDoc->fingerprint() == doc->fingerprint()) {
        switchDocument(previousDoc);
        mergeEnvironment(anotherDoc);
        m_snapshot.insert(anotherDoc);
        m_todo.remove(absoluteFileName);
        return;
    }

    doc->setUtf8Source(preprocessedCode);
    doc->keepSourceAndAST();
    doc->tokenize();

    m_snapshot.insert(doc);
    m_todo.remove(absoluteFileName);

    Process process(m_modelManager, doc, m_workingCopy);
    process();

    (void) switchDocument(previousDoc);
}
Beispiel #2
0
void CppPreprocessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType type)
{
    if (fileName.isEmpty())
        return;

    QString absoluteFileName = resolveFile(fileName, type);
    absoluteFileName = QDir::cleanPath(absoluteFileName);
    if (m_currentDoc)
        m_currentDoc->addIncludeFile(Document::Include(fileName, absoluteFileName, line, type));
    if (m_included.contains(absoluteFileName))
        return; // we've already seen this file.
    if (absoluteFileName != modelManager()->configurationFileName())
        m_included.insert(absoluteFileName);

    unsigned editorRevision = 0;
    QByteArray contents;
    getFileContents(absoluteFileName, &contents, &editorRevision);
    contents = convertToLatin1(contents);
    if (m_currentDoc) {
        if (contents.isEmpty() && !QFileInfo(absoluteFileName).isAbsolute()) {
            QString msg = QCoreApplication::translate(
                    "CppPreprocessor", "%1: No such file or directory").arg(fileName);

            Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning,
                                          m_currentDoc->fileName(),
                                          line, /*column = */ 0,
                                          msg);

            m_currentDoc->addDiagnosticMessage(d);
            return;
        }
    }

    if (m_dumpFileNameWhileParsing) {
        qDebug() << "Parsing file:" << absoluteFileName
                 << "contents:" << contents.size()
        ;
    }

    Document::Ptr doc = m_snapshot.document(absoluteFileName);
    if (doc) {
        mergeEnvironment(doc);
        return;
    }

    doc = Document::create(absoluteFileName);
    doc->setRevision(m_revision);
    doc->setEditorRevision(editorRevision);

    const QFileInfo info(absoluteFileName);
    if (info.exists())
        doc->setLastModified(info.lastModified());

    const Document::Ptr previousDoc = switchDocument(doc);

    const QByteArray preprocessedCode = m_preprocess.run(absoluteFileName, contents);
//    {
//        QByteArray b(preprocessedCode);
//        b.replace("\n", "<<<\n");
//        qDebug("Preprocessed code for \"%s\": [[%s]]", fileName.toUtf8().constData(),
//               b.constData());
//    }

    doc->setUtf8Source(preprocessedCode);
    doc->keepSourceAndAST();
    doc->tokenize();

    m_snapshot.insert(doc);
    m_todo.remove(absoluteFileName);

    Process process(m_modelManager, doc, m_workingCopy);
    process();

    (void) switchDocument(previousDoc);
}