forked from qt-creator/qt-creator
QmlJS: Allow QML plugins to ship pre-dumped type descriptions.
If there's a library.xml file next to the qmldir file, Creator will read that instead of trying to run qmldump on the library. Reviewed-by: Erik Verbruggen
This commit is contained in:
@@ -65,7 +65,8 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &
|
|||||||
if (m_runningQmldumps.values().contains(canonicalLibraryPath))
|
if (m_runningQmldumps.values().contains(canonicalLibraryPath))
|
||||||
return;
|
return;
|
||||||
const Snapshot snapshot = m_modelManager->snapshot();
|
const Snapshot snapshot = m_modelManager->snapshot();
|
||||||
if (snapshot.libraryInfo(canonicalLibraryPath).dumpStatus() != LibraryInfo::DumpNotStartedOrRunning)
|
const LibraryInfo libraryInfo = snapshot.libraryInfo(canonicalLibraryPath);
|
||||||
|
if (libraryInfo.dumpStatus() != LibraryInfo::DumpNotStartedOrRunning)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// avoid inserting the same plugin twice
|
// avoid inserting the same plugin twice
|
||||||
@@ -82,12 +83,20 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &
|
|||||||
plugin.importPath = importPath;
|
plugin.importPath = importPath;
|
||||||
plugin.importUri = importUri;
|
plugin.importUri = importUri;
|
||||||
|
|
||||||
|
// watch plugin libraries
|
||||||
foreach (const QmlDirParser::Plugin &plugin, snapshot.libraryInfo(canonicalLibraryPath).plugins()) {
|
foreach (const QmlDirParser::Plugin &plugin, snapshot.libraryInfo(canonicalLibraryPath).plugins()) {
|
||||||
const QString pluginLibrary = resolvePlugin(canonicalLibraryPath, plugin.path, plugin.name);
|
const QString pluginLibrary = resolvePlugin(canonicalLibraryPath, plugin.path, plugin.name);
|
||||||
m_pluginWatcher->addFile(pluginLibrary);
|
m_pluginWatcher->addFile(pluginLibrary);
|
||||||
m_libraryToPluginIndex.insert(pluginLibrary, index);
|
m_libraryToPluginIndex.insert(pluginLibrary, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// watch library xml file
|
||||||
|
if (plugin.hasPredumpedXmlFile()) {
|
||||||
|
const QString &path = plugin.predumpedXmlFilePath();
|
||||||
|
m_pluginWatcher->addFile(path);
|
||||||
|
m_libraryToPluginIndex.insert(path, index);
|
||||||
|
}
|
||||||
|
|
||||||
dump(plugin);
|
dump(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +121,23 @@ static QString qmldumpFailedMessage()
|
|||||||
return PluginDumper::tr("Type dump of C++ plugin failed.\nCheck 'General Messages' output pane for details.");
|
return PluginDumper::tr("Type dump of C++ plugin failed.\nCheck 'General Messages' output pane for details.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QList<const Interpreter::FakeMetaObject *> parseHelper(const QByteArray &xml, QString *error)
|
||||||
|
{
|
||||||
|
QList<const Interpreter::FakeMetaObject *> ret;
|
||||||
|
QMap<QString, Interpreter::FakeMetaObject *> newObjects;
|
||||||
|
*error = Interpreter::CppQmlTypesLoader::parseQmlTypeXml(xml, &newObjects);
|
||||||
|
|
||||||
|
if (error->isEmpty()) {
|
||||||
|
// convert from QList<T *> to QList<const T *>
|
||||||
|
QMapIterator<QString, Interpreter::FakeMetaObject *> it(newObjects);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
ret.append(it.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
|
void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
|
||||||
{
|
{
|
||||||
QProcess *process = qobject_cast<QProcess *>(sender());
|
QProcess *process = qobject_cast<QProcess *>(sender());
|
||||||
@@ -130,20 +156,13 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray output = process->readAllStandardOutput();
|
const QByteArray output = process->readAllStandardOutput();
|
||||||
QMap<QString, Interpreter::FakeMetaObject *> newObjects;
|
QString error;
|
||||||
const QString error = Interpreter::CppQmlTypesLoader::parseQmlTypeXml(output, &newObjects);
|
QList<const Interpreter::FakeMetaObject *> objectsList = parseHelper(output, &error);
|
||||||
if (!error.isEmpty()) {
|
if (exitCode == 0 && !error.isEmpty()) {
|
||||||
libraryInfo.setDumpStatus(LibraryInfo::DumpError, tr("Type dump of C++ plugin failed. Parse error:\n'%1'").arg(error));
|
libraryInfo.setDumpStatus(LibraryInfo::DumpError, tr("Type dump of C++ plugin failed. Parse error:\n'%1'").arg(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exitCode == 0 && error.isEmpty()) {
|
if (exitCode == 0 && error.isEmpty()) {
|
||||||
// convert from QList<T *> to QList<const T *>
|
|
||||||
QList<const Interpreter::FakeMetaObject *> objectsList;
|
|
||||||
QMapIterator<QString, Interpreter::FakeMetaObject *> it(newObjects);
|
|
||||||
while (it.hasNext()) {
|
|
||||||
it.next();
|
|
||||||
objectsList.append(it.value());
|
|
||||||
}
|
|
||||||
libraryInfo.setMetaObjects(objectsList);
|
libraryInfo.setMetaObjects(objectsList);
|
||||||
if (libraryPath.isEmpty())
|
if (libraryPath.isEmpty())
|
||||||
Interpreter::CppQmlTypesLoader::builtinObjects.append(objectsList);
|
Interpreter::CppQmlTypesLoader::builtinObjects.append(objectsList);
|
||||||
@@ -186,6 +205,38 @@ void PluginDumper::pluginChanged(const QString &pluginLibrary)
|
|||||||
|
|
||||||
void PluginDumper::dump(const Plugin &plugin)
|
void PluginDumper::dump(const Plugin &plugin)
|
||||||
{
|
{
|
||||||
|
if (plugin.hasPredumpedXmlFile()) {
|
||||||
|
const Snapshot snapshot = m_modelManager->snapshot();
|
||||||
|
LibraryInfo libraryInfo = snapshot.libraryInfo(plugin.qmldirPath);
|
||||||
|
if (!libraryInfo.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QString &path = plugin.predumpedXmlFilePath();
|
||||||
|
QFile libraryXmlFile(path);
|
||||||
|
if (!libraryXmlFile.open(QFile::ReadOnly | QFile::Text)) {
|
||||||
|
libraryInfo.setDumpStatus(LibraryInfo::DumpError,
|
||||||
|
tr("Could not open file '%1' for reading.").arg(path));
|
||||||
|
m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray xml = libraryXmlFile.readAll();
|
||||||
|
libraryXmlFile.close();
|
||||||
|
|
||||||
|
QString error;
|
||||||
|
const QList<const Interpreter::FakeMetaObject *> objectsList = parseHelper(xml, &error);
|
||||||
|
|
||||||
|
if (error.isEmpty()) {
|
||||||
|
libraryInfo.setMetaObjects(objectsList);
|
||||||
|
libraryInfo.setDumpStatus(LibraryInfo::DumpDone);
|
||||||
|
} else {
|
||||||
|
libraryInfo.setDumpStatus(LibraryInfo::DumpError,
|
||||||
|
tr("Failed to parse '%1'.\nError: %2").arg(path, error));
|
||||||
|
}
|
||||||
|
m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ProjectExplorer::Project *activeProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
|
ProjectExplorer::Project *activeProject = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
|
||||||
if (!activeProject)
|
if (!activeProject)
|
||||||
return;
|
return;
|
||||||
@@ -323,3 +374,13 @@ QString PluginDumper::resolvePlugin(const QDir &qmldirPath, const QString &qmldi
|
|||||||
return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib"));
|
return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PluginDumper::Plugin::hasPredumpedXmlFile() const
|
||||||
|
{
|
||||||
|
return QFileInfo(predumpedXmlFilePath()).isFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PluginDumper::Plugin::predumpedXmlFilePath() const
|
||||||
|
{
|
||||||
|
return QString("%1%2library.xml").arg(qmldirPath, QDir::separator());
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ private:
|
|||||||
QString qmldirPath;
|
QString qmldirPath;
|
||||||
QString importPath;
|
QString importPath;
|
||||||
QString importUri;
|
QString importUri;
|
||||||
|
|
||||||
|
bool hasPredumpedXmlFile() const;
|
||||||
|
QString predumpedXmlFilePath() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void dump(const Plugin &plugin);
|
void dump(const Plugin &plugin);
|
||||||
|
|||||||
Reference in New Issue
Block a user