2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2010-07-09 15:47:07 +02:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2010-07-09 15:47:07 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2010-07-09 15:47:07 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:58:39 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2010-07-09 15:47:07 +02:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2010-07-09 15:47:07 +02:00
|
|
|
|
2010-01-28 14:53:53 +01:00
|
|
|
#include "qmljslink.h"
|
|
|
|
|
|
|
|
|
|
#include "parser/qmljsast_p.h"
|
|
|
|
|
#include "qmljsdocument.h"
|
|
|
|
|
#include "qmljsbind.h"
|
2011-10-07 14:04:06 +02:00
|
|
|
#include "qmljsutils.h"
|
2010-08-25 14:15:57 +02:00
|
|
|
#include "qmljsmodelmanagerinterface.h"
|
2013-10-16 15:08:27 +02:00
|
|
|
#include "qmljsconstants.h"
|
2010-01-28 14:53:53 +01:00
|
|
|
|
2019-02-07 17:22:39 +01:00
|
|
|
#include <utils/qrcparser.h>
|
|
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
2020-03-26 12:17:03 +01:00
|
|
|
#include <QDirIterator>
|
2010-01-28 14:53:53 +01:00
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
using namespace LanguageUtils;
|
2010-01-28 14:53:53 +01:00
|
|
|
using namespace QmlJS::AST;
|
|
|
|
|
|
2015-02-03 23:48:57 +02:00
|
|
|
namespace QmlJS {
|
|
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
namespace {
|
|
|
|
|
class ImportCacheKey
|
|
|
|
|
{
|
|
|
|
|
public:
|
2011-08-08 12:47:49 +02:00
|
|
|
explicit ImportCacheKey(const ImportInfo &info)
|
2019-10-22 17:54:14 +02:00
|
|
|
: m_type(info.type())
|
|
|
|
|
, m_path(info.path())
|
|
|
|
|
, m_majorVersion(info.version().majorVersion())
|
|
|
|
|
, m_minorVersion(info.version().minorVersion())
|
2010-09-16 15:29:37 +02:00
|
|
|
{}
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
private:
|
|
|
|
|
friend uint qHash(const ImportCacheKey &);
|
|
|
|
|
friend bool operator==(const ImportCacheKey &, const ImportCacheKey &);
|
|
|
|
|
|
|
|
|
|
int m_type;
|
|
|
|
|
QString m_path;
|
|
|
|
|
int m_majorVersion;
|
|
|
|
|
int m_minorVersion;
|
2010-09-16 15:29:37 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
uint qHash(const ImportCacheKey &info)
|
|
|
|
|
{
|
2019-10-22 17:54:14 +02:00
|
|
|
return ::qHash(info.m_type) ^ ::qHash(info.m_path) ^
|
|
|
|
|
::qHash(info.m_majorVersion) ^ ::qHash(info.m_minorVersion);
|
2010-09-16 15:29:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator==(const ImportCacheKey &i1, const ImportCacheKey &i2)
|
|
|
|
|
{
|
2019-10-22 17:54:14 +02:00
|
|
|
return i1.m_type == i2.m_type
|
|
|
|
|
&& i1.m_path == i2.m_path
|
|
|
|
|
&& i1.m_majorVersion == i2.m_majorVersion
|
|
|
|
|
&& i1.m_minorVersion == i2.m_minorVersion;
|
2010-09-16 15:29:37 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-03 23:48:57 +02:00
|
|
|
class LinkPrivate
|
2010-09-16 15:29:37 +02:00
|
|
|
{
|
|
|
|
|
public:
|
2011-09-13 13:32:29 +02:00
|
|
|
Context::ImportsPerDocument linkImports();
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
void populateImportedTypes(Imports *imports, const Document::Ptr &doc);
|
2011-09-13 13:32:29 +02:00
|
|
|
Import importFileOrDirectory(
|
2019-10-22 17:54:14 +02:00
|
|
|
const Document::Ptr &doc,
|
2011-09-13 13:32:29 +02:00
|
|
|
const ImportInfo &importInfo);
|
|
|
|
|
Import importNonFile(
|
2019-10-22 17:54:14 +02:00
|
|
|
const Document::Ptr &doc,
|
2011-09-13 13:32:29 +02:00
|
|
|
const ImportInfo &importInfo);
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
bool importLibrary(const Document::Ptr &doc,
|
2011-09-13 13:32:29 +02:00
|
|
|
const QString &libraryPath,
|
2020-05-10 15:57:22 +02:00
|
|
|
Import *import, ObjectValue *targetObject,
|
2020-11-26 07:32:29 +01:00
|
|
|
const QString &importPath = QString(),
|
|
|
|
|
bool optional = false);
|
2011-09-13 13:32:29 +02:00
|
|
|
void loadQmldirComponents(ObjectValue *import,
|
|
|
|
|
LanguageUtils::ComponentVersion version,
|
|
|
|
|
const LibraryInfo &libraryInfo,
|
|
|
|
|
const QString &libraryPath);
|
2019-10-22 17:54:14 +02:00
|
|
|
void loadImplicitDirectoryImports(Imports *imports, const Document::Ptr &doc);
|
2011-09-13 13:32:29 +02:00
|
|
|
void loadImplicitDefaultImports(Imports *imports);
|
|
|
|
|
|
2020-02-28 17:51:32 +01:00
|
|
|
void error(const Document::Ptr &doc, const SourceLocation &loc, const QString &message);
|
|
|
|
|
void warning(const Document::Ptr &doc, const SourceLocation &loc, const QString &message);
|
2011-09-13 13:32:29 +02:00
|
|
|
void appendDiagnostic(const Document::Ptr &doc, const DiagnosticMessage &message);
|
2019-10-22 17:54:14 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
friend class Link;
|
|
|
|
|
|
|
|
|
|
Snapshot m_snapshot;
|
|
|
|
|
ValueOwner *m_valueOwner = nullptr;
|
|
|
|
|
QStringList m_importPaths;
|
2019-10-22 16:29:40 +02:00
|
|
|
QStringList m_applicationDirectories;
|
2019-10-22 17:54:14 +02:00
|
|
|
LibraryInfo m_builtins;
|
|
|
|
|
ViewerContext m_vContext;
|
|
|
|
|
|
|
|
|
|
QHash<ImportCacheKey, Import> importCache;
|
|
|
|
|
QHash<QString, QList<ModuleApiInfo>> importableModuleApis;
|
|
|
|
|
|
|
|
|
|
Document::Ptr document;
|
|
|
|
|
|
|
|
|
|
QList<DiagnosticMessage> *diagnosticMessages = nullptr;
|
|
|
|
|
QHash<QString, QList<DiagnosticMessage>> *allDiagnosticMessages = nullptr;
|
2010-09-16 15:29:37 +02:00
|
|
|
};
|
|
|
|
|
|
2010-09-15 15:25:59 +02:00
|
|
|
/*!
|
|
|
|
|
\class QmlJS::Link
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The Link class creates a Context for a Snapshot.
|
2011-11-09 16:02:59 +01:00
|
|
|
\sa Context Snapshot
|
2010-09-15 15:25:59 +02:00
|
|
|
|
2011-11-01 14:01:07 +01:00
|
|
|
Initializes a context by resolving imports. This is an expensive operation.
|
2010-09-15 15:25:59 +02:00
|
|
|
|
2011-11-01 14:01:07 +01:00
|
|
|
Instead of making a fresh context, consider reusing the one maintained in the
|
2014-01-24 16:53:16 +01:00
|
|
|
\l{QmlJSEditor::SemanticInfo} of a \l{QmlJSEditor::QmlJSEditorDocument}.
|
2010-09-15 15:25:59 +02:00
|
|
|
*/
|
|
|
|
|
|
2013-10-16 15:08:27 +02:00
|
|
|
Link::Link(const Snapshot &snapshot, const ViewerContext &vContext, const LibraryInfo &builtins)
|
2011-09-13 13:32:29 +02:00
|
|
|
: d(new LinkPrivate)
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
2019-10-22 17:54:14 +02:00
|
|
|
d->m_valueOwner = new ValueOwner;
|
|
|
|
|
d->m_snapshot = snapshot;
|
|
|
|
|
d->m_importPaths = vContext.paths;
|
2019-10-22 16:29:40 +02:00
|
|
|
d->m_applicationDirectories = vContext.applicationDirectories;
|
2019-10-22 17:54:14 +02:00
|
|
|
d->m_builtins = builtins;
|
|
|
|
|
d->m_vContext = vContext;
|
2010-09-16 15:29:37 +02:00
|
|
|
|
2019-07-31 17:21:41 +02:00
|
|
|
d->diagnosticMessages = nullptr;
|
|
|
|
|
d->allDiagnosticMessages = nullptr;
|
2011-04-21 11:09:29 +02:00
|
|
|
|
|
|
|
|
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
|
|
|
|
|
if (modelManager) {
|
2019-07-24 13:43:54 +02:00
|
|
|
const ModelManagerInterface::CppDataHash cppDataHash = modelManager->cppData();
|
2014-07-16 16:21:40 +02:00
|
|
|
{
|
|
|
|
|
// populate engine with types from C++
|
2019-07-24 13:43:54 +02:00
|
|
|
for (auto it = cppDataHash.cbegin(), end = cppDataHash.cend(); it != end; ++it)
|
2019-10-22 17:54:14 +02:00
|
|
|
d->m_valueOwner->cppQmlTypes().load(it.key(), it.value().exportedTypes);
|
2011-08-25 12:35:55 +02:00
|
|
|
}
|
|
|
|
|
|
2011-11-21 14:51:03 +01:00
|
|
|
// build an object with the context properties from C++
|
2019-10-22 17:54:14 +02:00
|
|
|
ObjectValue *cppContextProperties = d->m_valueOwner->newObject(/* prototype = */ nullptr);
|
2019-07-24 13:43:54 +02:00
|
|
|
for (const ModelManagerInterface::CppData &cppData : cppDataHash) {
|
2019-10-22 17:54:14 +02:00
|
|
|
for (auto it = cppData.contextProperties.cbegin(),
|
|
|
|
|
end = cppData.contextProperties.cend();
|
|
|
|
|
it != end; ++it) {
|
2019-07-31 17:21:41 +02:00
|
|
|
const Value *value = nullptr;
|
2019-10-22 17:54:14 +02:00
|
|
|
const QString &cppTypeName = it.value();
|
2011-08-25 12:35:55 +02:00
|
|
|
if (!cppTypeName.isEmpty())
|
2019-10-22 17:54:14 +02:00
|
|
|
value = d->m_valueOwner->cppQmlTypes().objectByCppName(cppTypeName);
|
2011-08-25 12:35:55 +02:00
|
|
|
if (!value)
|
2019-10-22 17:54:14 +02:00
|
|
|
value = d->m_valueOwner->unknownValue();
|
2011-11-21 14:51:03 +01:00
|
|
|
cppContextProperties->setMember(it.key(), value);
|
2011-08-25 12:35:55 +02:00
|
|
|
}
|
2011-04-21 11:09:29 +02:00
|
|
|
}
|
2019-10-22 17:54:14 +02:00
|
|
|
d->m_valueOwner->cppQmlTypes().setCppContextProperties(cppContextProperties);
|
2011-04-21 11:09:29 +02:00
|
|
|
}
|
2011-05-06 13:31:30 +02:00
|
|
|
}
|
2011-04-21 11:09:29 +02:00
|
|
|
|
2011-07-13 15:04:27 +02:00
|
|
|
ContextPtr Link::operator()(QHash<QString, QList<DiagnosticMessage> > *messages)
|
2011-05-06 13:31:30 +02:00
|
|
|
{
|
|
|
|
|
d->allDiagnosticMessages = messages;
|
2019-10-22 17:54:14 +02:00
|
|
|
return Context::create(d->m_snapshot, d->m_valueOwner, d->linkImports(), d->m_vContext);
|
2011-04-21 11:09:29 +02:00
|
|
|
}
|
|
|
|
|
|
2011-07-13 15:04:27 +02:00
|
|
|
ContextPtr Link::operator()(const Document::Ptr &doc, QList<DiagnosticMessage> *messages)
|
2011-04-21 11:09:29 +02:00
|
|
|
{
|
2011-09-13 13:32:29 +02:00
|
|
|
d->document = doc;
|
2011-04-21 11:09:29 +02:00
|
|
|
d->diagnosticMessages = messages;
|
2019-10-22 17:54:14 +02:00
|
|
|
return Context::create(d->m_snapshot, d->m_valueOwner, d->linkImports(), d->m_vContext);
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link::~Link()
|
|
|
|
|
{
|
2011-09-13 13:32:29 +02:00
|
|
|
delete d;
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
|
|
|
|
|
2011-09-13 13:32:29 +02:00
|
|
|
Context::ImportsPerDocument LinkPrivate::linkImports()
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
2011-07-05 12:06:41 +02:00
|
|
|
Context::ImportsPerDocument importsPerDocument;
|
|
|
|
|
|
2011-06-28 12:01:56 +02:00
|
|
|
// load builtin objects
|
2019-10-22 17:54:14 +02:00
|
|
|
if (m_builtins.pluginTypeInfoStatus() == LibraryInfo::DumpDone
|
|
|
|
|
|| m_builtins.pluginTypeInfoStatus() == LibraryInfo::TypeInfoFileDone) {
|
|
|
|
|
m_valueOwner->cppQmlTypes().load(QLatin1String("<builtins>"), m_builtins.metaObjects());
|
2011-06-28 12:01:56 +02:00
|
|
|
} else {
|
2019-10-22 17:54:14 +02:00
|
|
|
m_valueOwner->cppQmlTypes().load(QLatin1String("<defaults>"),
|
|
|
|
|
CppQmlTypesLoader::defaultQtObjects);
|
2011-06-28 12:01:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// load library objects shipped with Creator
|
2019-10-22 17:54:14 +02:00
|
|
|
m_valueOwner->cppQmlTypes().load(QLatin1String("<defaultQt4>"),
|
|
|
|
|
CppQmlTypesLoader::defaultLibraryObjects);
|
2011-06-28 12:01:56 +02:00
|
|
|
|
2011-09-13 13:32:29 +02:00
|
|
|
if (document) {
|
|
|
|
|
// do it on document first, to make sure import errors are shown
|
2019-10-22 17:54:14 +02:00
|
|
|
auto *imports = new Imports(m_valueOwner);
|
2015-04-24 14:32:43 +03:00
|
|
|
|
|
|
|
|
// Add custom imports for the opened document
|
2019-10-22 17:54:14 +02:00
|
|
|
for (const auto &provider : CustomImportsProvider::allProviders()) {
|
|
|
|
|
const auto providerImports = provider->imports(m_valueOwner, document.data());
|
|
|
|
|
for (const auto &import : providerImports)
|
2017-12-08 17:20:48 +01:00
|
|
|
importCache.insert(ImportCacheKey(import.info), import);
|
2019-10-22 17:54:14 +02:00
|
|
|
}
|
2015-04-24 14:32:43 +03:00
|
|
|
|
2011-09-13 13:32:29 +02:00
|
|
|
populateImportedTypes(imports, document);
|
|
|
|
|
importsPerDocument.insert(document.data(), QSharedPointer<Imports>(imports));
|
2011-04-21 11:09:29 +02:00
|
|
|
}
|
2010-02-04 09:44:43 +01:00
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
for (const Document::Ptr &doc : qAsConst(m_snapshot)) {
|
2011-09-13 13:32:29 +02:00
|
|
|
if (doc == document)
|
2010-09-16 15:29:37 +02:00
|
|
|
continue;
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
auto *imports = new Imports(m_valueOwner);
|
2011-05-27 10:43:06 +02:00
|
|
|
populateImportedTypes(imports, doc);
|
2011-07-05 12:06:41 +02:00
|
|
|
importsPerDocument.insert(doc.data(), QSharedPointer<Imports>(imports));
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
2011-07-05 12:06:41 +02:00
|
|
|
|
|
|
|
|
return importsPerDocument;
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-10 12:32:25 +02:00
|
|
|
/**
|
|
|
|
|
* A workaround for prototype issues with QEasingCurve in Qt 5.15.
|
|
|
|
|
*
|
|
|
|
|
* In this Qt version, QEasingCurve is declared in builtins.qmltypes, but its
|
|
|
|
|
* prototype, QQmlEasingValueType, is only contained in the QtQml module.
|
|
|
|
|
*
|
|
|
|
|
* This code attempts to resolve QEasingCurve's prototype if it hasn't been set
|
|
|
|
|
* already. It's intended to be called after all CppQmlTypes have been loaded.
|
|
|
|
|
*/
|
|
|
|
|
static void workaroundQEasingCurve(CppQmlTypes &cppTypes)
|
|
|
|
|
{
|
|
|
|
|
const CppComponentValue *easingCurve = cppTypes.objectByCppName("QEasingCurve");
|
|
|
|
|
if (!easingCurve || easingCurve->prototype())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const QString superclassName = easingCurve->metaObject()->superclassName();
|
|
|
|
|
if (superclassName.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const CppComponentValue *prototype = cppTypes.objectByCppName(superclassName);
|
|
|
|
|
if (!prototype)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const_cast<CppComponentValue *>(easingCurve)->setPrototype(prototype);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
void LinkPrivate::populateImportedTypes(Imports *imports, const Document::Ptr &doc)
|
2010-01-28 14:53:53 +01:00
|
|
|
{
|
2011-10-12 08:36:02 +02:00
|
|
|
importableModuleApis.clear();
|
|
|
|
|
|
2010-12-03 10:13:15 +01:00
|
|
|
// implicit imports: the <default> package is always available
|
2011-05-27 10:43:06 +02:00
|
|
|
loadImplicitDefaultImports(imports);
|
2010-12-03 10:13:15 +01:00
|
|
|
|
2010-01-29 13:21:50 +01:00
|
|
|
// implicit imports:
|
|
|
|
|
// qml files in the same directory are available without explicit imports
|
2011-09-27 15:12:22 +02:00
|
|
|
if (doc->isQmlDocument())
|
|
|
|
|
loadImplicitDirectoryImports(imports, doc);
|
2011-02-25 16:16:37 +01:00
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
// explicit imports, whether directories, files or libraries
|
2019-10-22 17:54:14 +02:00
|
|
|
const auto docImports = doc->bind()->imports();
|
|
|
|
|
for (const ImportInfo &info : docImports) {
|
2011-09-13 13:32:29 +02:00
|
|
|
Import import = importCache.value(ImportCacheKey(info));
|
2011-04-06 09:19:46 +02:00
|
|
|
|
2011-05-27 11:00:39 +02:00
|
|
|
// ensure usage of the right ImportInfo, the cached import
|
|
|
|
|
// can have a different 'as' clause...
|
|
|
|
|
import.info = info;
|
|
|
|
|
|
2011-05-12 15:29:00 +02:00
|
|
|
if (!import.object) {
|
2010-09-16 15:29:37 +02:00
|
|
|
switch (info.type()) {
|
2013-10-16 14:59:28 +02:00
|
|
|
case ImportType::File:
|
|
|
|
|
case ImportType::Directory:
|
|
|
|
|
case ImportType::QrcFile:
|
|
|
|
|
case ImportType::QrcDirectory:
|
2011-03-10 14:49:38 +01:00
|
|
|
import = importFileOrDirectory(doc, info);
|
2010-09-16 15:29:37 +02:00
|
|
|
break;
|
2013-10-16 14:59:28 +02:00
|
|
|
case ImportType::Library:
|
2010-09-16 15:29:37 +02:00
|
|
|
import = importNonFile(doc, info);
|
|
|
|
|
break;
|
2013-10-16 14:59:28 +02:00
|
|
|
case ImportType::UnknownFile:
|
2011-09-29 11:48:13 +02:00
|
|
|
imports->setImportFailed();
|
2011-09-27 15:12:22 +02:00
|
|
|
if (info.ast()) {
|
|
|
|
|
error(doc, info.ast()->fileNameToken,
|
2015-10-23 15:09:08 +02:00
|
|
|
Link::tr("File or directory not found."));
|
2011-09-27 15:12:22 +02:00
|
|
|
}
|
2011-08-10 09:00:40 +02:00
|
|
|
break;
|
2010-09-16 15:29:37 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-05-12 15:29:00 +02:00
|
|
|
if (import.object)
|
2011-09-13 13:32:29 +02:00
|
|
|
importCache.insert(ImportCacheKey(info), import);
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
2011-05-16 12:21:20 +02:00
|
|
|
if (import.object)
|
2011-05-27 10:43:06 +02:00
|
|
|
imports->append(import);
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
2020-06-10 12:32:25 +02:00
|
|
|
|
|
|
|
|
workaroundQEasingCurve(m_valueOwner->cppQmlTypes());
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
2010-01-28 14:53:53 +01:00
|
|
|
|
2010-02-02 15:55:17 +01:00
|
|
|
/*
|
|
|
|
|
import "content"
|
|
|
|
|
import "content" as Xxx
|
|
|
|
|
import "content" 4.6
|
|
|
|
|
import "content" 4.6 as Xxx
|
2010-01-29 13:36:07 +01:00
|
|
|
|
2010-02-02 15:55:17 +01:00
|
|
|
import "http://www.ovi.com/" as Ovi
|
2011-05-27 10:43:06 +02:00
|
|
|
|
|
|
|
|
import "file.js" as Foo
|
2010-02-02 15:55:17 +01:00
|
|
|
*/
|
2019-10-22 17:54:14 +02:00
|
|
|
Import LinkPrivate::importFileOrDirectory(const Document::Ptr &doc, const ImportInfo &importInfo)
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
2011-05-27 10:43:06 +02:00
|
|
|
Import import;
|
2011-05-12 15:29:00 +02:00
|
|
|
import.info = importInfo;
|
2019-07-31 17:21:41 +02:00
|
|
|
import.object = nullptr;
|
2011-09-29 11:48:13 +02:00
|
|
|
import.valid = true;
|
2011-05-12 15:29:00 +02:00
|
|
|
|
2013-05-21 11:35:15 +02:00
|
|
|
QString path = importInfo.path();
|
2010-01-29 13:36:07 +01:00
|
|
|
|
2013-10-16 14:59:28 +02:00
|
|
|
if (importInfo.type() == ImportType::Directory
|
|
|
|
|
|| importInfo.type() == ImportType::ImplicitDirectory) {
|
2019-10-22 17:54:14 +02:00
|
|
|
import.object = new ObjectValue(m_valueOwner);
|
2011-03-10 14:49:38 +01:00
|
|
|
|
2020-05-10 15:57:22 +02:00
|
|
|
importLibrary(doc, path, &import, import.object);
|
2011-03-10 14:49:38 +01:00
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
const QList<Document::Ptr> documentsInDirectory = m_snapshot.documentsInDirectory(path);
|
|
|
|
|
for (const Document::Ptr &importedDoc : documentsInDirectory) {
|
2010-05-20 14:00:19 +02:00
|
|
|
if (importedDoc->bind()->rootObjectValue()) {
|
|
|
|
|
const QString targetName = importedDoc->componentName();
|
2011-05-24 11:50:10 +02:00
|
|
|
import.object->setMember(targetName, importedDoc->bind()->rootObjectValue());
|
2010-05-20 14:00:19 +02:00
|
|
|
}
|
2010-03-16 16:34:33 +01:00
|
|
|
}
|
2013-10-16 14:59:28 +02:00
|
|
|
} else if (importInfo.type() == ImportType::File) {
|
2019-10-22 17:54:14 +02:00
|
|
|
if (Document::Ptr importedDoc = m_snapshot.document(path))
|
2011-05-12 15:29:00 +02:00
|
|
|
import.object = importedDoc->bind()->rootObjectValue();
|
2013-10-16 14:59:28 +02:00
|
|
|
} else if (importInfo.type() == ImportType::QrcFile) {
|
2013-05-21 11:35:15 +02:00
|
|
|
QLocale locale;
|
|
|
|
|
QStringList filePaths = ModelManagerInterface::instance()
|
2019-07-31 17:21:41 +02:00
|
|
|
->filesAtQrcPath(path, &locale, nullptr, ModelManagerInterface::ActiveQrcResources);
|
2013-11-11 22:20:47 +02:00
|
|
|
if (filePaths.isEmpty())
|
2013-05-21 11:35:15 +02:00
|
|
|
filePaths = ModelManagerInterface::instance()->filesAtQrcPath(path);
|
|
|
|
|
if (!filePaths.isEmpty()) {
|
2019-10-22 17:54:14 +02:00
|
|
|
if (Document::Ptr importedDoc = m_snapshot.document(filePaths.at(0)))
|
2013-05-21 11:35:15 +02:00
|
|
|
import.object = importedDoc->bind()->rootObjectValue();
|
|
|
|
|
}
|
2013-10-16 14:59:28 +02:00
|
|
|
} else if (importInfo.type() == ImportType::QrcDirectory){
|
2019-10-22 17:54:14 +02:00
|
|
|
import.object = new ObjectValue(m_valueOwner);
|
2013-05-21 11:35:15 +02:00
|
|
|
|
2020-05-10 15:57:22 +02:00
|
|
|
importLibrary(doc, path, &import, import.object);
|
2010-02-02 15:55:17 +01:00
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
const QMap<QString, QStringList> paths
|
|
|
|
|
= ModelManagerInterface::instance()->filesInQrcPath(path);
|
2019-07-24 13:43:54 +02:00
|
|
|
for (auto iter = paths.cbegin(), end = paths.cend(); iter != end; ++iter) {
|
2014-07-22 19:06:44 +02:00
|
|
|
if (ModelManagerInterface::guessLanguageOfFile(iter.key()).isQmlLikeLanguage()) {
|
2019-10-22 17:54:14 +02:00
|
|
|
Document::Ptr importedDoc = m_snapshot.document(iter.value().at(0));
|
2013-05-21 11:35:15 +02:00
|
|
|
if (importedDoc && importedDoc->bind()->rootObjectValue()) {
|
|
|
|
|
const QString targetName = QFileInfo(iter.key()).baseName();
|
|
|
|
|
import.object->setMember(targetName, importedDoc->bind()->rootObjectValue());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-16 15:29:37 +02:00
|
|
|
return import;
|
2010-03-25 14:47:28 +01:00
|
|
|
}
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
static ModuleApiInfo findBestModuleApi(const QList<ModuleApiInfo> &apis,
|
|
|
|
|
const ComponentVersion &version)
|
2011-10-12 08:36:02 +02:00
|
|
|
{
|
|
|
|
|
ModuleApiInfo best;
|
2019-10-22 17:54:14 +02:00
|
|
|
for (const ModuleApiInfo &moduleApi : apis) {
|
2011-10-12 08:36:02 +02:00
|
|
|
if (moduleApi.version <= version
|
|
|
|
|
&& (!best.version.isValid() || best.version < moduleApi.version)) {
|
|
|
|
|
best = moduleApi;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return best;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-02 15:55:17 +01:00
|
|
|
/*
|
|
|
|
|
import Qt 4.6
|
|
|
|
|
import Qt 4.6 as Xxx
|
|
|
|
|
*/
|
2019-10-22 17:54:14 +02:00
|
|
|
Import LinkPrivate::importNonFile(const Document::Ptr &doc, const ImportInfo &importInfo)
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
2011-05-27 10:43:06 +02:00
|
|
|
Import import;
|
2011-05-12 15:29:00 +02:00
|
|
|
import.info = importInfo;
|
2019-10-22 17:54:14 +02:00
|
|
|
import.object = new ObjectValue(m_valueOwner);
|
2011-09-29 11:48:13 +02:00
|
|
|
import.valid = true;
|
2011-05-12 15:29:00 +02:00
|
|
|
|
2011-09-21 12:42:27 +02:00
|
|
|
const QString packageName = importInfo.name();
|
2010-09-16 15:29:37 +02:00
|
|
|
const ComponentVersion version = importInfo.version();
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
QString libraryPath = modulePath(packageName, version.toString(), m_importPaths);
|
2020-05-10 15:57:22 +02:00
|
|
|
bool importFound = !libraryPath.isEmpty() && importLibrary(doc, libraryPath, &import, import.object);
|
2010-06-09 14:27:30 +02:00
|
|
|
|
2019-10-22 16:29:40 +02:00
|
|
|
if (!importFound) {
|
|
|
|
|
for (const QString &dir : qAsConst(m_applicationDirectories)) {
|
2020-03-26 12:17:03 +01:00
|
|
|
QDirIterator it(dir, QStringList { "*.qmltypes" }, QDir::Files);
|
|
|
|
|
|
2019-10-22 16:29:40 +02:00
|
|
|
// This adds the types to the C++ types, to be found below if applicable.
|
2020-03-26 12:17:03 +01:00
|
|
|
if (it.hasNext())
|
2020-05-10 15:57:22 +02:00
|
|
|
importLibrary(doc, dir, &import, import.object);
|
2019-10-22 16:29:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
// if there are cpp-based types for this package, use them too
|
2019-10-22 17:54:14 +02:00
|
|
|
if (m_valueOwner->cppQmlTypes().hasModule(packageName)) {
|
2010-06-09 14:27:30 +02:00
|
|
|
importFound = true;
|
2019-10-22 17:54:14 +02:00
|
|
|
const auto objects = m_valueOwner->cppQmlTypes().createObjectsForImport(packageName,
|
|
|
|
|
version);
|
|
|
|
|
for (const CppComponentValue *object : objects)
|
2011-05-24 11:50:10 +02:00
|
|
|
import.object->setMember(object->className(), object);
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
2010-03-25 14:47:28 +01:00
|
|
|
|
2011-10-12 08:36:02 +02:00
|
|
|
// check module apis that previous imports may have enabled
|
|
|
|
|
ModuleApiInfo moduleApi = findBestModuleApi(importableModuleApis.value(packageName), version);
|
|
|
|
|
if (moduleApi.version.isValid()) {
|
|
|
|
|
importFound = true;
|
2019-10-22 17:54:14 +02:00
|
|
|
import.object->setPrototype(m_valueOwner->cppQmlTypes().objectByCppName(moduleApi.cppName));
|
2011-10-12 08:36:02 +02:00
|
|
|
}
|
|
|
|
|
|
2018-02-27 13:13:51 +01:00
|
|
|
// TODO: at the moment there is not any types information on Qbs imports.
|
2019-01-07 09:40:10 +01:00
|
|
|
if (doc->language() == Dialect::QmlQbs)
|
|
|
|
|
importFound = true;
|
2018-02-27 13:13:51 +01:00
|
|
|
|
2011-04-06 09:19:46 +02:00
|
|
|
if (!importFound && importInfo.ast()) {
|
2011-09-29 11:48:13 +02:00
|
|
|
import.valid = false;
|
2010-09-16 15:29:37 +02:00
|
|
|
error(doc, locationFromRange(importInfo.ast()->firstSourceLocation(),
|
|
|
|
|
importInfo.ast()->lastSourceLocation()),
|
2011-09-13 13:32:29 +02:00
|
|
|
Link::tr(
|
2016-11-01 15:23:02 +01:00
|
|
|
"QML module not found (%1).\n\n"
|
2011-09-13 13:32:29 +02:00
|
|
|
"Import paths:\n"
|
2016-10-05 12:12:16 +02:00
|
|
|
"%2\n\n"
|
2011-09-13 13:32:29 +02:00
|
|
|
"For qmake projects, use the QML_IMPORT_PATH variable to add import paths.\n"
|
2015-10-23 15:09:08 +02:00
|
|
|
"For Qbs projects, declare and set a qmlImportPaths property in your product "
|
2015-08-04 15:52:22 +02:00
|
|
|
"to add import paths.\n"
|
2016-04-18 13:06:41 +02:00
|
|
|
"For qmlproject projects, use the importPaths property to add import paths.\n"
|
2019-10-22 17:54:14 +02:00
|
|
|
"For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.\n")
|
|
|
|
|
.arg(importInfo.name(), m_importPaths.join(QLatin1Char('\n'))));
|
2010-06-09 14:27:30 +02:00
|
|
|
}
|
2010-09-16 15:29:37 +02:00
|
|
|
|
|
|
|
|
return import;
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
bool LinkPrivate::importLibrary(const Document::Ptr &doc,
|
|
|
|
|
const QString &libraryPath,
|
|
|
|
|
Import *import,
|
2020-05-10 15:57:22 +02:00
|
|
|
ObjectValue *targetObject,
|
2020-11-26 07:32:29 +01:00
|
|
|
const QString &importPath,
|
|
|
|
|
bool optional
|
|
|
|
|
)
|
2011-03-10 14:49:38 +01:00
|
|
|
{
|
2011-05-12 15:29:00 +02:00
|
|
|
const ImportInfo &importInfo = import->info;
|
2014-09-02 14:42:51 +02:00
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
LibraryInfo libraryInfo = m_snapshot.libraryInfo(libraryPath);
|
2016-06-28 12:49:35 +02:00
|
|
|
if (!libraryInfo.isValid())
|
|
|
|
|
return false;
|
2011-03-10 14:49:38 +01:00
|
|
|
|
2011-05-12 15:29:00 +02:00
|
|
|
import->libraryPath = libraryPath;
|
|
|
|
|
|
2011-03-10 14:49:38 +01:00
|
|
|
const ComponentVersion version = importInfo.version();
|
|
|
|
|
SourceLocation errorLoc;
|
2011-09-27 15:12:22 +02:00
|
|
|
if (const UiImport *ast = importInfo.ast())
|
2011-03-10 14:49:38 +01:00
|
|
|
errorLoc = locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation());
|
|
|
|
|
|
2020-05-10 15:57:22 +02:00
|
|
|
// Load imports that are mentioned by the "import" command in a qmldir
|
|
|
|
|
// file into the same targetObject, using the same version and "as".
|
|
|
|
|
//
|
|
|
|
|
// Note: Since this works on the same targetObject, the ModuleApi setPrototype()
|
|
|
|
|
// logic will not work. But ModuleApi isn't used in Qt versions that use import
|
|
|
|
|
// commands in qmldir files, and is pending removal in Qt 6.
|
2020-11-26 07:32:29 +01:00
|
|
|
for (const auto &toImport : libraryInfo.imports()) {
|
|
|
|
|
QString importName = toImport.module;
|
|
|
|
|
ComponentVersion vNow = toImport.version;
|
|
|
|
|
// there was a period in which no version == auto, should we add || !vNow.isValid() to the if?
|
|
|
|
|
if (toImport.flags & QmlDirParser::Import::Auto)
|
|
|
|
|
vNow = version;
|
2020-05-10 15:57:22 +02:00
|
|
|
Import subImport;
|
|
|
|
|
subImport.valid = true;
|
2020-11-26 07:32:29 +01:00
|
|
|
subImport.info = ImportInfo::moduleImport(importName, vNow, importInfo.as(), importInfo.ast());
|
|
|
|
|
subImport.libraryPath = modulePath(importName, vNow.toString(), m_importPaths);
|
|
|
|
|
bool subImportFound = importLibrary(doc, subImport.libraryPath, &subImport, targetObject, importPath, true);
|
2020-05-10 15:57:22 +02:00
|
|
|
|
|
|
|
|
if (!subImportFound && errorLoc.isValid()) {
|
|
|
|
|
import->valid = false;
|
2020-11-26 13:56:14 +01:00
|
|
|
if (toImport.flags & QmlDirParser::Import::Optional)
|
2020-11-26 07:32:29 +01:00
|
|
|
error(doc, errorLoc,
|
|
|
|
|
Link::tr(
|
|
|
|
|
"Implicit import '%1' of QML module '%2' not found.\n\n"
|
2020-05-10 15:57:22 +02:00
|
|
|
"Import paths:\n"
|
|
|
|
|
"%3\n\n"
|
|
|
|
|
"For qmake projects, use the QML_IMPORT_PATH variable to add import paths.\n"
|
|
|
|
|
"For Qbs projects, declare and set a qmlImportPaths property in your product "
|
|
|
|
|
"to add import paths.\n"
|
|
|
|
|
"For qmlproject projects, use the importPaths property to add import paths.\n"
|
|
|
|
|
"For CMake projects, make sure QML_IMPORT_PATH variable is in CMakeCache.txt.\n")
|
|
|
|
|
.arg(importName, importInfo.name(), m_importPaths.join(QLatin1Char('\n'))));
|
|
|
|
|
} else if (!subImport.valid) {
|
|
|
|
|
import->valid = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load types from qmltypes or plugins
|
2015-01-22 15:00:34 +01:00
|
|
|
if (!libraryInfo.plugins().isEmpty() || !libraryInfo.typeInfos().isEmpty()) {
|
2011-05-12 15:29:00 +02:00
|
|
|
if (libraryInfo.pluginTypeInfoStatus() == LibraryInfo::NoTypeInfo) {
|
2011-03-10 14:49:38 +01:00
|
|
|
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
|
|
|
|
|
if (modelManager) {
|
2013-10-16 14:59:28 +02:00
|
|
|
if (importInfo.type() == ImportType::Library) {
|
2011-09-21 12:42:27 +02:00
|
|
|
if (version.isValid()) {
|
|
|
|
|
const QString uri = importInfo.name();
|
2011-03-16 15:34:50 +01:00
|
|
|
modelManager->loadPluginTypes(
|
|
|
|
|
libraryPath, importPath,
|
|
|
|
|
uri, version.toString());
|
|
|
|
|
}
|
2011-03-10 14:49:38 +01:00
|
|
|
} else {
|
|
|
|
|
modelManager->loadPluginTypes(
|
|
|
|
|
libraryPath, libraryPath,
|
|
|
|
|
QString(), version.toString());
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-26 07:32:29 +01:00
|
|
|
if (!optional && errorLoc.isValid()) {
|
2019-10-22 17:54:14 +02:00
|
|
|
appendDiagnostic(doc, DiagnosticMessage(
|
|
|
|
|
Severity::ReadingTypeInfoWarning, errorLoc,
|
|
|
|
|
Link::tr("QML module contains C++ plugins, "
|
2020-11-26 07:32:29 +01:00
|
|
|
"currently reading type information... %1").arg(import->info.name())));
|
2011-09-29 11:48:13 +02:00
|
|
|
import->valid = false;
|
2011-03-10 14:49:38 +01:00
|
|
|
}
|
2011-05-12 15:29:00 +02:00
|
|
|
} else if (libraryInfo.pluginTypeInfoStatus() == LibraryInfo::DumpError
|
|
|
|
|
|| libraryInfo.pluginTypeInfoStatus() == LibraryInfo::TypeInfoFileError) {
|
2011-06-28 12:01:56 +02:00
|
|
|
// Only underline import if package isn't described in .qmltypes anyway
|
2014-11-24 19:51:58 +01:00
|
|
|
// and is not a private package
|
2011-09-21 12:42:27 +02:00
|
|
|
QString packageName = importInfo.name();
|
2020-11-26 07:32:29 +01:00
|
|
|
if (!optional && errorLoc.isValid()
|
2019-10-22 17:54:14 +02:00
|
|
|
&& (packageName.isEmpty()
|
|
|
|
|
|| !m_valueOwner->cppQmlTypes().hasModule(packageName))
|
2014-11-24 19:51:58 +01:00
|
|
|
&& !packageName.endsWith(QLatin1String("private"), Qt::CaseInsensitive)) {
|
2011-06-28 12:01:56 +02:00
|
|
|
error(doc, errorLoc, libraryInfo.pluginTypeInfoError());
|
2011-09-29 11:48:13 +02:00
|
|
|
import->valid = false;
|
2011-03-10 14:49:38 +01:00
|
|
|
}
|
2011-09-21 12:42:27 +02:00
|
|
|
} else {
|
|
|
|
|
const QString packageName = importInfo.name();
|
2019-10-22 17:54:14 +02:00
|
|
|
m_valueOwner->cppQmlTypes().load(libraryPath, libraryInfo.metaObjects(), packageName);
|
|
|
|
|
const auto objects = m_valueOwner->cppQmlTypes().createObjectsForImport(packageName,
|
|
|
|
|
version);
|
|
|
|
|
for (const CppComponentValue *object : objects)
|
2020-05-10 15:57:22 +02:00
|
|
|
targetObject->setMember(object->className(), object);
|
2011-10-12 08:36:02 +02:00
|
|
|
|
|
|
|
|
// all but no-uri module apis become available for import
|
|
|
|
|
QList<ModuleApiInfo> noUriModuleApis;
|
2019-10-22 17:54:14 +02:00
|
|
|
const auto moduleApis = libraryInfo.moduleApis();
|
|
|
|
|
for (const ModuleApiInfo &moduleApi : moduleApis) {
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (moduleApi.uri.isEmpty())
|
2011-10-12 08:36:02 +02:00
|
|
|
noUriModuleApis += moduleApi;
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
else
|
2011-10-12 08:36:02 +02:00
|
|
|
importableModuleApis[moduleApi.uri] += moduleApi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if a module api has no uri, it shares the same name
|
|
|
|
|
ModuleApiInfo sameUriModuleApi = findBestModuleApi(noUriModuleApis, version);
|
2019-10-22 17:54:14 +02:00
|
|
|
if (sameUriModuleApi.version.isValid()) {
|
2020-05-10 15:57:22 +02:00
|
|
|
targetObject->setPrototype(m_valueOwner->cppQmlTypes()
|
2019-10-22 17:54:14 +02:00
|
|
|
.objectByCppName(sameUriModuleApi.cppName));
|
|
|
|
|
}
|
2011-03-10 14:49:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 15:57:22 +02:00
|
|
|
// Load types that are mentioned explicitly in the qmldir
|
|
|
|
|
loadQmldirComponents(targetObject, version, libraryInfo, libraryPath);
|
2011-03-10 14:49:38 +01:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-28 17:51:32 +01:00
|
|
|
void LinkPrivate::error(const Document::Ptr &doc, const SourceLocation &loc,
|
2019-10-22 17:54:14 +02:00
|
|
|
const QString &message)
|
2010-03-29 11:32:11 +02:00
|
|
|
{
|
2013-10-16 14:59:28 +02:00
|
|
|
appendDiagnostic(doc, DiagnosticMessage(Severity::Error, loc, message));
|
2010-03-29 11:32:11 +02:00
|
|
|
}
|
2010-11-24 09:30:46 +01:00
|
|
|
|
2020-02-28 17:51:32 +01:00
|
|
|
void LinkPrivate::warning(const Document::Ptr &doc, const SourceLocation &loc,
|
2019-10-22 17:54:14 +02:00
|
|
|
const QString &message)
|
2011-04-21 11:09:29 +02:00
|
|
|
{
|
2013-10-16 14:59:28 +02:00
|
|
|
appendDiagnostic(doc, DiagnosticMessage(Severity::Warning, loc, message));
|
2011-04-21 11:09:29 +02:00
|
|
|
}
|
|
|
|
|
|
2011-09-13 13:32:29 +02:00
|
|
|
void LinkPrivate::appendDiagnostic(const Document::Ptr &doc, const DiagnosticMessage &message)
|
2010-11-24 09:30:46 +01:00
|
|
|
{
|
2011-09-13 13:32:29 +02:00
|
|
|
if (diagnosticMessages && doc->fileName() == document->fileName())
|
|
|
|
|
diagnosticMessages->append(message);
|
|
|
|
|
if (allDiagnosticMessages)
|
|
|
|
|
(*allDiagnosticMessages)[doc->fileName()].append(message);
|
2010-11-24 09:30:46 +01:00
|
|
|
}
|
2011-02-25 16:16:37 +01:00
|
|
|
|
2011-09-13 13:32:29 +02:00
|
|
|
void LinkPrivate::loadQmldirComponents(ObjectValue *import, ComponentVersion version,
|
2011-02-25 16:16:37 +01:00
|
|
|
const LibraryInfo &libraryInfo, const QString &libraryPath)
|
|
|
|
|
{
|
2011-03-10 14:49:38 +01:00
|
|
|
// if the version isn't valid, import the latest
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (!version.isValid())
|
2011-05-27 14:51:30 +02:00
|
|
|
version = ComponentVersion(ComponentVersion::MaxVersion, ComponentVersion::MaxVersion);
|
2011-03-10 14:49:38 +01:00
|
|
|
|
|
|
|
|
|
2011-02-25 16:16:37 +01:00
|
|
|
QSet<QString> importedTypes;
|
2019-10-22 17:54:14 +02:00
|
|
|
const auto components = libraryInfo.components();
|
|
|
|
|
for (const QmlDirParser::Component &component : components) {
|
2011-02-25 16:16:37 +01:00
|
|
|
if (importedTypes.contains(component.typeName))
|
|
|
|
|
continue;
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
ComponentVersion componentVersion(component.majorVersion, component.minorVersion);
|
2011-02-25 16:16:37 +01:00
|
|
|
if (version < componentVersion)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
importedTypes.insert(component.typeName);
|
2019-10-22 17:54:14 +02:00
|
|
|
if (Document::Ptr importedDoc = m_snapshot.document(
|
2014-09-02 14:40:41 +02:00
|
|
|
libraryPath + QLatin1Char('/') + component.fileName)) {
|
2011-02-25 16:16:37 +01:00
|
|
|
if (ObjectValue *v = importedDoc->bind()->rootObjectValue())
|
2011-05-24 11:50:10 +02:00
|
|
|
import->setMember(component.typeName, v);
|
2011-02-25 16:16:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 17:54:14 +02:00
|
|
|
void LinkPrivate::loadImplicitDirectoryImports(Imports *imports, const Document::Ptr &doc)
|
2011-02-25 16:16:37 +01:00
|
|
|
{
|
2016-03-18 17:43:33 +01:00
|
|
|
auto processImport = [this, imports, doc](const ImportInfo &importInfo){
|
|
|
|
|
Import directoryImport = importCache.value(ImportCacheKey(importInfo));
|
|
|
|
|
if (!directoryImport.object) {
|
|
|
|
|
directoryImport = importFileOrDirectory(doc, importInfo);
|
|
|
|
|
if (directoryImport.object)
|
|
|
|
|
importCache.insert(ImportCacheKey(importInfo), directoryImport);
|
|
|
|
|
}
|
2011-05-12 15:29:00 +02:00
|
|
|
if (directoryImport.object)
|
2016-03-18 17:43:33 +01:00
|
|
|
imports->append(directoryImport);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
processImport(ImportInfo::implicitDirectoryImport(doc->path()));
|
2019-10-22 17:54:14 +02:00
|
|
|
const auto qrcPaths = ModelManagerInterface::instance()->qrcPathsForFile(doc->fileName());
|
|
|
|
|
for (const QString &path : qrcPaths) {
|
2016-03-18 17:43:33 +01:00
|
|
|
processImport(ImportInfo::qrcDirectoryImport(
|
2019-02-07 17:22:39 +01:00
|
|
|
Utils::QrcParser::qrcDirectoryPathForQrcFilePath(path)));
|
2011-02-25 16:16:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-13 13:32:29 +02:00
|
|
|
void LinkPrivate::loadImplicitDefaultImports(Imports *imports)
|
2011-02-25 16:16:37 +01:00
|
|
|
{
|
|
|
|
|
const QString defaultPackage = CppQmlTypes::defaultPackage;
|
2019-10-22 17:54:14 +02:00
|
|
|
if (m_valueOwner->cppQmlTypes().hasModule(defaultPackage)) {
|
|
|
|
|
const ComponentVersion maxVersion(ComponentVersion::MaxVersion,
|
|
|
|
|
ComponentVersion::MaxVersion);
|
2011-09-27 15:12:22 +02:00
|
|
|
const ImportInfo info = ImportInfo::moduleImport(defaultPackage, maxVersion, QString());
|
2011-09-13 13:32:29 +02:00
|
|
|
Import import = importCache.value(ImportCacheKey(info));
|
2011-05-12 15:29:00 +02:00
|
|
|
if (!import.object) {
|
2011-09-29 11:48:13 +02:00
|
|
|
import.valid = true;
|
2011-05-12 15:29:00 +02:00
|
|
|
import.info = info;
|
2019-10-22 17:54:14 +02:00
|
|
|
import.object = new ObjectValue(m_valueOwner, QLatin1String("<defaults>"));
|
|
|
|
|
|
|
|
|
|
const auto objects = m_valueOwner->cppQmlTypes().createObjectsForImport(defaultPackage,
|
|
|
|
|
maxVersion);
|
|
|
|
|
for (const CppComponentValue *object : objects)
|
2011-05-24 11:50:10 +02:00
|
|
|
import.object->setMember(object->className(), object);
|
2019-10-22 17:54:14 +02:00
|
|
|
|
2011-09-13 13:32:29 +02:00
|
|
|
importCache.insert(ImportCacheKey(info), import);
|
2011-02-25 16:16:37 +01:00
|
|
|
}
|
2011-05-27 10:43:06 +02:00
|
|
|
imports->append(import);
|
2011-02-25 16:16:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
2015-02-03 23:48:57 +02:00
|
|
|
|
|
|
|
|
} // namespace QmlJS
|