QmlJS: Output qmltypes parse warnings to General messages pane.

Change-Id: I8ca100ef141082c7606bb98f8a2f81502b14e1af
Reviewed-on: http://codereview.qt.nokia.com/204
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
Christian Kamm
2011-05-30 11:10:06 +02:00
committed by Kai Koehne
parent ec97fc95a0
commit f0a4e7e225
6 changed files with 103 additions and 51 deletions

View File

@@ -40,6 +40,7 @@
#include "parser/qmljsast_p.h" #include "parser/qmljsast_p.h"
#include <languageutils/fakemetaobject.h> #include <languageutils/fakemetaobject.h>
#include <coreplugin/messagemanager.h>
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QDir> #include <QtCore/QDir>
@@ -1580,31 +1581,38 @@ const Value *Function::invoke(const Activation *activation) const
QHash<QString, FakeMetaObject::ConstPtr> CppQmlTypesLoader::builtinObjects; QHash<QString, FakeMetaObject::ConstPtr> CppQmlTypesLoader::builtinObjects;
QHash<QString, QList<LanguageUtils::ComponentVersion> > CppQmlTypesLoader::builtinPackages; QHash<QString, QList<LanguageUtils::ComponentVersion> > CppQmlTypesLoader::builtinPackages;
QStringList CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles) void CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles)
{ {
QHash<QString, FakeMetaObject::ConstPtr> newObjects; QHash<QString, FakeMetaObject::ConstPtr> newObjects;
QStringList errorMsgs; Core::MessageManager *messageManager = Core::MessageManager::instance();
foreach (const QFileInfo &qmlTypeFile, qmlTypeFiles) { foreach (const QFileInfo &qmlTypeFile, qmlTypeFiles) {
QString error, warning;
QFile file(qmlTypeFile.absoluteFilePath()); QFile file(qmlTypeFile.absoluteFilePath());
if (file.open(QIODevice::ReadOnly)) { if (file.open(QIODevice::ReadOnly)) {
QString contents = QString::fromUtf8(file.readAll()); QString contents = QString::fromUtf8(file.readAll());
file.close(); file.close();
QmlJS::TypeDescriptionReader reader(contents); QmlJS::TypeDescriptionReader reader(contents);
if (!reader(&newObjects)) { if (!reader(&newObjects))
errorMsgs.append(reader.errorMessage()); error = reader.errorMessage();
} warning = reader.warningMessage();
} else { } else {
errorMsgs.append(QmlJS::TypeDescriptionReader::tr("%1: %2") error = file.errorString();
.arg(qmlTypeFile.absoluteFilePath(), }
file.errorString())); if (!error.isEmpty()) {
messageManager->printToOutputPane(
TypeDescriptionReader::tr("Errors while loading qmltypes from %1:\n%2").arg(
qmlTypeFile.absoluteFilePath(), error));
}
if (!warning.isEmpty()) {
messageManager->printToOutputPane(
TypeDescriptionReader::tr("Warnings while loading qmltypes from %1:\n%2").arg(
qmlTypeFile.absoluteFilePath(), warning));
} }
} }
if (errorMsgs.isEmpty()) {
builtinObjects.unite(newObjects); builtinObjects.unite(newObjects);
}
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr>::const_iterator iter QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr>::const_iterator iter
= builtinObjects.constBegin(); = builtinObjects.constBegin();
@@ -1617,18 +1625,24 @@ QStringList CppQmlTypesLoader::loadQmlTypes(const QFileInfoList &qmlTypeFiles)
} }
} }
} }
return errorMsgs;
} }
QString CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml, QHash<QString, FakeMetaObject::ConstPtr> *newObjects) void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml,
QHash<QString, FakeMetaObject::ConstPtr> *newObjects,
QString *errorMessage,
QString *warningMessage)
{ {
errorMessage->clear();
warningMessage->clear();
QmlJS::TypeDescriptionReader reader(QString::fromUtf8(xml)); QmlJS::TypeDescriptionReader reader(QString::fromUtf8(xml));
if (!reader(newObjects)) { if (!reader(newObjects)) {
if (reader.errorMessage().isEmpty()) if (reader.errorMessage().isEmpty()) {
return QLatin1String("unknown error"); *errorMessage = QLatin1String("unknown error");
return reader.errorMessage(); } else {
*errorMessage = reader.errorMessage();
} }
return QString(); }
*warningMessage = reader.warningMessage();
} }
const QLatin1String CppQmlTypes::defaultPackage("<default>"); const QLatin1String CppQmlTypes::defaultPackage("<default>");

