summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/qml/qmlengineutils.cpp
diff options
context:
space:
mode:
authorhjk <hjk@theqtcompany.com>2015-07-08 13:14:03 +0200
committerhjk <hjk@theqtcompany.com>2015-07-09 12:59:03 +0000
commitbcd29daa48d4294fc02e434c63f0d5b9ac87f1d3 (patch)
treedd9bd409cd8ac4a0fe259da105cb2baf0ba29817 /src/plugins/debugger/qml/qmlengineutils.cpp
parent0e0f1babdb1db8b17131dee0a1ba280074a675a5 (diff)
downloadqt-creator-bcd29daa48d4294fc02e434c63f0d5b9ac87f1d3.tar.gz
Debugger: Consolidate QmlEngine
Create a QmlEnginePrivate. Move the QmlDebugClient there. Merge QmlAdapter into QmlEngine Abstraction is not used anymore. Move some helper bits to a qmlengineutils.{h,cpp} Change-Id: I63117355d786cc12641101b7fd38c7cd208d11eb Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
Diffstat (limited to 'src/plugins/debugger/qml/qmlengineutils.cpp')
-rw-r--r--src/plugins/debugger/qml/qmlengineutils.cpp270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/plugins/debugger/qml/qmlengineutils.cpp b/src/plugins/debugger/qml/qmlengineutils.cpp
new file mode 100644
index 0000000000..a657a7fb23
--- /dev/null
+++ b/src/plugins/debugger/qml/qmlengineutils.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qmlengine.h"
+
+#include <qmljs/parser/qmljsast_p.h>
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmljs/consolemanagerinterface.h>
+
+#include <coreplugin/editormanager/documentmodel.h>
+
+#include <texteditor/textdocument.h>
+#include <texteditor/texteditor.h>
+
+using namespace Core;
+using namespace QmlDebug;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+using namespace TextEditor;
+
+namespace Debugger {
+namespace Internal {
+
+class ASTWalker : public Visitor
+{
+public:
+ void operator()(Node *ast, quint32 *l, quint32 *c)
+ {
+ done = false;
+ line = l;
+ column = c;
+ Node::accept(ast, this);
+ }
+
+ bool preVisit(Node *ast)
+ {
+ return !done && ast->lastSourceLocation().startLine >= *line;
+ }
+
+ //Case 1: Breakpoint is between sourceStart(exclusive) and
+ // sourceEnd(inclusive) --> End tree walk.
+ //Case 2: Breakpoint is on sourceStart --> Check for the start
+ // of the first executable code. Set the line number and
+ // column number. End tree walk.
+ //Case 3: Breakpoint is on "unbreakable" code --> Find the next "breakable"
+ // code and check for Case 2. End tree walk.
+
+ //Add more types when suitable.
+
+ bool visit(UiScriptBinding *ast)
+ {
+ if (!ast->statement)
+ return true;
+
+ quint32 sourceStartLine = ast->firstSourceLocation().startLine;
+ quint32 statementStartLine;
+ quint32 statementColumn;
+
+ if (ast->statement->kind == Node::Kind_ExpressionStatement) {
+ statementStartLine = ast->statement->firstSourceLocation().startLine;
+ statementColumn = ast->statement->firstSourceLocation().startColumn;
+
+ } else if (ast->statement->kind == Node::Kind_Block) {
+ Block *block = static_cast<Block *>(ast->statement);
+ if (!block || !block->statements)
+ return true;
+ statementStartLine = block->statements->firstSourceLocation().startLine;
+ statementColumn = block->statements->firstSourceLocation().startColumn;
+
+ } else {
+ return true;
+ }
+
+
+ //Case 1
+ //Check for possible relocation within the binding statement
+
+ //Rewritten to (function <token>() { { }})
+ //The offset 16 is position of inner lbrace without token length.
+ const int offset = 16;
+
+ //Case 2
+ if (statementStartLine == *line) {
+ if (sourceStartLine == *line)
+ *column = offset + ast->qualifiedId->identifierToken.length;
+ done = true;
+ }
+
+ //Case 3
+ if (statementStartLine > *line) {
+ *line = statementStartLine;
+ if (sourceStartLine == *line)
+ *column = offset + ast->qualifiedId->identifierToken.length;
+ else
+ *column = statementColumn;
+ done = true;
+ }
+ return true;
+ }
+
+ bool visit(FunctionDeclaration *ast) {
+ quint32 sourceStartLine = ast->firstSourceLocation().startLine;
+ quint32 sourceStartColumn = ast->firstSourceLocation().startColumn;
+ quint32 statementStartLine = ast->body->firstSourceLocation().startLine;
+ quint32 statementColumn = ast->body->firstSourceLocation().startColumn;
+
+ //Case 1
+ //Check for possible relocation within the function declaration
+
+ //Case 2
+ if (statementStartLine == *line) {
+ if (sourceStartLine == *line)
+ *column = statementColumn - sourceStartColumn + 1;
+ done = true;
+ }
+
+ //Case 3
+ if (statementStartLine > *line) {
+ *line = statementStartLine;
+ if (sourceStartLine == *line)
+ *column = statementColumn - sourceStartColumn + 1;
+ else
+ *column = statementColumn;
+ done = true;
+ }
+ return true;
+ }
+
+ bool visit(EmptyStatement *ast)
+ {
+ *line = ast->lastSourceLocation().startLine + 1;
+ return true;
+ }
+
+ bool visit(VariableStatement *ast) { test(ast); return true; }
+ bool visit(VariableDeclarationList *ast) { test(ast); return true; }
+ bool visit(VariableDeclaration *ast) { test(ast); return true; }
+ bool visit(ExpressionStatement *ast) { test(ast); return true; }
+ bool visit(IfStatement *ast) { test(ast); return true; }
+ bool visit(DoWhileStatement *ast) { test(ast); return true; }
+ bool visit(WhileStatement *ast) { test(ast); return true; }
+ bool visit(ForStatement *ast) { test(ast); return true; }
+ bool visit(LocalForStatement *ast) { test(ast); return true; }
+ bool visit(ForEachStatement *ast) { test(ast); return true; }
+ bool visit(LocalForEachStatement *ast) { test(ast); return true; }
+ bool visit(ContinueStatement *ast) { test(ast); return true; }
+ bool visit(BreakStatement *ast) { test(ast); return true; }
+ bool visit(ReturnStatement *ast) { test(ast); return true; }
+ bool visit(WithStatement *ast) { test(ast); return true; }
+ bool visit(SwitchStatement *ast) { test(ast); return true; }
+ bool visit(CaseBlock *ast) { test(ast); return true; }
+ bool visit(CaseClauses *ast) { test(ast); return true; }
+ bool visit(CaseClause *ast) { test(ast); return true; }
+ bool visit(DefaultClause *ast) { test(ast); return true; }
+ bool visit(LabelledStatement *ast) { test(ast); return true; }
+ bool visit(ThrowStatement *ast) { test(ast); return true; }
+ bool visit(TryStatement *ast) { test(ast); return true; }
+ bool visit(Catch *ast) { test(ast); return true; }
+ bool visit(Finally *ast) { test(ast); return true; }
+ bool visit(FunctionExpression *ast) { test(ast); return true; }
+ bool visit(DebuggerStatement *ast) { test(ast); return true; }
+
+ void test(Node *ast)
+ {
+ quint32 statementStartLine = ast->firstSourceLocation().startLine;
+ //Case 1/2
+ if (statementStartLine <= *line && *line <= ast->lastSourceLocation().startLine)
+ done = true;
+
+ //Case 3
+ if (statementStartLine > *line) {
+ *line = statementStartLine;
+ *column = ast->firstSourceLocation().startColumn;
+ done = true;
+ }
+ }
+
+ bool done;
+ quint32 *line;
+ quint32 *column;
+};
+
+bool adjustBreakpointLineAndColumn(const QString &filePath, quint32 *line, quint32 *column, bool *valid)
+{
+ bool success = false;
+ //check if file is in the latest snapshot
+ //ignoring documentChangedOnDisk
+ //TODO:: update breakpoints if document is changed.
+ ModelManagerInterface *mmIface = ModelManagerInterface::instance();
+ if (mmIface) {
+ Document::Ptr doc = mmIface->newestSnapshot().document(filePath);
+ if (doc.isNull()) {
+ ModelManagerInterface::instance()->updateSourceFiles(
+ QStringList() << filePath, false);
+ } else {
+ ASTWalker walker;
+ walker(doc->ast(), line, column);
+ *valid = walker.done;
+ success = true;
+ }
+ }
+ return success;
+}
+
+void appendDebugOutput(QtMsgType type, const QString &message, const QDebugContextInfo &info)
+{
+ ConsoleItem::ItemType itemType;
+ switch (type) {
+ case QtDebugMsg:
+ itemType = ConsoleItem::DebugType;
+ break;
+ case QtWarningMsg:
+ itemType = ConsoleItem::WarningType;
+ break;
+ case QtCriticalMsg:
+ case QtFatalMsg:
+ itemType = ConsoleItem::ErrorType;
+ break;
+ default:
+ //This case is not possible
+ return;
+ }
+
+ if (auto consoleManager = ConsoleManagerInterface::instance()) {
+ ConsoleItem *item = new ConsoleItem(consoleManager->rootItem(), itemType, message);
+ item->file = info.file;
+ item->line = info.line;
+ consoleManager->printToConsolePane(item);
+ }
+}
+
+void clearExceptionSelection()
+{
+ QList<QTextEdit::ExtraSelection> selections;
+
+ foreach (IEditor *editor, DocumentModel::editorsForOpenedDocuments()) {
+ if (auto ed = qobject_cast<TextEditorWidget *>(editor->widget()))
+ ed->setExtraSelections(TextEditorWidget::DebuggerExceptionSelection, selections);
+ }
+}
+
+} // Internal
+} // Debugger