forked from qt-creator/qt-creator
		
	Conflicts: src/libs/utils/tooltip/tipcontents.cpp src/libs/utils/tooltip/tipcontents.h src/plugins/android/androiddeployqtstep.cpp src/plugins/baremetal/baremetalconstants.h src/plugins/baremetal/baremetaldevice.cpp src/plugins/baremetal/baremetaldevice.h src/plugins/baremetal/baremetaldeviceconfigurationwidget.cpp src/plugins/baremetal/baremetaldeviceconfigurationwidget.h src/plugins/baremetal/baremetaldeviceconfigurationwizard.cpp src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.cpp src/plugins/baremetal/baremetaldeviceconfigurationwizardpages.h src/plugins/baremetal/baremetalplugin.cpp src/plugins/baremetal/baremetalplugin.h src/plugins/baremetal/baremetalruncontrolfactory.cpp src/plugins/baremetal/baremetalruncontrolfactory.h src/plugins/cppeditor/cppcodemodelinspectordialog.cpp src/plugins/cppeditor/cppdoxygen_test.cpp src/plugins/cppeditor/cppdoxygen_test.h src/plugins/debugger/breakpointmarker.cpp src/plugins/debugger/debuggeritemmodel.cpp src/plugins/debugger/debuggeritemmodel.h src/plugins/debugger/loadcoredialog.cpp src/plugins/genericprojectmanager/cppmodelmanagerhelper.cpp src/plugins/projectexplorer/addnewmodel.cpp src/plugins/projectexplorer/addnewmodel.h src/plugins/projectexplorer/jsonwizard/jsonfieldpage.cpp src/plugins/qmlprofiler/abstracttimelinemodel.cpp src/plugins/qmlprofiler/abstracttimelinemodel.h src/plugins/qmlprofiler/notesmodel.cpp src/plugins/qmlprofiler/qml/CategoryLabel.qml src/plugins/qmlprofiler/qml/MainView.qml src/plugins/qmlprofiler/qml/Overview.js src/plugins/qmlprofiler/qml/Overview.qml src/plugins/qmlprofiler/qml/TimeDisplay.qml src/plugins/qmlprofiler/qml/TimeMarks.qml src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp src/plugins/qmlprofiler/sortedtimelinemodel.cpp src/plugins/qmlprofiler/sortedtimelinemodel.h src/plugins/qmlprofiler/timelinemodelaggregator.cpp src/plugins/qmlprofiler/timelinemodelaggregator.h src/plugins/qmlprofiler/timelinerenderer.cpp src/plugins/qmlprofiler/timelinerenderer.h src/plugins/qmlprojectmanager/QmlProjectManager.json.in src/plugins/texteditor/findinfiles.cpp src/plugins/vcsbase/vcsconfigurationpage.cpp src/shared/qbs src/shared/scriptwrapper/interface_wrap_helpers.h src/shared/scriptwrapper/wrap_helpers.h tests/auto/qmlprofiler/abstracttimelinemodel/tst_abstracttimelinemodel.cpp tests/system/suite_debugger/tst_debug_empty_main/test.py tests/system/suite_debugger/tst_qml_js_console/test.py tests/system/suite_debugger/tst_qml_locals/test.py Change-Id: I67540b648f8b162496f4aa606b04d50c7c9125c6
		
			
				
	
	
		
			218 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/****************************************************************************
 | 
						|
**
 | 
						|
** Copyright (C) 2015 The Qt Company Ltd.
 | 
						|
** Contact: http://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 http://www.qt.io/terms-conditions.  For further information
 | 
						|
** use the contact form at http://www.qt.io/contact-us.
 | 
						|
**
 | 
						|
** GNU Lesser General Public License Usage
 | 
						|
** Alternatively, this file may be used under the terms of the GNU Lesser
 | 
						|
** General Public License version 2.1 or version 3 as published by the Free
 | 
						|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
 | 
						|
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
 | 
						|
** following information to ensure the GNU Lesser General Public License
 | 
						|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
 | 
						|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
						|
**
 | 
						|
** In addition, as a special exception, The Qt Company gives you certain additional
 | 
						|
** rights.  These rights are described in The Qt Company LGPL Exception
 | 
						|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 | 
						|
**
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
#include "cppsemanticinfoupdater.h"
 | 
						|
 | 
						|
#include "cpplocalsymbols.h"
 | 
						|
 | 
						|
#include <utils/qtcassert.h>
 | 
						|
#include <utils/runextensions.h>
 | 
						|
 | 
						|
#include <cplusplus/Control.h>
 | 
						|
#include <cplusplus/CppDocument.h>
 | 
						|
#include <cplusplus/TranslationUnit.h>
 | 
						|
 | 
						|
#include <QLoggingCategory>
 | 
						|
 | 
						|
enum { debug = 0 };
 | 
						|
 | 
						|
using namespace CPlusPlus;
 | 
						|
using namespace CppTools;
 | 
						|
 | 
						|
static Q_LOGGING_CATEGORY(log, "qtc.cpptools.semanticinfoupdater")
 | 
						|
 | 
						|
namespace CppTools {
 | 
						|
 | 
						|
class SemanticInfoUpdaterPrivate
 | 
						|
{
 | 
						|
public:
 | 
						|
    class FuturizedTopLevelDeclarationProcessor: public TopLevelDeclarationProcessor
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        FuturizedTopLevelDeclarationProcessor(QFutureInterface<void> &future): m_future(future) {}
 | 
						|
        bool processDeclaration(DeclarationAST *) { return !isCanceled(); }
 | 
						|
        bool isCanceled() { return m_future.isCanceled(); }
 | 
						|
    private:
 | 
						|
        QFutureInterface<void> m_future;
 | 
						|
    };
 | 
						|
 | 
						|
public:
 | 
						|
    SemanticInfoUpdaterPrivate(SemanticInfoUpdater *q);
 | 
						|
    ~SemanticInfoUpdaterPrivate();
 | 
						|
 | 
						|
    SemanticInfo semanticInfo() const;
 | 
						|
    void setSemanticInfo(const SemanticInfo &semanticInfo, bool emitSignal);
 | 
						|
 | 
						|
    SemanticInfo update(const SemanticInfo::Source &source,
 | 
						|
                        bool emitSignalWhenFinished,
 | 
						|
                        FuturizedTopLevelDeclarationProcessor *processor);
 | 
						|
 | 
						|
    bool reuseCurrentSemanticInfo(const SemanticInfo::Source &source, bool emitSignalWhenFinished);
 | 
						|
 | 
						|
    void update_helper(QFutureInterface<void> &future, const SemanticInfo::Source source);
 | 
						|
 | 
						|
public:
 | 
						|
    SemanticInfoUpdater *q;
 | 
						|
    mutable QMutex m_lock;
 | 
						|
    SemanticInfo m_semanticInfo;
 | 
						|
    QFuture<void> m_future;
 | 
						|
};
 | 
						|
 | 
						|
SemanticInfoUpdaterPrivate::SemanticInfoUpdaterPrivate(SemanticInfoUpdater *q)
 | 
						|
    : q(q)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
SemanticInfoUpdaterPrivate::~SemanticInfoUpdaterPrivate()
 | 
						|
{
 | 
						|
    m_future.cancel();
 | 
						|
    m_future.waitForFinished();
 | 
						|
}
 | 
						|
 | 
						|
SemanticInfo SemanticInfoUpdaterPrivate::semanticInfo() const
 | 
						|
{
 | 
						|
    QMutexLocker locker(&m_lock);
 | 
						|
    return m_semanticInfo;
 | 
						|
}
 | 
						|
 | 
						|
void SemanticInfoUpdaterPrivate::setSemanticInfo(const SemanticInfo &semanticInfo, bool emitSignal)
 | 
						|
{
 | 
						|
    {
 | 
						|
        QMutexLocker locker(&m_lock);
 | 
						|
        m_semanticInfo = semanticInfo;
 | 
						|
    }
 | 
						|
    if (emitSignal) {
 | 
						|
        qCDebug(log) << "emiting new info";
 | 
						|
        emit q->updated(semanticInfo);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
SemanticInfo SemanticInfoUpdaterPrivate::update(const SemanticInfo::Source &source,
 | 
						|
                                                bool emitSignalWhenFinished,
 | 
						|
                                                FuturizedTopLevelDeclarationProcessor *processor)
 | 
						|
{
 | 
						|
    SemanticInfo newSemanticInfo;
 | 
						|
    newSemanticInfo.revision = source.revision;
 | 
						|
    newSemanticInfo.snapshot = source.snapshot;
 | 
						|
 | 
						|
    Document::Ptr doc = newSemanticInfo.snapshot.preprocessedDocument(source.code, source.fileName);
 | 
						|
    if (processor)
 | 
						|
        doc->control()->setTopLevelDeclarationProcessor(processor);
 | 
						|
    doc->check();
 | 
						|
    if (processor && processor->isCanceled())
 | 
						|
        newSemanticInfo.complete = false;
 | 
						|
    newSemanticInfo.doc = doc;
 | 
						|
 | 
						|
    qCDebug(log) << "update() for source revision:" << source.revision
 | 
						|
                 << "canceled:" << !newSemanticInfo.complete;
 | 
						|
 | 
						|
    setSemanticInfo(newSemanticInfo, emitSignalWhenFinished);
 | 
						|
    return newSemanticInfo;
 | 
						|
}
 | 
						|
 | 
						|
bool SemanticInfoUpdaterPrivate::reuseCurrentSemanticInfo(const SemanticInfo::Source &source,
 | 
						|
                                                          bool emitSignalWhenFinished)
 | 
						|
{
 | 
						|
    const SemanticInfo currentSemanticInfo = semanticInfo();
 | 
						|
 | 
						|
    if (!source.force
 | 
						|
            && currentSemanticInfo.complete
 | 
						|
            && currentSemanticInfo.revision == source.revision
 | 
						|
            && currentSemanticInfo.doc
 | 
						|
            && currentSemanticInfo.doc->translationUnit()->ast()
 | 
						|
            && currentSemanticInfo.doc->fileName() == source.fileName
 | 
						|
            && !currentSemanticInfo.snapshot.isEmpty()
 | 
						|
            && currentSemanticInfo.snapshot == source.snapshot) {
 | 
						|
        SemanticInfo newSemanticInfo;
 | 
						|
        newSemanticInfo.revision = source.revision;
 | 
						|
        newSemanticInfo.snapshot = source.snapshot;
 | 
						|
        newSemanticInfo.doc = currentSemanticInfo.doc;
 | 
						|
        setSemanticInfo(newSemanticInfo, emitSignalWhenFinished);
 | 
						|
        qCDebug(log) << "re-using current semantic info, source revision:" << source.revision;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
void SemanticInfoUpdaterPrivate::update_helper(QFutureInterface<void> &future,
 | 
						|
                                               const SemanticInfo::Source source)
 | 
						|
{
 | 
						|
    FuturizedTopLevelDeclarationProcessor processor(future);
 | 
						|
    update(source, true, &processor);
 | 
						|
}
 | 
						|
 | 
						|
SemanticInfoUpdater::SemanticInfoUpdater()
 | 
						|
    : d(new SemanticInfoUpdaterPrivate(this))
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
SemanticInfoUpdater::~SemanticInfoUpdater()
 | 
						|
{
 | 
						|
    d->m_future.cancel();
 | 
						|
    d->m_future.waitForFinished();
 | 
						|
}
 | 
						|
 | 
						|
SemanticInfo SemanticInfoUpdater::update(const SemanticInfo::Source &source)
 | 
						|
{
 | 
						|
    qCDebug(log) << "update() - synchronous";
 | 
						|
    d->m_future.cancel();
 | 
						|
 | 
						|
    const bool emitSignalWhenFinished = false;
 | 
						|
    if (d->reuseCurrentSemanticInfo(source, emitSignalWhenFinished)) {
 | 
						|
        d->m_future = QFuture<void>();
 | 
						|
        return semanticInfo();
 | 
						|
    }
 | 
						|
 | 
						|
    return d->update(source, emitSignalWhenFinished, 0);
 | 
						|
}
 | 
						|
 | 
						|
void SemanticInfoUpdater::updateDetached(const SemanticInfo::Source source)
 | 
						|
{
 | 
						|
    qCDebug(log) << "updateDetached() - asynchronous";
 | 
						|
    d->m_future.cancel();
 | 
						|
 | 
						|
    const bool emitSignalWhenFinished = true;
 | 
						|
    if (d->reuseCurrentSemanticInfo(source, emitSignalWhenFinished)) {
 | 
						|
        d->m_future = QFuture<void>();
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    d->m_future = QtConcurrent::run<SemanticInfoUpdaterPrivate, void, const SemanticInfo::Source>
 | 
						|
            (&SemanticInfoUpdaterPrivate::update_helper, d.data(), source);
 | 
						|
}
 | 
						|
 | 
						|
SemanticInfo SemanticInfoUpdater::semanticInfo() const
 | 
						|
{
 | 
						|
    return d->semanticInfo();
 | 
						|
}
 | 
						|
 | 
						|
} // namespace CppTools
 |