View File

@@ -614,15 +614,19 @@ private:
class QMLJS_EXPORT CppQmlTypesLoader class QMLJS_EXPORT CppQmlTypesLoader
{ {
public: public:
/** \return an empty list when successful, error messages otherwise. */ /** Loads a set of qmltypes files into the builtin objects list
static QStringList loadQmlTypes(const QFileInfoList &xmlFiles); and prints any errors to the General Messages pane
*/
static void loadQmlTypes(const QFileInfoList &qmltypesFiles);
static QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> builtinObjects; static QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> builtinObjects;
static QHash<QString, QList<LanguageUtils::ComponentVersion> > builtinPackages; static QHash<QString, QList<LanguageUtils::ComponentVersion> > builtinPackages;
// parses the xml string and fills the newObjects map // parses the contents of a qmltypes file and fills the newObjects map
static QString parseQmlTypeDescriptions(const QByteArray &xml, static void parseQmlTypeDescriptions(
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *newObjects); const QByteArray &qmlTypes,
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *newObjects,
QString *errorMessage, QString *warningMessage);
}; };
class QMLJS_EXPORT CppQmlTypes class QMLJS_EXPORT CppQmlTypes

View File

@@ -89,6 +89,11 @@ QString TypeDescriptionReader::errorMessage() const
return _errorMessage; return _errorMessage;
} }
QString TypeDescriptionReader::warningMessage() const
{
return _warningMessage;
}
void TypeDescriptionReader::readDocument(UiProgram *ast) void TypeDescriptionReader::readDocument(UiProgram *ast)
{ {
if (!ast) { if (!ast) {
@@ -144,7 +149,7 @@ void TypeDescriptionReader::readModule(UiObjectDefinition *ast)
UiObjectMember *member = it->member; UiObjectMember *member = it->member;
UiObjectDefinition *component = dynamic_cast<UiObjectDefinition *>(member); UiObjectDefinition *component = dynamic_cast<UiObjectDefinition *>(member);
if (!component || Bind::toString(component->qualifiedTypeNameId) != "Component") { if (!component || Bind::toString(component->qualifiedTypeNameId) != "Component") {
//addError(member->firstSourceLocation(), "Expected only 'Component' object definitions"); addWarning(member->firstSourceLocation(), "Expected only 'Component' object definitions");
continue; continue;
} }
@@ -160,6 +165,14 @@ void TypeDescriptionReader::addError(const SourceLocation &loc, const QString &m
message); message);
} }
void TypeDescriptionReader::addWarning(const SourceLocation &loc, const QString &message)
{
_warningMessage += QString("%1:%2: %3\n").arg(
QString::number(loc.startLine),
QString::number(loc.startColumn),
message);
}
void TypeDescriptionReader::readComponent(UiObjectDefinition *ast) void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
{ {
FakeMetaObject::Ptr fmo(new FakeMetaObject); FakeMetaObject::Ptr fmo(new FakeMetaObject);
@@ -177,7 +190,7 @@ void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
} else if (name == "Enum") { } else if (name == "Enum") {
readEnum(component, fmo); readEnum(component, fmo);
} else { } else {
//addError(component->firstSourceLocation(), "Expected only Property, Method, Signal and Enum object definitions"); addWarning(component->firstSourceLocation(), "Expected only Property, Method, Signal and Enum object definitions");
} }
} else if (script) { } else if (script) {
QString name = Bind::toString(script->qualifiedId); QString name = Bind::toString(script->qualifiedId);
@@ -192,10 +205,10 @@ void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
} else if (name == "attachedType") { } else if (name == "attachedType") {
fmo->setAttachedTypeName(readStringBinding(script)); fmo->setAttachedTypeName(readStringBinding(script));
} else { } else {
//addError(script->firstSourceLocation(), "Expected only name, prototype, defaultProperty, attachedType and exports script bindings"); addWarning(script->firstSourceLocation(), "Expected only name, prototype, defaultProperty, attachedType and exports script bindings");
} }
} else { } else {
//addError(member->firstSourceLocation(), "Expected only script bindings and object definitions"); addWarning(member->firstSourceLocation(), "Expected only script bindings and object definitions");
} }
} }
@@ -227,7 +240,7 @@ void TypeDescriptionReader::readSignalOrMethod(UiObjectDefinition *ast, bool isM
if (name == "Parameter") { if (name == "Parameter") {
readParameter(component, &fmm); readParameter(component, &fmm);
} else { } else {
//addError(component->firstSourceLocation(), "Expected only Parameter object definitions"); addWarning(component->firstSourceLocation(), "Expected only Parameter object definitions");
} }
} else if (script) { } else if (script) {
QString name = Bind::toString(script->qualifiedId); QString name = Bind::toString(script->qualifiedId);
@@ -238,11 +251,11 @@ void TypeDescriptionReader::readSignalOrMethod(UiObjectDefinition *ast, bool isM
} else if (name == "revision") { } else if (name == "revision") {
fmm.setRevision(readIntBinding(script)); fmm.setRevision(readIntBinding(script));
} else { } else {
//addError(script->firstSourceLocation(), "Expected only name and type script bindings"); addWarning(script->firstSourceLocation(), "Expected only name and type script bindings");
} }
} else { } else {
//addError(member->firstSourceLocation(), "Expected only script bindings and object definitions"); addWarning(member->firstSourceLocation(), "Expected only script bindings and object definitions");
} }
} }
@@ -267,7 +280,7 @@ void TypeDescriptionReader::readProperty(UiObjectDefinition *ast, FakeMetaObject
UiObjectMember *member = it->member; UiObjectMember *member = it->member;
UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member); UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member);
if (!script) { if (!script) {
//addError(member->firstSourceLocation(), "Expected script binding"); addWarning(member->firstSourceLocation(), "Expected script binding");
continue; continue;
} }
@@ -285,7 +298,7 @@ void TypeDescriptionReader::readProperty(UiObjectDefinition *ast, FakeMetaObject
} else if (id == "revision") { } else if (id == "revision") {
revision = readIntBinding(script); revision = readIntBinding(script);
} else { } else {
//addError(script->firstSourceLocation(), "Expected only type, name, revision, isPointer, isReadonly and isList script bindings"); addWarning(script->firstSourceLocation(), "Expected only type, name, revision, isPointer, isReadonly and isList script bindings");
} }
} }
@@ -305,7 +318,7 @@ void TypeDescriptionReader::readEnum(UiObjectDefinition *ast, FakeMetaObject::Pt
UiObjectMember *member = it->member; UiObjectMember *member = it->member;
UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member); UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member);
if (!script) { if (!script) {
//addError(member->firstSourceLocation(), "Expected script binding"); addWarning(member->firstSourceLocation(), "Expected script binding");
continue; continue;
} }
@@ -315,7 +328,7 @@ void TypeDescriptionReader::readEnum(UiObjectDefinition *ast, FakeMetaObject::Pt
} else if (name == "values") { } else if (name == "values") {
readEnumValues(script, &fme); readEnumValues(script, &fme);
} else { } else {
//addError(script->firstSourceLocation(), "Expected only name and values script bindings"); addWarning(script->firstSourceLocation(), "Expected only name and values script bindings");
} }
} }
@@ -331,7 +344,7 @@ void TypeDescriptionReader::readParameter(UiObjectDefinition *ast, FakeMetaMetho
UiObjectMember *member = it->member; UiObjectMember *member = it->member;
UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member); UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member);
if (!script) { if (!script) {
//addError(member->firstSourceLocation(), "Expected script binding"); addWarning(member->firstSourceLocation(), "Expected script binding");
continue; continue;
} }
@@ -347,7 +360,7 @@ void TypeDescriptionReader::readParameter(UiObjectDefinition *ast, FakeMetaMetho
} else if (id == "isList") { } else if (id == "isList") {
// ### unhandled // ### unhandled
} else { } else {
//addError(script->firstSourceLocation(), "Expected only name and type script bindings"); addWarning(script->firstSourceLocation(), "Expected only name and type script bindings");
} }
} }

