Hi,

A while ago i went through the Code Review process for QML/JS AST model to 
support generic Javascript development, not just QML files. I’ve been using 
this for more than a year to develop mobile apps with Qt and node.js apps, all 
in QtCreator. The patch never got accepted and it is ok, i keep patching the 
latest master and run my copy of QtC.
 
To make life easier i compiled several help files for node, bootstrap, ios… and 
other documentation for projects i use but i noticed that the wait cursor many 
times never disappear, this is due to failed Web requests in the Html 
documentation. Today i think i fixed it.

Below is my full patch with all the changes i use including the help viewer 
cursor fix. Maybe someone will find it useful but i just do not have time to go 
over the CodeReview process, for occasional fixes and changes and me not being 
the core developer for QtC the process is too time consuming and complicated, 
but the QtCreator gets better and better every day and i want to help and make 
it better as well, so my solution is to send my patches, they all simple so if 
good enough it is easy to be picked up by someone who can apply or just fix the 
code directly.

Thanks
diff --git a/src/plugins/help/macwebkithelpviewer.mm 
b/src/plugins/help/macwebkithelpviewer.mm
index 6cd509e..707f3ca 100644
--- a/src/plugins/help/macwebkithelpviewer.mm
+++ b/src/plugins/help/macwebkithelpviewer.mm
@@ -208,6 +208,7 @@ - (void)webView:(WebView *)sender 
didStartProvisionalLoadForFrame:(WebFrame *)fr
 - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title 
forFrame:(WebFrame *)frame;
 - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame;
 - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError 
*)error forFrame:(WebFrame *)frame;
+- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error 
forFrame:(WebFrame *)frame;
 
 @end
 
@@ -253,6 +254,12 @@ - (void)webView:(WebView *)sender 
didFailProvisionalLoadWithError:(NSError *)err
         viewer->slotLoadFinished();
 }
 
+- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error 
forFrame:(WebFrame *)frame;
+{
+    Q_UNUSED(error)
+    if (frame == mainFrame)
+        viewer->slotLoadFinished();
+}
 @end
 
 // #pragma mark -- UIDelegate
diff --git a/src/plugins/qmljseditor/qmljseditordocument.cpp 
b/src/plugins/qmljseditor/qmljseditordocument.cpp
index d5bdc26..7c684586 100644
--- a/src/plugins/qmljseditor/qmljseditordocument.cpp
+++ b/src/plugins/qmljseditor/qmljseditordocument.cpp
@@ -324,9 +324,37 @@ protected:
         decl.endColumn = first.startColumn + first.length;
 
         _declarations.append(decl);
-
         return false;
     }
+
+    bool visit(AST::BinaryExpression *ast)
+    {
+        AST::FieldMemberExpression *field = 
AST::cast<AST::FieldMemberExpression *>(ast->left);
+        AST::FunctionExpression *funcExpr = AST::cast<AST::FunctionExpression 
*>(ast->right);
+
+        if (field && funcExpr && funcExpr->body && (ast->op == 
QSOperator::Assign)) {
+            Declaration decl;
+            init(&decl, ast);
+
+            decl.text.fill(QLatin1Char(' '), _depth);
+            decl.text += field->name;
+
+            decl.text += QLatin1Char('(');
+            for (FormalParameterList *it = funcExpr->formals; it; it = 
it->next) {
+                if (!it->name.isEmpty())
+                    decl.text += it->name;
+
+                if (it->next)
+                    decl.text += QLatin1String(", ");
+            }
+            decl.text += QLatin1Char(')');
+
+            _declarations.append(decl);
+            return true;
+        }
+
+        return true;
+    }
 };
 
 class CreateRanges: protected AST::Visitor
@@ -373,6 +401,16 @@ protected:
         return true;
     }
 
