forked from qt-creator/qt-creator
qmljs: fingerprints for documents, libraries and FakeMetaObjects
Change-Id: Ib9c9b86fbed19539dc42696292bdb3b93dd1b575 Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com>
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
Reference in New Issue
Block a user