void QmlProfilerDetailsRewriter::documentReady(QmlJS::Document::Ptr doc)
{
    // this could be triggered by an unrelated reload in Creator
    if (!d->m_pendingDocs.contains(doc->fileName()))
        return;

    // if the file could not be opened this slot is still triggered but source will be an empty string
    QString source = doc->source();
    if (!source.isEmpty()) {
        QTextStream st(&source, QIODevice::ReadOnly);

        for (int i = d->m_pendingEvents.count()-1; i>=0; i--) {
            PendingEvent ev = d->m_pendingEvents[i];
            if (ev.localFile == doc->fileName()) {
                d->m_pendingEvents.removeAt(i);
                rewriteDetailsForLocation(st, doc, ev.requestId, ev.location);
            }
        }
    }

    d->m_pendingDocs.removeOne(doc->fileName());

    if (d->m_pendingDocs.isEmpty()) {
        disconnect(QmlJS::ModelManagerInterface::instance(),
                   SIGNAL(documentUpdated(QmlJS::Document::Ptr)),
                   this,
                   SLOT(documentReady(QmlJS::Document::Ptr)));
        emit eventDetailsChanged();
    }
}
void QmlJsTodoItemsScanner::processDocument(QmlJS::Document::Ptr doc)
{
    QList<TodoItem> itemList;

    foreach (const QmlJS::AST::SourceLocation &sourceLocation, doc->engine()->comments()) {
        QString source = doc->source().mid(sourceLocation.begin(), sourceLocation.length).trimmed();

        // Process every line
        // TODO: Do not create QStringList, just iterate through a string tracking line endings.
        QStringList commentLines = source.split(QLatin1Char('\n'), QString::SkipEmptyParts);
        quint32 startLine = sourceLocation.startLine;
        for (int j = 0; j < commentLines.count(); ++j) {
            const QString &commentLine = commentLines.at(j);
            processCommentLine(doc->fileName(), commentLine, startLine + j, itemList);
        }

    }

    emit itemsFetched(doc->fileName(), itemList);
}