diff options
author | Fawzi Mohamed <fawzi.mohamed@digia.com> | 2013-11-13 16:31:04 +0100 |
---|---|---|
committer | Fawzi Mohamed <fawzi.mohamed@digia.com> | 2013-11-20 12:27:31 +0100 |
commit | 7fb87fbb0609af9a52b1a2d6a0f7f9290fec87ae (patch) | |
tree | 5e9f7f1c84cf0fdffa3714ba1dcf1b63dee8f8d2 /src/libs/qmljs/qmljsdocument.cpp | |
parent | e1b44e870f5c15daad136f609df2175278e1f62c (diff) | |
download | qt-creator-7fb87fbb0609af9a52b1a2d6a0f7f9290fec87ae.tar.gz |
qmljs: fingerprints for documents, libraries and FakeMetaObjects
Change-Id: Ib9c9b86fbed19539dc42696292bdb3b93dd1b575
Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com>
Diffstat (limited to 'src/libs/qmljs/qmljsdocument.cpp')
-rw-r--r-- | src/libs/qmljs/qmljsdocument.cpp | 118 |
1 files changed, 116 insertions, 2 deletions
diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp index 7d8db768be..bdc1e8c5b4 100644 --- a/src/libs/qmljs/qmljsdocument.cpp +++ b/src/libs/qmljs/qmljsdocument.cpp @@ -34,8 +34,13 @@ #include <qmljs/parser/qmljslexer_p.h> #include <qmljs/parser/qmljsparser_p.h> +#include <utils/qtcassert.h> + +#include <QCryptographicHash> #include <QDir> +#include <algorithm> + using namespace QmlJS; using namespace QmlJS::AST; @@ -205,6 +210,16 @@ void Document::setLanguage(Language::Enum l) _language = l; } +QString Document::importId() const +{ + return path(); +} + +QByteArray Document::fingerprint() const +{ + return _fingerprint; +} + AST::UiProgram *Document::qmlProgram() const { return cast<UiProgram *>(_ast); @@ -246,6 +261,9 @@ QString Document::source() const void Document::setSource(const QString &source) { _source = source; + QCryptographicHash sha(QCryptographicHash::Sha1); + sha.addData(source.toUtf8()); + _fingerprint = sha.result(); } int Document::editorRevision() const @@ -374,21 +392,88 @@ LibraryInfo::LibraryInfo(Status status) : _status(status) , _dumpStatus(NoTypeInfo) { + updateFingerprint(); } -LibraryInfo::LibraryInfo(const QmlDirParser &parser) +LibraryInfo::LibraryInfo(const QmlDirParser &parser, const QByteArray &fingerprint) : _status(Found) , _components(parser.components().values()) , _plugins(parser.plugins()) , _typeinfos(parser.typeInfos()) + , _fingerprint(fingerprint) , _dumpStatus(NoTypeInfo) { + if (_fingerprint.isEmpty()) + updateFingerprint(); } LibraryInfo::~LibraryInfo() { } +QByteArray LibraryInfo::calculateFingerprint() const +{ + QCryptographicHash hash(QCryptographicHash::Sha1); + hash.addData(reinterpret_cast<const char *>(&_status), sizeof(_status)); + int len = _components.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + foreach (const QmlDirParser::Component &component, _components) { + len = component.fileName.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + hash.addData(reinterpret_cast<const char *>(component.fileName.constData()), len * sizeof(QChar)); + hash.addData(reinterpret_cast<const char *>(&component.majorVersion), sizeof(component.majorVersion)); + hash.addData(reinterpret_cast<const char *>(&component.minorVersion), sizeof(component.minorVersion)); + len = component.typeName.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + hash.addData(reinterpret_cast<const char *>(component.typeName.constData()), component.typeName.size() * sizeof(QChar)); + int flags = (component.singleton ? (1 << 0) : 0) + (component.internal ? (1 << 1) : 0); + hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags)); + } + len = _plugins.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + foreach (const QmlDirParser::Plugin &plugin, _plugins) { + len = plugin.path.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + hash.addData(reinterpret_cast<const char *>(plugin.path.constData()), len * sizeof(QChar)); + len = plugin.name.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + hash.addData(reinterpret_cast<const char *>(plugin.name.constData()), len * sizeof(QChar)); + } + len = _typeinfos.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + foreach (const QmlDirParser::TypeInfo &typeinfo, _typeinfos) { + len = typeinfo.fileName.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + hash.addData(reinterpret_cast<const char *>(typeinfo.fileName.constData()), len * sizeof(QChar)); + } + len = _metaObjects.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + QList<QByteArray> metaFingerprints; + foreach (const LanguageUtils::FakeMetaObject::ConstPtr &metaObject, _metaObjects) + metaFingerprints.append(metaObject->fingerprint()); + std::sort(metaFingerprints.begin(), metaFingerprints.end()); + foreach (const QByteArray &fp, metaFingerprints) + hash.addData(fp); + hash.addData(reinterpret_cast<const char *>(&_dumpStatus), sizeof(_dumpStatus)); + len = _dumpError.size(); // localization dependent (avoid?) + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + hash.addData(reinterpret_cast<const char *>(_dumpError.constData()), len * sizeof(QChar)); + + len = _moduleApis.size(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + foreach (const ModuleApiInfo &moduleInfo, _moduleApis) + moduleInfo.addToHash(hash); // make it order independent? + + QByteArray res(hash.result()); + res.append('L'); + return res; +} + +void LibraryInfo::updateFingerprint() +{ + _fingerprint = calculateFingerprint(); +} + Snapshot::Snapshot() { } @@ -410,16 +495,33 @@ void Snapshot::insert(const Document::Ptr &document, bool allowInvalid) if (document && (allowInvalid || document->qmlProgram() || document->jsProgram())) { const QString fileName = document->fileName(); const QString path = document->path(); - remove(fileName); _documentsByPath[path].append(document); _documents.insert(fileName, document); + CoreImport cImport; + cImport.importId = document->importId(); + cImport.language = document->language(); + cImport.possibleExports << Export(ImportKey(ImportType::File, document->path()), + QString(), true); + cImport.fingerprint = document->fingerprint(); + _dependencies.addCoreImport(cImport); } } void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info) { + QTC_CHECK(info.fingerprint() == info.calculateFingerprint()); _libraries.insert(QDir::cleanPath(path), info); + CoreImport cImport; + cImport.importId = path; + cImport.language = Language::Unknown; + foreach (const ModuleApiInfo &moduleInfo, info.moduleApis()) { + ImportKey iKey(ImportType::Library, moduleInfo.uri, moduleInfo.version.majorVersion(), + moduleInfo.version.minorVersion()); + cImport.possibleExports << Export(iKey, path, true); + } + cImport.fingerprint = info.fingerprint(); + _dependencies.addCoreImport(cImport); } void Snapshot::remove(const QString &fileName) @@ -473,3 +575,15 @@ LibraryInfo Snapshot::libraryInfo(const QString &path) const { return _libraries.value(QDir::cleanPath(path)); } + + +void ModuleApiInfo::addToHash(QCryptographicHash &hash) const +{ + int len = uri.length(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + hash.addData(reinterpret_cast<const char *>(uri.constData()), len * sizeof(QChar)); + version.addToHash(hash); + len = cppName.length(); + hash.addData(reinterpret_cast<const char *>(&len), sizeof(len)); + hash.addData(reinterpret_cast<const char *>(cppName.constData()), len * sizeof(QChar)); +} |