summaryrefslogtreecommitdiff
path: root/src/libs/qmljs/qmljsdocument.cpp
diff options
context:
space:
mode:
authorFawzi Mohamed <fawzi.mohamed@digia.com>2013-11-13 16:31:04 +0100
committerFawzi Mohamed <fawzi.mohamed@digia.com>2013-11-20 12:27:31 +0100
commit7fb87fbb0609af9a52b1a2d6a0f7f9290fec87ae (patch)
tree5e9f7f1c84cf0fdffa3714ba1dcf1b63dee8f8d2 /src/libs/qmljs/qmljsdocument.cpp
parente1b44e870f5c15daad136f609df2175278e1f62c (diff)
downloadqt-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.cpp118
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));
+}