QmlProject: port changes from QtForMcus

Task-number: QTCREATORBUG-26041
Change-Id: I5068381fb2c4c901d8621e0b8358db77d2cb0b21
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Christiaan Janssen
2021-09-27 15:28:36 +02:00
parent 3ad9c64977
commit 525039daeb
10 changed files with 424 additions and 343 deletions

View File

@@ -25,9 +25,15 @@
#include "qmljssimplereader.h"
#include "parser/qmljsparser_p.h"
#include "parser/qmljslexer_p.h"
#ifdef QT_CREATOR
#include "parser/qmljsengine_p.h"
#include "parser/qmljslexer_p.h"
#include "parser/qmljsparser_p.h"
#else
#include "parser/qqmljsengine_p.h"
#include "parser/qqmljslexer_p.h"
#include "qqmljsparser_p.h"
#endif
#include "qmljsutils.h"
@@ -37,308 +43,331 @@
static Q_LOGGING_CATEGORY(simpleReaderLog, "qtc.qmljs.simpleReader", QtWarningMsg)
namespace QmlJS{
QVariant SimpleReaderNode::property(const QString &name) const
namespace QmlJS
{
return m_properties.value(name);
}
#ifdef QT_CREATOR
using UiQualifiedId = QmlJS::AST::UiQualifiedId;
#else
using UiQualifiedId = QQmlJS::AST::UiQualifiedId;
#endif
QStringList SimpleReaderNode::propertyNames() const
{
return m_properties.keys();
}
SimpleReaderNode::PropertyHash SimpleReaderNode::properties() const
{
return m_properties;
}
bool SimpleReaderNode::isRoot() const
{
return m_parentNode.isNull();
}
bool SimpleReaderNode::isValid() const
{
return !m_name.isEmpty();
}
SimpleReaderNode::Ptr SimpleReaderNode::invalidNode()
{
return Ptr(new SimpleReaderNode);
}
SimpleReaderNode::WeakPtr SimpleReaderNode::parent() const
{
return m_parentNode;
}
QString SimpleReaderNode::name() const
{
return m_name;
}
SimpleReaderNode::SimpleReaderNode()
{
}
SimpleReaderNode::SimpleReaderNode(const QString &name, WeakPtr parent)
: m_name(name), m_parentNode(parent)
{
}
SimpleReaderNode::Ptr SimpleReaderNode::create(const QString &name, WeakPtr parent)
{
Ptr newNode(new SimpleReaderNode(name, parent));
newNode->m_weakThis = newNode;
if (parent)
parent.toStrongRef().data()->m_children.append(newNode);
return newNode;
}
const SimpleReaderNode::List SimpleReaderNode::children() const
{
return m_children;
}
void SimpleReaderNode::setProperty(const QString &name, const QVariant &value)
{
m_properties.insert(name, value);
}
SimpleAbstractStreamReader::SimpleAbstractStreamReader()
{
}
bool SimpleAbstractStreamReader::readFile(const QString &fileName)
{
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QByteArray source = file.readAll();
file.close();
return readFromSource(QString::fromLocal8Bit(source));
static SourceLocation toSourceLocation(SourceLocation first, SourceLocation last)
{
first.length = last.end() - first.begin();
return first;
}
addError(tr("Cannot find file %1.").arg(fileName));
return false;
}
bool SimpleAbstractStreamReader::readFromSource(const QString &source)
{
m_errors.clear();
m_currentSourceLocation = SourceLocation();
m_source = source;
Engine engine;
Lexer lexer(&engine);
Parser parser(&engine);
lexer.setCode(source, /*line = */ 1, /*qmlMode = */true);
if (!parser.parse()) {
QString errorMessage = QString::fromLatin1("%1:%2: %3").arg(
QString::number(parser.errorLineNumber()),
QString::number(parser.errorColumnNumber()),
parser.errorMessage());
addError(errorMessage);
return false;
static SourceLocation toSourceLocation(UiQualifiedId * qualifiedId)
{
SourceLocation first = qualifiedId->firstSourceLocation();
SourceLocation last;
for (UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) {
if (iter->lastSourceLocation().isValid())
last = iter->lastSourceLocation();
}
return toSourceLocation(first, last);
}
return readDocument(parser.ast());
}
QStringList SimpleAbstractStreamReader::errors() const
{
return m_errors;
}
SimpleReaderNode::Property SimpleReaderNode::property(const QString &name) const
{
return m_properties.value(name);
}
void SimpleAbstractStreamReader::addError(const QString &error, const SourceLocation &sourceLocation)
{
m_errors << QString::fromLatin1("%1:%2: %3\n").arg(
QString::number(sourceLocation.startLine),
QString::number(sourceLocation.startColumn),
error);
}
QStringList SimpleReaderNode::propertyNames() const { return m_properties.keys(); }
SourceLocation SimpleAbstractStreamReader::currentSourceLocation() const
{
return m_currentSourceLocation;
}
SimpleReaderNode::PropertyHash SimpleReaderNode::properties() const { return m_properties; }
bool SimpleAbstractStreamReader::readDocument(AST::UiProgram *ast)
{
if (!ast) {
addError(tr("Could not parse document."));
bool SimpleReaderNode::isRoot() const { return m_parentNode.isNull(); }
bool SimpleReaderNode::isValid() const { return !m_name.isEmpty(); }
SimpleReaderNode::Ptr SimpleReaderNode::invalidNode() { return Ptr(new SimpleReaderNode); }
SimpleReaderNode::WeakPtr SimpleReaderNode::parent() const { return m_parentNode; }
QString SimpleReaderNode::name() const { return m_name; }
SourceLocation SimpleReaderNode::nameLocation() const { return m_nameLocation; }
SimpleReaderNode::SimpleReaderNode() {}
SimpleReaderNode::SimpleReaderNode(const QString &name,
const SourceLocation &nameLocation,
WeakPtr parent)
: m_name(name)
, m_nameLocation(nameLocation)
, m_parentNode(parent)
{}
SimpleReaderNode::Ptr SimpleReaderNode::create(const QString &name,
const SourceLocation &nameLocation,
WeakPtr parent)
{
Ptr newNode(new SimpleReaderNode(name, nameLocation, parent));
newNode->m_weakThis = newNode;
if (parent)
parent.toStrongRef().data()->m_children.append(newNode);
return newNode;
}
const SimpleReaderNode::List SimpleReaderNode::children() const { return m_children; }
void SimpleReaderNode::setProperty(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation)
{
m_properties.insert(name, {value, nameLocation, valueLocation});
}
SimpleAbstractStreamReader::SimpleAbstractStreamReader() {}
SimpleAbstractStreamReader::~SimpleAbstractStreamReader() {}
bool SimpleAbstractStreamReader::readFile(const QString &fileName)
{
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QByteArray source = file.readAll();
file.close();
return readFromSource(QString::fromLocal8Bit(source));
}
addError(tr("Cannot find file %1.").arg(fileName));
return false;
}
AST::UiObjectDefinition *uiObjectDefinition = AST::cast<AST::UiObjectDefinition *>(ast->members->member);
if (!uiObjectDefinition) {
addError(tr("Expected document to contain a single object definition."));
return false;
}
readChild(uiObjectDefinition);
bool SimpleAbstractStreamReader::readFromSource(const QString &source)
{
m_errors.clear();
m_currentSourceLocation = SourceLocation();
m_source.clear();
m_source = source;
return errors().isEmpty();
}
Engine engine;
Lexer lexer(&engine);
Parser parser(&engine);
void SimpleAbstractStreamReader::readChildren(AST::UiObjectDefinition *uiObjectDefinition)
{
Q_ASSERT(uiObjectDefinition);
lexer.setCode(source, /*line = */ 1, /*qmlMode = */ true);
for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it; it = it->next) {
AST::UiObjectMember *member = it->member;
AST::UiObjectDefinition *uiObjectDefinition = AST::cast<AST::UiObjectDefinition *>(member);
if (uiObjectDefinition)
readChild(uiObjectDefinition);
}
}
void SimpleAbstractStreamReader::readChild(AST::UiObjectDefinition *uiObjectDefinition)
{
Q_ASSERT(uiObjectDefinition);
setSourceLocation(uiObjectDefinition->firstSourceLocation());
elementStart(toString(uiObjectDefinition->qualifiedTypeNameId));
readProperties(uiObjectDefinition);
readChildren(uiObjectDefinition);
elementEnd();
}
void SimpleAbstractStreamReader::readProperties(AST::UiObjectDefinition *uiObjectDefinition)
{
Q_ASSERT(uiObjectDefinition);
for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it; it = it->next) {
AST::UiObjectMember *member = it->member;
AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(member);
if (scriptBinding)
readProperty(scriptBinding);
}
}
void SimpleAbstractStreamReader::readProperty(AST::UiScriptBinding *uiScriptBinding)
{
Q_ASSERT(uiScriptBinding);
setSourceLocation(uiScriptBinding->firstSourceLocation());
const QString name = toString(uiScriptBinding->qualifiedId);
const QVariant value = parsePropertyScriptBinding(uiScriptBinding);
propertyDefinition(name, value);
}
QVariant SimpleAbstractStreamReader::parsePropertyScriptBinding(AST::UiScriptBinding *uiScriptBinding)
{
Q_ASSERT(uiScriptBinding);
AST::ExpressionStatement *expStmt = AST::cast<AST::ExpressionStatement *>(uiScriptBinding->statement);
if (!expStmt) {
addError(tr("Expected expression statement after colon."), uiScriptBinding->statement->firstSourceLocation());
return QVariant();
if (!parser.parse()) {
QString errorMessage = QString::fromLatin1("%1:%2: %3")
.arg(QString::number(parser.errorLineNumber()),
QString::number(parser.errorColumnNumber()),
parser.errorMessage());
addError(errorMessage);
return false;
}
return readDocument(parser.ast());
}
return parsePropertyExpression(expStmt->expression);
}
QStringList SimpleAbstractStreamReader::errors() const { return m_errors; }
QVariant SimpleAbstractStreamReader::parsePropertyExpression(AST::ExpressionNode *expressionNode)
{
Q_ASSERT(expressionNode);
AST::ArrayPattern *arrayLiteral = AST::cast<AST::ArrayPattern *>(expressionNode);
if (arrayLiteral) {
QList<QVariant> variantList;
for (AST::PatternElementList *it = arrayLiteral->elements; it; it = it->next)
variantList << parsePropertyExpression(it->element->initializer);
return variantList;
void SimpleAbstractStreamReader::addError(const QString &error,
const SourceLocation &sourceLocation)
{
m_errors << QString::fromLatin1("%1:%2: %3\n")
.arg(QString::number(sourceLocation.startLine),
QString::number(sourceLocation.startColumn),
error);
}
AST::StringLiteral *stringLiteral = AST::cast<AST::StringLiteral *>(expressionNode);
if (stringLiteral)
return stringLiteral->value.toString();
SourceLocation SimpleAbstractStreamReader::currentSourceLocation() const
{
return m_currentSourceLocation;
}
AST::TrueLiteral *trueLiteral = AST::cast<AST::TrueLiteral *>(expressionNode);
if (trueLiteral)
return true;
bool SimpleAbstractStreamReader::readDocument(AST::UiProgram * ast)
{
if (!ast) {
addError(tr("Could not parse document."));
return false;
}
AST::FalseLiteral *falseLiteral = AST::cast<AST::FalseLiteral *>(expressionNode);
if (falseLiteral)
return false;
AST::UiObjectDefinition *uiObjectDefinition = AST::cast<AST::UiObjectDefinition *>(
ast->members->member);
if (!uiObjectDefinition) {
addError(tr("Expected document to contain a single object definition."));
return false;
}
readChild(uiObjectDefinition);
AST::NumericLiteral *numericLiteral = AST::cast<AST::NumericLiteral *>(expressionNode);
if (numericLiteral)
return numericLiteral->value;
m_source.clear();
return textAt(expressionNode->firstSourceLocation(), expressionNode->lastSourceLocation());
}
return errors().isEmpty();
}
void SimpleAbstractStreamReader::setSourceLocation(const SourceLocation &sourceLocation)
{
m_currentSourceLocation = sourceLocation;
}
void SimpleAbstractStreamReader::readChildren(AST::UiObjectDefinition * uiObjectDefinition)
{
Q_ASSERT(uiObjectDefinition);
QString SimpleAbstractStreamReader::textAt(const SourceLocation &from,
const SourceLocation &to)
{
return m_source.mid(from.offset, to.end() - from.begin());
}
for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it;
it = it->next) {
AST::UiObjectMember *member = it->member;
AST::UiObjectDefinition *uiObjectDefinition = AST::cast<AST::UiObjectDefinition *>(
member);
if (uiObjectDefinition)
readChild(uiObjectDefinition);
}
}
SimpleReader::SimpleReader()
{
}
void SimpleAbstractStreamReader::readChild(AST::UiObjectDefinition * uiObjectDefinition)
{
Q_ASSERT(uiObjectDefinition);
SimpleReaderNode::Ptr SimpleReader::readFile(const QString &fileName)
{
SimpleAbstractStreamReader::readFile(fileName);
return m_rootNode;
}
setSourceLocation(uiObjectDefinition->firstSourceLocation());
SimpleReaderNode::Ptr SimpleReader::readFromSource(const QString &source)
{
SimpleAbstractStreamReader::readFromSource(source);
return m_rootNode;
}
elementStart(toString(uiObjectDefinition->qualifiedTypeNameId),
toSourceLocation(uiObjectDefinition->qualifiedTypeNameId));
void SimpleReader::elementStart(const QString &name)
{
qCDebug(simpleReaderLog) << "elementStart()" << name;
readProperties(uiObjectDefinition);
readChildren(uiObjectDefinition);
SimpleReaderNode::Ptr newNode = SimpleReaderNode::create(name, m_currentNode);
elementEnd();
}
if (newNode->isRoot())
m_rootNode = newNode;
void SimpleAbstractStreamReader::readProperties(AST::UiObjectDefinition * uiObjectDefinition)
{
Q_ASSERT(uiObjectDefinition);
Q_ASSERT(newNode->isValid());
for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it;
it = it->next) {
AST::UiObjectMember *member = it->member;
AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(member);
if (scriptBinding)
readProperty(scriptBinding);
}
}
m_currentNode = newNode;
}
void SimpleAbstractStreamReader::readProperty(AST::UiScriptBinding * uiScriptBinding)
{
Q_ASSERT(uiScriptBinding);
void SimpleReader::elementEnd()
{
Q_ASSERT(m_currentNode);
setSourceLocation(uiScriptBinding->firstSourceLocation());
qCDebug(simpleReaderLog) << "elementEnd()" << m_currentNode.toStrongRef().data()->name();
const QString name = toString(uiScriptBinding->qualifiedId);
auto nameLoc = toSourceLocation(uiScriptBinding->qualifiedId);
auto value = parsePropertyScriptBinding(uiScriptBinding);
m_currentNode = m_currentNode.toStrongRef().data()->parent();
}
propertyDefinition(name, nameLoc, value.first, value.second);
}
void SimpleReader::propertyDefinition(const QString &name, const QVariant &value)
{
Q_ASSERT(m_currentNode);
std::pair<QVariant, SourceLocation> SimpleAbstractStreamReader::parsePropertyScriptBinding(
AST::UiScriptBinding * uiScriptBinding)
{
Q_ASSERT(uiScriptBinding);
qCDebug(simpleReaderLog) << "propertyDefinition()" << m_currentNode.toStrongRef().data()->name() << name << value;
AST::ExpressionStatement *expStmt = AST::cast<AST::ExpressionStatement *>(
uiScriptBinding->statement);
if (!expStmt) {
addError(tr("Expected expression statement after colon."),
uiScriptBinding->statement->firstSourceLocation());
return std::make_pair(QVariant(), SourceLocation());
}
if (m_currentNode.toStrongRef().data()->propertyNames().contains(name))
addError(tr("Property is defined twice."), currentSourceLocation());
return std::make_pair(parsePropertyExpression(expStmt->expression),
toSourceLocation(expStmt->firstSourceLocation(),
expStmt->lastSourceLocation()));
}
m_currentNode.toStrongRef().data()->setProperty(name, value);
}
QVariant SimpleAbstractStreamReader::parsePropertyExpression(AST::ExpressionNode
* expressionNode)
{
Q_ASSERT(expressionNode);
AST::ArrayPattern *arrayLiteral = AST::cast<AST::ArrayPattern *>(expressionNode);
if (arrayLiteral) {
QList<QVariant> variantList;
for (AST::PatternElementList *it = arrayLiteral->elements; it; it = it->next)
variantList << parsePropertyExpression(it->element->initializer);
return variantList;
}
AST::StringLiteral *stringLiteral = AST::cast<AST::StringLiteral *>(expressionNode);
if (stringLiteral)
return stringLiteral->value.toString();
AST::TrueLiteral *trueLiteral = AST::cast<AST::TrueLiteral *>(expressionNode);
if (trueLiteral)
return true;
AST::FalseLiteral *falseLiteral = AST::cast<AST::FalseLiteral *>(expressionNode);
if (falseLiteral)
return false;
AST::NumericLiteral *numericLiteral = AST::cast<AST::NumericLiteral *>(expressionNode);
if (numericLiteral)
return numericLiteral->value;
return textAt(expressionNode->firstSourceLocation(), expressionNode->lastSourceLocation());
}
void SimpleAbstractStreamReader::setSourceLocation(const SourceLocation &sourceLocation)
{
m_currentSourceLocation = sourceLocation;
}
QString SimpleAbstractStreamReader::textAt(const SourceLocation &from, const SourceLocation &to)
{
return m_source.mid(from.offset, to.end() - from.begin());
}
SimpleReader::SimpleReader() {}
SimpleReaderNode::Ptr SimpleReader::readFile(const QString &fileName)
{
SimpleAbstractStreamReader::readFile(fileName);
return m_rootNode;
}
SimpleReaderNode::Ptr SimpleReader::readFromSource(const QString &source)
{
SimpleAbstractStreamReader::readFromSource(source);
return m_rootNode;
}
void SimpleReader::elementStart(const QString &name, const SourceLocation &nameLocation)
{
qCDebug(simpleReaderLog) << "elementStart()" << name;
SimpleReaderNode::Ptr newNode = SimpleReaderNode::create(name, nameLocation, m_currentNode);
if (newNode->isRoot())
m_rootNode = newNode;
Q_ASSERT(newNode->isValid());
m_currentNode = newNode;
}
void SimpleReader::elementEnd()
{
Q_ASSERT(m_currentNode);
qCDebug(simpleReaderLog) << "elementEnd()" << m_currentNode.toStrongRef().data()->name();
m_currentNode = m_currentNode.toStrongRef().data()->parent();
}
void SimpleReader::propertyDefinition(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation)
{
Q_ASSERT(m_currentNode);
qCDebug(simpleReaderLog) << "propertyDefinition()"
<< m_currentNode.toStrongRef().data()->name() << name << value;
if (m_currentNode.toStrongRef().data()->propertyNames().contains(name)) {
auto previousSourceLoc = m_currentNode.toStrongRef().data()->property(name).nameLocation;
addError(tr("Property is defined twice, previous definition at %1:%2")
.arg(QString::number(previousSourceLoc.startLine),
QString::number(previousSourceLoc.startColumn)),
currentSourceLocation());
}
m_currentNode.toStrongRef().data()->setProperty(name, nameLocation, value, valueLocation);
}
} // namespace QmlJS

View File

@@ -26,13 +26,18 @@
#pragma once
#include <qmljs/qmljs_global.h>
#include <qmljs/parser/qmljsastfwd_p.h>
#ifdef QT_CREATOR
#include <qmljs/parser/qmljsastfwd_p.h>
#else
#include <parser/qqmljsastfwd_p.h>
#endif
#include <QHash>
#include <QList>
#include <QStringList>
#include <QSharedPointer>
#include <QStringList>
#include <QVariant>
#include <QWeakPointer>
// for Q_DECLARE_TR_FUNCTIONS
@@ -40,15 +45,31 @@
namespace QmlJS {
#ifndef QT_CREATOR
using SourceLocation = QQmlJS::SourceLocation;
#endif
class QMLJS_EXPORT SimpleReaderNode
{
public:
struct Property
{
QVariant value;
SourceLocation nameLocation;
SourceLocation valueLocation;
bool isValid() const { return !value.isNull() && value.isValid(); }
bool isDefaultValue() const
{
return !value.isNull() && !nameLocation.isValid() && !valueLocation.isValid();
}
};
typedef QSharedPointer<SimpleReaderNode> Ptr;
typedef QWeakPointer<SimpleReaderNode> WeakPtr;
typedef QHash<QString, QVariant> PropertyHash;
typedef QHash<QString, Property> PropertyHash;
typedef QList<Ptr> List;
QVariant property(const QString &name) const;
Property property(const QString &name) const;
QStringList propertyNames() const;
PropertyHash properties() const;
bool isRoot() const;
@@ -56,16 +77,21 @@ public:
static Ptr invalidNode();
WeakPtr parent() const;
QString name() const;
SourceLocation nameLocation() const;
const List children() const;
protected:
SimpleReaderNode();
SimpleReaderNode(const QString &name, WeakPtr parent);
static Ptr create(const QString &name, WeakPtr parent);
void setProperty(const QString &name, const QVariant &value);
SimpleReaderNode(const QString &name, const SourceLocation &nameLocation, WeakPtr parent);
static Ptr create(const QString &name, const SourceLocation &nameLocation, WeakPtr parent);
void setProperty(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation);
private:
const QString m_name;
const SourceLocation m_nameLocation;
PropertyHash m_properties;
const WeakPtr m_parentNode;
List m_children;
@@ -74,12 +100,17 @@ private:
friend class SimpleReader;
};
#ifndef QT_CREATOR
using namespace QQmlJS;
#endif
class QMLJS_EXPORT SimpleAbstractStreamReader
{
Q_DECLARE_TR_FUNCTIONS(QmlJS::SimpleAbstractStreamReader)
public:
SimpleAbstractStreamReader();
virtual ~SimpleAbstractStreamReader();
bool readFile(const QString &fileName);
bool readFromSource(const QString &source);
QStringList errors() const;
@@ -88,9 +119,13 @@ protected:
void addError(const QString &error, const SourceLocation &sourceLocation = SourceLocation());
SourceLocation currentSourceLocation() const;
virtual void elementStart(const QString &name) = 0;
virtual void elementStart(const QString &name, const SourceLocation &nameLocation) = 0;
virtual void elementEnd() = 0;
virtual void propertyDefinition(const QString &name, const QVariant &value) = 0;
virtual void propertyDefinition(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation)
= 0;
private:
bool readDocument(AST::UiProgram *ast);
@@ -98,7 +133,8 @@ private:
void readChild(AST::UiObjectDefinition *uiObjectDefinition);
void readProperties(AST::UiObjectDefinition *ast);
void readProperty(AST::UiScriptBinding *uiScriptBinding);
QVariant parsePropertyScriptBinding(AST::UiScriptBinding *ExpressionNode);
std::pair<QVariant, SourceLocation> parsePropertyScriptBinding(
AST::UiScriptBinding *ExpressionNode);
QVariant parsePropertyExpression(AST::ExpressionNode *expressionNode);
void setSourceLocation(const SourceLocation &sourceLocation);
QString textAt(const SourceLocation &from, const SourceLocation &to);
@@ -118,9 +154,12 @@ public:
SimpleReaderNode::Ptr readFromSource(const QString &source);
protected:
void elementStart(const QString &name) override;
void elementStart(const QString &name, const SourceLocation &nameLocation) override;
void elementEnd() override;
void propertyDefinition(const QString &name, const QVariant &value) override;
void propertyDefinition(const QString &name,
const SourceLocation &nameLocation,
const QVariant &value,
const SourceLocation &valueLocation) override;
private:
SimpleReaderNode::Ptr m_rootNode;