Commit 5dd92328 authored by Christian Kamm's avatar Christian Kamm
Browse files

QmlJS: Improve error reporting for failed plugin dumps.

Reviewed-by: Erik Verbruggen
parent b548ab16
......@@ -356,6 +356,7 @@ void Document::extractPragmas(QString *source)
LibraryInfo::LibraryInfo()
: _valid(false)
, _dumpStatus(DumpNotStartedOrRunning)
{
}
......@@ -363,7 +364,7 @@ LibraryInfo::LibraryInfo(const QmlDirParser &parser)
: _valid(true)
, _components(parser.components())
, _plugins(parser.plugins())
, _dumped(false)
, _dumpStatus(DumpNotStartedOrRunning)
{
}
......
......@@ -119,12 +119,22 @@ private:
class QMLJS_EXPORT LibraryInfo
{
public:
enum DumpStatus {
DumpNotStartedOrRunning,
DumpDone,
DumpError
};
private:
bool _valid;
QList<QmlDirParser::Component> _components;
QList<QmlDirParser::Plugin> _plugins;
typedef QList<const Interpreter::FakeMetaObject *> FakeMetaObjectList;
FakeMetaObjectList _metaObjects;
bool _dumped;
DumpStatus _dumpStatus;
QString _dumpError;
public:
LibraryInfo();
......@@ -146,11 +156,14 @@ public:
bool isValid() const
{ return _valid; }
bool isDumped() const
{ return _dumped; }
DumpStatus dumpStatus() const
{ return _dumpStatus; }
QString dumpError() const
{ return _dumpError; }
void setDumped(bool dumped)
{ _dumped = dumped; }
void setDumpStatus(DumpStatus dumped, const QString &error = QString())
{ _dumpStatus = dumped; _dumpError = error; }
};
class QMLJS_EXPORT Snapshot
......
......@@ -256,10 +256,17 @@ ObjectValue *Link::importNonFile(Document::Ptr doc, const ImportInfo &importInfo
importFound = true;
if (!libraryInfo.plugins().isEmpty()) {
if (libraryInfo.metaObjects().isEmpty()) {
if (libraryInfo.dumpStatus() == LibraryInfo::DumpNotStartedOrRunning) {
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
if (modelManager)
modelManager->loadPluginTypes(libraryPath, importPath, packageName);
warning(doc, locationFromRange(importInfo.ast()->firstSourceLocation(),
importInfo.ast()->lastSourceLocation()),
tr("Library contains C++ plugins, type dump is in progress."));
} else if (libraryInfo.dumpStatus() == LibraryInfo::DumpError) {
error(doc, locationFromRange(importInfo.ast()->firstSourceLocation(),
importInfo.ast()->lastSourceLocation()),
libraryInfo.dumpError());
} else {
engine()->cppQmlTypes().load(engine(), libraryInfo.metaObjects());
}
......@@ -321,3 +328,11 @@ void Link::error(const Document::Ptr &doc, const AST::SourceLocation &loc, const
if (doc->fileName() == d->doc->fileName())
d->diagnosticMessages.append(DiagnosticMessage(DiagnosticMessage::Error, loc, message));
}
void Link::warning(const Document::Ptr &doc, const AST::SourceLocation &loc, const QString &message)
{
Q_D(Link);
if (doc->fileName() == d->doc->fileName())
d->diagnosticMessages.append(DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
}
......@@ -73,6 +73,7 @@ private:
void importObject(Bind *bind, const QString &name, Interpreter::ObjectValue *object, NameId *targetNamespace);
void error(const Document::Ptr &doc, const AST::SourceLocation &loc, const QString &message);
void warning(const Document::Ptr &doc, const AST::SourceLocation &loc, const QString &message);
private:
QScopedPointer<LinkPrivate> d_ptr;
......
......@@ -215,6 +215,9 @@ void ModelManager::updateProjectInfo(const ProjectInfo &pinfo)
oldInfo = m_projects.value(pinfo.project);
m_projects.insert(pinfo.project, pinfo);
snapshot = _snapshot;
if (oldInfo.qmlDumpPath != pinfo.qmlDumpPath)
m_pluginDumper->scheduleCompleteRedump();
}
updateImportPaths();
......
......@@ -65,7 +65,7 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &
if (m_runningQmldumps.values().contains(canonicalLibraryPath))
return;
const Snapshot snapshot = m_modelManager->snapshot();
if (snapshot.libraryInfo(canonicalLibraryPath).isDumped())
if (snapshot.libraryInfo(canonicalLibraryPath).dumpStatus() != LibraryInfo::DumpNotStartedOrRunning)
return;
// avoid inserting the same plugin twice
......@@ -91,11 +91,27 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &
dump(plugin);
}
void PluginDumper::scheduleCompleteRedump()
{
metaObject()->invokeMethod(this, "dumpAllPlugins", Qt::QueuedConnection);
}
void PluginDumper::dumpAllPlugins()
{
foreach (const Plugin &plugin, m_plugins)
dump(plugin);
}
static QString qmldumpErrorMessage(const QString &libraryPath, const QString &error)
{
return PluginDumper::tr("Type dump of QML plugin in %0 failed.\nErrors:\n%1\n").arg(libraryPath, error);
}
static QString qmldumpFailedMessage()
{
return PluginDumper::tr("Type dump of C++ plugin failed.\nCheck 'General Messages' output pane for details.");
}
void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
{
QProcess *process = qobject_cast<QProcess *>(sender());
......@@ -106,16 +122,19 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
const QString libraryPath = m_runningQmldumps.take(process);
const Snapshot snapshot = m_modelManager->snapshot();
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
libraryInfo.setDumped(true);
if (exitCode != 0) {
Core::MessageManager *messageManager = Core::MessageManager::instance();
messageManager->printToOutputPane(qmldumpErrorMessage(libraryPath, process->readAllStandardError()));
libraryInfo.setDumpStatus(LibraryInfo::DumpError, qmldumpFailedMessage());
}
const QByteArray output = process->readAllStandardOutput();
QMap<QString, Interpreter::FakeMetaObject *> newObjects;
const QString error = Interpreter::CppQmlTypesLoader::parseQmlTypeXml(output, &newObjects);
if (!error.isEmpty()) {
libraryInfo.setDumpStatus(LibraryInfo::DumpError, tr("Type dump of C++ plugin failed. Parse error:\n'%1'").arg(error));
}
if (exitCode == 0 && error.isEmpty()) {
// convert from QList<T *> to QList<const T *>
......@@ -128,6 +147,7 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
libraryInfo.setMetaObjects(objectsList);
if (libraryPath.isEmpty())
Interpreter::CppQmlTypesLoader::builtinObjects.append(objectsList);
libraryInfo.setDumpStatus(LibraryInfo::DumpDone);
}
if (!libraryPath.isEmpty())
......@@ -149,7 +169,7 @@ void PluginDumper::qmlPluginTypeDumpError(QProcess::ProcessError)
if (!libraryPath.isEmpty()) {
const Snapshot snapshot = m_modelManager->snapshot();
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
libraryInfo.setDumped(true);
libraryInfo.setDumpStatus(LibraryInfo::DumpError, qmldumpFailedMessage());
m_modelManager->updateLibraryInfo(libraryPath, libraryInfo);
}
}
......@@ -172,8 +192,18 @@ void PluginDumper::dump(const Plugin &plugin)
ModelManagerInterface::ProjectInfo info = m_modelManager->projectInfo(activeProject);
if (info.qmlDumpPath.isEmpty())
if (info.qmlDumpPath.isEmpty()) {
const Snapshot snapshot = m_modelManager->snapshot();
LibraryInfo libraryInfo = snapshot.libraryInfo(plugin.qmldirPath);
if (!libraryInfo.isValid())
return;
libraryInfo.setDumpStatus(LibraryInfo::DumpError,
tr("Could not locate the helper application for dumping type information from C++ plugins.\n"
"Please build the debugging helpers on the Qt version options page."));
m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo);
return;
}
QProcess *process = new QProcess(this);
process->setEnvironment(info.qmlDumpEnvironment.toStringList());
......
......@@ -56,10 +56,12 @@ public:
public:
void loadPluginTypes(const QString &libraryPath, const QString &importPath,
const QString &importUri);
void scheduleCompleteRedump();
private slots:
void onLoadPluginTypes(const QString &libraryPath, const QString &importPath,
const QString &importUri);
void dumpAllPlugins();
void qmlPluginTypeDumpDone(int exitCode);
void qmlPluginTypeDumpError(QProcess::ProcessError error);
void pluginChanged(const QString &pluginLibrary);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment