1
/****************************************************************************
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of Qt Creator.
8
** Commercial License Usage
9
** Licensees holding valid commercial Qt licenses may use this file in
10
** accordance with the commercial license agreement provided with the
11
** Software or, alternatively, in accordance with the terms contained in
12
** a written agreement between you and Digia. For licensing terms and
13
** conditions see http://qt.digia.com/licensing. For further information
14
** use the contact form at http://qt.digia.com/contact-us.
16
** GNU Lesser General Public License Usage
17
** Alternatively, this file may be used under the terms of the GNU Lesser
18
** General Public License version 2.1 as published by the Free Software
19
** Foundation and appearing in the file LICENSE.LGPL included in the
20
** packaging of this file. Please review the following information to
21
** ensure the GNU Lesser General Public License version 2.1 requirements
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
** In addition, as a special exception, Digia gives you certain additional
25
** rights. These rights are described in the Digia Qt LGPL Exception
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28
****************************************************************************/
30
#include "qmljsimportdependencies.h"
31
#include "qmljsinterpreter.h"
32
#include "qmljsqrcparser.h"
34
#include <utils/qtcassert.h>
35
#include <utils/function.h>
37
#include <QCryptographicHash>
43
static bool debugImportDependencies = false;
45
ImportKind::Enum toImportKind(ImportType::Enum type)
48
case ImportType::Invalid:
50
case ImportType::Library:
51
return ImportKind::Library;
52
case ImportType::ImplicitDirectory:
53
case ImportType::File:
54
case ImportType::Directory:
55
case ImportType::UnknownFile:
56
return ImportKind::Path;
57
case ImportType::QrcFile:
58
case ImportType::QrcDirectory:
59
return ImportKind::QrcPath;
61
return ImportKind::Invalid;
64
ImportMatchStrength::ImportMatchStrength(QList<int> match)
68
int ImportMatchStrength::compareMatch(const ImportMatchStrength &o) const
70
int len1 = m_match.size();
71
int len2 = o.m_match.size();
72
int len = ((len1 < len2) ? len1 : len2);
73
for (int i = 0; i < len; ++ i) {
74
int v1 = m_match.at(i);
75
int v2 = o.m_match.at(i);
88
bool ImportMatchStrength::hasNoMatch()
90
return m_match.isEmpty();
93
bool ImportMatchStrength::hasMatch()
95
return !m_match.isEmpty();
98
bool operator ==(const ImportMatchStrength &m1, const ImportMatchStrength &m2)
100
return m1.m_match == m2.m_match;
103
bool operator !=(const ImportMatchStrength &m1, const ImportMatchStrength &m2)
108
bool operator <(const ImportMatchStrength &m1, const ImportMatchStrength &m2)
110
return m1.compareMatch(m2) < 0;
113
ImportKey::ImportKey()
114
: type(ImportType::Invalid),
115
majorVersion(LanguageUtils::ComponentVersion::NoVersion),
116
minorVersion(LanguageUtils::ComponentVersion::NoVersion)
119
ImportKey::ImportKey(const ImportInfo &info)
121
, majorVersion(info.version().majorVersion())
122
, minorVersion(info.version().minorVersion())
124
splitPath = QFileInfo(info.path()).canonicalFilePath().split(QLatin1Char('/'),
125
QString::KeepEmptyParts);
128
ImportKey::ImportKey(ImportType::Enum type, const QString &path, int majorVersion, int minorVersion)
130
, majorVersion(majorVersion)
131
, minorVersion(minorVersion)
134
case ImportType::Library:
135
splitPath = path.split(QLatin1Char('.'));
137
case ImportType::ImplicitDirectory:
138
case ImportType::Directory:
139
splitPath = path.split(QLatin1Char('/'));
140
if (splitPath.length() > 1 && splitPath.last().isEmpty())
141
splitPath.removeLast();
143
case ImportType::File:
144
case ImportType::QrcFile:
145
splitPath = QrcParser::normalizedQrcFilePath(path).split(QLatin1Char('/'));
147
case ImportType::QrcDirectory:
148
splitPath = QrcParser::normalizedQrcDirectoryPath(path).split(QLatin1Char('/'));
149
if (splitPath.length() > 1 && splitPath.last().isEmpty())
150
splitPath.removeLast();
152
case ImportType::Invalid:
153
case ImportType::UnknownFile:
154
splitPath = path.split(QLatin1Char('/'));
159
void ImportKey::addToHash(QCryptographicHash &hash) const
161
hash.addData(reinterpret_cast<const char *>(&type), sizeof(type));
162
hash.addData(reinterpret_cast<const char *>(&majorVersion), sizeof(majorVersion));
163
hash.addData(reinterpret_cast<const char *>(&minorVersion), sizeof(minorVersion));
164
foreach (const QString &s, splitPath) {
165
hash.addData("/", 1);
166
hash.addData(reinterpret_cast<const char *>(s.constData()), sizeof(QChar) * s.size());
168
hash.addData("/", 1);
171
ImportKey ImportKey::flatKey() const {
173
case ImportType::Invalid:
175
case ImportType::ImplicitDirectory:
176
case ImportType::Library:
177
case ImportType::File:
178
case ImportType::Directory:
179
case ImportType::QrcFile:
180
case ImportType::QrcDirectory:
181
case ImportType::UnknownFile:
184
QStringList flatPath = splitPath;
186
while (i < flatPath.size()) {
187
if (flatPath.at(i).startsWith(QLatin1Char('+')))
188
flatPath.removeAt(i);
192
if (flatPath.size() == splitPath.size())
194
ImportKey res = *this;
195
res.splitPath = flatPath;
199
QString ImportKey::path() const
201
QString res = splitPath.join(QString::fromLatin1("/"));
202
if (res.isEmpty() && !splitPath.isEmpty())
203
return QLatin1String("/");
207
ImportMatchStrength ImportKey::matchImport(const ImportKey &o, const ViewerContext &vContext) const
209
if (majorVersion != o.majorVersion || minorVersion > o.minorVersion)
210
return ImportMatchStrength();
211
bool dirToFile = false;
213
case ImportType::Invalid:
214
return ImportMatchStrength();
215
case ImportType::ImplicitDirectory:
216
case ImportType::Directory:
218
case ImportType::File:
219
case ImportType::UnknownFile:
222
case ImportType::ImplicitDirectory:
223
case ImportType::Directory:
226
return ImportMatchStrength();
229
case ImportType::Library:
230
if (type != ImportType::Library)
231
return ImportMatchStrength();
233
case ImportType::QrcDirectory:
235
case ImportType::QrcFile:
238
case ImportType::QrcDirectory:
241
return ImportMatchStrength();
244
case ImportType::QrcFile:
245
if (type != ImportType::QrcFile)
246
return ImportMatchStrength();
247
case ImportType::UnknownFile:
248
case ImportType::File:
250
case ImportType::UnknownFile:
251
case ImportType::File:
254
return ImportMatchStrength();
261
int lenPath1 = splitPath.size();
263
int lenPath2 = o.splitPath.size();
267
int nSelectors = vContext.selectors.size();
268
while (iPath1 < lenPath1) {
269
if (lenPath2 - iPath2 > lenPath1 - iPath1)
270
return ImportMatchStrength();
271
QString p1 = splitPath.at(iPath1);
272
if (iPath2 < lenPath2) {
273
QString p2 = splitPath.at(iPath2);
280
if (!p1.startsWith(QLatin1Char('+')))
282
QStringRef selectorAtt(&p1, 1, p1.size()-1);
283
while (iSelector < nSelectors) {
284
if (selectorAtt == vContext.selectors.at(iSelector))
288
if (iSelector == nSelectors)
290
res << (nSelectors - iSelector);
294
if (iPath2 != lenPath2)
298
return ImportMatchStrength(res);
301
int ImportKey::compare(const ImportKey &other) const
303
ImportKind::Enum k1 = toImportKind(type);
304
ImportKind::Enum k2 = toImportKind(other.type);
309
int len1 = splitPath.size();
310
int len2 = other.splitPath.size();
311
int len = ((len1 < len2) ? len1 : len2);
312
for (int i = 0; i < len; ++ i) {
313
QString v1 = splitPath.at(i);
314
QString v2 = other.splitPath.at(i);
324
if (majorVersion < other.majorVersion)
326
if (majorVersion > other.majorVersion)
328
if (minorVersion < other.minorVersion)
330
if (minorVersion > other.minorVersion)
332
if (type < other.type)
334
if (type > other.type)
339
bool ImportKey::isDirectoryLike() const
342
case ImportType::Directory:
343
case ImportType::ImplicitDirectory:
344
case ImportType::QrcDirectory:
351
ImportKey::DirCompareInfo ImportKey::compareDir(const ImportKey &superDir) const
353
// assumes dir/+selectors/file (i.e. no directories inside selectors)
354
switch (superDir.type) {
355
case ImportType::UnknownFile:
356
case ImportType::File:
357
case ImportType::Directory:
358
case ImportType::ImplicitDirectory:
359
if (type != ImportType::File && type != ImportType::ImplicitDirectory
360
&& type != ImportType::Directory && type != ImportType::UnknownFile)
363
case ImportType::QrcDirectory:
364
case ImportType::QrcFile:
365
if (type != ImportType::QrcDirectory && type != ImportType::QrcFile)
368
case ImportType::Invalid:
369
case ImportType::Library:
372
bool isDir1 = isDirectoryLike();
373
bool isDir2 = superDir.isDirectoryLike();
374
int len1 = splitPath.size();
375
int len2 = superDir.splitPath.size();
376
if (isDir1 && len1 > 0)
378
if (isDir2 && len2 > 0)
383
while (i1 < len1 && i2 < len2) {
384
QString p1 = splitPath.at(i1);
385
QString p2 = superDir.splitPath.at(i2);
391
if (p1.startsWith(QLatin1Char('+'))) {
392
if (p2.startsWith(QLatin1Char('+')))
394
return SecondInFirst;
396
if (p2.startsWith(QLatin1Char('+')))
397
return FirstInSecond;
401
if (splitPath.at(i1).startsWith(QLatin1Char('+')))
403
return SecondInFirst;
406
if (superDir.splitPath.at(i2).startsWith(QLatin1Char('+')))
408
return SecondInFirst;
413
QString ImportKey::toString() const
417
case ImportType::UnknownFile:
418
case ImportType::File:
421
case ImportType::Directory:
422
case ImportType::ImplicitDirectory:
423
res = path() + QLatin1Char('/');
425
case ImportType::QrcDirectory:
426
res = QLatin1String("qrc:") + path() + QLatin1Char('/');
428
case ImportType::QrcFile:
429
res = QLatin1String("qrc:") + path() + QLatin1Char('/');
431
case ImportType::Invalid:
434
case ImportType::Library:
435
res = splitPath.join(QLatin1String("."));
439
if (majorVersion != LanguageUtils::ComponentVersion::NoVersion
440
|| minorVersion != LanguageUtils::ComponentVersion::NoVersion)
441
return res + QLatin1Char(' ') + QString::number(majorVersion)
442
+ QLatin1Char('.') + QString::number(minorVersion);
447
uint qHash(const ImportKey &info)
449
uint res = ::qHash(info.type) ^
450
::qHash(info.majorVersion) ^ ::qHash(info.minorVersion);
451
foreach (const QString &s, info.splitPath)
452
res = res ^ ::qHash(s);
456
bool operator==(const ImportKey &i1, const ImportKey &i2)
458
return i1.type == i2.type
459
&& i1.splitPath == i2.splitPath
460
&& i1.majorVersion == i2.majorVersion
461
&& i1.minorVersion == i2.minorVersion;
464
bool operator !=(const ImportKey &i1, const ImportKey &i2)
469
bool operator <(const ImportKey &i1, const ImportKey &i2)
471
return i1.compare(i2) < 0;
478
Export::Export(ImportKey exportName, QString pathRequired, bool intrinsic)
479
: exportName(exportName), pathRequired(pathRequired), intrinsic(intrinsic)
482
bool Export::visibleInVContext(const ViewerContext &vContext) const
484
return pathRequired.isEmpty() || vContext.paths.contains(pathRequired);
487
bool operator ==(const Export &i1, const Export &i2)
489
return i1.exportName == i2.exportName
490
&& i1.pathRequired == i2.pathRequired
491
&& i1.intrinsic == i2.intrinsic;
494
bool operator !=(const Export &i1, const Export &i2)
499
CoreImport::CoreImport() : language(Language::Qml) { }
501
CoreImport::CoreImport(const QString &importId, const QList<Export> &possibleExports,
502
Language::Enum language, const QByteArray &fingerprint)
503
: importId(importId), possibleExports(possibleExports), language(language),
504
fingerprint(fingerprint)
507
bool CoreImport::valid() {
508
return !fingerprint.isEmpty();
511
QByteArray DependencyInfo::calculateFingerprint(const ImportDependencies &deps)
513
QCryptographicHash hash(QCryptographicHash::Sha1);
514
rootImport.addToHash(hash);
515
QStringList coreImports = allCoreImports.toList();
517
foreach (const QString importId, coreImports) {
518
hash.addData(reinterpret_cast<const char*>(importId.constData()), importId.size() * sizeof(QChar));
519
QByteArray coreImportFingerprint = deps.coreImport(importId).fingerprint;
520
hash.addData(coreImportFingerprint);
522
hash.addData("/", 1);
523
QList<ImportKey> imports(allImports.toList());
524
std::sort(imports.begin(), imports.end());
525
foreach (const ImportKey &k, imports)
527
return hash.result();
530
MatchedImport::MatchedImport()
533
MatchedImport::MatchedImport(ImportMatchStrength matchStrength, ImportKey importKey,
534
const QString &coreImportId)
535
: matchStrength(matchStrength), importKey(importKey), coreImportId(coreImportId)
538
int MatchedImport::compare(const MatchedImport &o) const {
539
int res = matchStrength.compareMatch(o.matchStrength);
542
res = importKey.compare(o.importKey);
545
if (coreImportId < o.coreImportId)
547
if (coreImportId > o.coreImportId)
552
bool operator ==(const MatchedImport &m1, const MatchedImport &m2)
554
return m1.compare(m2) == 0;
557
bool operator !=(const MatchedImport &m1, const MatchedImport &m2)
559
return m1.compare(m2) != 0;
562
bool operator <(const MatchedImport &m1, const MatchedImport &m2)
564
return m1.compare(m2) < 0;
567
ImportDependencies::ImportDependencies()
570
ImportDependencies::~ImportDependencies()
573
void ImportDependencies::filter(const ViewerContext &vContext)
575
QMap<QString, CoreImport> newCoreImports;
576
QMap<ImportKey, QStringList> newImportCache;
577
QMapIterator<QString, CoreImport> j(m_coreImports);
578
bool hasChanges = false;
579
while (j.hasNext()) {
581
const CoreImport &cImport = j.value();
582
if (vContext.languageIsCompatible(cImport.language)) {
583
QList<Export> newExports;
584
foreach (const Export &e, cImport.possibleExports) {
585
if (e.visibleInVContext(vContext)) {
586
newExports.append(e);
587
QStringList &candidateImports = newImportCache[e.exportName];
588
if (!candidateImports.contains(cImport.importId))
589
candidateImports.append(cImport.importId);
592
if (newExports.size() == cImport.possibleExports.size()) {
593
newCoreImports.insert(cImport.importId, cImport);
594
} else if (newExports.length() > 0) {
595
CoreImport newCImport = cImport;
596
newCImport.possibleExports = newExports;
597
newCoreImports.insert(newCImport.importId, newCImport);
608
m_coreImports = newCoreImports;
609
m_importCache = newImportCache;
612
CoreImport ImportDependencies::coreImport(const QString &importId) const
614
return m_coreImports.value(importId);
617
void ImportDependencies::iterateOnCandidateImports(
618
const ImportKey &key, const ViewerContext &vContext,
619
Utils::function<bool (const ImportMatchStrength &,const Export &,const CoreImport &)>
623
case ImportType::Directory:
624
case ImportType::QrcDirectory:
625
case ImportType::ImplicitDirectory:
629
const QStringList imp = m_importCache.value(key.flatKey());
630
foreach (const QString &cImportName, imp) {
631
CoreImport cImport = coreImport(cImportName);
632
if (vContext.languageIsCompatible(cImport.language)) {
633
foreach (const Export e, cImport.possibleExports) {
634
if (e.visibleInVContext(vContext)) {
635
ImportMatchStrength m = e.exportName.matchImport(key, vContext);
637
if (!iterF(m, e, cImport))
647
QMap<ImportKey, QStringList>::const_iterator lb = m_importCache.lowerBound(key.flatKey());
648
QMap<ImportKey, QStringList>::const_iterator end = m_importCache.constEnd();
650
ImportKey::DirCompareInfo c = key.compareDir(lb.key());
651
if (c == ImportKey::SameDir) {
652
foreach (const QString &cImportName, lb.value()) {
653
CoreImport cImport = coreImport(cImportName);
654
if (vContext.languageIsCompatible(cImport.language)) {
655
foreach (const Export e, cImport.possibleExports) {
656
if (e.visibleInVContext(vContext)) {
657
ImportMatchStrength m = e.exportName.matchImport(key, vContext);
659
if (!iterF(m, e, cImport))
666
} else if (c != ImportKey::SecondInFirst) {
673
class CollectCandidateImports
676
ImportDependencies::ImportElements &res;
678
CollectCandidateImports(ImportDependencies::ImportElements & res)
682
bool operator ()(const ImportMatchStrength &m, const Export &e, const CoreImport &cI) const
684
ImportKey flatName = e.exportName.flatKey();
685
res[flatName].append(MatchedImport(m, e.exportName, cI.importId));
690
ImportDependencies::ImportElements ImportDependencies::candidateImports(
691
const ImportKey &key,
692
const ViewerContext &vContext) const
694
ImportDependencies::ImportElements res;
695
CollectCandidateImports collector(res);
696
iterateOnCandidateImports(key, vContext, collector);
697
typedef QMap<ImportKey, QList<MatchedImport> >::iterator iter_t;
698
iter_t i = res.begin();
699
iter_t end = res.end();
701
std::sort(i.value().begin(), i.value().end());
707
QList<DependencyInfo::ConstPtr> ImportDependencies::createDependencyInfos(
708
const ImportKey &mainDoc, const ViewerContext &vContext) const
712
QList<DependencyInfo::ConstPtr> res;
717
void ImportDependencies::addCoreImport(const CoreImport &import)
719
CoreImport newImport = import;
720
if (m_coreImports.contains(import.importId)) {
721
CoreImport oldVal = m_coreImports.value(import.importId);
722
foreach (const Export &e, oldVal.possibleExports) {
724
removeImportCacheEntry(e.exportName, import.importId);
726
newImport.possibleExports.append(e);
729
foreach (const Export &e, import.possibleExports)
730
m_importCache[e.exportName].append(import.importId);
731
m_coreImports.insert(newImport.importId, newImport);
732
if (debugImportDependencies) {
733
QDebug dbg(qDebug());
734
dbg << "added import "<< newImport.importId << " for";
735
foreach (const Export &e, newImport.possibleExports)
736
dbg << " " << e.exportName.toString() << "(" << e.pathRequired << ")";
740
void ImportDependencies::removeCoreImport(const QString &importId)
742
if (!m_coreImports.contains(importId)) {
743
qDebug() << "missing importId in removeCoreImport(" << importId << ")";
746
CoreImport &cImport = m_coreImports[importId];
747
QList<Export> newExports;
748
foreach (const Export &e, cImport.possibleExports)
750
removeImportCacheEntry(e.exportName, importId);
752
newExports.append(e);
753
if (newExports.size()>0)
754
cImport.possibleExports = newExports;
756
m_coreImports.remove(importId);
758
if (debugImportDependencies)
759
qDebug() << "removed import with id:"<< importId;
762
void ImportDependencies::removeImportCacheEntry(const ImportKey &importKey, const QString &importId)
764
QStringList &cImp = m_importCache[importKey];
765
if (!cImp.removeOne(importId)) {
766
qDebug() << "missing possibleExport backpointer for " << importKey.toString() << " to "
770
m_importCache.remove(importKey);
773
void ImportDependencies::addExport(const QString &importId, const ImportKey &importKey,
774
const QString &requiredPath)
776
if (!m_coreImports.contains(importId)) {
777
CoreImport newImport(importId);
778
newImport.language = Language::Unknown;
779
newImport.possibleExports.append(Export(importKey, requiredPath, false));
780
m_coreImports.insert(newImport.importId, newImport);
781
m_importCache[importKey].append(importId);
784
CoreImport &importValue = m_coreImports[importId];
785
importValue.possibleExports.append(Export(importKey, requiredPath, false));
786
m_importCache[importKey].append(importId);
787
if (debugImportDependencies)
788
qDebug() << "added export "<< importKey.toString() << " for id " <<importId
789
<< " (" << requiredPath << ")";
792
void ImportDependencies::removeExport(const QString &importId, const ImportKey &importKey,
793
const QString &requiredPath)
795
if (!m_coreImports.contains(importId)) {
796
qDebug() << "non existing core import for removeExport(" << importId << ", "
797
<< importKey.toString() << ")";
799
CoreImport &importValue = m_coreImports[importId];
800
if (!importValue.possibleExports.removeOne(Export(importKey, requiredPath, false))) {
801
qDebug() << "non existing export for removeExport(" << importId << ", "
802
<< importKey.toString() << ")";
804
if (importValue.possibleExports.isEmpty() && importValue.fingerprint.isEmpty())
805
m_coreImports.remove(importId);
807
if (!m_importCache.contains(importKey)) {
808
qDebug() << "missing possibleExport for " << importKey.toString() << " when removing export of "
811
removeImportCacheEntry(importKey, importId);
813
if (debugImportDependencies)
814
qDebug() << "removed export "<< importKey.toString() << " for id " << importId
815
<< " (" << requiredPath << ")";
818
void ImportDependencies::iterateOnCoreImports(
819
const ViewerContext &vContext,
820
Utils::function<bool (const CoreImport &)> const &iterF) const
822
QMapIterator<QString, CoreImport> i(m_coreImports);
823
while (i.hasNext()) {
825
if (vContext.languageIsCompatible(i.value().language))
826
iterF(i.value()); // check also that at least one export is visible?
830
void ImportDependencies::iterateOnLibraryImports(
831
const ViewerContext &vContext,
832
Utils::function<bool (const ImportMatchStrength &,
834
const CoreImport &)> const &iterF) const
836
typedef QMap<ImportKey, QStringList>::const_iterator iter_t;
838
firstLib.type = ImportType::Library;
839
iter_t i = m_importCache.lowerBound(firstLib);
840
iter_t end = m_importCache.constEnd();
841
while (i != end && i.key().type == ImportType::Library) {
842
if (debugImportDependencies)
843
qDebug() << "libloop:" << i.key().toString() << i.value();
844
foreach (const QString &cImportName, i.value()) {
845
CoreImport cImport = coreImport(cImportName);
846
if (vContext.languageIsCompatible(cImport.language)) {
847
foreach (const Export &e, cImport.possibleExports) {
848
if (e.visibleInVContext(vContext) && e.exportName.type == ImportType::Library) {
849
ImportMatchStrength m = e.exportName.matchImport(i.key(), vContext);
851
if (debugImportDependencies)
852
qDebug() << "import iterate:" << e.exportName.toString()
853
<< " (" << e.pathRequired << "), id:" << cImport.importId;
854
if (!iterF(m, e, cImport))
865
void ImportDependencies::iterateOnSubImports(
866
const ImportKey &baseKey,
867
const ViewerContext &vContext,
868
Utils::function<bool (const ImportMatchStrength &,
870
const CoreImport &)> const &iterF) const
872
typedef QMap<ImportKey, QStringList>::const_iterator iter_t;
873
iter_t i = m_importCache.lowerBound(baseKey);
874
iter_t end = m_importCache.constEnd();
876
ImportKey::DirCompareInfo c = baseKey.compareDir(i.key());
877
if (c != ImportKey::SameDir && c != ImportKey::SecondInFirst)
879
foreach (const QString &cImportName, i.value()) {
880
CoreImport cImport = coreImport(cImportName);
881
if (vContext.languageIsCompatible(cImport.language)) {
882
foreach (const Export &e, cImport.possibleExports) {
883
if (e.visibleInVContext(vContext)) {
884
ImportMatchStrength m = e.exportName.matchImport(i.key(), vContext);
886
if (!iterF(m, e, cImport))
897
class CollectImportKeys {
899
QSet<ImportKey> &imports;
900
CollectImportKeys(QSet<ImportKey> &imports)
903
bool operator()(const ImportMatchStrength &m,
905
const CoreImport &cI) const
909
imports.insert(e.exportName.flatKey());
914
QSet<ImportKey> ImportDependencies::libraryImports(const ViewerContext &viewContext) const
917
CollectImportKeys importCollector(res);
918
iterateOnLibraryImports(viewContext, importCollector);
922
QSet<ImportKey> ImportDependencies::subdirImports(
923
const ImportKey &baseKey, const ViewerContext &viewContext) const
926
CollectImportKeys importCollector(res);
927
iterateOnSubImports(baseKey, viewContext, importCollector);
931
void ImportDependencies::checkConsistency() const
933
QMapIterator<ImportKey, QStringList> j(m_importCache);
934
while (j.hasNext()) {
936
foreach (const QString &s, j.value()) {
938
foreach (const Export &e, m_coreImports.value(s).possibleExports)
939
if (e.exportName == j.key())
944
QMapIterator<QString,CoreImport> i(m_coreImports);
945
while (i.hasNext()) {
947
foreach (const Export &e, i.value().possibleExports) {
948
if (!m_importCache.value(e.exportName).contains(i.key())) {
949
qDebug() << e.exportName.toString();
952
QMapIterator<ImportKey, QStringList> j(m_importCache);
953
while (j.hasNext()) {
955
qDebug() << j.key().toString() << j.value();
957
qDebug() << m_importCache.contains(e.exportName);
958
qDebug() << m_importCache.value(e.exportName);
960
Q_ASSERT(m_importCache.value(e.exportName).contains(i.key()));