forked from qt-creator/qt-creator
QmlJS: Add semantic errors to task window.
Task-number: QTCREATORBUG-4103 Reviewed-by: Leandro Melo
This commit is contained in:
@@ -237,7 +237,13 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
|
||||
addAutoReleasedObject(m_qmlTaskManager);
|
||||
|
||||
connect(m_modelManager, SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)),
|
||||
m_qmlTaskManager, SLOT(documentChangedOnDisk(QmlJS::Document::Ptr)));
|
||||
m_qmlTaskManager, SLOT(updateMessages()));
|
||||
// recompute messages when information about libraries changes
|
||||
connect(m_modelManager, SIGNAL(libraryInfoUpdated(QString,QmlJS::LibraryInfo)),
|
||||
m_qmlTaskManager, SLOT(updateMessages()));
|
||||
// recompute messages when project data changes (files added or removed)
|
||||
connect(m_modelManager, SIGNAL(projectInfoUpdated(ProjectInfo)),
|
||||
m_qmlTaskManager, SLOT(updateMessages()));
|
||||
connect(m_modelManager, SIGNAL(aboutToRemoveFiles(QStringList)),
|
||||
m_qmlTaskManager, SLOT(documentsRemoved(QStringList)));
|
||||
|
||||
|
||||
@@ -626,7 +626,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
|
||||
if (!doc)
|
||||
return;
|
||||
|
||||
Link link(&context, doc, snapshot, ModelManagerInterface::instance()->importPaths());
|
||||
Link link(&context, snapshot, ModelManagerInterface::instance()->importPaths());
|
||||
ScopeBuilder builder(&context, doc, snapshot);
|
||||
ScopeAstPath astPath(doc);
|
||||
builder.push(astPath(offset));
|
||||
|
||||
@@ -133,13 +133,9 @@ SemanticInfo SemanticHighlighter::semanticInfo(const SemanticHighlighterSource &
|
||||
semanticInfo.document = doc;
|
||||
|
||||
QmlJS::Interpreter::Context *ctx = new QmlJS::Interpreter::Context;
|
||||
QmlJS::Link link(ctx, doc, snapshot, QmlJS::ModelManagerInterface::instance()->importPaths());
|
||||
QmlJS::Link link(ctx, snapshot, QmlJS::ModelManagerInterface::instance()->importPaths(), doc, &semanticInfo.semanticMessages);
|
||||
semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx);
|
||||
semanticInfo.semanticMessages = link.diagnosticMessages();
|
||||
|
||||
QStringList importPaths;
|
||||
if (m_modelManager)
|
||||
importPaths = m_modelManager->importPaths();
|
||||
QmlJS::Check checker(doc, snapshot, ctx);
|
||||
semanticInfo.semanticMessages.append(checker());
|
||||
|
||||
|
||||
@@ -33,11 +33,21 @@
|
||||
#include "qmltaskmanager.h"
|
||||
#include "qmljseditorconstants.h"
|
||||
|
||||
#include <coreplugin/ifile.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <projectexplorer/taskhub.h>
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
#include <qmljs/qmljsinterpreter.h>
|
||||
#include <qmljs/qmljslink.h>
|
||||
#include <qmljs/qmljscheck.h>
|
||||
#include <qmljseditor/qmljseditor.h>
|
||||
#include <qmljseditor/qmljseditoreditable.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QtConcurrentRun>
|
||||
#include <qtconcurrent/runextensions.h>
|
||||
|
||||
using namespace QmlJS;
|
||||
|
||||
namespace QmlJSEditor {
|
||||
namespace Internal {
|
||||
@@ -47,35 +57,103 @@ QmlTaskManager::QmlTaskManager(QObject *parent) :
|
||||
m_taskHub(0)
|
||||
{
|
||||
m_taskHub = ExtensionSystem::PluginManager::instance()->getObject<ProjectExplorer::TaskHub>();
|
||||
// displaying results incrementally leads to flickering
|
||||
// connect(&m_messageCollector, SIGNAL(resultsReadyAt(int,int)),
|
||||
// SLOT(displayResults(int,int)));
|
||||
connect(&m_messageCollector, SIGNAL(finished()),
|
||||
SLOT(displayAllResults()));
|
||||
|
||||
m_updateDelay.setInterval(100);
|
||||
m_updateDelay.setSingleShot(true);
|
||||
connect(&m_updateDelay, SIGNAL(timeout()),
|
||||
SLOT(updateMessagesNow()));
|
||||
}
|
||||
|
||||
void QmlTaskManager::documentChangedOnDisk(QmlJS::Document::Ptr doc)
|
||||
void QmlTaskManager::collectMessages(QFutureInterface<FileErrorMessages> &future,
|
||||
Snapshot snapshot, QStringList files, QStringList importPaths)
|
||||
{
|
||||
const QString fileName = doc->fileName();
|
||||
removeTasksForFile(fileName);
|
||||
Interpreter::Context ctx;
|
||||
QHash<QString, QList<DiagnosticMessage> > linkMessages;
|
||||
Link link(&ctx, snapshot, importPaths, &linkMessages);
|
||||
|
||||
foreach (const QmlJS::DiagnosticMessage &msg, doc->diagnosticMessages()) {
|
||||
ProjectExplorer::Task::TaskType type
|
||||
= msg.isError() ? ProjectExplorer::Task::Error
|
||||
: ProjectExplorer::Task::Warning;
|
||||
foreach (const QString &fileName, files) {
|
||||
Document::Ptr document = snapshot.document(fileName);
|
||||
if (!document)
|
||||
continue;
|
||||
|
||||
ProjectExplorer::Task task(type, msg.message, fileName, msg.loc.startLine,
|
||||
Constants::TASK_CATEGORY_QML);
|
||||
insertTask(fileName, task);
|
||||
FileErrorMessages result;
|
||||
result.fileName = fileName;
|
||||
result.messages = document->diagnosticMessages();
|
||||
result.messages += linkMessages.value(fileName);
|
||||
|
||||
Check checker(document, snapshot, &ctx);
|
||||
result.messages.append(checker());
|
||||
|
||||
future.reportResult(result);
|
||||
if (future.isCanceled())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QmlTaskManager::updateMessages()
|
||||
{
|
||||
m_updateDelay.start();
|
||||
}
|
||||
|
||||
void QmlTaskManager::updateMessagesNow()
|
||||
{
|
||||
// abort any update that's going on already
|
||||
m_messageCollector.cancel();
|
||||
removeAllTasks();
|
||||
|
||||
// collect all the source files in open projects
|
||||
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
|
||||
QStringList sourceFiles;
|
||||
foreach (const ModelManagerInterface::ProjectInfo &info, modelManager->projectInfos()) {
|
||||
sourceFiles += info.sourceFiles;
|
||||
}
|
||||
|
||||
// process them
|
||||
QFuture<FileErrorMessages> future =
|
||||
QtConcurrent::run<FileErrorMessages>(
|
||||
&collectMessages, modelManager->snapshot(), sourceFiles,
|
||||
modelManager->importPaths());
|
||||
m_messageCollector.setFuture(future);
|
||||
}
|
||||
|
||||
void QmlTaskManager::documentsRemoved(const QStringList path)
|
||||
{
|
||||
foreach (const QString &item, path)
|
||||
removeTasksForFile(item);
|
||||
}
|
||||
|
||||
void QmlTaskManager::insertTask(const QString &fileName, const ProjectExplorer::Task &task)
|
||||
void QmlTaskManager::displayResults(int begin, int end)
|
||||
{
|
||||
QList<ProjectExplorer::Task> tasks = m_docsWithTasks.value(fileName);
|
||||
for (int i = begin; i < end; ++i) {
|
||||
FileErrorMessages result = m_messageCollector.resultAt(i);
|
||||
foreach (const DiagnosticMessage &msg, result.messages) {
|
||||
ProjectExplorer::Task::TaskType type
|
||||
= msg.isError() ? ProjectExplorer::Task::Error
|
||||
: ProjectExplorer::Task::Warning;
|
||||
|
||||
ProjectExplorer::Task task(type, msg.message, result.fileName, msg.loc.startLine,
|
||||
Constants::TASK_CATEGORY_QML);
|
||||
|
||||
insertTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QmlTaskManager::displayAllResults()
|
||||
{
|
||||
displayResults(0, m_messageCollector.future().resultCount());
|
||||
}
|
||||
|
||||
void QmlTaskManager::insertTask(const ProjectExplorer::Task &task)
|
||||
{
|
||||
QList<ProjectExplorer::Task> tasks = m_docsWithTasks.value(task.file);
|
||||
tasks.append(task);
|
||||
m_docsWithTasks.insert(fileName, tasks);
|
||||
m_docsWithTasks.insert(task.file, tasks);
|
||||
m_taskHub->addTask(task);
|
||||
}
|
||||
|
||||
@@ -89,5 +167,16 @@ void QmlTaskManager::removeTasksForFile(const QString &fileName)
|
||||
}
|
||||
}
|
||||
|
||||
void QmlTaskManager::removeAllTasks()
|
||||
{
|
||||
QMapIterator<QString, QList<ProjectExplorer::Task> > it(m_docsWithTasks);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
foreach (const ProjectExplorer::Task &task, it.value())
|
||||
m_taskHub->removeTask(task);
|
||||
}
|
||||
m_docsWithTasks.clear();
|
||||
}
|
||||
|
||||
} // Internal
|
||||
} // QmlProjectManager
|
||||
|
||||
@@ -40,6 +40,12 @@
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QFutureWatcher>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
namespace QmlJSEditor {
|
||||
class QmlJSTextEditorWidget;
|
||||
}
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class TaskHub;
|
||||
@@ -57,16 +63,34 @@ public:
|
||||
void extensionsInitialized();
|
||||
|
||||
public slots:
|
||||
void documentChangedOnDisk(QmlJS::Document::Ptr doc);
|
||||
void updateMessages();
|
||||
void documentsRemoved(const QStringList path);
|
||||
|
||||
private slots:
|
||||
void displayResults(int begin, int end);
|
||||
void displayAllResults();
|
||||
void updateMessagesNow();
|
||||
|
||||
private:
|
||||
void insertTask(const QString &fileName, const ProjectExplorer::Task &task);
|
||||
void insertTask(const ProjectExplorer::Task &task);
|
||||
void removeTasksForFile(const QString &fileName);
|
||||
void removeAllTasks();
|
||||
|
||||
private:
|
||||
class FileErrorMessages
|
||||
{
|
||||
public:
|
||||
QString fileName;
|
||||
QList<QmlJS::DiagnosticMessage> messages;
|
||||
};
|
||||
static void collectMessages(QFutureInterface<FileErrorMessages> &future,
|
||||
QmlJS::Snapshot snapshot, QStringList files, QStringList importPaths);
|
||||
|
||||
private:
|
||||
ProjectExplorer::TaskHub *m_taskHub;
|
||||
QMap<QString, QList<ProjectExplorer::Task> > m_docsWithTasks;
|
||||
QFutureWatcher<FileErrorMessages> m_messageCollector;
|
||||
QTimer m_updateDelay;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
|
||||
Reference in New Issue
Block a user