forked from qt-creator/qt-creator
QmlJS: Fix type detection for alias properties.
Task-number: QTCREATORBUG-2306
This commit is contained in:
@@ -27,7 +27,8 @@ HEADERS += \
|
|||||||
$$PWD/qmljsrewriter.h \
|
$$PWD/qmljsrewriter.h \
|
||||||
$$PWD/qmljsicons.h \
|
$$PWD/qmljsicons.h \
|
||||||
$$PWD/qmljsdelta.h \
|
$$PWD/qmljsdelta.h \
|
||||||
$$PWD/qmljstypedescriptionreader.h
|
$$PWD/qmljstypedescriptionreader.h \
|
||||||
|
$$PWD/qmljsscopeastpath.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/qmljsbind.cpp \
|
$$PWD/qmljsbind.cpp \
|
||||||
@@ -46,7 +47,8 @@ SOURCES += \
|
|||||||
$$PWD/qmljsrewriter.cpp \
|
$$PWD/qmljsrewriter.cpp \
|
||||||
$$PWD/qmljsicons.cpp \
|
$$PWD/qmljsicons.cpp \
|
||||||
$$PWD/qmljsdelta.cpp \
|
$$PWD/qmljsdelta.cpp \
|
||||||
$$PWD/qmljstypedescriptionreader.cpp
|
$$PWD/qmljstypedescriptionreader.cpp \
|
||||||
|
$$PWD/qmljsscopeastpath.cpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
$$PWD/qmljs.qrc
|
$$PWD/qmljs.qrc
|
||||||
|
|||||||
@@ -365,11 +365,10 @@ private:
|
|||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
Check::Check(Document::Ptr doc, const Snapshot &snapshot, const Context *linkedContextNoScope)
|
Check::Check(Document::Ptr doc, const Context *linkedContextNoScope)
|
||||||
: _doc(doc)
|
: _doc(doc)
|
||||||
, _snapshot(snapshot)
|
|
||||||
, _context(*linkedContextNoScope)
|
, _context(*linkedContextNoScope)
|
||||||
, _scopeBuilder(&_context, doc, snapshot)
|
, _scopeBuilder(&_context, doc)
|
||||||
, _options(WarnDangerousNonStrictEqualityChecks | WarnBlocks | WarnWith
|
, _options(WarnDangerousNonStrictEqualityChecks | WarnBlocks | WarnWith
|
||||||
| WarnVoid | WarnCommaExpression | WarnExpressionStatement
|
| WarnVoid | WarnCommaExpression | WarnExpressionStatement
|
||||||
| WarnAssignInCondition | WarnUseBeforeDeclaration | WarnDuplicateDeclaration
|
| WarnAssignInCondition | WarnUseBeforeDeclaration | WarnDuplicateDeclaration
|
||||||
@@ -844,12 +843,17 @@ const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
|
|||||||
if (!value) {
|
if (!value) {
|
||||||
error(id->identifierToken,
|
error(id->identifierToken,
|
||||||
Check::tr("'%1' is not a valid property name").arg(propertyName));
|
Check::tr("'%1' is not a valid property name").arg(propertyName));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// can't look up members for attached properties
|
// can't look up members for attached properties
|
||||||
if (isAttachedProperty)
|
if (isAttachedProperty)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// resolve references
|
||||||
|
if (const Reference *ref = value->asReference())
|
||||||
|
value = _context.lookupReference(ref);
|
||||||
|
|
||||||
// member lookup
|
// member lookup
|
||||||
const UiQualifiedId *idPart = id;
|
const UiQualifiedId *idPart = id;
|
||||||
while (idPart->next) {
|
while (idPart->next) {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class QMLJS_EXPORT Check: protected AST::Visitor
|
|||||||
typedef QSet<QString> StringSet;
|
typedef QSet<QString> StringSet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Check(Document::Ptr doc, const Snapshot &snapshot, const Interpreter::Context *linkedContextNoScope);
|
Check(Document::Ptr doc, const Interpreter::Context *linkedContextNoScope);
|
||||||
virtual ~Check();
|
virtual ~Check();
|
||||||
|
|
||||||
QList<DiagnosticMessage> operator()();
|
QList<DiagnosticMessage> operator()();
|
||||||
@@ -125,7 +125,6 @@ private:
|
|||||||
AST::Node *parent(int distance = 0);
|
AST::Node *parent(int distance = 0);
|
||||||
|
|
||||||
Document::Ptr _doc;
|
Document::Ptr _doc;
|
||||||
Snapshot _snapshot;
|
|
||||||
|
|
||||||
Interpreter::Context _context;
|
Interpreter::Context _context;
|
||||||
ScopeBuilder _scopeBuilder;
|
ScopeBuilder _scopeBuilder;
|
||||||
|
|||||||
@@ -126,9 +126,15 @@ Document::~Document()
|
|||||||
Document::Ptr Document::create(const QString &fileName)
|
Document::Ptr Document::create(const QString &fileName)
|
||||||
{
|
{
|
||||||
Document::Ptr doc(new Document(fileName));
|
Document::Ptr doc(new Document(fileName));
|
||||||
|
doc->_ptr = doc;
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Document::Ptr Document::ptr() const
|
||||||
|
{
|
||||||
|
return _ptr.toStrongRef();
|
||||||
|
}
|
||||||
|
|
||||||
bool Document::isQmlDocument() const
|
bool Document::isQmlDocument() const
|
||||||
{
|
{
|
||||||
return _isQmlDocument;
|
return _isQmlDocument;
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ public:
|
|||||||
|
|
||||||
static Document::Ptr create(const QString &fileName);
|
static Document::Ptr create(const QString &fileName);
|
||||||
|
|
||||||
|
Document::Ptr ptr() const;
|
||||||
|
|
||||||
bool isQmlDocument() const;
|
bool isQmlDocument() const;
|
||||||
bool isJSDocument() const;
|
bool isJSDocument() const;
|
||||||
|
|
||||||
@@ -113,6 +115,7 @@ private:
|
|||||||
QString _path;
|
QString _path;
|
||||||
QString _componentName;
|
QString _componentName;
|
||||||
QString _source;
|
QString _source;
|
||||||
|
QWeakPointer<Document> _ptr;
|
||||||
|
|
||||||
// for documentFromSource
|
// for documentFromSource
|
||||||
friend class Snapshot;
|
friend class Snapshot;
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
|
|
||||||
#include "qmljsevaluate.h"
|
#include "qmljsevaluate.h"
|
||||||
#include "qmljsinterpreter.h"
|
#include "qmljsinterpreter.h"
|
||||||
#include "parser/qmljsparser_p.h"
|
|
||||||
#include "parser/qmljsast_p.h"
|
#include "parser/qmljsast_p.h"
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ public:
|
|||||||
Evaluate(const Interpreter::Context *context);
|
Evaluate(const Interpreter::Context *context);
|
||||||
virtual ~Evaluate();
|
virtual ~Evaluate();
|
||||||
|
|
||||||
|
// evaluate ast in the given context
|
||||||
const Interpreter::Value *operator()(AST::Node *ast);
|
const Interpreter::Value *operator()(AST::Node *ast);
|
||||||
|
|
||||||
|
// evaluate, but stop when encountering a Reference
|
||||||
const Interpreter::Value *reference(AST::Node *ast);
|
const Interpreter::Value *reference(AST::Node *ast);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "qmljsbind.h"
|
#include "qmljsbind.h"
|
||||||
#include "qmljsscopebuilder.h"
|
#include "qmljsscopebuilder.h"
|
||||||
#include "qmljstypedescriptionreader.h"
|
#include "qmljstypedescriptionreader.h"
|
||||||
|
#include "qmljsscopeastpath.h"
|
||||||
#include "parser/qmljsast_p.h"
|
#include "parser/qmljsast_p.h"
|
||||||
|
|
||||||
#include <languageutils/fakemetaobject.h>
|
#include <languageutils/fakemetaobject.h>
|
||||||
@@ -1378,8 +1379,9 @@ QList<const ObjectValue *> ScopeChain::all() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Context::Context()
|
Context::Context(const Snapshot &snapshot)
|
||||||
: _engine(new Engine),
|
: _snapshot(snapshot),
|
||||||
|
_engine(new Engine),
|
||||||
_qmlScopeObjectIndex(-1),
|
_qmlScopeObjectIndex(-1),
|
||||||
_qmlScopeObjectSet(false)
|
_qmlScopeObjectSet(false)
|
||||||
{
|
{
|
||||||
@@ -1395,6 +1397,11 @@ Engine *Context::engine() const
|
|||||||
return _engine.data();
|
return _engine.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QmlJS::Snapshot Context::snapshot() const
|
||||||
|
{
|
||||||
|
return _snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
const ScopeChain &Context::scopeChain() const
|
const ScopeChain &Context::scopeChain() const
|
||||||
{
|
{
|
||||||
return _scopeChain;
|
return _scopeChain;
|
||||||
@@ -3270,8 +3277,20 @@ bool ASTPropertyReference::getSourceLocation(QString *fileName, int *line, int *
|
|||||||
const Value *ASTPropertyReference::value(const Context *context) const
|
const Value *ASTPropertyReference::value(const Context *context) const
|
||||||
{
|
{
|
||||||
if (_ast->expression
|
if (_ast->expression
|
||||||
&& (!_ast->memberType || _ast->memberType->asString() == QLatin1String("variant"))) {
|
&& (!_ast->memberType || _ast->memberType->asString() == QLatin1String("variant")
|
||||||
Evaluate check(context);
|
|| _ast->memberType->asString() == QLatin1String("alias"))) {
|
||||||
|
|
||||||
|
// Adjust the context for the current location - expensive!
|
||||||
|
// ### Improve efficiency by caching the 'use chain' constructed in ScopeBuilder.
|
||||||
|
|
||||||
|
QmlJS::Document::Ptr doc = _doc->ptr();
|
||||||
|
Context localContext(*context);
|
||||||
|
QmlJS::ScopeBuilder builder(&localContext, doc);
|
||||||
|
|
||||||
|
int offset = _ast->expression->firstSourceLocation().begin();
|
||||||
|
builder.push(ScopeAstPath(doc)(offset));
|
||||||
|
|
||||||
|
Evaluate check(&localContext);
|
||||||
return check(_ast->expression);
|
return check(_ast->expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -317,10 +317,12 @@ private:
|
|||||||
class QMLJS_EXPORT Context
|
class QMLJS_EXPORT Context
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Context();
|
Context(const Snapshot &snapshot);
|
||||||
~Context();
|
~Context();
|
||||||
|
|
||||||
Engine *engine() const;
|
Engine *engine() const;
|
||||||
|
Snapshot snapshot() const;
|
||||||
|
|
||||||
const ScopeChain &scopeChain() const;
|
const ScopeChain &scopeChain() const;
|
||||||
ScopeChain &scopeChain();
|
ScopeChain &scopeChain();
|
||||||
|
|
||||||
@@ -340,6 +342,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
typedef QHash<QString, const Value *> Properties;
|
typedef QHash<QString, const Value *> Properties;
|
||||||
|
|
||||||
|
Snapshot _snapshot;
|
||||||
QSharedPointer<Engine> _engine;
|
QSharedPointer<Engine> _engine;
|
||||||
QHash<const ObjectValue *, Properties> _properties;
|
QHash<const ObjectValue *, Properties> _properties;
|
||||||
QHash<const Document *, const TypeEnvironment *> _typeEnvironments;
|
QHash<const Document *, const TypeEnvironment *> _typeEnvironments;
|
||||||
|
|||||||
@@ -36,7 +36,6 @@
|
|||||||
#include "qmljsdocument.h"
|
#include "qmljsdocument.h"
|
||||||
#include "qmljsbind.h"
|
#include "qmljsbind.h"
|
||||||
#include "qmljscheck.h"
|
#include "qmljscheck.h"
|
||||||
#include "qmljsscopebuilder.h"
|
|
||||||
#include "qmljsmodelmanagerinterface.h"
|
#include "qmljsmodelmanagerinterface.h"
|
||||||
|
|
||||||
#include <QtCore/QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ class QmlJS::LookupContextData
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LookupContextData(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path)
|
LookupContextData(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path)
|
||||||
: doc(doc),
|
: context(snapshot),
|
||||||
snapshot(snapshot)
|
doc(doc)
|
||||||
{
|
{
|
||||||
// since we keep the document and snapshot around, we don't need to keep the Link instance
|
// since we keep the document and snapshot around, we don't need to keep the Link instance
|
||||||
Link link(&context, snapshot, ModelManagerInterface::instance()->importPaths());
|
Link link(&context, snapshot, ModelManagerInterface::instance()->importPaths());
|
||||||
|
|
||||||
ScopeBuilder scopeBuilder(&context, doc, snapshot);
|
ScopeBuilder scopeBuilder(&context, doc);
|
||||||
scopeBuilder.push(path);
|
scopeBuilder.push(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,16 +57,15 @@ public:
|
|||||||
const Interpreter::Context &linkedContextWithoutScope,
|
const Interpreter::Context &linkedContextWithoutScope,
|
||||||
const QList<AST::Node *> &path)
|
const QList<AST::Node *> &path)
|
||||||
: context(linkedContextWithoutScope),
|
: context(linkedContextWithoutScope),
|
||||||
doc(doc),
|
doc(doc)
|
||||||
snapshot(snapshot)
|
|
||||||
{
|
{
|
||||||
ScopeBuilder scopeBuilder(&context, doc, snapshot);
|
ScopeBuilder scopeBuilder(&context, doc);
|
||||||
scopeBuilder.push(path);
|
scopeBuilder.push(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Interpreter::Context context;
|
Interpreter::Context context;
|
||||||
Document::Ptr doc;
|
Document::Ptr doc;
|
||||||
Snapshot snapshot;
|
// snapshot is in context
|
||||||
};
|
};
|
||||||
|
|
||||||
LookupContext::LookupContext(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path)
|
LookupContext::LookupContext(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path)
|
||||||
@@ -112,7 +111,7 @@ Document::Ptr LookupContext::document() const
|
|||||||
|
|
||||||
Snapshot LookupContext::snapshot() const
|
Snapshot LookupContext::snapshot() const
|
||||||
{
|
{
|
||||||
return d->snapshot;
|
return d->context.snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
// the engine is only guaranteed to live as long as the LookupContext
|
// the engine is only guaranteed to live as long as the LookupContext
|
||||||
|
|||||||
@@ -41,9 +41,8 @@ using namespace QmlJS;
|
|||||||
using namespace QmlJS::Interpreter;
|
using namespace QmlJS::Interpreter;
|
||||||
using namespace QmlJS::AST;
|
using namespace QmlJS::AST;
|
||||||
|
|
||||||
ScopeBuilder::ScopeBuilder(Context *context, Document::Ptr doc, const Snapshot &snapshot)
|
ScopeBuilder::ScopeBuilder(Context *context, Document::Ptr doc)
|
||||||
: _doc(doc)
|
: _doc(doc)
|
||||||
, _snapshot(snapshot)
|
|
||||||
, _context(context)
|
, _context(context)
|
||||||
{
|
{
|
||||||
initializeScopeChain();
|
initializeScopeChain();
|
||||||
@@ -121,25 +120,26 @@ void ScopeBuilder::initializeScopeChain()
|
|||||||
|
|
||||||
Bind *bind = _doc->bind();
|
Bind *bind = _doc->bind();
|
||||||
QHash<Document *, ScopeChain::QmlComponentChain *> componentScopes;
|
QHash<Document *, ScopeChain::QmlComponentChain *> componentScopes;
|
||||||
|
const Snapshot &snapshot = _context->snapshot();
|
||||||
|
|
||||||
ScopeChain::QmlComponentChain *chain = new ScopeChain::QmlComponentChain;
|
ScopeChain::QmlComponentChain *chain = new ScopeChain::QmlComponentChain;
|
||||||
scopeChain.qmlComponentScope = QSharedPointer<const ScopeChain::QmlComponentChain>(chain);
|
scopeChain.qmlComponentScope = QSharedPointer<const ScopeChain::QmlComponentChain>(chain);
|
||||||
if (_doc->qmlProgram()) {
|
if (_doc->qmlProgram()) {
|
||||||
componentScopes.insert(_doc.data(), chain);
|
componentScopes.insert(_doc.data(), chain);
|
||||||
makeComponentChain(_doc, chain, &componentScopes);
|
makeComponentChain(_doc, snapshot, chain, &componentScopes);
|
||||||
|
|
||||||
if (const TypeEnvironment *typeEnvironment = _context->typeEnvironment(_doc.data())) {
|
if (const TypeEnvironment *typeEnvironment = _context->typeEnvironment(_doc.data())) {
|
||||||
scopeChain.qmlTypes = typeEnvironment;
|
scopeChain.qmlTypes = typeEnvironment;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// add scope chains for all components that import this file
|
// add scope chains for all components that import this file
|
||||||
foreach (Document::Ptr otherDoc, _snapshot) {
|
foreach (Document::Ptr otherDoc, snapshot) {
|
||||||
foreach (const ImportInfo &import, otherDoc->bind()->imports()) {
|
foreach (const ImportInfo &import, otherDoc->bind()->imports()) {
|
||||||
if (import.type() == ImportInfo::FileImport && _doc->fileName() == import.name()) {
|
if (import.type() == ImportInfo::FileImport && _doc->fileName() == import.name()) {
|
||||||
ScopeChain::QmlComponentChain *component = new ScopeChain::QmlComponentChain;
|
ScopeChain::QmlComponentChain *component = new ScopeChain::QmlComponentChain;
|
||||||
componentScopes.insert(otherDoc.data(), component);
|
componentScopes.insert(otherDoc.data(), component);
|
||||||
chain->instantiatingComponents += component;
|
chain->instantiatingComponents += component;
|
||||||
makeComponentChain(otherDoc, component, &componentScopes);
|
makeComponentChain(otherDoc, snapshot, component, &componentScopes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,6 +155,7 @@ void ScopeBuilder::initializeScopeChain()
|
|||||||
|
|
||||||
void ScopeBuilder::makeComponentChain(
|
void ScopeBuilder::makeComponentChain(
|
||||||
Document::Ptr doc,
|
Document::Ptr doc,
|
||||||
|
const Snapshot &snapshot,
|
||||||
ScopeChain::QmlComponentChain *target,
|
ScopeChain::QmlComponentChain *target,
|
||||||
QHash<Document *, ScopeChain::QmlComponentChain *> *components)
|
QHash<Document *, ScopeChain::QmlComponentChain *> *components)
|
||||||
{
|
{
|
||||||
@@ -164,7 +165,7 @@ void ScopeBuilder::makeComponentChain(
|
|||||||
Bind *bind = doc->bind();
|
Bind *bind = doc->bind();
|
||||||
|
|
||||||
// add scopes for all components instantiating this one
|
// add scopes for all components instantiating this one
|
||||||
foreach (Document::Ptr otherDoc, _snapshot) {
|
foreach (Document::Ptr otherDoc, snapshot) {
|
||||||
if (otherDoc == doc)
|
if (otherDoc == doc)
|
||||||
continue;
|
continue;
|
||||||
if (otherDoc->bind()->usesQmlPrototype(bind->rootObjectValue(), _context)) {
|
if (otherDoc->bind()->usesQmlPrototype(bind->rootObjectValue(), _context)) {
|
||||||
@@ -175,7 +176,7 @@ void ScopeBuilder::makeComponentChain(
|
|||||||
components->insert(otherDoc.data(), component);
|
components->insert(otherDoc.data(), component);
|
||||||
target->instantiatingComponents += component;
|
target->instantiatingComponents += component;
|
||||||
|
|
||||||
makeComponentChain(otherDoc, component, components);
|
makeComponentChain(otherDoc, snapshot, component, components);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace AST {
|
|||||||
class QMLJS_EXPORT ScopeBuilder
|
class QMLJS_EXPORT ScopeBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScopeBuilder(Interpreter::Context *context, Document::Ptr doc, const Snapshot &snapshot);
|
ScopeBuilder(Interpreter::Context *context, Document::Ptr doc);
|
||||||
~ScopeBuilder();
|
~ScopeBuilder();
|
||||||
|
|
||||||
void push(AST::Node *node);
|
void push(AST::Node *node);
|
||||||
@@ -58,14 +58,14 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeScopeChain();
|
void initializeScopeChain();
|
||||||
void makeComponentChain(Document::Ptr doc, Interpreter::ScopeChain::QmlComponentChain *target,
|
void makeComponentChain(Document::Ptr doc, const Snapshot &snapshot,
|
||||||
|
Interpreter::ScopeChain::QmlComponentChain *target,
|
||||||
QHash<Document *, Interpreter::ScopeChain::QmlComponentChain *> *components);
|
QHash<Document *, Interpreter::ScopeChain::QmlComponentChain *> *components);
|
||||||
|
|
||||||
void setQmlScopeObject(AST::Node *node);
|
void setQmlScopeObject(AST::Node *node);
|
||||||
const Interpreter::Value *scopeObjectLookup(AST::UiQualifiedId *id);
|
const Interpreter::Value *scopeObjectLookup(AST::UiQualifiedId *id);
|
||||||
|
|
||||||
Document::Ptr _doc;
|
Document::Ptr _doc;
|
||||||
Snapshot _snapshot;
|
|
||||||
Interpreter::Context *_context;
|
Interpreter::Context *_context;
|
||||||
QList<AST::Node *> _nodes;
|
QList<AST::Node *> _nodes;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -282,10 +282,10 @@ public:
|
|||||||
const QStringList importPaths)
|
const QStringList importPaths)
|
||||||
: m_snapshot(snapshot)
|
: m_snapshot(snapshot)
|
||||||
, m_doc(doc)
|
, m_doc(doc)
|
||||||
, m_context(new Interpreter::Context)
|
, m_context(new Interpreter::Context(snapshot))
|
||||||
, m_link(m_context, snapshot, importPaths, doc, &m_diagnosticLinkMessages)
|
, m_link(m_context, snapshot, importPaths, doc, &m_diagnosticLinkMessages)
|
||||||
, m_lookupContext(LookupContext::create(doc, snapshot, *m_context, QList<AST::Node*>()))
|
, m_lookupContext(LookupContext::create(doc, snapshot, *m_context, QList<AST::Node*>()))
|
||||||
, m_scopeBuilder(m_context, doc, snapshot)
|
, m_scopeBuilder(m_context, doc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,6 +381,10 @@ public:
|
|||||||
if (isAttachedProperty)
|
if (isAttachedProperty)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// resolve references
|
||||||
|
if (const Interpreter::Reference *ref = value->asReference())
|
||||||
|
value = m_context->lookupReference(ref);
|
||||||
|
|
||||||
// member lookup
|
// member lookup
|
||||||
const UiQualifiedId *idPart = id;
|
const UiQualifiedId *idPart = id;
|
||||||
if (prefix.isEmpty())
|
if (prefix.isEmpty())
|
||||||
@@ -664,7 +668,7 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (view()->checkSemanticErrors()) {
|
if (view()->checkSemanticErrors()) {
|
||||||
Check check(doc, snapshot, m_lookupContext->context());
|
Check check(doc, m_lookupContext->context());
|
||||||
check.setOptions(check.options() & ~Check::ErrCheckTypeErrors);
|
check.setOptions(check.options() & ~Check::ErrCheckTypeErrors);
|
||||||
foreach (const QmlJS::DiagnosticMessage &diagnosticMessage, check())
|
foreach (const QmlJS::DiagnosticMessage &diagnosticMessage, check())
|
||||||
if (diagnosticMessage.isError())
|
if (diagnosticMessage.isError())
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include <qmljs/qmljslink.h>
|
#include <qmljs/qmljslink.h>
|
||||||
#include <qmljs/qmljsevaluate.h>
|
#include <qmljs/qmljsevaluate.h>
|
||||||
#include <qmljs/qmljsscopebuilder.h>
|
#include <qmljs/qmljsscopebuilder.h>
|
||||||
|
#include <qmljs/qmljsscopeastpath.h>
|
||||||
#include <qmljs/parser/qmljsastvisitor_p.h>
|
#include <qmljs/parser/qmljsastvisitor_p.h>
|
||||||
#include <qmljs/parser/qmljsast_p.h>
|
#include <qmljs/parser/qmljsast_p.h>
|
||||||
|
|
||||||
@@ -80,7 +81,7 @@ public:
|
|||||||
: _doc(doc)
|
: _doc(doc)
|
||||||
, _snapshot(snapshot)
|
, _snapshot(snapshot)
|
||||||
, _context(context)
|
, _context(context)
|
||||||
, _builder(context, doc, snapshot)
|
, _builder(context, doc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,79 +287,6 @@ private:
|
|||||||
const ObjectValue *_scope;
|
const ObjectValue *_scope;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScopeAstPath: protected Visitor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ScopeAstPath(Document::Ptr doc)
|
|
||||||
: _doc(doc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Node *> operator()(quint32 offset)
|
|
||||||
{
|
|
||||||
_result.clear();
|
|
||||||
_offset = offset;
|
|
||||||
if (_doc)
|
|
||||||
Node::accept(_doc->ast(), this);
|
|
||||||
return _result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void accept(AST::Node *node)
|
|
||||||
{ AST::Node::acceptChild(node, this); }
|
|
||||||
|
|
||||||
using Visitor::visit;
|
|
||||||
|
|
||||||
virtual bool preVisit(Node *node)
|
|
||||||
{
|
|
||||||
if (Statement *stmt = node->statementCast()) {
|
|
||||||
return containsOffset(stmt->firstSourceLocation(), stmt->lastSourceLocation());
|
|
||||||
} else if (ExpressionNode *exp = node->expressionCast()) {
|
|
||||||
return containsOffset(exp->firstSourceLocation(), exp->lastSourceLocation());
|
|
||||||
} else if (UiObjectMember *ui = node->uiObjectMemberCast()) {
|
|
||||||
return containsOffset(ui->firstSourceLocation(), ui->lastSourceLocation());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visit(AST::UiObjectDefinition *node)
|
|
||||||
{
|
|
||||||
_result.append(node);
|
|
||||||
Node::accept(node->initializer, this);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visit(AST::UiObjectBinding *node)
|
|
||||||
{
|
|
||||||
_result.append(node);
|
|
||||||
Node::accept(node->initializer, this);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visit(AST::FunctionDeclaration *node)
|
|
||||||
{
|
|
||||||
return visit(static_cast<FunctionExpression *>(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visit(AST::FunctionExpression *node)
|
|
||||||
{
|
|
||||||
Node::accept(node->formals, this);
|
|
||||||
_result.append(node);
|
|
||||||
Node::accept(node->body, this);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool containsOffset(SourceLocation start, SourceLocation end)
|
|
||||||
{
|
|
||||||
return _offset >= start.begin() && _offset <= end.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Node *> _result;
|
|
||||||
Document::Ptr _doc;
|
|
||||||
quint32 _offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FindTargetExpression: protected Visitor
|
class FindTargetExpression: protected Visitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -621,13 +549,13 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find the scope for the name we're searching
|
// find the scope for the name we're searching
|
||||||
Context context;
|
Context context(snapshot);
|
||||||
Document::Ptr doc = snapshot.document(fileName);
|
Document::Ptr doc = snapshot.document(fileName);
|
||||||
if (!doc)
|
if (!doc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Link link(&context, snapshot, ModelManagerInterface::instance()->importPaths());
|
Link link(&context, snapshot, ModelManagerInterface::instance()->importPaths());
|
||||||
ScopeBuilder builder(&context, doc, snapshot);
|
ScopeBuilder builder(&context, doc);
|
||||||
ScopeAstPath astPath(doc);
|
ScopeAstPath astPath(doc);
|
||||||
builder.push(astPath(offset));
|
builder.push(astPath(offset));
|
||||||
|
|
||||||
|
|||||||
@@ -132,11 +132,11 @@ SemanticInfo SemanticHighlighter::semanticInfo(const SemanticHighlighterSource &
|
|||||||
semanticInfo.snapshot = snapshot;
|
semanticInfo.snapshot = snapshot;
|
||||||
semanticInfo.document = doc;
|
semanticInfo.document = doc;
|
||||||
|
|
||||||
QmlJS::Interpreter::Context *ctx = new QmlJS::Interpreter::Context;
|
QmlJS::Interpreter::Context *ctx = new QmlJS::Interpreter::Context(snapshot);
|
||||||
QmlJS::Link link(ctx, snapshot, QmlJS::ModelManagerInterface::instance()->importPaths(), doc, &semanticInfo.semanticMessages);
|
QmlJS::Link link(ctx, snapshot, QmlJS::ModelManagerInterface::instance()->importPaths(), doc, &semanticInfo.semanticMessages);
|
||||||
semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx);
|
semanticInfo.m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx);
|
||||||
|
|
||||||
QmlJS::Check checker(doc, snapshot, ctx);
|
QmlJS::Check checker(doc, ctx);
|
||||||
semanticInfo.semanticMessages.append(checker());
|
semanticInfo.semanticMessages.append(checker());
|
||||||
|
|
||||||
return semanticInfo;
|
return semanticInfo;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ QmlTaskManager::QmlTaskManager(QObject *parent) :
|
|||||||
void QmlTaskManager::collectMessages(QFutureInterface<FileErrorMessages> &future,
|
void QmlTaskManager::collectMessages(QFutureInterface<FileErrorMessages> &future,
|
||||||
Snapshot snapshot, QStringList files, QStringList importPaths)
|
Snapshot snapshot, QStringList files, QStringList importPaths)
|
||||||
{
|
{
|
||||||
Interpreter::Context ctx;
|
Interpreter::Context ctx(snapshot);
|
||||||
QHash<QString, QList<DiagnosticMessage> > linkMessages;
|
QHash<QString, QList<DiagnosticMessage> > linkMessages;
|
||||||
Link link(&ctx, snapshot, importPaths, &linkMessages);
|
Link link(&ctx, snapshot, importPaths, &linkMessages);
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ void QmlTaskManager::collectMessages(QFutureInterface<FileErrorMessages> &future
|
|||||||
result.messages = document->diagnosticMessages();
|
result.messages = document->diagnosticMessages();
|
||||||
result.messages += linkMessages.value(fileName);
|
result.messages += linkMessages.value(fileName);
|
||||||
|
|
||||||
Check checker(document, snapshot, &ctx);
|
Check checker(document, &ctx);
|
||||||
result.messages.append(checker());
|
result.messages.append(checker());
|
||||||
|
|
||||||
future.reportResult(result);
|
future.reportResult(result);
|
||||||
|
|||||||
Reference in New Issue
Block a user