summaryrefslogtreecommitdiff
path: root/src/libs/qmljs/qmljsdocument.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/qmljs/qmljsdocument.cpp')
-rw-r--r--src/libs/qmljs/qmljsdocument.cpp158
1 files changed, 156 insertions, 2 deletions
diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp
index fe169f795c..68fb5eadd5 100644
--- a/src/libs/qmljs/qmljsdocument.cpp
+++ b/src/libs/qmljs/qmljsdocument.cpp
@@ -30,11 +30,17 @@
#include "qmljsdocument.h"
#include "qmljsbind.h"
#include "qmljsconstants.h"
+#include "qmljsimportdependencies.h"
#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;
@@ -204,6 +210,16 @@ void Document::setLanguage(Language::Enum l)
_language = l;
}
+QString Document::importId() const
+{
+ return _fileName;
+}
+
+QByteArray Document::fingerprint() const
+{
+ return _fingerprint;
+}
+
AST::UiProgram *Document::qmlProgram() const
{
return cast<UiProgram *>(_ast);
@@ -245,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
@@ -373,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()
{
}
@@ -396,21 +482,67 @@ Snapshot::~Snapshot()
{
}
+Snapshot::Snapshot(const Snapshot &o)
+ : _documents(o._documents),
+ _documentsByPath(o._documentsByPath),
+ _libraries(o._libraries),
+ _dependencies(o._dependencies)
+{
+}
+
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, fileName),
+ 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);
+ if (!info.wasFound()) return;
+ CoreImport cImport;
+ cImport.importId = path;
+ cImport.language = Language::Unknown;
+ QSet<ImportKey> packages;
+ foreach (const ModuleApiInfo &moduleInfo, info.moduleApis()) {
+ ImportKey iKey(ImportType::Library, moduleInfo.uri, moduleInfo.version.majorVersion(),
+ moduleInfo.version.minorVersion());
+ packages.insert(iKey);
+ }
+ foreach (const LanguageUtils::FakeMetaObject::ConstPtr &metaO, info.metaObjects()) {
+ foreach (const LanguageUtils::FakeMetaObject::Export &e, metaO->exports()) {
+ ImportKey iKey(ImportType::Library, e.package, e.version.majorVersion(),
+ e.version.minorVersion());
+ packages.insert(iKey);
+ }
+ }
+
+ QStringList splitPath = path.split(QLatin1Char('/'));
+ foreach (const ImportKey &importKey, packages) {
+ QString requiredPath = QStringList(splitPath.mid(0, splitPath.size() - importKey.splitPath.size()))
+ .join(QLatin1String("/"));
+ cImport.possibleExports << Export(importKey, requiredPath, true);
+ }
+ foreach (const QmlDirParser::Component &component, info.components()) {
+ foreach (const Export &e, cImport.possibleExports)
+ // renaming of type name not really represented here... fix?
+ _dependencies.addExport(component.fileName, e.exportName, e.pathRequired);
+ }
+ cImport.fingerprint = info.fingerprint();
+ _dependencies.addCoreImport(cImport);
}
void Snapshot::remove(const QString &fileName)
@@ -427,6 +559,16 @@ void Snapshot::remove(const QString &fileName)
}
}
+const QmlJS::ImportDependencies *Snapshot::importDependencies() const
+{
+ return &_dependencies;
+}
+
+QmlJS::ImportDependencies *Snapshot::importDependencies()
+{
+ return &_dependencies;
+}
+
Document::MutablePtr Snapshot::documentFromSource(
const QString &code, const QString &fileName,
Language::Enum language) const
@@ -454,3 +596,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));
+}