View File

@@ -64,6 +64,7 @@ public:
bool operator()(QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *objects); bool operator()(QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *objects);
QString errorMessage() const; QString errorMessage() const;
QString warningMessage() const;
private: private:
void readDocument(AST::UiProgram *ast); void readDocument(AST::UiProgram *ast);
@@ -80,10 +81,13 @@ private:
int readIntBinding(AST::UiScriptBinding *ast); int readIntBinding(AST::UiScriptBinding *ast);
void readExports(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaObject::Ptr fmo); void readExports(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaObject::Ptr fmo);
void readEnumValues(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaEnum *fme); void readEnumValues(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaEnum *fme);
void addError(const AST::SourceLocation &loc, const QString &message); void addError(const AST::SourceLocation &loc, const QString &message);
void addWarning(const AST::SourceLocation &loc, const QString &message);
QString _source; QString _source;
QString _errorMessage; QString _errorMessage;
QString _warningMessage;
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *_objects; QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *_objects;
}; };

View File

@@ -118,9 +118,7 @@ void ModelManager::loadQmlTypeDescriptions(const QString &resourcePath)
QDir::Files, QDir::Files,
QDir::Name); QDir::Name);
const QStringList errors = Interpreter::CppQmlTypesLoader::loadQmlTypes(qmlTypesFiles); Interpreter::CppQmlTypesLoader::loadQmlTypes(qmlTypesFiles);
foreach (const QString &error, errors)
qWarning() << qPrintable(error);
// disabled for now: Prefer the xml file until the type dumping functionality // disabled for now: Prefer the xml file until the type dumping functionality
// has been moved into Qt. // has been moved into Qt.