+    bool visit(AST::BinaryExpression *ast)
+    {
+        AST::FieldMemberExpression *field = 
AST::cast<AST::FieldMemberExpression *>(ast->left);
+        AST::FunctionExpression *funcExpr = AST::cast<AST::FunctionExpression 
*>(ast->right);
+
+        if (field && funcExpr && funcExpr->body && (ast->op == 
QSOperator::Assign))
+            _ranges.append(createRange(ast, ast->firstSourceLocation(), 
ast->lastSourceLocation()));
+        return true;
+    }
+
     virtual bool visit(AST::UiScriptBinding *ast)
     {
         if (AST::Block *block = AST::cast<AST::Block *>(ast->statement))
@@ -469,8 +507,8 @@ void QmlJSEditorDocumentPrivate::invalidateFormatterCache()
 
 void QmlJSEditorDocumentPrivate::reparseDocument()
 {
-    
ModelManagerInterface::instance()->updateSourceFiles(QStringList(q->filePath().toString()),
-                                                         false);
+    ModelManagerInterface::instance()->updateSourceFiles(QStringList() << 
q->filePath().toString(),
+                                                                false);
 }
 
 void QmlJSEditorDocumentPrivate::onDocumentUpdated(Document::Ptr doc)
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.cpp 
b/src/plugins/qmljseditor/qmloutlinemodel.cpp
index 7102c07..9b7f151 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.cpp
+++ b/src/plugins/qmljseditor/qmloutlinemodel.cpp
@@ -274,7 +274,20 @@ private:
                 visitProperties(properties);
 
             m_model->leaveTestCase();
+            return true;
         }
+
+        // Collect method assignments for prototypes and objects and show as 
functions
+        AST::FieldMemberExpression *lhsField = 
AST::cast<AST::FieldMemberExpression *>(binExp->left);
+        AST::FunctionExpression *rhsFuncExpr = 
AST::cast<AST::FunctionExpression *>(binExp->right);
+
+        if (lhsField && rhsFuncExpr && rhsFuncExpr->body && (binExp->op == 
QSOperator::Assign)) {
+            QModelIndex index = m_model->enterFieldMemberExpression(lhsField, 
rhsFuncExpr);
+            m_nodeToIndex.insert(lhsField, index);
+            m_model->leaveFieldMemberExpression();
+            return true;
+        }
+
         return true;
     }
 
@@ -568,12 +581,26 @@ void QmlOutlineModel::leavePublicMember()
     leaveNode();
 }
 
+static QString functionDisplayName(QStringRef name, AST::FormalParameterList 
*formals)
+{
+    QString display;
+
+    if (!name.isEmpty()) {
+        display += name.toString() + QString::fromLatin1("(");
+    }
+    for (AST::FormalParameterList *param = formals; param != NULL; param = 
param->next) {
+        display += param->name.toString();
+        if (param->next) display += QString::fromLatin1(", ");
+    }
+    display += QString::fromLatin1(")");
+    return display;
+}
+
 QModelIndex QmlOutlineModel::enterFunctionDeclaration(AST::FunctionDeclaration 
*functionDeclaration)
 {
     QMap<int, QVariant> objectData;
 
-    if (!functionDeclaration->name.isEmpty())
-        objectData.insert(Qt::DisplayRole, 
functionDeclaration->name.toString());
+    objectData.insert(Qt::DisplayRole, 
functionDisplayName(functionDeclaration->name, functionDeclaration->formals));
     objectData.insert(ItemTypeRole, ElementBindingType);
 
     QmlOutlineItem *item = enterNode(objectData, functionDeclaration, 0, 
Icons::functionDeclarationIcon());
@@ -586,6 +613,36 @@ void QmlOutlineModel::leaveFunctionDeclaration()
     leaveNode();
 }
 
