Commit 8f528e24 authored by Olivier Goffart's avatar Olivier Goffart
Browse files

QMLJS::Delta: Improved the delta

Use a smarter way to compare the AST (based on the diffX algorithm)
That way we do not rely anymore on the id property
parent 46b57ff7
This diff is collapsed.
......@@ -43,53 +43,6 @@ using namespace QmlJS::AST;
namespace QmlJSInspector {
namespace Internal {
class ScriptBindingParser : protected Visitor
{
public:
QmlJS::Document::Ptr doc;
QList<UiScriptBinding *> scripts;
ScriptBindingParser(Document::Ptr doc,
const QList<QDeclarativeDebugObjectReference> &objectReferences = QList<QDeclarativeDebugObjectReference>());
void process();
UiObjectMember *parent(UiScriptBinding *script) const;
UiScriptBinding *id(UiObjectMember *parent) const;
QList<UiScriptBinding *> ids() const;
QDeclarativeDebugObjectReference objectReferenceForPosition(const QUrl &url, int line, int col) const;
QDeclarativeDebugObjectReference objectReferenceForScriptBinding(UiScriptBinding *binding) const;
QDeclarativeDebugObjectReference objectReferenceForOffset(unsigned int offset);
QString header(UiObjectMember *member) const;
QString scriptCode(UiScriptBinding *script) const;
QString methodName(UiSourceElement *source) const;
QString methodCode(UiSourceElement *source) const;
protected:
QDeclarativeDebugObjectReference objectReference(const QString &id) const;
virtual bool visit(UiObjectDefinition *ast);
virtual void endVisit(UiObjectDefinition *);
virtual bool visit(UiObjectBinding *ast);
virtual void endVisit(UiObjectBinding *);
virtual bool visit(UiScriptBinding *ast);
private:
QList<UiObjectMember *> objectStack;
QHash<UiScriptBinding *, UiObjectMember *> _parent;
QHash<UiObjectMember *, UiScriptBinding *> _id;
QHash<UiScriptBinding *, QDeclarativeDebugObjectReference> _idBindings;
QList<QDeclarativeDebugObjectReference> objectReferences;
QDeclarativeDebugObjectReference m_foundObjectReference;
unsigned int m_searchElementOffset;
};
class Delta
{
public:
......@@ -102,14 +55,15 @@ public:
};
public:
void operator()(QmlJS::Document::Ptr doc, QmlJS::Document::Ptr previousDoc);
typedef QHash< UiObjectMember*, QList<QDeclarativeDebugObjectReference > > DebugIdMap;
DebugIdMap operator()(Document::Ptr doc1, Document::Ptr doc2, const DebugIdMap& debugIds);
QList<Change> changes() const;
QmlJS::Document::Ptr document() const;
QmlJS::Document::Ptr previousDocument() const;
private:
public:
void updateScriptBinding(const QDeclarativeDebugObjectReference &objectReference,
QmlJS::AST::UiScriptBinding *scriptBinding,
const QString &propertyName,
......@@ -119,10 +73,9 @@ private:
const QString &methodName,
const QString &methodBody);
bool compare(UiSourceElement *source, UiSourceElement *other);
bool compare(QmlJS::AST::UiQualifiedId *id, QmlJS::AST::UiQualifiedId *other);
QmlJS::AST::UiObjectMemberList *objectMembers(QmlJS::AST::UiObjectMember *object);
QDeclarativeDebugObjectReference objectReferenceForUiObject(const ScriptBindingParser &bindingParser, UiObjectMember *object);
static bool compare(UiSourceElement *source, UiSourceElement *other);
static bool compare(QmlJS::AST::UiQualifiedId *id, QmlJS::AST::UiQualifiedId *other);
static QmlJS::AST::UiObjectMemberList *objectMembers(QmlJS::AST::UiObjectMember *object);
private:
QmlJS::Document::Ptr _doc;
......
......@@ -101,6 +101,11 @@ using namespace QmlJS::AST;
using namespace QmlJSInspector::Internal;
using namespace Debugger::Internal;
enum {
MaxConnectionAttempts = 50,
ConnectionAttemptDefaultInterval = 75,
......@@ -138,6 +143,7 @@ Inspector::Inspector(QObject *parent)
connect(m_clientProxy, SIGNAL(aboutToReloadEngines()), SLOT(aboutToReloadEngines()));
connect(m_clientProxy, SIGNAL(enginesChanged()), SLOT(updateEngineList()));
connect(m_clientProxy, SIGNAL(aboutToDisconnect()), SLOT(disconnectWidgets()));
connect(m_clientProxy, SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)),SLOT(objectTreeUpdated(QDeclarativeDebugObjectReference)));
connect(Debugger::DebuggerPlugin::instance(),
SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int)));
......@@ -145,6 +151,7 @@ Inspector::Inspector(QObject *parent)
connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInspector()));
}
Inspector::~Inspector()
{
}
......@@ -562,3 +569,68 @@ bool Inspector::addQuotesForData(const QVariant &value) const
return false;
}
/*!
Associates the UiObjectMember* to their QDeclarativeDebugObjectReference.
*/
class MapObjectWithDebugReference : public Visitor
{
public:
virtual void endVisit(UiObjectDefinition *ast) ;
virtual void endVisit(UiObjectBinding *ast) ;
QDeclarativeDebugObjectReference root;
QString filename;
QHash<UiObjectMember *, QList<QDeclarativeDebugObjectReference> > result;
private:
void processRecursive(const QDeclarativeDebugObjectReference &object, UiObjectMember *ast);
};
void MapObjectWithDebugReference::endVisit(UiObjectDefinition* ast)
{
if (ast->qualifiedTypeNameId->name->asString().at(0).isUpper())
processRecursive(root, ast);
}
void MapObjectWithDebugReference::endVisit(UiObjectBinding* ast)
{
if (ast->qualifiedId->name->asString().at(0).isUpper())
processRecursive(root, ast);
}
void MapObjectWithDebugReference::processRecursive(const QDeclarativeDebugObjectReference& object, UiObjectMember* ast)
{
// If this is too slow, it can be speed up by indexing
// the QDeclarativeDebugObjectReference by filename/loc in a fist pass
SourceLocation loc = ast->firstSourceLocation();
if (object.source().lineNumber() == int(loc.startLine) && object.source().url().toLocalFile() == filename) {
result[ast] += object;
}
foreach (const QDeclarativeDebugObjectReference &it, object.children()) {
processRecursive(it, ast);
}
}
void QmlJSInspector::Internal::Inspector::objectTreeUpdated(const QDeclarativeDebugObjectReference &ref)
{
QmlJS::ModelManagerInterface *m = QmlJS::ModelManagerInterface::instance();
Snapshot snapshot = m->snapshot();
QHash<QString, QHash<UiObjectMember *, QList< QDeclarativeDebugObjectReference> > > allDebugIds;
foreach(const Document::Ptr &doc, snapshot) {
if (!doc->qmlProgram())
continue;
MapObjectWithDebugReference visitor;
visitor.root = ref;
QString filename = doc->fileName();
visitor.filename = filename;
doc->qmlProgram()->accept(&visitor);
allDebugIds[filename] = visitor.result;
}
//FIXME
m_textPreview->m_initialTable = allDebugIds;
m_textPreview->m_debugIds.clear();
}
......@@ -72,6 +72,8 @@ public:
QmlProjectWithCppPlugins
};
QHash< QString, QList< QPair< QmlJS::AST::UiObjectMember*, int > > > m_initialTable;
public:
Inspector(QObject *parent = 0);
virtual ~Inspector();
......@@ -115,6 +117,8 @@ private slots:
void disconnectWidgets();
void disconnected();
void objectTreeUpdated(const QDeclarativeDebugObjectReference &ref);
private:
Debugger::DebuggerRunControl *createDebuggerRunControl(ProjectExplorer::RunConfiguration *runConfig,
const QString &executableFile = QString(),
......
......@@ -60,7 +60,7 @@ void QmlJSLiveTextPreview::changeSelectedElement(int offset, const QString &word
ClientProxy *clientProxy = ClientProxy::instance();
QUrl url = QUrl::fromLocalFile(m_currentEditor.data()->file()->fileName());
QmlJS::Document::Ptr doc = modelManager()->snapshot().document(m_currentEditor.data()->file()->fileName());
ScriptBindingParser info(doc, clientProxy->objectReferences(url));
//ScriptBindingParser info(doc, clientProxy->objectReferences(url));
QDeclarativeDebugObjectReference objectRef;
......@@ -72,9 +72,10 @@ void QmlJSLiveTextPreview::changeSelectedElement(int offset, const QString &word
}
}
/* FIXME
if (objectRef.debugId() == -1 && offset >= 0) {
objectRef = info.objectReferenceForOffset(offset);
}
}*/
if (objectRef.debugId() != -1)
emit selectedItemsChanged(QList<QDeclarativeDebugObjectReference>() << objectRef);
......@@ -96,20 +97,28 @@ void QmlJSLiveTextPreview::setEditor(Core::IEditor *editor)
}
}
void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc)
{
{
/* FIXME
Core::ICore *core = Core::ICore::instance();
const int dbgcontext = core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE);
if (!core->hasContext(dbgcontext))
return;
*/
if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName()) {
if (m_debugIds.isEmpty())
m_debugIds = m_initialTable.value(doc->fileName());
Delta delta;
delta(doc, m_previousDoc);
m_debugIds = delta(m_previousDoc, doc, m_debugIds);
m_previousDoc = doc;
}
}
} // namespace Internal
} // namespace QmlJSInspector
......@@ -31,6 +31,7 @@ namespace Internal {
class QmlJSLiveTextPreview : public QObject
{
Q_OBJECT
public:
explicit QmlJSLiveTextPreview(QObject *parent = 0);
static QmlJS::ModelManagerInterface *modelManager();
......@@ -39,6 +40,9 @@ public:
void setActiveObject(const QDeclarativeDebugObjectReference &object);
void mapObjectToQml(const QDeclarativeDebugObjectReference &object);
QHash<QString, QHash<QmlJS::AST::UiObjectMember *, QList< QDeclarativeDebugObjectReference> > > m_initialTable;
QHash< QmlJS::AST::UiObjectMember*, QList<QDeclarativeDebugObjectReference > > m_debugIds;
signals:
void selectedItemsChanged(const QList<QDeclarativeDebugObjectReference> &objects);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment