diff --git a/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml b/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml
index 044d71fbf64..f5ddfda7de0 100644
--- a/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml
+++ b/src/plugins/qmljseditor/QmlJSEditor.mimetypes.xml
@@ -14,5 +14,6 @@
Qt Script file
+
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.cpp b/src/plugins/qmljseditor/qmloutlinemodel.cpp
index 862852db1f3..c3107322322 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.cpp
+++ b/src/plugins/qmljseditor/qmloutlinemodel.cpp
@@ -266,6 +266,38 @@ private:
m_model->leaveFunctionDeclaration();
}
+ bool visit(AST::BinaryExpression *binExp)
+ {
+ AST::IdentifierExpression *lhsIdent = AST::cast(binExp->left);
+ AST::ObjectLiteral *rhsObjLit = AST::cast(binExp->right);
+
+ if (lhsIdent && rhsObjLit && (lhsIdent->name->asString() == "testcase")
+ && (binExp->op == QSOperator::Assign)) {
+ QModelIndex index = m_model->enterTestCase(rhsObjLit);
+ m_nodeToIndex.insert(rhsObjLit, index);
+
+ if (AST::PropertyNameAndValueList *properties = rhsObjLit->properties)
+ visitProperties(properties);
+
+ m_model->leaveTestCase();
+ }
+ return true;
+ }
+
+ void visitProperties(AST::PropertyNameAndValueList *properties)
+ {
+ while (properties) {
+ QModelIndex index = m_model->enterTestCaseProperties(properties);
+ m_nodeToIndex.insert(properties, index);
+
+ if (AST::ObjectLiteral *objLiteral = AST::cast(properties->value))
+ visitProperties(objLiteral->properties);
+
+ m_model->leaveTestCaseProperties();
+ properties = properties->next;
+ }
+ }
+
QmlOutlineModel *m_model;
QHash m_nodeToIndex;
@@ -553,6 +585,49 @@ void QmlOutlineModel::leaveFunctionDeclaration()
leaveNode();
}
+QModelIndex QmlOutlineModel::enterTestCase(AST::ObjectLiteral *objectLiteral)
+{
+ QMap objectData;
+
+ objectData.insert(Qt::DisplayRole, "testcase");
+ objectData.insert(ItemTypeRole, ElementBindingType);
+
+ QmlOutlineItem *item = enterNode(objectData, objectLiteral, 0, m_icons->objectDefinitionIcon());
+
+ return item->index();
+}
+
+void QmlOutlineModel::leaveTestCase()
+{
+ leaveNode();
+}
+
+QModelIndex QmlOutlineModel::enterTestCaseProperties(AST::PropertyNameAndValueList *propertyNameAndValueList)
+{
+ QMap objectData;
+ if (AST::IdentifierPropertyName *propertyName = AST::cast(propertyNameAndValueList->name)) {
+ objectData.insert(Qt::DisplayRole, propertyName->id->asString());
+ objectData.insert(ItemTypeRole, ElementBindingType);
+ QmlOutlineItem *item;
+ if (propertyNameAndValueList->value->kind == AST::Node::Kind_FunctionExpression) {
+ item = enterNode(objectData, propertyNameAndValueList, 0, m_icons->functionDeclarationIcon());
+ } else if (propertyNameAndValueList->value->kind == AST::Node::Kind_ObjectLiteral) {
+ item = enterNode(objectData, propertyNameAndValueList, 0, m_icons->objectDefinitionIcon());
+ } else {
+ item = enterNode(objectData, propertyNameAndValueList, 0, m_icons->scriptBindingIcon());
+ }
+
+ return item->index();
+ } else {
+ return QModelIndex();
+ }
+}
+
+void QmlOutlineModel::leaveTestCaseProperties()
+{
+ leaveNode();
+}
+
AST::Node *QmlOutlineModel::nodeForIndex(const QModelIndex &index) const
{
QTC_ASSERT(index.isValid() && (index.model() == this), return 0);
@@ -575,6 +650,8 @@ AST::SourceLocation QmlOutlineModel::sourceLocation(const QModelIndex &index) co
location = getLocation(member);
} else if (AST::ExpressionNode *expression = node->expressionCast()) {
location = getLocation(expression);
+ } else if (AST::PropertyNameAndValueList *propertyNameAndValueList = AST::cast(node)) {
+ location = getLocation(propertyNameAndValueList);
}
}
return location;
@@ -847,6 +924,14 @@ AST::SourceLocation QmlOutlineModel::getLocation(AST::ExpressionNode *exprNode)
return location;
}
+AST::SourceLocation QmlOutlineModel::getLocation(AST::PropertyNameAndValueList *propertyNode) {
+ AST::SourceLocation location;
+ location.offset = propertyNode->name->propertyNameToken.offset;
+ location.length = propertyNode->value->lastSourceLocation().end() - location.offset;
+
+ return location;
+}
+
QIcon QmlOutlineModel::getIcon(AST::UiQualifiedId *qualifiedId) {
QIcon icon;
if (qualifiedId) {
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.h b/src/plugins/qmljseditor/qmloutlinemodel.h
index 914a75a47f0..fea526125d1 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.h
+++ b/src/plugins/qmljseditor/qmloutlinemodel.h
@@ -125,6 +125,12 @@ private:
QModelIndex enterFunctionDeclaration(QmlJS::AST::FunctionDeclaration *functionDeclaration);
void leaveFunctionDeclaration();
+ QModelIndex enterTestCase(QmlJS::AST::ObjectLiteral *objectLiteral);
+ void leaveTestCase();
+
+ QModelIndex enterTestCaseProperties(QmlJS::AST::PropertyNameAndValueList *propertyNameAndValueList);
+ void leaveTestCaseProperties();
+
private:
QmlOutlineItem *enterNode(QMap data, QmlJS::AST::Node *node, QmlJS::AST::UiQualifiedId *idNode, const QIcon &icon);
void leaveNode();
@@ -139,6 +145,7 @@ private:
static QString asString(QmlJS::AST::UiQualifiedId *id);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::UiObjectMember *objMember);
static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::ExpressionNode *exprNode);
+ static QmlJS::AST::SourceLocation getLocation(QmlJS::AST::PropertyNameAndValueList *propertyNode);
QIcon getIcon(QmlJS::AST::UiQualifiedId *objDef);
QString getAnnotation(QmlJS::AST::UiObjectInitializer *objInitializer);