+QModelIndex 
QmlOutlineModel::enterFieldMemberExpression(AST::FieldMemberExpression 
*expression, AST::FunctionExpression *functionExpression)
+{
+    QMap<int, QVariant> objectData;
+
+    QString display = functionDisplayName(expression->name, 
functionExpression->formals);
+    while (expression) {
+        AST::FieldMemberExpression *field = 
AST::cast<AST::FieldMemberExpression *>(expression->base);
+        if (field) {
+            display.prepend(field->name.toString() + QString::fromLatin1("."));
+            expression = field;
+        } else {
+            AST::IdentifierExpression *ident = 
AST::cast<AST::IdentifierExpression *>(expression->base);
+            if (ident) display.prepend(ident->name.toString() + 
QString::fromLatin1("."));
+            break;
+        }
+    }
+
+    objectData.insert(Qt::DisplayRole, display);
+    objectData.insert(ItemTypeRole, ElementBindingType);
+
+    QmlOutlineItem *item = enterNode(objectData, expression, 0, 
m_icons->functionDeclarationIcon());
+
+    return item->index();
+}
+
+void QmlOutlineModel::leaveFieldMemberExpression()
+{
+    leaveNode();
+}
+
 QModelIndex QmlOutlineModel::enterTestCase(AST::ObjectLiteral *objectLiteral)
 {
     QMap<int, QVariant> objectData;
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.h 
b/src/plugins/qmljseditor/qmloutlinemodel.h
index 86094c6..0df5d20 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.h
+++ b/src/plugins/qmljseditor/qmloutlinemodel.h
@@ -115,6 +115,9 @@ private:
     QModelIndex enterFunctionDeclaration(QmlJS::AST::FunctionDeclaration 
*functionDeclaration);
     void leaveFunctionDeclaration();
 
+    QModelIndex enterFieldMemberExpression(QmlJS::AST::FieldMemberExpression 
*expression, QmlJS::AST::FunctionExpression *functionExpression);
+    void leaveFieldMemberExpression();
+
     QModelIndex enterTestCase(QmlJS::AST::ObjectLiteral *objectLiteral);
     void leaveTestCase();
 
diff --git a/src/plugins/qmljstools/qmljslocatordata.cpp 
b/src/plugins/qmljstools/qmljslocatordata.cpp
index 5806e57..a61e05b 100644
--- a/src/plugins/qmljstools/qmljslocatordata.cpp
+++ b/src/plugins/qmljstools/qmljslocatordata.cpp
@@ -171,6 +171,48 @@ protected:
         accept(ast->initializer, contextString(context));
         return false;
     }
+
+    bool visit(AST::BinaryExpression *ast)
+    {
+        AST::FieldMemberExpression *fieldExpr = 
AST::cast<AST::FieldMemberExpression *>(ast->left);
+        AST::FunctionExpression *funcExpr = AST::cast<AST::FunctionExpression 
*>(ast->right);
+
+        if (fieldExpr && funcExpr && funcExpr->body && (ast->op == 
QSOperator::Assign)) {
+
+            LocatorData::Entry entry = basicEntry(ast->operatorToken);
+
+            entry.type = LocatorData::Function;
+            entry.displayName = fieldExpr->name.toString();
+            while (fieldExpr) {
+                AST::FieldMemberExpression *field = 
AST::cast<AST::FieldMemberExpression *>(fieldExpr->base);
+                if (field) {
+                    entry.displayName.prepend(field->name.toString() + 
QString::fromLatin1("."));
+                    fieldExpr = field;
+                } else {
+                    AST::IdentifierExpression *ident = 
AST::cast<AST::IdentifierExpression *>(fieldExpr->base);
+                    if (ident) 
entry.displayName.prepend(ident->name.toString() + QString::fromLatin1("."));
+                    break;
+                }
+            }
+
+            entry.displayName += QLatin1Char('(');
+            for (FormalParameterList *it = funcExpr->formals; it; it = 
it->next) {
+                if (it != funcExpr->formals)
+                    entry.displayName += QLatin1String(", ");
+                if (!it->name.isEmpty())
+                    entry.displayName += it->name.toString();
+            }
+            entry.displayName += QLatin1Char(')');
+            entry.symbolName = entry.displayName;
+
+            m_entries += entry;
+
+            accept(funcExpr->body, contextString(QString::fromLatin1("function 
%1").arg(entry.displayName)));
+            return false;
+        }
+
+        return true;
+    }
 };
 } // anonymous namespace
 
_______________________________________________
Qt-creator mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/qt-creator

Reply via email to