You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
8.4 KiB
286 lines
8.4 KiB
15 years ago
|
/*
|
||
|
* This file is part of the KDE libraries
|
||
|
* Copyright (C) 2000-2001 Harri Porten (porten@kde.org)
|
||
|
* Copyright (C) 2001,2003 Peter Kelly (pmk@post.com)
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Library General Public
|
||
|
* License as published by the Free Software Foundation; either
|
||
|
* version 2 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* This library is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Library General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Library General Public
|
||
|
* License along with this library; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
*/
|
||
|
|
||
|
#ifndef _KJS_DEBUGGER_H_
|
||
|
#define _KJS_DEBUGGER_H_
|
||
|
|
||
|
#include <qglobal.h>
|
||
|
|
||
|
#define KJS_DEBUGGER
|
||
|
|
||
|
#ifdef KJS_DEBUGGER
|
||
|
|
||
|
#include <qwidget.h>
|
||
|
#include <qmultilineedit.h>
|
||
|
#include <qpixmap.h>
|
||
|
#include <qptrlist.h>
|
||
|
#include <qptrstack.h>
|
||
|
#include <qcheckbox.h>
|
||
|
#include <kdialogbase.h>
|
||
|
#include <kmainwindow.h>
|
||
|
#include <qscrollview.h>
|
||
|
|
||
|
#include <kjs/debugger.h>
|
||
|
|
||
|
#include "dom/dom_misc.h"
|
||
|
|
||
|
class QListBox;
|
||
|
class QComboBox;
|
||
|
class KActionCollection;
|
||
|
class KAction;
|
||
|
|
||
|
namespace KJS {
|
||
|
class FunctionImp;
|
||
|
class List;
|
||
|
class Interpreter;
|
||
|
class KJSDebugWin;
|
||
|
|
||
|
class SourceFile : public DOM::DomShared
|
||
|
{
|
||
|
public:
|
||
|
SourceFile(QString u, QString c, Interpreter *interp)
|
||
|
: url(u), code(c), interpreter(interp) {}
|
||
|
QString getCode();
|
||
|
QString url;
|
||
|
QString code;
|
||
|
Interpreter *interpreter;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @internal
|
||
|
*
|
||
|
* When kjs parses some code, it generates a source code fragment (or just "source").
|
||
|
* This is referenced by its source id in future calls to functions such as atLine()
|
||
|
* and callEvent(). We keep a record of all source fragments parsed in order to display
|
||
|
* then to the user.
|
||
|
*
|
||
|
* For .js files, the source fragment will be the entire file. For js code included
|
||
|
* in html files, however, there may be multiple source fragments within the one file
|
||
|
* (e.g. multiple SCRIPT tags or onclick="..." attributes)
|
||
|
*
|
||
|
* In the case where a single file has multiple source fragments, the source objects
|
||
|
* for these fragments will all point to the same SourceFile for their code.
|
||
|
*/
|
||
|
class SourceFragment
|
||
|
{
|
||
|
public:
|
||
|
SourceFragment(int sid, int bl, int el, SourceFile *sf);
|
||
|
~SourceFragment();
|
||
|
|
||
|
int sourceId;
|
||
|
int baseLine;
|
||
|
int errorLine;
|
||
|
SourceFile *sourceFile;
|
||
|
private:
|
||
|
SourceFragment(const SourceFragment& other);
|
||
|
SourceFragment& operator = (const SourceFragment& other);
|
||
|
};
|
||
|
|
||
|
class KJSErrorDialog : public KDialogBase {
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
KJSErrorDialog(QWidget *parent, const QString& errorMessage, bool showDebug);
|
||
|
virtual ~KJSErrorDialog();
|
||
|
|
||
|
bool debugSelected() const { return m_debugSelected; }
|
||
|
bool dontShowAgain() const { return m_dontShowAgainCb->isChecked(); }
|
||
|
|
||
|
protected slots:
|
||
|
virtual void slotUser1();
|
||
|
|
||
|
private:
|
||
|
QCheckBox *m_dontShowAgainCb;
|
||
|
bool m_debugSelected;
|
||
|
};
|
||
|
|
||
|
class EvalMultiLineEdit : public QMultiLineEdit {
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
EvalMultiLineEdit(QWidget *parent);
|
||
|
const QString & code() const { return m_code; }
|
||
|
protected:
|
||
|
void keyPressEvent(QKeyEvent * e);
|
||
|
private:
|
||
|
QString m_code;
|
||
|
};
|
||
|
|
||
|
class SourceDisplay : public QScrollView {
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
SourceDisplay(KJSDebugWin *debugWin, QWidget *parent, const char *name = 0);
|
||
|
~SourceDisplay();
|
||
|
|
||
|
void setSource(SourceFile *sourceFile);
|
||
|
void setCurrentLine(int lineno, bool doCenter = true);
|
||
|
|
||
|
signals:
|
||
|
void lineDoubleClicked(int lineno);
|
||
|
|
||
|
protected:
|
||
|
virtual void contentsMousePressEvent(QMouseEvent *e);
|
||
|
virtual void showEvent(QShowEvent *);
|
||
|
virtual void drawContents(QPainter *p, int clipx, int clipy, int clipw, int cliph);
|
||
|
|
||
|
QString m_source;
|
||
|
int m_currentLine;
|
||
|
SourceFile *m_sourceFile;
|
||
|
QStringList m_lines;
|
||
|
|
||
|
KJSDebugWin *m_debugWin;
|
||
|
QFont m_font;
|
||
|
QPixmap m_breakpointIcon;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @internal
|
||
|
*
|
||
|
* KJSDebugWin represents the debugger window that is visible to the user. It contains
|
||
|
* a stack frame list, a code viewer and a source fragment selector, plus buttons
|
||
|
* to control execution including next, step and continue.
|
||
|
*
|
||
|
* There is only one debug window per program. This can be obtained by calling #instance
|
||
|
*/
|
||
|
class KJSDebugWin : public KMainWindow, public Debugger, public KInstance
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
friend class SourceDisplay;
|
||
|
public:
|
||
|
KJSDebugWin(QWidget *parent=0, const char *name=0);
|
||
|
virtual ~KJSDebugWin();
|
||
|
|
||
|
static KJSDebugWin *createInstance();
|
||
|
static void destroyInstance();
|
||
|
static KJSDebugWin *debugWindow() { return kjs_html_debugger; }
|
||
|
|
||
|
enum Mode { Disabled = 0, // No break on any statements
|
||
|
Next = 1, // Will break on next statement in current context
|
||
|
Step = 2, // Will break on next statement in current or deeper context
|
||
|
Continue = 3, // Will continue until next breakpoint
|
||
|
Stop = 4 // The script will stop execution completely,
|
||
|
// as soon as possible
|
||
|
};
|
||
|
|
||
|
void setSourceLine(int sourceId, int lineno);
|
||
|
void setNextSourceInfo(QString url, int baseLine);
|
||
|
void sourceChanged(Interpreter *interpreter, QString url);
|
||
|
bool inSession() const { return !m_execStates.isEmpty(); }
|
||
|
void setMode(Mode m) { m_mode = m; }
|
||
|
void clearInterpreter(Interpreter *interpreter);
|
||
|
ExecState *getExecState() const { return m_execStates.top(); }
|
||
|
|
||
|
// functions overridden from KJS:Debugger
|
||
|
bool sourceParsed(ExecState *exec, int sourceId,
|
||
|
const UString &source, int errorLine);
|
||
|
bool sourceUnused(ExecState * exec, int sourceId);
|
||
|
bool exception(ExecState *exec, const Value &value, bool inTryCatch);
|
||
|
bool atStatement(ExecState *exec);
|
||
|
bool enterContext(ExecState *exec);
|
||
|
bool exitContext(ExecState *exec, const Completion &completion);
|
||
|
|
||
|
public slots:
|
||
|
void slotNext();
|
||
|
void slotStep();
|
||
|
void slotContinue();
|
||
|
void slotStop();
|
||
|
void slotBreakNext();
|
||
|
void slotToggleBreakpoint(int lineno);
|
||
|
void slotShowFrame(int frameno);
|
||
|
void slotSourceSelected(int sourceSelIndex);
|
||
|
void slotEval();
|
||
|
|
||
|
protected:
|
||
|
|
||
|
void closeEvent(QCloseEvent *e);
|
||
|
bool eventFilter(QObject *obj, QEvent *evt);
|
||
|
void disableOtherWindows();
|
||
|
void enableOtherWindows();
|
||
|
|
||
|
private:
|
||
|
|
||
|
SourceFile *getSourceFile(Interpreter *interpreter, QString url);
|
||
|
void setSourceFile(Interpreter *interpreter, QString url, SourceFile *sourceFile);
|
||
|
void removeSourceFile(Interpreter *interpreter, QString url);
|
||
|
|
||
|
void checkBreak(ExecState *exec);
|
||
|
void enterSession(ExecState *exec);
|
||
|
void leaveSession();
|
||
|
void displaySourceFile(SourceFile *sourceFile, bool forceRefresh);
|
||
|
void updateContextList();
|
||
|
|
||
|
QString contextStr(const Context &ctx);
|
||
|
|
||
|
struct Breakpoint {
|
||
|
int sourceId;
|
||
|
int lineno;
|
||
|
};
|
||
|
Breakpoint *m_breakpoints;
|
||
|
int m_breakpointCount;
|
||
|
bool setBreakpoint(int sourceId, int lineno);
|
||
|
bool deleteBreakpoint(int sourceId, int lineno);
|
||
|
bool haveBreakpoint(SourceFile *sourceFile, int line0, int line1);
|
||
|
bool haveBreakpoint(int sourceId, int line0, int line1) const {
|
||
|
for (int i = 0; i < m_breakpointCount; i++) {
|
||
|
if (m_breakpoints[i].sourceId == sourceId &&
|
||
|
m_breakpoints[i].lineno >= line0 &&
|
||
|
m_breakpoints[i].lineno <= line1)
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
SourceFile *m_curSourceFile;
|
||
|
Mode m_mode;
|
||
|
QString m_nextSourceUrl;
|
||
|
int m_nextSourceBaseLine;
|
||
|
QPtrStack<ExecState> m_execStates;
|
||
|
ExecState **m_execs;
|
||
|
int m_execsCount;
|
||
|
int m_execsAlloc;
|
||
|
int m_steppingDepth;
|
||
|
|
||
|
QMap<QString,SourceFile*> m_sourceFiles; /* maps url->SourceFile */
|
||
|
QMap<int,SourceFragment*> m_sourceFragments; /* maps SourceId->SourceFragment */
|
||
|
QPtrList<SourceFile> m_sourceSelFiles; /* maps combobox index->SourceFile */
|
||
|
|
||
|
KActionCollection *m_actionCollection;
|
||
|
QPixmap m_stopIcon;
|
||
|
QPixmap m_emptyIcon;
|
||
|
SourceDisplay *m_sourceDisplay;
|
||
|
QListBox *m_contextList;
|
||
|
|
||
|
KAction *m_stepAction;
|
||
|
KAction *m_nextAction;
|
||
|
KAction *m_continueAction;
|
||
|
KAction *m_stopAction;
|
||
|
KAction *m_breakAction;
|
||
|
|
||
|
QComboBox *m_sourceSel;
|
||
|
EvalMultiLineEdit *m_evalEdit;
|
||
|
int m_evalDepth;
|
||
|
|
||
|
static KJSDebugWin *kjs_html_debugger;
|
||
|
};
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
#endif // KJS_DEBUGGER
|
||
|
|
||
|
#endif // _KJS_DEBUGGER_H_
|