View File

@@ -147,11 +147,22 @@ static QString qmldumpFailedMessage(const QString &error)
).arg(firstLines); ).arg(firstLines);
} }
static QList<FakeMetaObject::ConstPtr> parseHelper(const QByteArray &qmlTypeDescriptions, QString *error) static void printParseWarnings(const QString &libraryPath, const QString &warning)
{
Core::MessageManager *messageManager = Core::MessageManager::instance();
messageManager->printToOutputPane(
PluginDumper::tr("Warnings while parsing qmltypes information of %1:\n"
"%2").arg(libraryPath, warning));
}
static QList<FakeMetaObject::ConstPtr> parseHelper(const QByteArray &qmlTypeDescriptions,
QString *error,
QString *warning)
{ {
QList<FakeMetaObject::ConstPtr> ret; QList<FakeMetaObject::ConstPtr> ret;
QHash<QString, FakeMetaObject::ConstPtr> newObjects; QHash<QString, FakeMetaObject::ConstPtr> newObjects;
*error = Interpreter::CppQmlTypesLoader::parseQmlTypeDescriptions(qmlTypeDescriptions, &newObjects); Interpreter::CppQmlTypesLoader::parseQmlTypeDescriptions(qmlTypeDescriptions, &newObjects,
error, warning);
if (error->isEmpty()) { if (error->isEmpty()) {
ret = newObjects.values(); ret = newObjects.values();
@@ -179,17 +190,21 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode)
const QByteArray output = process->readAllStandardOutput(); const QByteArray output = process->readAllStandardOutput();
QString error; QString error;
QList<FakeMetaObject::ConstPtr> objectsList = parseHelper(output, &error); QString warning;
if (exitCode == 0 && !error.isEmpty()) { QList<FakeMetaObject::ConstPtr> objectsList = parseHelper(output, &error, &warning);
if (exitCode == 0) {
if (!error.isEmpty()) {
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, tr("Type dump of C++ plugin failed. Parse error:\n'%1'").arg(error)); libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, tr("Type dump of C++ plugin failed. Parse error:\n'%1'").arg(error));
} else {
libraryInfo.setMetaObjects(objectsList);
// ### disabled code path for running qmldump to get Qt's builtins
// if (libraryPath.isEmpty())
// Interpreter::CppQmlTypesLoader::builtinObjects.append(objectsList);
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpDone);
} }
if (exitCode == 0 && error.isEmpty()) { if (!warning.isEmpty())
libraryInfo.setMetaObjects(objectsList); printParseWarnings(libraryPath, warning);
// ### disabled code path for running qmldump to get Qt's builtins
// if (libraryPath.isEmpty())
// Interpreter::CppQmlTypesLoader::builtinObjects.append(objectsList);
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpDone);
} }
if (!libraryPath.isEmpty()) if (!libraryPath.isEmpty())
@@ -244,7 +259,8 @@ void PluginDumper::dump(const Plugin &plugin)
} }
QString error; QString error;
const QList<FakeMetaObject::ConstPtr> objectsList = parseHelper(reader.data(), &error); QString warning;
const QList<FakeMetaObject::ConstPtr> objectsList = parseHelper(reader.data(), &error, &warning);
if (error.isEmpty()) { if (error.isEmpty()) {
libraryInfo.setMetaObjects(objectsList); libraryInfo.setMetaObjects(objectsList);
@@ -253,6 +269,9 @@ void PluginDumper::dump(const Plugin &plugin)
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileError, libraryInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileError,
tr("Failed to parse '%1'.\nError: %2").arg(path, error)); tr("Failed to parse '%1'.\nError: %2").arg(path, error));
} }
if (!warning.isEmpty())
printParseWarnings(plugin.qmldirPath, warning);
m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo); m_modelManager->updateLibraryInfo(plugin.qmldirPath, libraryInfo);
return; return;
} }