2010-07-09 15:47:07 +02:00
|
|
|
/**************************************************************************
|
|
|
|
**
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
**
|
2011-01-11 16:28:15 +01:00
|
|
|
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
2010-07-09 15:47:07 +02:00
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** Contact: Nokia Corporation (info@qt.nokia.com)
|
2010-07-09 15:47:07 +02:00
|
|
|
**
|
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
|
|
** Please review the following information to ensure the GNU Lesser General
|
|
|
|
** Public License version 2.1 requirements will be met:
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2010-07-09 15:47:07 +02:00
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
2011-04-13 08:42:33 +02:00
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** Other Usage
|
|
|
|
**
|
|
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** If you have questions regarding the use of this file, please contact
|
2011-05-06 15:05:37 +02:00
|
|
|
** Nokia at info@qt.nokia.com.
|
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"
|
2010-09-16 15:29:37 +02:00
|
|
|
#include "qmljscheck.h"
|
2010-08-25 14:15:57 +02:00
|
|
|
#include "qmljsmodelmanagerinterface.h"
|
2010-01-28 14:53:53 +01:00
|
|
|
|
|
|
|
#include <QtCore/QFileInfo>
|
|
|
|
#include <QtCore/QDir>
|
|
|
|
#include <QtCore/QDebug>
|
|
|
|
|
2010-12-03 11:17:25 +01:00
|
|
|
using namespace LanguageUtils;
|
2010-01-28 14:53:53 +01:00
|
|
|
using namespace QmlJS;
|
|
|
|
using namespace QmlJS::Interpreter;
|
|
|
|
using namespace QmlJS::AST;
|
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
namespace {
|
|
|
|
class ImportCacheKey
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit ImportCacheKey(const Interpreter::ImportInfo &info)
|
|
|
|
: type(info.type())
|
|
|
|
, name(info.name())
|
|
|
|
, majorVersion(info.version().majorVersion())
|
|
|
|
, minorVersion(info.version().minorVersion())
|
|
|
|
{}
|
|
|
|
|
|
|
|
int type;
|
|
|
|
QString name;
|
|
|
|
int majorVersion;
|
|
|
|
int minorVersion;
|
|
|
|
};
|
|
|
|
|
|
|
|
uint qHash(const ImportCacheKey &info)
|
|
|
|
{
|
|
|
|
return ::qHash(info.type) ^ ::qHash(info.name) ^
|
|
|
|
::qHash(info.majorVersion) ^ ::qHash(info.minorVersion);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const ImportCacheKey &i1, const ImportCacheKey &i2)
|
|
|
|
{
|
|
|
|
return i1.type == i2.type
|
|
|
|
&& i1.name == i2.name
|
|
|
|
&& i1.majorVersion == i2.majorVersion
|
|
|
|
&& i1.minorVersion == i2.minorVersion;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class QmlJS::LinkPrivate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Snapshot snapshot;
|
|
|
|
Interpreter::Context *context;
|
|
|
|
QStringList importPaths;
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
QHash<ImportCacheKey, Import> importCache;
|
2010-09-16 15:29:37 +02:00
|
|
|
|
2011-04-21 11:09:29 +02:00
|
|
|
Document::Ptr doc;
|
|
|
|
QList<DiagnosticMessage> *diagnosticMessages;
|
|
|
|
|
|
|
|
QHash<QString, QList<DiagnosticMessage> > *allDiagnosticMessages;
|
2010-09-16 15:29:37 +02:00
|
|
|
};
|
|
|
|
|
2010-09-15 15:25:59 +02:00
|
|
|
/*!
|
|
|
|
\class QmlJS::Link
|
|
|
|
\brief Initializes the Context for a Document.
|
|
|
|
\sa QmlJS::Document QmlJS::Interpreter::Context
|
|
|
|
|
|
|
|
Initializes a context by resolving imports and building the root scope
|
|
|
|
chain. Currently, this is a expensive operation.
|
|
|
|
|
|
|
|
It's recommended to use a the \l{LookupContext} returned by
|
|
|
|
\l{QmlJSEditor::SemanticInfo::lookupContext()} instead of building a new
|
|
|
|
\l{Context} with \l{Link}.
|
|
|
|
*/
|
|
|
|
|
2011-05-06 13:31:30 +02:00
|
|
|
Link::Link(Context *context, const Snapshot &snapshot, const QStringList &importPaths)
|
2010-09-16 15:29:37 +02:00
|
|
|
: d_ptr(new LinkPrivate)
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
2010-09-16 15:29:37 +02:00
|
|
|
Q_D(Link);
|
|
|
|
d->context = context;
|
|
|
|
d->snapshot = snapshot;
|
|
|
|
d->importPaths = importPaths;
|
|
|
|
|
2011-04-21 11:09:29 +02:00
|
|
|
d->diagnosticMessages = 0;
|
2011-05-06 13:31:30 +02:00
|
|
|
d->allDiagnosticMessages = 0;
|
2011-04-21 11:09:29 +02:00
|
|
|
|
|
|
|
// populate engine with types from C++
|
|
|
|
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
|
|
|
|
if (modelManager) {
|
|
|
|
foreach (const QList<FakeMetaObject::ConstPtr> &cppTypes, modelManager->cppQmlTypes()) {
|
2011-07-01 12:11:02 +02:00
|
|
|
valueOwner()->cppQmlTypes().load(valueOwner(), cppTypes);
|
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-05-06 13:31:30 +02:00
|
|
|
void Link::operator()(QHash<QString, QList<DiagnosticMessage> > *messages)
|
|
|
|
{
|
|
|
|
Q_D(Link);
|
|
|
|
d->allDiagnosticMessages = messages;
|
2011-04-21 11:09:29 +02:00
|
|
|
linkImports();
|
|
|
|
}
|
|
|
|
|
2011-05-06 13:31:30 +02:00
|
|
|
void Link::operator()(const Document::Ptr &doc, QList<DiagnosticMessage> *messages)
|
2011-04-21 11:09:29 +02:00
|
|
|
{
|
|
|
|
Q_D(Link);
|
|
|
|
d->doc = doc;
|
|
|
|
d->diagnosticMessages = messages;
|
2010-02-02 15:55:17 +01:00
|
|
|
linkImports();
|
|
|
|
}
|
|
|
|
|
|
|
|
Link::~Link()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
Interpreter::ValueOwner *Link::valueOwner()
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
2010-09-16 15:29:37 +02:00
|
|
|
Q_D(Link);
|
2011-07-01 12:11:02 +02:00
|
|
|
return d->context->valueOwner();
|
2010-02-03 10:59:52 +01:00
|
|
|
}
|
2010-02-02 15:55:17 +01:00
|
|
|
|
|
|
|
void Link::linkImports()
|
|
|
|
{
|
2010-09-16 15:29:37 +02:00
|
|
|
Q_D(Link);
|
2010-02-02 15:55:17 +01:00
|
|
|
|
2011-04-21 11:09:29 +02:00
|
|
|
if (d->doc) {
|
|
|
|
// do it on d->doc first, to make sure import errors are shown
|
2011-07-01 12:11:02 +02:00
|
|
|
Imports *imports = new Imports(valueOwner());
|
2011-05-27 10:43:06 +02:00
|
|
|
populateImportedTypes(imports, d->doc);
|
|
|
|
d->context->setImports(d->doc.data(), imports);
|
2011-04-21 11:09:29 +02:00
|
|
|
}
|
2010-02-04 09:44:43 +01:00
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
foreach (Document::Ptr doc, d->snapshot) {
|
|
|
|
if (doc == d->doc)
|
|
|
|
continue;
|
|
|
|
|
2011-07-01 12:11:02 +02:00
|
|
|
Imports *imports = new Imports(valueOwner());
|
2011-05-27 10:43:06 +02:00
|
|
|
populateImportedTypes(imports, doc);
|
|
|
|
d->context->setImports(doc.data(), imports);
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
void Link::populateImportedTypes(Imports *imports, Document::Ptr doc)
|
2010-01-28 14:53:53 +01:00
|
|
|
{
|
2010-09-16 15:29:37 +02:00
|
|
|
Q_D(Link);
|
|
|
|
|
2010-12-03 10:13:15 +01:00
|
|
|
if (! doc->qmlProgram())
|
2010-01-28 14:53:53 +01:00
|
|
|
return;
|
|
|
|
|
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-05-27 10:43:06 +02:00
|
|
|
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
|
|
|
|
foreach (const ImportInfo &info, doc->bind()->imports()) {
|
2011-05-27 10:43:06 +02:00
|
|
|
Import import = d->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()) {
|
|
|
|
case ImportInfo::FileImport:
|
|
|
|
case ImportInfo::DirectoryImport:
|
2011-03-10 14:49:38 +01:00
|
|
|
import = importFileOrDirectory(doc, info);
|
2010-09-16 15:29:37 +02:00
|
|
|
break;
|
|
|
|
case ImportInfo::LibraryImport:
|
|
|
|
import = importNonFile(doc, info);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2011-05-12 15:29:00 +02:00
|
|
|
if (import.object)
|
2010-09-16 15:29:37 +02:00
|
|
|
d->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
|
|
|
}
|
|
|
|
}
|
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
|
|
|
*/
|
2011-05-27 10:43:06 +02:00
|
|
|
Import Link::importFileOrDirectory(Document::Ptr doc, const ImportInfo &importInfo)
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
2010-09-16 15:29:37 +02:00
|
|
|
Q_D(Link);
|
2010-01-28 14:53:53 +01:00
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
Import import;
|
2011-05-12 15:29:00 +02:00
|
|
|
import.info = importInfo;
|
|
|
|
import.object = 0;
|
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
const QString &path = importInfo.name();
|
2010-01-29 13:36:07 +01:00
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
if (importInfo.type() == ImportInfo::DirectoryImport
|
|
|
|
|| importInfo.type() == ImportInfo::ImplicitDirectoryImport) {
|
2011-07-01 12:11:02 +02:00
|
|
|
import.object = new ObjectValue(valueOwner());
|
2011-03-10 14:49:38 +01:00
|
|
|
|
2011-05-12 15:29:00 +02:00
|
|
|
importLibrary(doc, path, &import);
|
2011-03-10 14:49:38 +01:00
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
const QList<Document::Ptr> &documentsInDirectory = d->snapshot.documentsInDirectory(path);
|
2010-04-01 11:27:49 +02:00
|
|
|
foreach (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
|
|
|
}
|
2010-09-16 15:29:37 +02:00
|
|
|
} else if (importInfo.type() == ImportInfo::FileImport) {
|
|
|
|
Document::Ptr importedDoc = d->snapshot.document(path);
|
2010-09-24 09:49:35 +02:00
|
|
|
if (importedDoc)
|
2011-05-12 15:29:00 +02:00
|
|
|
import.object = importedDoc->bind()->rootObjectValue();
|
2010-03-16 16:34:33 +01:00
|
|
|
}
|
2010-02-02 15:55:17 +01:00
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
return import;
|
2010-03-25 14:47:28 +01:00
|
|
|
}
|
|
|
|
|
2010-02-02 15:55:17 +01:00
|
|
|
/*
|
|
|
|
import Qt 4.6
|
|
|
|
import Qt 4.6 as Xxx
|
|
|
|
(import com.nokia.qt is the same as the ones above)
|
|
|
|
*/
|
2011-05-27 10:43:06 +02:00
|
|
|
Import Link::importNonFile(Document::Ptr doc, const ImportInfo &importInfo)
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
2010-09-16 15:29:37 +02:00
|
|
|
Q_D(Link);
|
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;
|
2011-07-01 12:11:02 +02:00
|
|
|
import.object = new ObjectValue(valueOwner());
|
2011-05-12 15:29:00 +02:00
|
|
|
|
2011-05-11 09:11:43 +02:00
|
|
|
const QString packageName = Bind::toString(importInfo.ast()->importUri, '.');
|
2010-09-16 15:29:37 +02:00
|
|
|
const ComponentVersion version = importInfo.version();
|
2010-03-01 13:01:05 +01:00
|
|
|
|
2010-06-09 14:27:30 +02:00
|
|
|
bool importFound = false;
|
2010-03-16 16:34:33 +01:00
|
|
|
|
2010-09-16 15:29:37 +02:00
|
|
|
const QString &packagePath = importInfo.name();
|
2011-05-27 14:51:30 +02:00
|
|
|
// check the filesystem with full version
|
2010-09-16 15:29:37 +02:00
|
|
|
foreach (const QString &importPath, d->importPaths) {
|
2011-05-27 14:51:30 +02:00
|
|
|
QString libraryPath = QString("%1/%2.%3").arg(importPath, packagePath, version.toString());
|
2011-05-12 15:29:00 +02:00
|
|
|
if (importLibrary(doc, libraryPath, &import, importPath)) {
|
2011-03-10 14:49:38 +01:00
|
|
|
importFound = true;
|
|
|
|
break;
|
2010-08-25 14:15:57 +02:00
|
|
|
}
|
2010-06-09 14:27:30 +02:00
|
|
|
}
|
2011-05-27 14:51:30 +02:00
|
|
|
if (!importFound) {
|
|
|
|
// check the filesystem with major version
|
|
|
|
foreach (const QString &importPath, d->importPaths) {
|
|
|
|
QString libraryPath = QString("%1/%2.%3").arg(importPath, packagePath,
|
|
|
|
QString::number(version.majorVersion()));
|
|
|
|
if (importLibrary(doc, libraryPath, &import, importPath)) {
|
|
|
|
importFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!importFound) {
|
|
|
|
// check the filesystem with no version
|
|
|
|
foreach (const QString &importPath, d->importPaths) {
|
|
|
|
QString libraryPath = QString("%1/%2").arg(importPath, packagePath);
|
|
|
|
if (importLibrary(doc, libraryPath, &import, importPath)) {
|
|
|
|
importFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-06-09 14:27:30 +02:00
|
|
|
|
|
|
|
// if there are cpp-based types for this package, use them too
|
2011-07-01 12:11:02 +02:00
|
|
|
if (valueOwner()->cppQmlTypes().hasPackage(packageName)) {
|
2010-06-09 14:27:30 +02:00
|
|
|
importFound = true;
|
2010-09-16 15:29:37 +02:00
|
|
|
foreach (QmlObjectValue *object,
|
2011-07-01 12:11:02 +02:00
|
|
|
valueOwner()->cppQmlTypes().typesForImport(packageName, version)) {
|
2011-05-24 11:50:10 +02:00
|
|
|
import.object->setMember(object->className(), object);
|
2010-03-16 16:34:33 +01:00
|
|
|
}
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
2010-03-25 14:47:28 +01:00
|
|
|
|
2011-04-06 09:19:46 +02:00
|
|
|
if (!importFound && importInfo.ast()) {
|
2010-09-16 15:29:37 +02:00
|
|
|
error(doc, locationFromRange(importInfo.ast()->firstSourceLocation(),
|
|
|
|
importInfo.ast()->lastSourceLocation()),
|
2010-06-09 14:27:30 +02:00
|
|
|
tr("package not found"));
|
|
|
|
}
|
2010-09-16 15:29:37 +02:00
|
|
|
|
|
|
|
return import;
|
2010-02-02 15:55:17 +01:00
|
|
|
}
|
|
|
|
|
2011-05-12 15:29:00 +02:00
|
|
|
bool Link::importLibrary(Document::Ptr doc,
|
2011-03-10 14:49:38 +01:00
|
|
|
const QString &libraryPath,
|
2011-05-27 10:43:06 +02:00
|
|
|
Import *import,
|
2011-03-10 14:49:38 +01:00
|
|
|
const QString &importPath)
|
|
|
|
{
|
|
|
|
Q_D(Link);
|
|
|
|
|
2011-05-12 15:29:00 +02:00
|
|
|
const ImportInfo &importInfo = import->info;
|
|
|
|
|
2011-03-10 14:49:38 +01:00
|
|
|
const LibraryInfo libraryInfo = d->snapshot.libraryInfo(libraryPath);
|
|
|
|
if (!libraryInfo.isValid())
|
|
|
|
return false;
|
|
|
|
|
2011-05-12 15:29:00 +02:00
|
|
|
import->libraryPath = libraryPath;
|
|
|
|
|
2011-03-10 14:49:38 +01:00
|
|
|
const ComponentVersion version = importInfo.version();
|
|
|
|
const UiImport *ast = importInfo.ast();
|
|
|
|
SourceLocation errorLoc;
|
|
|
|
if (ast)
|
|
|
|
errorLoc = locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation());
|
|
|
|
|
|
|
|
if (!libraryInfo.plugins().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) {
|
|
|
|
if (importInfo.type() == ImportInfo::LibraryImport) {
|
2011-03-16 15:34:50 +01:00
|
|
|
if (importInfo.version().isValid()) {
|
|
|
|
const QString uri = importInfo.name().replace(QDir::separator(), QLatin1Char('.'));
|
|
|
|
modelManager->loadPluginTypes(
|
|
|
|
libraryPath, importPath,
|
|
|
|
uri, version.toString());
|
|
|
|
}
|
2011-03-10 14:49:38 +01:00
|
|
|
} else {
|
|
|
|
modelManager->loadPluginTypes(
|
|
|
|
libraryPath, libraryPath,
|
|
|
|
QString(), version.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (errorLoc.isValid()) {
|
|
|
|
warning(doc, errorLoc,
|
|
|
|
tr("Library contains C++ plugins, type dump is in progress."));
|
|
|
|
}
|
2011-05-12 15:29:00 +02:00
|
|
|
} else if (libraryInfo.pluginTypeInfoStatus() == LibraryInfo::DumpError
|
|
|
|
|| libraryInfo.pluginTypeInfoStatus() == LibraryInfo::TypeInfoFileError) {
|
2011-04-12 09:14:31 +02:00
|
|
|
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
|
|
|
|
|
|
|
|
// Only underline import if package/version isn't described in .qmltypes anyway
|
|
|
|
const QmlJS::ModelManagerInterface::BuiltinPackagesHash builtinPackages
|
|
|
|
= modelManager->builtinPackages();
|
|
|
|
const QString packageName = importInfo.name().replace(QDir::separator(), QLatin1Char('.'));
|
|
|
|
if (!builtinPackages.value(packageName).contains(importInfo.version())) {
|
|
|
|
if (errorLoc.isValid()) {
|
2011-05-12 15:29:00 +02:00
|
|
|
error(doc, errorLoc, libraryInfo.pluginTypeInfoError());
|
2011-04-12 09:14:31 +02:00
|
|
|
}
|
2011-03-10 14:49:38 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
QList<QmlObjectValue *> loadedObjects =
|
2011-07-01 12:11:02 +02:00
|
|
|
valueOwner()->cppQmlTypes().load(valueOwner(), libraryInfo.metaObjects());
|
2011-03-10 14:49:38 +01:00
|
|
|
foreach (QmlObjectValue *object, loadedObjects) {
|
|
|
|
if (object->packageName().isEmpty()) {
|
2011-05-24 11:50:10 +02:00
|
|
|
import->object->setMember(object->className(), object);
|
2011-03-10 14:49:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-12 15:29:00 +02:00
|
|
|
loadQmldirComponents(import->object, version, libraryInfo, libraryPath);
|
2011-03-10 14:49:38 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-02-02 17:06:48 +01:00
|
|
|
UiQualifiedId *Link::qualifiedTypeNameId(Node *node)
|
|
|
|
{
|
|
|
|
if (UiObjectBinding *binding = AST::cast<UiObjectBinding *>(node))
|
|
|
|
return binding->qualifiedTypeNameId;
|
|
|
|
else if (UiObjectDefinition *binding = AST::cast<UiObjectDefinition *>(node))
|
|
|
|
return binding->qualifiedTypeNameId;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-29 11:32:11 +02:00
|
|
|
|
|
|
|
void Link::error(const Document::Ptr &doc, const AST::SourceLocation &loc, const QString &message)
|
|
|
|
{
|
2011-04-21 11:09:29 +02:00
|
|
|
appendDiagnostic(doc, DiagnosticMessage(DiagnosticMessage::Error, loc, message));
|
2010-03-29 11:32:11 +02:00
|
|
|
}
|
2010-11-24 09:30:46 +01:00
|
|
|
|
|
|
|
void Link::warning(const Document::Ptr &doc, const AST::SourceLocation &loc, const QString &message)
|
2011-04-21 11:09:29 +02:00
|
|
|
{
|
|
|
|
appendDiagnostic(doc, DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Link::appendDiagnostic(const Document::Ptr &doc, const DiagnosticMessage &message)
|
2010-11-24 09:30:46 +01:00
|
|
|
{
|
|
|
|
Q_D(Link);
|
|
|
|
|
2011-04-21 11:09:29 +02:00
|
|
|
if (d->diagnosticMessages && doc->fileName() == d->doc->fileName())
|
|
|
|
d->diagnosticMessages->append(message);
|
|
|
|
if (d->allDiagnosticMessages)
|
|
|
|
(*d->allDiagnosticMessages)[doc->fileName()].append(message);
|
2010-11-24 09:30:46 +01:00
|
|
|
}
|
2011-02-25 16:16:37 +01:00
|
|
|
|
|
|
|
void Link::loadQmldirComponents(Interpreter::ObjectValue *import, ComponentVersion version,
|
|
|
|
const LibraryInfo &libraryInfo, const QString &libraryPath)
|
|
|
|
{
|
|
|
|
Q_D(Link);
|
|
|
|
|
2011-03-10 14:49:38 +01:00
|
|
|
// if the version isn't valid, import the latest
|
|
|
|
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;
|
|
|
|
foreach (const QmlDirParser::Component &component, libraryInfo.components()) {
|
|
|
|
if (importedTypes.contains(component.typeName))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ComponentVersion componentVersion(component.majorVersion,
|
|
|
|
component.minorVersion);
|
|
|
|
if (version < componentVersion)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
importedTypes.insert(component.typeName);
|
|
|
|
if (Document::Ptr importedDoc = d->snapshot.document(
|
|
|
|
libraryPath + QDir::separator() + component.fileName)) {
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
void Link::loadImplicitDirectoryImports(Imports *imports, Document::Ptr doc)
|
2011-02-25 16:16:37 +01:00
|
|
|
{
|
|
|
|
Q_D(Link);
|
|
|
|
|
2011-03-10 14:49:38 +01:00
|
|
|
ImportInfo implcitDirectoryImportInfo(
|
|
|
|
ImportInfo::ImplicitDirectoryImport, doc->path());
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
Import directoryImport = d->importCache.value(ImportCacheKey(implcitDirectoryImportInfo));
|
2011-05-12 15:29:00 +02:00
|
|
|
if (!directoryImport.object) {
|
2011-03-10 14:49:38 +01:00
|
|
|
directoryImport = importFileOrDirectory(doc, implcitDirectoryImportInfo);
|
2011-05-12 15:29:00 +02:00
|
|
|
if (directoryImport.object)
|
2011-02-25 16:16:37 +01:00
|
|
|
d->importCache.insert(ImportCacheKey(implcitDirectoryImportInfo), directoryImport);
|
|
|
|
}
|
2011-05-12 15:29:00 +02:00
|
|
|
if (directoryImport.object) {
|
2011-05-27 10:43:06 +02:00
|
|
|
imports->append(directoryImport);
|
2011-05-12 15:29:00 +02:00
|
|
|
}
|
2011-02-25 16:16:37 +01:00
|
|
|
}
|
|
|
|
|
2011-05-27 10:43:06 +02:00
|
|
|
void Link::loadImplicitDefaultImports(Imports *imports)
|
2011-02-25 16:16:37 +01:00
|
|
|
{
|
|
|
|
Q_D(Link);
|
|
|
|
|
|
|
|
const QString defaultPackage = CppQmlTypes::defaultPackage;
|
2011-07-01 12:11:02 +02:00
|
|
|
if (valueOwner()->cppQmlTypes().hasPackage(defaultPackage)) {
|
2011-02-25 16:16:37 +01:00
|
|
|
ImportInfo info(ImportInfo::LibraryImport, defaultPackage);
|
2011-05-27 10:43:06 +02:00
|
|
|
Import import = d->importCache.value(ImportCacheKey(info));
|
2011-05-12 15:29:00 +02:00
|
|
|
if (!import.object) {
|
|
|
|
import.info = info;
|
2011-07-01 12:11:02 +02:00
|
|
|
import.object = new ObjectValue(valueOwner());
|
2011-02-25 16:16:37 +01:00
|
|
|
foreach (QmlObjectValue *object,
|
2011-07-01 12:11:02 +02:00
|
|
|
valueOwner()->cppQmlTypes().typesForImport(defaultPackage, ComponentVersion())) {
|
2011-05-24 11:50:10 +02:00
|
|
|
import.object->setMember(object->className(), object);
|
2011-02-25 16:16:37 +01:00
|
|
|
}
|
|
|
|
d->importCache.insert(ImportCacheKey(info), import);
|
|
|
|
}
|
2011-05-27 10:43:06 +02:00
|
|
|
imports->append(import);
|
2011-02-25 16:16:37 +01:00
|
|
|
}
|
|
|
|
}
|