refactor(debug): 从DebugToolFragment中分离debug逻辑
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package org.autojs.autojs.pluginclient;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class JsonSocket {
|
||||
|
||||
private Socket mSocket;
|
||||
|
||||
public JsonSocket(Socket socket) {
|
||||
mSocket = socket;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class SocketReader implements Runnable {
|
||||
|
||||
private final Socket mSocket;
|
||||
private final InputStream mInputStream;
|
||||
private ByteBuffer mByteBuffer;
|
||||
private int mJsonDataLength = -1;
|
||||
private int mReceivedDataLength = 0;
|
||||
private byte[] mBuffer;
|
||||
|
||||
private SocketReader(Socket socket) throws IOException {
|
||||
mSocket = socket;
|
||||
mInputStream = mSocket.getInputStream();
|
||||
mByteBuffer = ByteBuffer.allocateDirect(3);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
readLoop();
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
private void readLoop() throws IOException {
|
||||
byte[] buffer = new byte[4096];
|
||||
int n;
|
||||
while ((n = mInputStream.read(buffer)) > 0) {
|
||||
onChunk(buffer, 0, n);
|
||||
}
|
||||
}
|
||||
|
||||
private void onChunk(byte[] data, int offset, int length) {
|
||||
if(mJsonDataLength != 0){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import android.support.design.widget.Snackbar;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.pio.PFiles;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.engine.ScriptEngine;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.rhino.debug.Debugger;
|
||||
import com.stardust.pio.PFiles;
|
||||
import com.stardust.util.BackPressedHandler;
|
||||
import com.stardust.util.Callback;
|
||||
@@ -386,12 +387,14 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
.subscribe(s -> run(true));
|
||||
}
|
||||
|
||||
public void run(boolean showMessage) {
|
||||
public ScriptExecution run(boolean showMessage) {
|
||||
if(showMessage){
|
||||
Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
mScriptExecutionId = Scripts.runWithBroadcastSender(mFile).getId();
|
||||
ScriptExecution execution = Scripts.runWithBroadcastSender(mFile);
|
||||
mScriptExecutionId = execution.getId();
|
||||
setMenuItemStatus(R.id.run, false);
|
||||
return execution;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.autojs.autojs.ui.edit.debug;
|
||||
|
||||
import com.stardust.autojs.rhino.debug.Debugger;
|
||||
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
|
||||
public class DebuggerSingleton {
|
||||
|
||||
private static Debugger sDebugger = new Debugger(AutoJs.getInstance().getScriptEngineService(), ContextFactory.getGlobal());
|
||||
|
||||
public static Debugger get(){
|
||||
return sDebugger;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class CodeEditor extends HVScrollView {
|
||||
|
||||
|
||||
private CodeEditText mCodeEditText;
|
||||
private TextViewRedoUndo mTextViewRedoUndo;
|
||||
private TextViewUndoRedo mTextViewRedoUndo;
|
||||
private JavaScriptHighlighter mJavaScriptHighlighter;
|
||||
private Theme mTheme;
|
||||
private JsBeautifier mJsBeautifier;
|
||||
@@ -77,7 +77,7 @@ public class CodeEditor extends HVScrollView {
|
||||
inflate(getContext(), R.layout.code_editor, this);
|
||||
mCodeEditText = findViewById(R.id.code_edit_text);
|
||||
mCodeEditText.addTextChangedListener(new AutoIndent(mCodeEditText));
|
||||
mTextViewRedoUndo = new TextViewRedoUndo(mCodeEditText);
|
||||
mTextViewRedoUndo = new TextViewUndoRedo(mCodeEditText);
|
||||
mJavaScriptHighlighter = new JavaScriptHighlighter(mTheme, mCodeEditText);
|
||||
setTheme(Theme.getDefault(getContext()));
|
||||
mJsBeautifier = new JsBeautifier(this, "js/beautify.js");
|
||||
@@ -144,7 +144,7 @@ public class CodeEditor extends HVScrollView {
|
||||
}
|
||||
|
||||
public boolean canUndo() {
|
||||
return mTextViewRedoUndo.canUndo();
|
||||
return mTextViewRedoUndo.canRedo();
|
||||
}
|
||||
|
||||
public boolean canRedo() {
|
||||
|
||||
@@ -21,14 +21,13 @@ import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* 撤销和恢复撤销
|
||||
* Created by 沈钦赐 on 16/6/23.
|
||||
*/
|
||||
public class TextViewRedoUndo {
|
||||
public class TextViewRedoUndoer {
|
||||
//操作序号(一次编辑可能对应多个操作,如替换文字,就是删除+插入)
|
||||
int index;
|
||||
//撤销栈
|
||||
@@ -44,7 +43,7 @@ public class TextViewRedoUndo {
|
||||
private int mInitialHistoryStackSize;
|
||||
private boolean mEnabled = true;
|
||||
|
||||
public TextViewRedoUndo(@NonNull EditText editText) {
|
||||
public TextViewRedoUndoer(@NonNull EditText editText) {
|
||||
this.editable = editText.getText();
|
||||
this.editText = editText;
|
||||
editText.addTextChangedListener(new Watcher());
|
||||
@@ -246,7 +245,7 @@ public class TextViewRedoUndo {
|
||||
editable = s;
|
||||
onEditableChanged(s);
|
||||
}
|
||||
TextViewRedoUndo.this.onTextChanged(s);
|
||||
TextViewRedoUndoer.this.onTextChanged(s);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
package org.autojs.autojs.ui.edit.editor;
|
||||
|
||||
/*
|
||||
* THIS CLASS IS PROVIDED TO THE PUBLIC DOMAIN FOR FREE WITHOUT ANY
|
||||
* RESTRICTIONS OR ANY WARRANTY.
|
||||
*/
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.text.Editable;
|
||||
import android.text.Selection;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* A generic undo/redo implementation for TextViews.
|
||||
*/
|
||||
public class TextViewUndoRedo {
|
||||
|
||||
/**
|
||||
* Is undo/redo being performed? This member signals if an undo/redo
|
||||
* operation is currently being performed. Changes in the text during
|
||||
* undo/redo are not recorded because it would mess up the undo history.
|
||||
*/
|
||||
private boolean mIsUndoOrRedo = false;
|
||||
|
||||
/**
|
||||
* The edit history.
|
||||
*/
|
||||
private EditHistory mEditHistory;
|
||||
|
||||
/**
|
||||
* The change listener.
|
||||
*/
|
||||
private EditTextChangeListener mChangeListener;
|
||||
|
||||
/**
|
||||
* The edit text.
|
||||
*/
|
||||
private TextView mTextView;
|
||||
|
||||
private boolean mEnabled = true;
|
||||
|
||||
private int mInitialHistoryStackSize;
|
||||
|
||||
// =================================================================== //
|
||||
|
||||
/**
|
||||
* Create a new TextViewUndoRedo and attach it to the specified TextView.
|
||||
*
|
||||
* @param textView The text view for which the undo/redo is implemented.
|
||||
*/
|
||||
public TextViewUndoRedo(TextView textView) {
|
||||
mTextView = textView;
|
||||
mEditHistory = new EditHistory();
|
||||
mChangeListener = new EditTextChangeListener();
|
||||
mTextView.addTextChangedListener(mChangeListener);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
mEnabled = enabled;
|
||||
}
|
||||
|
||||
public final void setDefaultText(CharSequence text) {
|
||||
clearHistory();
|
||||
mIsUndoOrRedo = true;
|
||||
((Editable) mTextView.getText()).replace(0, text.length(), text);
|
||||
mIsUndoOrRedo = false;
|
||||
}
|
||||
|
||||
public boolean isTextChanged(){
|
||||
return mInitialHistoryStackSize != mEditHistory.size();
|
||||
}
|
||||
|
||||
|
||||
public void markTextAsUnchanged() {
|
||||
mInitialHistoryStackSize = mEditHistory.size();
|
||||
}
|
||||
|
||||
// =================================================================== //
|
||||
|
||||
/**
|
||||
* Disconnect this undo/redo from the text view.
|
||||
*/
|
||||
public void disconnect() {
|
||||
mTextView.removeTextChangedListener(mChangeListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum history size. If size is negative, then history size is
|
||||
* only limited by the device memory.
|
||||
*/
|
||||
public void setMaxHistorySize(int maxHistorySize) {
|
||||
mEditHistory.setMaxHistorySize(maxHistorySize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear history.
|
||||
*/
|
||||
public void clearHistory() {
|
||||
mEditHistory.clear();
|
||||
mInitialHistoryStackSize = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can undo be performed?
|
||||
*/
|
||||
public boolean canUndo() {
|
||||
return (mEditHistory.mmPosition > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform undo.
|
||||
*/
|
||||
public void undo() {
|
||||
EditItem edit = mEditHistory.getPrevious();
|
||||
if (edit == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Editable text = mTextView.getEditableText();
|
||||
int start = edit.mmStart;
|
||||
int end = start + (edit.mmAfter != null ? edit.mmAfter.length() : 0);
|
||||
|
||||
mIsUndoOrRedo = true;
|
||||
text.replace(start, end, edit.mmBefore);
|
||||
mIsUndoOrRedo = false;
|
||||
|
||||
// This will get rid of underlines inserted when editor tries to come
|
||||
// up with a suggestion.
|
||||
for (Object o : text.getSpans(0, text.length(), UnderlineSpan.class)) {
|
||||
text.removeSpan(o);
|
||||
}
|
||||
|
||||
Selection.setSelection(text, edit.mmBefore == null ? start
|
||||
: (start + edit.mmBefore.length()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Can redo be performed?
|
||||
*/
|
||||
public boolean canRedo() {
|
||||
return (mEditHistory.mmPosition < mEditHistory.mmHistory.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform redo.
|
||||
*/
|
||||
public void redo() {
|
||||
EditItem edit = mEditHistory.getNext();
|
||||
if (edit == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Editable text = mTextView.getEditableText();
|
||||
int start = edit.mmStart;
|
||||
int end = start + (edit.mmBefore != null ? edit.mmBefore.length() : 0);
|
||||
|
||||
mIsUndoOrRedo = true;
|
||||
text.replace(start, end, edit.mmAfter);
|
||||
mIsUndoOrRedo = false;
|
||||
|
||||
// This will get rid of underlines inserted when editor tries to come
|
||||
// up with a suggestion.
|
||||
for (Object o : text.getSpans(0, text.length(), UnderlineSpan.class)) {
|
||||
text.removeSpan(o);
|
||||
}
|
||||
|
||||
Selection.setSelection(text, edit.mmAfter == null ? start
|
||||
: (start + edit.mmAfter.length()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store preferences.
|
||||
*/
|
||||
public void storePersistentState(Editor editor, String prefix) {
|
||||
// Store hash code of text in the editor so that we can check if the
|
||||
// editor contents has changed.
|
||||
editor.putString(prefix + ".hash",
|
||||
String.valueOf(mTextView.getText().toString().hashCode()));
|
||||
editor.putInt(prefix + ".maxSize", mEditHistory.mmMaxHistorySize);
|
||||
editor.putInt(prefix + ".position", mEditHistory.mmPosition);
|
||||
editor.putInt(prefix + ".size", mEditHistory.mmHistory.size());
|
||||
|
||||
int i = 0;
|
||||
for (EditItem ei : mEditHistory.mmHistory) {
|
||||
String pre = prefix + "." + i;
|
||||
|
||||
editor.putInt(pre + ".start", ei.mmStart);
|
||||
editor.putString(pre + ".before", ei.mmBefore.toString());
|
||||
editor.putString(pre + ".after", ei.mmAfter.toString());
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore preferences.
|
||||
*
|
||||
* @param prefix The preference key prefix used when state was stored.
|
||||
* @return did restore succeed? If this is false, the undo history will be
|
||||
* empty.
|
||||
*/
|
||||
public boolean restorePersistentState(SharedPreferences sp, String prefix)
|
||||
throws IllegalStateException {
|
||||
|
||||
boolean ok = doRestorePersistentState(sp, prefix);
|
||||
if (!ok) {
|
||||
mEditHistory.clear();
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean doRestorePersistentState(SharedPreferences sp, String prefix) {
|
||||
|
||||
String hash = sp.getString(prefix + ".hash", null);
|
||||
if (hash == null) {
|
||||
// No state to be restored.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Integer.valueOf(hash) != mTextView.getText().toString().hashCode()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mEditHistory.clear();
|
||||
mEditHistory.mmMaxHistorySize = sp.getInt(prefix + ".maxSize", -1);
|
||||
|
||||
int count = sp.getInt(prefix + ".size", -1);
|
||||
if (count == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
String pre = prefix + "." + i;
|
||||
|
||||
int start = sp.getInt(pre + ".start", -1);
|
||||
String before = sp.getString(pre + ".before", null);
|
||||
String after = sp.getString(pre + ".after", null);
|
||||
|
||||
if (start == -1 || before == null || after == null) {
|
||||
return false;
|
||||
}
|
||||
mEditHistory.add(new EditItem(start, before, after));
|
||||
}
|
||||
|
||||
mEditHistory.mmPosition = sp.getInt(prefix + ".position", -1);
|
||||
if (mEditHistory.mmPosition == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// =================================================================== //
|
||||
|
||||
/**
|
||||
* Keeps track of all the edit history of a text.
|
||||
*/
|
||||
private final class EditHistory {
|
||||
|
||||
/**
|
||||
* The position from which an EditItem will be retrieved when getNext()
|
||||
* is called. If getPrevious() has not been called, this has the same
|
||||
* value as mmHistory.size().
|
||||
*/
|
||||
private int mmPosition = 0;
|
||||
|
||||
/**
|
||||
* Maximum undo history size.
|
||||
*/
|
||||
private int mmMaxHistorySize = -1;
|
||||
|
||||
/**
|
||||
* The list of edits in chronological order.
|
||||
*/
|
||||
private final LinkedList<EditItem> mmHistory = new LinkedList<EditItem>();
|
||||
|
||||
/**
|
||||
* Clear history.
|
||||
*/
|
||||
private void clear() {
|
||||
mmPosition = 0;
|
||||
mmHistory.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new edit operation to the history at the current position. If
|
||||
* executed after a call to getPrevious() removes all the future history
|
||||
* (elements with positions >= current history position).
|
||||
*/
|
||||
private void add(EditItem item) {
|
||||
while (mmHistory.size() > mmPosition) {
|
||||
mmHistory.removeLast();
|
||||
}
|
||||
mmHistory.add(item);
|
||||
mmPosition++;
|
||||
|
||||
if (mmMaxHistorySize >= 0) {
|
||||
trimHistory();
|
||||
}
|
||||
}
|
||||
|
||||
public int size(){
|
||||
return mmHistory.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum history size. If size is negative, then history size
|
||||
* is only limited by the device memory.
|
||||
*/
|
||||
private void setMaxHistorySize(int maxHistorySize) {
|
||||
mmMaxHistorySize = maxHistorySize;
|
||||
if (mmMaxHistorySize >= 0) {
|
||||
trimHistory();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim history when it exceeds max history size.
|
||||
*/
|
||||
private void trimHistory() {
|
||||
while (mmHistory.size() > mmMaxHistorySize) {
|
||||
mmHistory.removeFirst();
|
||||
mmPosition--;
|
||||
}
|
||||
|
||||
if (mmPosition < 0) {
|
||||
mmPosition = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the history backward by one position, returns and item at
|
||||
* that position.
|
||||
*/
|
||||
private EditItem getPrevious() {
|
||||
if (mmPosition == 0) {
|
||||
return null;
|
||||
}
|
||||
mmPosition--;
|
||||
return mmHistory.get(mmPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the history forward by one position, returns and item at
|
||||
* that position.
|
||||
*/
|
||||
private EditItem getNext() {
|
||||
if (mmPosition >= mmHistory.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EditItem item = mmHistory.get(mmPosition);
|
||||
mmPosition++;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the changes performed by a single edit operation.
|
||||
*/
|
||||
private final class EditItem {
|
||||
private final int mmStart;
|
||||
private final CharSequence mmBefore;
|
||||
private final CharSequence mmAfter;
|
||||
|
||||
/**
|
||||
* Constructs EditItem of a modification that was applied at position
|
||||
* start and replaced CharSequence before with CharSequence after.
|
||||
*/
|
||||
public EditItem(int start, CharSequence before, CharSequence after) {
|
||||
mmStart = start;
|
||||
mmBefore = before;
|
||||
mmAfter = after;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that listens to changes in the text.
|
||||
*/
|
||||
private final class EditTextChangeListener implements TextWatcher {
|
||||
|
||||
/**
|
||||
* The text that will be removed by the change event.
|
||||
*/
|
||||
private CharSequence mBeforeChange;
|
||||
|
||||
/**
|
||||
* The text that was inserted by the change event.
|
||||
*/
|
||||
private CharSequence mAfterChange;
|
||||
|
||||
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||
int after) {
|
||||
if (mIsUndoOrRedo || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
mBeforeChange = s.subSequence(start, start + count);
|
||||
}
|
||||
|
||||
public void onTextChanged(CharSequence s, int start, int before,
|
||||
int count) {
|
||||
if (mIsUndoOrRedo || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAfterChange = s.subSequence(start, start + count);
|
||||
mEditHistory.add(new EditItem(start, mBeforeChange, mAfterChange));
|
||||
}
|
||||
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (mEditHistory.size() < mInitialHistoryStackSize) {
|
||||
mInitialHistoryStackSize = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package org.autojs.autojs.ui.edit.toolbar;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
@@ -10,25 +9,23 @@ import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
import com.stardust.autojs.engine.RhinoJavaScriptEngine;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.rhino.debug.Dim;
|
||||
import com.stardust.autojs.rhino.debug.DebugCallback;
|
||||
import com.stardust.autojs.rhino.debug.Debugger;
|
||||
import com.stardust.autojs.rhino.debug.Dim;
|
||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import com.stardust.pio.PFiles;
|
||||
|
||||
import org.androidannotations.annotations.Click;
|
||||
import org.androidannotations.annotations.EFragment;
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.ui.edit.EditorView;
|
||||
import org.autojs.autojs.ui.edit.debug.CodeEvaluator;
|
||||
import org.autojs.autojs.ui.edit.debug.DebugBar;
|
||||
import org.autojs.autojs.ui.edit.debug.DebuggerSingleton;
|
||||
import org.autojs.autojs.ui.edit.debug.WatchingVariable;
|
||||
import org.autojs.autojs.ui.edit.editor.CodeEditor;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -36,15 +33,14 @@ import java.util.List;
|
||||
public class DebugToolbarFragment extends ToolbarFragment implements DebugCallback, CodeEditor.CursorChangeCallback, CodeEvaluator {
|
||||
|
||||
private static final String LOG_TAG = "DebugToolbarFragment";
|
||||
private Dim mDim;
|
||||
private EditorView mEditorView;
|
||||
private boolean mCursorChangeFromUser = true;
|
||||
private Debugger mDebugger;
|
||||
private Handler mHandler;
|
||||
private boolean mSkipOtherFileBreakpoint = false;
|
||||
private String mCurrentEditorSourceUrl;
|
||||
private String mInitialEditorSourceUrl;
|
||||
private String mInitialEditorSource;
|
||||
private boolean mCursorChangeFromUser = true;
|
||||
private Dim.SourceInfo mSourceInfo;
|
||||
|
||||
private final RecyclerView.AdapterDataObserver mVariableChangeObserver = new RecyclerView.AdapterDataObserver() {
|
||||
@Override
|
||||
public void onItemRangeInserted(int positionStart, int itemCount) {
|
||||
@@ -54,21 +50,17 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
private CodeEditor.BreakpointChangeListener mBreakpointChangeListener = new CodeEditor.BreakpointChangeListener() {
|
||||
@Override
|
||||
public void onBreakpointChange(int line, boolean enabled) {
|
||||
if (mSourceInfo != null) {
|
||||
mSourceInfo.breakpoint(line + 1, enabled);
|
||||
if (mDebugger != null) {
|
||||
mDebugger.breakpoint(line + 1, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllBreakpointRemoved(int count) {
|
||||
mDim.clearAllBreakpoints();
|
||||
mDebugger.clearAllBreakpoints();
|
||||
}
|
||||
};
|
||||
|
||||
public DebugToolbarFragment() {
|
||||
Log.d(LOG_TAG, "DebugToolbarFragment()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -79,13 +71,13 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mEditorView = findEditorView(view);
|
||||
mDim = createDim();
|
||||
mDebugger = DebuggerSingleton.get();
|
||||
mDebugger.setWeakDebugCallback(new WeakReference<>(this));
|
||||
setInterrupted(false);
|
||||
mSkipOtherFileBreakpoint = true;
|
||||
mCurrentEditorSourceUrl = mInitialEditorSourceUrl = mEditorView.getFile().toString();
|
||||
mInitialEditorSource = mEditorView.getEditor().getText();
|
||||
setupEditor();
|
||||
mEditorView.run(false);
|
||||
mDebugger.attach(mEditorView.run(false));
|
||||
Log.d(LOG_TAG, "onViewCreated");
|
||||
}
|
||||
|
||||
@@ -97,16 +89,6 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
DebugBar debugBar = mEditorView.getDebugBar();
|
||||
debugBar.registerVariableChangeObserver(mVariableChangeObserver);
|
||||
debugBar.setCodeEvaluator(this);
|
||||
|
||||
}
|
||||
|
||||
private Dim createDim() {
|
||||
Dim dim = new Dim();
|
||||
dim.setBreak();
|
||||
dim.setBreakOnExceptions(true);
|
||||
dim.attachTo(AutoJs.getInstance().getScriptEngineService(), ContextFactory.getGlobal());
|
||||
dim.setGuiCallback(this);
|
||||
return dim;
|
||||
}
|
||||
|
||||
private void setInterrupted(boolean interrupted) {
|
||||
@@ -120,19 +102,15 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
}
|
||||
|
||||
public void detachDebugger() {
|
||||
if (!mDim.isAttached()) {
|
||||
if (!mDebugger.isAttached()) {
|
||||
return;
|
||||
}
|
||||
Log.d(LOG_TAG, "detachDebugger");
|
||||
mDim.detach();
|
||||
mDim.setGuiCallback(null);
|
||||
mDebugger.detach();
|
||||
if (mEditorView == null) {
|
||||
return;
|
||||
}
|
||||
CodeEditor editor = mEditorView.getEditor();
|
||||
editor.removeCursorChangeCallback(this);
|
||||
editor.setBreakpointChangeListener(null);
|
||||
mSourceInfo = null;
|
||||
editor.setRedoUndoEnabled(true);
|
||||
if (!TextUtils.equals(mInitialEditorSourceUrl, mCurrentEditorSourceUrl)) {
|
||||
editor.setText(mInitialEditorSource);
|
||||
@@ -140,25 +118,24 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
DebugBar debugBar = mEditorView.getDebugBar();
|
||||
debugBar.setTitle(null);
|
||||
debugBar.setCodeEvaluator(null);
|
||||
debugBar.unregisterVariableChangeObserver(mVariableChangeObserver);
|
||||
}
|
||||
|
||||
@Click(R.id.step_over)
|
||||
void stepOver() {
|
||||
setInterrupted(false);
|
||||
mDim.setReturnValue(Dim.STEP_OVER);
|
||||
mDebugger.stepOver();
|
||||
}
|
||||
|
||||
@Click(R.id.step_into)
|
||||
void stepInto() {
|
||||
setInterrupted(false);
|
||||
mDim.setReturnValue(Dim.STEP_INTO);
|
||||
mDebugger.stepInto();
|
||||
}
|
||||
|
||||
@Click(R.id.step_out)
|
||||
void stepOut() {
|
||||
setInterrupted(false);
|
||||
mDim.setReturnValue(Dim.STEP_OUT);
|
||||
mDebugger.stepOut();
|
||||
}
|
||||
|
||||
@Click(R.id.stop_script)
|
||||
@@ -169,15 +146,12 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
@Click(R.id.resume_script)
|
||||
void resumeScript() {
|
||||
setInterrupted(false);
|
||||
mDim.setReturnValue(Dim.GO);
|
||||
mDebugger.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSourceText(Dim.SourceInfo sourceInfo) {
|
||||
Log.d(LOG_TAG, "updateSourceText: url = " + sourceInfo.url());
|
||||
if (!sourceInfo.url().equals(mEditorView.getFile().toString())) {
|
||||
return;
|
||||
}
|
||||
sourceInfo.removeAllBreakpoints();
|
||||
for (CodeEditor.Breakpoint breakpoint : mEditorView.getEditor().getBreakpoints().values()) {
|
||||
int line = breakpoint.line + 1;
|
||||
@@ -186,18 +160,10 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
Log.d(LOG_TAG, "not breakable: " + line);
|
||||
}
|
||||
}
|
||||
mSourceInfo = sourceInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterInterrupt(Dim.StackFrame stackFrame, String threadName, String message) {
|
||||
Log.d(LOG_TAG, "enterInterrupt: threadName = " + threadName + ", url = " + stackFrame.getUrl() + ", line = " + stackFrame.getLineNumber());
|
||||
//刚启动调试时会在init脚本的第一行自动停下,此时应该让脚本继续运行
|
||||
if (mSkipOtherFileBreakpoint && !stackFrame.getUrl().equals(mInitialEditorSourceUrl) && message == null) {
|
||||
mHandler.post(this::resumeScript);
|
||||
return;
|
||||
}
|
||||
mSkipOtherFileBreakpoint = false;
|
||||
showDebuggingLineOnEditor(stackFrame, message);
|
||||
mHandler.post(this::updateWatchingVariables);
|
||||
}
|
||||
@@ -207,7 +173,7 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
}
|
||||
|
||||
private void updateWatchingVariables(int start, int end) {
|
||||
if (!mDim.isAttached()) {
|
||||
if (!mDebugger.isAttached()) {
|
||||
return;
|
||||
}
|
||||
DebugBar debugBar = mEditorView.getDebugBar();
|
||||
@@ -221,11 +187,7 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
}
|
||||
|
||||
public String eval(String expr) {
|
||||
if (expr == null || !mDim.isAttached() || !mDim.stringIsCompilableUnit(expr)) {
|
||||
return null;
|
||||
}
|
||||
mDim.contextSwitch(0);
|
||||
return mDim.eval(expr);
|
||||
return mDebugger.eval(expr);
|
||||
}
|
||||
|
||||
private void showDebuggingLineOnEditor(Dim.StackFrame stackFrame, String message) {
|
||||
@@ -258,21 +220,6 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGuiEventThread() {
|
||||
return Looper.getMainLooper() == Looper.myLooper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchNextGuiEvent() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAttachDebugger(RhinoJavaScriptEngine engine) {
|
||||
ScriptExecution execution = mEditorView.getScriptExecution();
|
||||
return execution != null && execution.getId() == engine.getId();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCursorChange(String line, int ch) {
|
||||
@@ -281,7 +228,7 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
return;
|
||||
}
|
||||
mCursorChangeFromUser = true;
|
||||
if (!mDim.isAttached()) {
|
||||
if (!mDebugger.isAttached()) {
|
||||
return;
|
||||
}
|
||||
String variable = findVariableOnCursor(line, ch);
|
||||
@@ -322,6 +269,13 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
detachDebugger();
|
||||
if (mEditorView == null) {
|
||||
return;
|
||||
}
|
||||
CodeEditor editor = mEditorView.getEditor();
|
||||
editor.removeCursorChangeCallback(this);
|
||||
editor.setBreakpointChangeListener(null);
|
||||
DebugBar debugBar = mEditorView.getDebugBar();
|
||||
debugBar.unregisterVariableChangeObserver(mVariableChangeObserver);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user