mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-21 21:01:43 +08:00
feat(debug): supports debugging across files; supports watching variables; supports evaluate code on debug;
This commit is contained in:
parent
5329278e8d
commit
a2c46d0787
@ -10,6 +10,7 @@ import com.stardust.pio.PFiles;
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.ui.build.BuildActivity;
|
||||
import org.autojs.autojs.ui.build.BuildActivity_;
|
||||
import org.autojs.autojs.ui.common.NotAskAgainDialog;
|
||||
import org.autojs.autojs.ui.edit.editor.CodeEditor;
|
||||
import org.autojs.autojs.ui.log.LogActivity_;
|
||||
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
@ -68,7 +69,15 @@ public class EditorMenu {
|
||||
mEditor.addOrRemoveBreakpointAtCurrentLine();
|
||||
return true;
|
||||
case R.id.action_launch_debugger:
|
||||
mEditorView.launchDebugger();
|
||||
new NotAskAgainDialog.Builder(mEditorView.getContext(), "editor.debug.long_click_hint")
|
||||
.title(R.string.text_alert)
|
||||
.content(R.string.hint_long_click_run_to_debug)
|
||||
.positiveText(R.string.ok)
|
||||
.show();
|
||||
mEditorView.debug();
|
||||
return true;
|
||||
case R.id.action_remove_all_breakpoints:
|
||||
mEditor.removeAllBreakpoints();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -48,6 +48,7 @@ import org.autojs.autojs.model.indices.Property;
|
||||
import org.autojs.autojs.model.script.Scripts;
|
||||
import org.autojs.autojs.ui.doc.ManualDialog;
|
||||
import org.autojs.autojs.ui.edit.completion.CodeCompletionBar;
|
||||
import org.autojs.autojs.ui.edit.debug.DebugBar;
|
||||
import org.autojs.autojs.ui.edit.editor.CodeEditor;
|
||||
import org.autojs.autojs.ui.edit.keyboard.FunctionsKeyboardHelper;
|
||||
import org.autojs.autojs.ui.edit.keyboard.FunctionsKeyboardView;
|
||||
@ -104,6 +105,9 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
@ViewById(R.id.functions_keyboard)
|
||||
FunctionsKeyboardView mFunctionsKeyboard;
|
||||
|
||||
@ViewById(R.id.debug_bar)
|
||||
DebugBar mDebugBar;
|
||||
|
||||
@ViewById(R.id.docs)
|
||||
EWebView mDocsWebView;
|
||||
|
||||
@ -273,8 +277,15 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
|
||||
private void initNormalToolbar() {
|
||||
mNormalToolbar.setOnMenuItemClickListener(this);
|
||||
mNormalToolbar.setOnMenuItemLongClickListener(id -> {
|
||||
if(id == R.id.run){
|
||||
debug();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
Fragment fragment = getActivity().getSupportFragmentManager().findFragmentById(R.id.toolbar_menu);
|
||||
if(fragment == null){
|
||||
if (fragment == null) {
|
||||
showNormalToolbar();
|
||||
}
|
||||
}
|
||||
@ -304,7 +315,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
setMenuItemStatus(R.id.undo, mEditor.canUndo());
|
||||
setMenuItemStatus(R.id.redo, mEditor.canRedo());
|
||||
}));
|
||||
mEditor.setCursorChangeCallback(this::autoComplete);
|
||||
mEditor.addCursorChangeCallback(this::autoComplete);
|
||||
mEditor.getCodeEditText().setTextSize(Pref.getEditorTextSize((int) ViewUtils.pxToSp(getContext(), mEditor.getCodeEditText().getTextSize())));
|
||||
}
|
||||
|
||||
@ -312,6 +323,10 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
mAutoCompletion.onCursorChange(line, cursor);
|
||||
}
|
||||
|
||||
public DebugBar getDebugBar() {
|
||||
return mDebugBar;
|
||||
}
|
||||
|
||||
public void setTheme(Theme theme) {
|
||||
mEditorTheme = theme;
|
||||
mEditor.setTheme(theme);
|
||||
@ -368,11 +383,13 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
@SuppressLint("CheckResult")
|
||||
public void runAndSaveFileIfNeeded() {
|
||||
save().observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(s -> run());
|
||||
.subscribe(s -> run(true));
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
|
||||
public void run(boolean showMessage) {
|
||||
if(showMessage){
|
||||
Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
mScriptExecutionId = Scripts.runWithBroadcastSender(mFile).getId();
|
||||
setMenuItemStatus(R.id.run, false);
|
||||
}
|
||||
@ -534,12 +551,14 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
}
|
||||
|
||||
|
||||
public void launchDebugger() {
|
||||
public void debug() {
|
||||
DebugToolbarFragment debugToolbarFragment = DebugToolbarFragment_.builder()
|
||||
.build();
|
||||
getActivity().getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.toolbar_menu, debugToolbarFragment)
|
||||
.commit();
|
||||
mDebugBar.setVisibility(VISIBLE);
|
||||
mInputMethodEnhanceBar.setVisibility(GONE);
|
||||
mDebugging = true;
|
||||
}
|
||||
|
||||
@ -551,6 +570,8 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
}
|
||||
showNormalToolbar();
|
||||
mEditor.setDebuggingLine(-1);
|
||||
mDebugBar.setVisibility(GONE);
|
||||
mInputMethodEnhanceBar.setVisibility(VISIBLE);
|
||||
mDebugging = false;
|
||||
}
|
||||
|
||||
@ -622,7 +643,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ScriptExecution getScriptExecution(){
|
||||
public ScriptExecution getScriptExecution() {
|
||||
return AutoJs.getInstance().getScriptEngineService().getScriptExecution(mScriptExecutionId);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
package org.autojs.autojs.ui.edit.debug;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
|
||||
public class CodeEvaluateDialogBuilder extends ThemeColorMaterialDialogBuilder {
|
||||
|
||||
private static final String KEY_CODE = CodeEvaluateDialogBuilder.class.getName() + ".code";
|
||||
private CodeEvaluator mCodeEvaluator;
|
||||
private TextView mResult;
|
||||
private EditText mCode;
|
||||
private SharedPreferences mSharedPreferences;
|
||||
|
||||
public CodeEvaluateDialogBuilder(@NonNull Context context) {
|
||||
super(context);
|
||||
setupViews();
|
||||
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
mCode.setText(mSharedPreferences.getString(KEY_CODE, ""));
|
||||
}
|
||||
|
||||
private void setupViews() {
|
||||
View view = View.inflate(context, R.layout.dialog_code_evaluate, null);
|
||||
customView(view, true);
|
||||
mResult = view.findViewById(R.id.result);
|
||||
mCode = view.findViewById(R.id.code);
|
||||
positiveText(R.string.text_run);
|
||||
negativeText(R.string.text_close);
|
||||
autoDismiss(false);
|
||||
onNegative((dialog, which) -> dialog.dismiss());
|
||||
onPositive(((dialog, which) -> {
|
||||
Editable code = mCode.getText();
|
||||
if (!TextUtils.isEmpty(code)) {
|
||||
String codeStr = code.toString();
|
||||
mSharedPreferences.edit().putString(KEY_CODE, codeStr).apply();
|
||||
mResult.setText(mCodeEvaluator.eval(codeStr));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public CodeEvaluateDialogBuilder codeEvaluator(CodeEvaluator evaluator) {
|
||||
mCodeEvaluator = evaluator;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package org.autojs.autojs.ui.edit.debug;
|
||||
|
||||
public interface CodeEvaluator {
|
||||
String eval(String code);
|
||||
}
|
||||
165
app/src/main/java/org/autojs/autojs/ui/edit/debug/DebugBar.java
Normal file
165
app/src/main/java/org/autojs/autojs/ui/edit/debug/DebugBar.java
Normal file
@ -0,0 +1,165 @@
|
||||
package org.autojs.autojs.ui.edit.debug;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.util.ClipboardUtil;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||
import org.autojs.autojs.ui.widget.AutoAdapter;
|
||||
import org.autojs.autojs.ui.widget.BindableViewHolder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class DebugBar extends FrameLayout {
|
||||
|
||||
private AutoAdapter<WatchingVariable> mVariablesAdapter;
|
||||
private final WatchingVariable mCurrentVariable = new WatchingVariable(null, null, true);
|
||||
private TextView mTitle;
|
||||
private CodeEvaluator mCodeEvaluator;
|
||||
|
||||
public DebugBar(@NonNull Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public DebugBar(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public DebugBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
public void setCodeEvaluator(CodeEvaluator codeEvaluator) {
|
||||
mCodeEvaluator = codeEvaluator;
|
||||
}
|
||||
|
||||
public List<WatchingVariable> getWatchingVariables() {
|
||||
return mVariablesAdapter.getData();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
inflate(getContext(), R.layout.debug_bar, this);
|
||||
mVariablesAdapter = new AutoAdapter<>(VariableViewHolder::new, R.layout.item_debug_variable_recycler_view);
|
||||
RecyclerView variablesView = findViewById(R.id.variables);
|
||||
variablesView.setAdapter(mVariablesAdapter);
|
||||
variablesView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
mVariablesAdapter.add(mCurrentVariable);
|
||||
findViewById(R.id.add).setOnClickListener(view -> showNewWatchingVariableDialog());
|
||||
findViewById(R.id.execute).setOnClickListener(view -> showExecuteCodeDialog());
|
||||
mTitle = findViewById(R.id.title);
|
||||
}
|
||||
|
||||
private void showExecuteCodeDialog() {
|
||||
if (mCodeEvaluator == null) {
|
||||
return;
|
||||
}
|
||||
new CodeEvaluateDialogBuilder(getContext())
|
||||
.codeEvaluator(mCodeEvaluator)
|
||||
.title(R.string.text_execute_code)
|
||||
.show();
|
||||
}
|
||||
|
||||
|
||||
public void setTitle(String title) {
|
||||
if (title == null) {
|
||||
mTitle.setText(R.string.text_debug);
|
||||
} else {
|
||||
mTitle.setText(getResources().getString(R.string.format_debug_bar_title, title));
|
||||
}
|
||||
}
|
||||
|
||||
private void showNewWatchingVariableDialog() {
|
||||
new ThemeColorMaterialDialogBuilder(getContext())
|
||||
.title(R.string.text_new_watching_variable)
|
||||
.input(getResources().getString(R.string.text_variable_or_expr), "", (dialog, input) -> {
|
||||
if (TextUtils.isEmpty(input)) {
|
||||
return;
|
||||
}
|
||||
mVariablesAdapter.add(new WatchingVariable(input.toString()));
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
public void updateCurrentVariable(String name, String value) {
|
||||
mCurrentVariable.setDisplayName(name);
|
||||
mCurrentVariable.setName(name);
|
||||
mCurrentVariable.setValue(value);
|
||||
mVariablesAdapter.notifyItemChanged(0);
|
||||
}
|
||||
|
||||
public void refresh(int start, int count) {
|
||||
mVariablesAdapter.notifyItemRangeChanged(start, count);
|
||||
}
|
||||
|
||||
public void registerVariableChangeObserver(RecyclerView.AdapterDataObserver observer) {
|
||||
mVariablesAdapter.registerAdapterDataObserver(observer);
|
||||
}
|
||||
|
||||
public void unregisterVariableChangeObserver(RecyclerView.AdapterDataObserver observer) {
|
||||
mVariablesAdapter.unregisterAdapterDataObserver(observer);
|
||||
}
|
||||
|
||||
|
||||
private void showVariable(WatchingVariable variable) {
|
||||
new ThemeColorMaterialDialogBuilder(getContext())
|
||||
.title(variable.getDisplayName())
|
||||
.content(variable.getValue())
|
||||
.positiveText(R.string.ok)
|
||||
.negativeText(R.string.text_copy_value)
|
||||
.autoDismiss(true)
|
||||
.onNegative((dialog, which) -> ClipboardUtil.setClip(getContext(), variable.getValue()))
|
||||
.show();
|
||||
}
|
||||
|
||||
|
||||
class VariableViewHolder extends BindableViewHolder<WatchingVariable> {
|
||||
|
||||
private final TextView mVariable;
|
||||
private final ImageView mIcon;
|
||||
|
||||
VariableViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
mVariable = itemView.findViewById(R.id.variable);
|
||||
mIcon = itemView.findViewById(R.id.icon);
|
||||
mIcon.setOnClickListener(view -> {
|
||||
int pos = getAdapterPosition();
|
||||
WatchingVariable variable = mVariablesAdapter.get(pos);
|
||||
if (!variable.isPinned()) {
|
||||
mVariablesAdapter.remove(pos);
|
||||
}
|
||||
});
|
||||
itemView.setOnClickListener(view -> {
|
||||
int pos = getAdapterPosition();
|
||||
WatchingVariable variable = mVariablesAdapter.get(pos);
|
||||
showVariable(variable);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(WatchingVariable data, int position) {
|
||||
if (TextUtils.isEmpty(data.getDisplayName())) {
|
||||
mVariable.setText("");
|
||||
} else {
|
||||
mVariable.setText(String.format("%s = %s", data.getDisplayName(), data.getSingleLineValue()));
|
||||
}
|
||||
mIcon.setVisibility(data.isPinned() ? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package org.autojs.autojs.ui.edit.debug;
|
||||
|
||||
public class WatchingVariable {
|
||||
|
||||
private String mDisplayName;
|
||||
private String mName;
|
||||
private final boolean mPinned;
|
||||
private String mValue;
|
||||
private String mSingleLineValue;
|
||||
|
||||
public WatchingVariable(String displayName, String name, boolean pinned) {
|
||||
mDisplayName = displayName;
|
||||
mName = name;
|
||||
mPinned = pinned;
|
||||
}
|
||||
|
||||
public WatchingVariable(String name) {
|
||||
this(name, name, false);
|
||||
}
|
||||
|
||||
public boolean isPinned() {
|
||||
return mPinned;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
mValue = value;
|
||||
mSingleLineValue = value == null ? null : value.replaceAll("\n", " ");
|
||||
}
|
||||
|
||||
public String getSingleLineValue() {
|
||||
return mSingleLineValue;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
mDisplayName = displayName;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return mDisplayName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
}
|
||||
@ -32,18 +32,16 @@ import android.util.Log;
|
||||
import android.util.TimingLogger;
|
||||
import android.view.Gravity;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.ui.edit.theme.Theme;
|
||||
import org.autojs.autojs.ui.edit.theme.TokenMapping;
|
||||
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.util.ClipboardUtil;
|
||||
import com.stardust.util.TextUtils;
|
||||
|
||||
import org.mozilla.javascript.Token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import static org.autojs.autojs.ui.edit.editor.BracketMatching.UNMATCHED_BRACKET;
|
||||
|
||||
@ -60,7 +58,7 @@ public class CodeEditText extends AppCompatEditText {
|
||||
// 文字范围
|
||||
protected HVScrollView mParentScrollView;
|
||||
|
||||
private CodeEditor.CursorChangeCallback mCallback;
|
||||
private final CopyOnWriteArrayList<CodeEditor.CursorChangeCallback> mCursorChangeCallbacks = new CopyOnWriteArrayList<>();
|
||||
private volatile JavaScriptHighlighter.HighlightTokens mHighlightTokens;
|
||||
private Theme mTheme;
|
||||
private TimingLogger mLogger = new TimingLogger(LOG_TAG, "draw");
|
||||
@ -110,6 +108,11 @@ public class CodeEditText extends AppCompatEditText {
|
||||
if (mParentScrollView == null) {
|
||||
mParentScrollView = (HVScrollView) getParent();
|
||||
}
|
||||
if (getLayout() == null) {
|
||||
super.onDraw(canvas);
|
||||
invalidate();
|
||||
return;
|
||||
}
|
||||
updatePaddingForGutter();
|
||||
updateLineRangeForDraw(canvas);
|
||||
|
||||
@ -266,8 +269,12 @@ public class CodeEditText extends AppCompatEditText {
|
||||
if (line < mFirstLineForDraw || line > mLastLineForDraw || mFirstLineForDraw < 0 || line < 0) {
|
||||
return;
|
||||
}
|
||||
int lineTop = getLayout().getLineTop(line);
|
||||
int lineBottom = getLayout().getLineTop(line + 1);
|
||||
Layout layout = getLayout();
|
||||
if(layout == null){
|
||||
return;
|
||||
}
|
||||
int lineTop = layout.getLineTop(line);
|
||||
int lineBottom = layout.getLineTop(line + 1);
|
||||
canvas.drawRect(0, lineTop, canvas.getWidth(), lineBottom, paint);
|
||||
}
|
||||
|
||||
@ -322,7 +329,8 @@ public class CodeEditText extends AppCompatEditText {
|
||||
protected void onSelectionChanged(int selStart, int selEnd) {
|
||||
//调用父类的onSelectionChanged时会发送一个AccessibilityEvent,当文本过大时造成异常
|
||||
//super.onSelectionChanged(selStart, selEnd);
|
||||
if (mCallback == null || selStart != selEnd) {
|
||||
//父类构造函数会调用onSelectionChanged, 此时mCursorChangeCallbacks还没有初始化
|
||||
if (mCursorChangeCallbacks == null || mCursorChangeCallbacks.isEmpty() || selStart != selEnd) {
|
||||
return;
|
||||
}
|
||||
callCursorChangeCallback(getText(), selStart);
|
||||
@ -365,7 +373,7 @@ public class CodeEditText extends AppCompatEditText {
|
||||
if (text.length() == 0) {
|
||||
return;
|
||||
}
|
||||
if (mCallback == null)
|
||||
if (mCursorChangeCallbacks.isEmpty())
|
||||
return;
|
||||
int lineStart = TextUtils.lastIndexOf(text, '\n', sel - 1) + 1;
|
||||
if (lineStart < 0) {
|
||||
@ -382,13 +390,21 @@ public class CodeEditText extends AppCompatEditText {
|
||||
return;
|
||||
String line = text.subSequence(lineStart, lineEnd).toString();
|
||||
int cursor = sel - lineStart;
|
||||
mCallback.onCursorChange(line, cursor);
|
||||
for(CodeEditor.CursorChangeCallback callback : mCursorChangeCallbacks){
|
||||
callback.onCursorChange(line, cursor);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCursorChangeCallback(CodeEditor.CursorChangeCallback callback) {
|
||||
mCallback = callback;
|
||||
public void addCursorChangeCallback(CodeEditor.CursorChangeCallback callback) {
|
||||
mCursorChangeCallbacks.add(callback);
|
||||
}
|
||||
|
||||
public boolean removeCursorChangeCallback(CodeEditor.CursorChangeCallback callback) {
|
||||
return mCursorChangeCallbacks.remove(callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void updateHighlightTokens(JavaScriptHighlighter.HighlightTokens highlightTokens) {
|
||||
mHighlightTokens = highlightTokens;
|
||||
postInvalidate();
|
||||
@ -427,7 +443,7 @@ public class CodeEditText extends AppCompatEditText {
|
||||
Parcelable superData = bundle.getParcelable("super_data");
|
||||
mDebuggingLine = bundle.getInt("debugging_line", -1);
|
||||
int[] breakpoints = bundle.getIntArray("breakpoints");
|
||||
if(breakpoints != null){
|
||||
if (breakpoints != null) {
|
||||
for (int breakpoint : breakpoints) {
|
||||
mBreakpoints.put(breakpoint, new CodeEditor.Breakpoint(breakpoint));
|
||||
}
|
||||
|
||||
@ -176,9 +176,14 @@ public class CodeEditor extends HVScrollView {
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
setEnabled(!readOnly);
|
||||
mCodeEditText.setEnabled(!readOnly);
|
||||
}
|
||||
|
||||
public void setRedoUndoEnabled(boolean enabled) {
|
||||
mTextViewRedoUndo.setEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
public void setProgress(boolean progress) {
|
||||
if (progress) {
|
||||
if (mProcessDialog != null) {
|
||||
@ -202,8 +207,12 @@ public class CodeEditor extends HVScrollView {
|
||||
mCodeEditText.setText(text);
|
||||
}
|
||||
|
||||
public void setCursorChangeCallback(CursorChangeCallback callback) {
|
||||
mCodeEditText.setCursorChangeCallback(callback);
|
||||
public void addCursorChangeCallback(CursorChangeCallback callback) {
|
||||
mCodeEditText.addCursorChangeCallback(callback);
|
||||
}
|
||||
|
||||
public boolean removeCursorChangeCallback(CursorChangeCallback callback) {
|
||||
return mCodeEditText.removeCursorChangeCallback(callback);
|
||||
}
|
||||
|
||||
|
||||
@ -337,7 +346,6 @@ public class CodeEditor extends HVScrollView {
|
||||
}
|
||||
|
||||
public void setDebuggingLine(int line) {
|
||||
jumpTo(line, 0);
|
||||
mCodeEditText.setDebuggingLine(line);
|
||||
}
|
||||
|
||||
@ -356,6 +364,11 @@ public class CodeEditor extends HVScrollView {
|
||||
addOrRemoveBreakpoint(line);
|
||||
}
|
||||
|
||||
public void removeAllBreakpoints(){
|
||||
mCodeEditText.getBreakpoints().clear();
|
||||
mCodeEditText.invalidate();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
|
||||
@ -42,6 +42,7 @@ public class TextViewRedoUndo {
|
||||
private boolean flag = false;
|
||||
|
||||
private int mInitialHistoryStackSize;
|
||||
private boolean mEnabled = true;
|
||||
|
||||
public TextViewRedoUndo(@NonNull EditText editText) {
|
||||
this.editable = editText.getText();
|
||||
@ -156,6 +157,14 @@ public class TextViewRedoUndo {
|
||||
mInitialHistoryStackSize = history.size();
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
mEnabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
private class Watcher implements TextWatcher {
|
||||
|
||||
/**
|
||||
@ -168,6 +177,9 @@ public class TextViewRedoUndo {
|
||||
*/
|
||||
@Override
|
||||
public final void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
if (!editText.isEnabled() || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
if (flag) return;
|
||||
int end = start + count;
|
||||
if (end > start && end <= s.length()) {
|
||||
@ -201,6 +213,9 @@ public class TextViewRedoUndo {
|
||||
*/
|
||||
@Override
|
||||
public final void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (!editText.isEnabled() || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
if (flag) return;
|
||||
int end = start + count;
|
||||
if (end > start) {
|
||||
@ -223,6 +238,9 @@ public class TextViewRedoUndo {
|
||||
|
||||
@Override
|
||||
public final void afterTextChanged(Editable s) {
|
||||
if (!editText.isEnabled() || !mEnabled) {
|
||||
return;
|
||||
}
|
||||
if (flag) return;
|
||||
if (s != editable) {
|
||||
editable = s;
|
||||
|
||||
@ -4,20 +4,28 @@ 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;
|
||||
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.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.WatchingVariable;
|
||||
import org.autojs.autojs.ui.edit.editor.CodeEditor;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
|
||||
@ -25,12 +33,23 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@EFragment(R.layout.fragment_debug_toolbar)
|
||||
public class DebugToolbarFragment extends ToolbarFragment implements DebugCallback {
|
||||
public class DebugToolbarFragment extends ToolbarFragment implements DebugCallback, CodeEditor.CursorChangeCallback, CodeEvaluator {
|
||||
|
||||
private static final String LOG_TAG = "DebugToolbarFragment";
|
||||
private Dim mDim;
|
||||
private EditorView mEditorView;
|
||||
private Handler mHandler;
|
||||
private boolean mSkipOtherFileBreakpoint = false;
|
||||
private String mCurrentEditorSourceUrl;
|
||||
private String mInitialEditorSourceUrl;
|
||||
private String mInitialEditorSource;
|
||||
private boolean mCursorChangeFromUser = true;
|
||||
private final RecyclerView.AdapterDataObserver mVariableChangeObserver = new RecyclerView.AdapterDataObserver() {
|
||||
@Override
|
||||
public void onItemRangeInserted(int positionStart, int itemCount) {
|
||||
updateWatchingVariables(positionStart, positionStart + itemCount);
|
||||
}
|
||||
};
|
||||
|
||||
public DebugToolbarFragment() {
|
||||
Log.d(LOG_TAG, "DebugToolbarFragment()");
|
||||
@ -46,37 +65,64 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mEditorView = findEditorView(view);
|
||||
ScriptExecution scriptExecution = mEditorView.getScriptExecution();
|
||||
if (scriptExecution != null) {
|
||||
mDim = (Dim) scriptExecution.getEngine().getTag(Dim.TAG);
|
||||
}
|
||||
if (mDim == null) {
|
||||
mDim = new Dim();
|
||||
mDim.setBreak();
|
||||
mDim.setBreakOnExceptions(true);
|
||||
mDim.attachTo(AutoJs.getInstance().getScriptEngineService(), ContextFactory.getGlobal());
|
||||
mDim.setGuiCallback(this);
|
||||
setInterrupted(false);
|
||||
mEditorView.run();
|
||||
} else {
|
||||
mDim.setGuiCallback(this);
|
||||
}
|
||||
mDim = createDim();
|
||||
setInterrupted(false);
|
||||
mSkipOtherFileBreakpoint = true;
|
||||
mCurrentEditorSourceUrl = mInitialEditorSourceUrl = mEditorView.getFile().toString();
|
||||
mInitialEditorSource = mEditorView.getEditor().getText();
|
||||
setupEditor();
|
||||
mEditorView.run(false);
|
||||
Log.d(LOG_TAG, "onViewCreated");
|
||||
}
|
||||
|
||||
private void setupEditor() {
|
||||
CodeEditor editor = mEditorView.getEditor();
|
||||
editor.setRedoUndoEnabled(false);
|
||||
editor.addCursorChangeCallback(this);
|
||||
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) {
|
||||
setMenuItemStatus(R.id.step_into, interrupted);
|
||||
setMenuItemStatus(R.id.step_over, interrupted);
|
||||
setMenuItemStatus(R.id.step_out, interrupted);
|
||||
setMenuItemStatus(R.id.resume_script, interrupted);
|
||||
if (!interrupted) {
|
||||
if (!interrupted && mEditorView != null) {
|
||||
mEditorView.getEditor().setDebuggingLine(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void detachDebugger() {
|
||||
if (!mDim.isAttached()) {
|
||||
return;
|
||||
}
|
||||
mDim.detach();
|
||||
mDim.setGuiCallback(null);
|
||||
if (mEditorView == null) {
|
||||
return;
|
||||
}
|
||||
CodeEditor editor = mEditorView.getEditor();
|
||||
editor.removeCursorChangeCallback(this);
|
||||
editor.setRedoUndoEnabled(true);
|
||||
if (!TextUtils.equals(mInitialEditorSourceUrl, mCurrentEditorSourceUrl)) {
|
||||
editor.setText(mInitialEditorSource);
|
||||
}
|
||||
DebugBar debugBar = mEditorView.getDebugBar();
|
||||
debugBar.setTitle(null);
|
||||
debugBar.setCodeEvaluator(null);
|
||||
debugBar.unregisterVariableChangeObserver(mVariableChangeObserver);
|
||||
}
|
||||
|
||||
@Click(R.id.step_over)
|
||||
@ -125,18 +171,72 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterInterrupt(Dim.StackFrame stackFrame, String threadName, String s1) {
|
||||
public void enterInterrupt(Dim.StackFrame stackFrame, String threadName, String message) {
|
||||
Log.d(LOG_TAG, "enterInterrupt: threadName = " + threadName + ", url = " + stackFrame.getUrl() + ", line = " + stackFrame.getLineNumber());
|
||||
if (stackFrame.getUrl().equals(mEditorView.getFile().toString())) {
|
||||
final int line = stackFrame.getLineNumber() - 1;
|
||||
mHandler.post(() -> {
|
||||
mEditorView.getEditor().setDebuggingLine(line);
|
||||
setInterrupted(true);
|
||||
});
|
||||
|
||||
} else {
|
||||
//刚启动调试时会在init脚本的第一行自动停下,此时应该让脚本继续运行
|
||||
if (mSkipOtherFileBreakpoint && !stackFrame.getUrl().equals(mInitialEditorSourceUrl) && message == null) {
|
||||
mHandler.post(this::resumeScript);
|
||||
return;
|
||||
}
|
||||
mSkipOtherFileBreakpoint = false;
|
||||
showDebuggingLineOnEditor(stackFrame, message);
|
||||
mHandler.post(this::updateWatchingVariables);
|
||||
}
|
||||
|
||||
private void updateWatchingVariables() {
|
||||
updateWatchingVariables(0, mEditorView.getDebugBar().getWatchingVariables().size());
|
||||
}
|
||||
|
||||
private void updateWatchingVariables(int start, int end) {
|
||||
if (!mDim.isAttached()) {
|
||||
return;
|
||||
}
|
||||
DebugBar debugBar = mEditorView.getDebugBar();
|
||||
List<WatchingVariable> variables = debugBar.getWatchingVariables();
|
||||
for (int i = start; i < end; i++) {
|
||||
WatchingVariable variable = variables.get(i);
|
||||
String value = eval(variable.getName());
|
||||
variable.setValue(value);
|
||||
}
|
||||
debugBar.refresh(start, end - start);
|
||||
}
|
||||
|
||||
public String eval(String expr) {
|
||||
if (expr == null || !mDim.isAttached() || !mDim.stringIsCompilableUnit(expr)) {
|
||||
return null;
|
||||
}
|
||||
mDim.contextSwitch(0);
|
||||
return mDim.eval(expr);
|
||||
}
|
||||
|
||||
private void showDebuggingLineOnEditor(Dim.StackFrame stackFrame, String message) {
|
||||
//如果调试进入到其他脚本(例如模块脚本),则改变当前编辑器的文本为自动调试的脚本的代码
|
||||
String source;
|
||||
//标记是否需要更改编辑器文本
|
||||
boolean shouldChangeText = !stackFrame.getUrl().equals(mCurrentEditorSourceUrl);
|
||||
if (shouldChangeText) {
|
||||
source = stackFrame.sourceInfo().source();
|
||||
} else {
|
||||
source = null;
|
||||
}
|
||||
mCurrentEditorSourceUrl = stackFrame.getUrl();
|
||||
final int line = stackFrame.getLineNumber() - 1;
|
||||
mHandler.post(() -> {
|
||||
if (mEditorView == null) {
|
||||
return;
|
||||
}
|
||||
if (shouldChangeText) {
|
||||
mEditorView.getEditor().setText(source);
|
||||
}
|
||||
mCursorChangeFromUser = false;
|
||||
mEditorView.getEditor().setDebuggingLine(line);
|
||||
mEditorView.getEditor().jumpTo(line, 0);
|
||||
mEditorView.getDebugBar().setTitle(PFiles.getName(mCurrentEditorSourceUrl));
|
||||
setInterrupted(true);
|
||||
if (message != null && !message.equals(ScriptInterruptedException.class.getName())) {
|
||||
Toast.makeText(mEditorView.getContext(), message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -155,9 +255,54 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCursorChange(String line, int ch) {
|
||||
if (ch == 0 && !mCursorChangeFromUser) {
|
||||
mCursorChangeFromUser = true;
|
||||
return;
|
||||
}
|
||||
mCursorChangeFromUser = true;
|
||||
if (!mDim.isAttached()) {
|
||||
return;
|
||||
}
|
||||
String variable = findVariableOnCursor(line, ch);
|
||||
Log.d(LOG_TAG, "onCursorChange: variable = " + variable + ", ch = " + ch + ", line = " + line);
|
||||
String value = eval(variable);
|
||||
mEditorView.getDebugBar().updateCurrentVariable(variable, value);
|
||||
}
|
||||
|
||||
private String findVariableOnCursor(String line, int ch) {
|
||||
int end;
|
||||
for (end = ch; end < line.length(); end++) {
|
||||
if (!isIdentifierChar(line.charAt(end))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int start;
|
||||
for (start = Math.min(ch - 1, line.length() - 1); start >= 0; start--) {
|
||||
if (!isIdentifierChar(line.charAt(start))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
start++;
|
||||
if (start < end && start < line.length() && start >= 0) {
|
||||
return line.substring(start, end);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isIdentifierChar(char c) {
|
||||
return Character.isDigit(c) || Character.isLetter(c) || c == '.' || c == '_';
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getMenuItemIds() {
|
||||
return Arrays.asList(R.id.step_over, R.id.step_into, R.id.step_out, R.id.resume_script, R.id.stop_script);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
detachDebugger();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
package org.autojs.autojs.ui.edit.toolbar;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import org.androidannotations.annotations.Click;
|
||||
import org.androidannotations.annotations.EFragment;
|
||||
import org.autojs.autojs.R;
|
||||
|
||||
@ -12,7 +9,6 @@ import java.util.List;
|
||||
@EFragment(R.layout.fragment_normal_toolbar)
|
||||
public class NormalToolbarFragment extends ToolbarFragment {
|
||||
|
||||
|
||||
@Override
|
||||
public List<Integer> getMenuItemIds() {
|
||||
return Arrays.asList(R.id.run, R.id.undo, R.id.redo, R.id.save);
|
||||
|
||||
@ -11,19 +11,29 @@ import org.autojs.autojs.ui.edit.EditorView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ToolbarFragment extends Fragment implements View.OnClickListener {
|
||||
public abstract class ToolbarFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener {
|
||||
|
||||
|
||||
public interface OnMenuItemClickListener {
|
||||
void onToolbarMenuItemClick(int id);
|
||||
}
|
||||
|
||||
public interface OnMenuItemLongClickListener {
|
||||
boolean onToolbarMenuItemLongClick(int id);
|
||||
}
|
||||
|
||||
private OnMenuItemClickListener mOnMenuItemClickListener;
|
||||
private OnMenuItemLongClickListener mOnMenuItemLongClickListener;
|
||||
private List<Integer> mMenuItemIds;
|
||||
|
||||
public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
|
||||
mOnMenuItemClickListener = listener;
|
||||
}
|
||||
|
||||
public void setOnMenuItemLongClickListener(OnMenuItemLongClickListener onMenuItemLongClickListener) {
|
||||
mOnMenuItemLongClickListener = onMenuItemLongClickListener;
|
||||
}
|
||||
|
||||
public abstract List<Integer> getMenuItemIds();
|
||||
|
||||
@Override
|
||||
@ -54,6 +64,7 @@ public abstract class ToolbarFragment extends Fragment implements View.OnClickLi
|
||||
for (int id : mMenuItemIds) {
|
||||
View view = rootView.findViewById(id);
|
||||
view.setOnClickListener(this);
|
||||
view.setOnLongClickListener(this);
|
||||
view.setEnabled(editorView.getMenuItemStatus(id, view.isEnabled()));
|
||||
}
|
||||
}
|
||||
@ -66,6 +77,13 @@ public abstract class ToolbarFragment extends Fragment implements View.OnClickLi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
return mOnMenuItemLongClickListener != null &&
|
||||
mOnMenuItemLongClickListener.onToolbarMenuItemLongClick(v.getId());
|
||||
}
|
||||
|
||||
public void setMenuItemStatus(int id, boolean enabled) {
|
||||
if (mMenuItemIds == null) {
|
||||
mMenuItemIds = getMenuItemIds();
|
||||
|
||||
@ -89,7 +89,7 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
RecyclerView mDrawerMenu;
|
||||
|
||||
|
||||
private DrawerMenuItem mConnectionItem = new DrawerMenuItem(R.drawable.ic_debug, R.string.debug, 0, this::connectOrDisconnectToRemote);
|
||||
private DrawerMenuItem mConnectionItem = new DrawerMenuItem(R.drawable.ic_connect_to_pc, R.string.debug, 0, this::connectOrDisconnectToRemote);
|
||||
private DrawerMenuItem mAccessibilityServiceItem = new DrawerMenuItem(R.drawable.ic_service_green, R.string.text_accessibility_service, 0, this::enableOrDisableAccessibilityService);
|
||||
private DrawerMenuItem mStableModeItem = new DrawerMenuItem(R.drawable.ic_stable, R.string.text_stable_mode, R.string.key_stable_mode, null) {
|
||||
@Override
|
||||
|
||||
@ -14,12 +14,16 @@ import java.util.List;
|
||||
public class AutoAdapter<DT> extends RecyclerView.Adapter<BindableViewHolder<DT>> {
|
||||
|
||||
private ViewHolderSupplier<? extends BindableViewHolder<DT>> mViewHolderSupplier;
|
||||
private List<DT> mList = new ArrayList<>();
|
||||
private final List<DT> mData = new ArrayList<>();
|
||||
|
||||
public AutoAdapter(ViewHolderSupplier<? extends BindableViewHolder<DT>> viewHolderSupplier) {
|
||||
mViewHolderSupplier = viewHolderSupplier;
|
||||
}
|
||||
|
||||
public AutoAdapter(ViewHolderSupplier.ViewHolderCreator<? extends BindableViewHolder<DT>> viewHolderCreator, int layoutRes) {
|
||||
mViewHolderSupplier = ViewHolderSupplier.of(viewHolderCreator, layoutRes);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BindableViewHolder<DT> onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
@ -28,36 +32,48 @@ public class AutoAdapter<DT> extends RecyclerView.Adapter<BindableViewHolder<DT>
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(BindableViewHolder<DT> holder, int position) {
|
||||
holder.bind(mList.get(position), position);
|
||||
holder.bind(mData.get(position), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size();
|
||||
return mData.size();
|
||||
}
|
||||
|
||||
public void remove(DT data) {
|
||||
int pos = mList.indexOf(data);
|
||||
int pos = mData.indexOf(data);
|
||||
if (pos < 0)
|
||||
return;
|
||||
mList.remove(pos);
|
||||
mData.remove(pos);
|
||||
notifyItemRemoved(pos);
|
||||
}
|
||||
|
||||
public void remove(int index) {
|
||||
mList.remove(index);
|
||||
mData.remove(index);
|
||||
notifyItemRemoved(index);
|
||||
}
|
||||
|
||||
public void addAll(Collection<? extends DT> c) {
|
||||
mList.addAll(c);
|
||||
notifyItemRangeInserted(mList.size() - c.size() - 1, mList.size() - 1);
|
||||
mData.addAll(c);
|
||||
notifyItemRangeInserted(mData.size() - c.size() - 1, mData.size() - 1);
|
||||
}
|
||||
|
||||
public DT get(int index){
|
||||
return mData.get(index);
|
||||
}
|
||||
|
||||
public void setData(Collection<? extends DT> c) {
|
||||
mList.clear();
|
||||
mList.addAll(c);
|
||||
mData.clear();
|
||||
mData.addAll(c);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void add(DT item) {
|
||||
mData.add(item);
|
||||
notifyItemInserted(mData.size() - 1);
|
||||
}
|
||||
|
||||
public List<DT> getData() {
|
||||
return mData;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,22 +11,30 @@ import java.lang.reflect.Constructor;
|
||||
* Created by Stardust on 2017/4/8.
|
||||
*/
|
||||
|
||||
public abstract class ViewHolderSupplier<VH extends RecyclerView.ViewHolder> {
|
||||
public interface ViewHolderSupplier<VH extends RecyclerView.ViewHolder> {
|
||||
|
||||
public abstract VH createViewHolder(ViewGroup parent, int viewType);
|
||||
VH createViewHolder(ViewGroup parent, int viewType);
|
||||
|
||||
public static <VH extends RecyclerView.ViewHolder> ViewHolderSupplier<VH> of(final Class<VH> c, final int layoutRes) {
|
||||
return new ViewHolderSupplier<VH>() {
|
||||
@Override
|
||||
public VH createViewHolder(ViewGroup parent, int viewType) {
|
||||
try {
|
||||
Constructor<VH> constructor = c.getConstructor(View.class);
|
||||
return constructor.newInstance(LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
interface ViewHolderCreator<VH extends RecyclerView.ViewHolder> {
|
||||
VH createViewHolder(View itemView);
|
||||
}
|
||||
|
||||
static <VH extends RecyclerView.ViewHolder> ViewHolderSupplier<VH> of(final Class<VH> c, final int layoutRes) {
|
||||
return (parent, viewType) -> {
|
||||
try {
|
||||
Constructor<VH> constructor = c.getConstructor(View.class);
|
||||
return constructor.newInstance(LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static <VH extends RecyclerView.ViewHolder> ViewHolderSupplier<VH> of(ViewHolderCreator<VH> creator, final int layoutRes) {
|
||||
return (parent, viewType) ->
|
||||
creator.createViewHolder(LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
BIN
app/src/main/res/drawable-xhdpi/ic_connect_to_pc.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_connect_to_pc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable/ic_script.png
Normal file
BIN
app/src/main/res/drawable/ic_script.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
54
app/src/main/res/layout/debug_bar.xml
Normal file
54
app/src/main/res/layout/debug_bar.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#aaffa726"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:src="@drawable/ic_debug"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/text_debug"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="15sp"/>
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/execute"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_script"
|
||||
android:tint="@android:color/white"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/add"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_add_white_48dp"
|
||||
android:tint="@android:color/white"/>
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/variables"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</LinearLayout>
|
||||
38
app/src/main/res/layout/dialog_code_evaluate.xml
Normal file
38
app/src/main/res/layout/dialog_code_evaluate.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.stardust.theme.widget.ThemeColorTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="8dp"
|
||||
android:text="@string/text_code"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/code"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:textSize="15sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@android:color/primary_text_light"/>
|
||||
|
||||
<com.stardust.theme.widget.ThemeColorTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:text="@string/text_result"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result"
|
||||
android:paddingLeft="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#727377"
|
||||
android:textSize="16sp"/>
|
||||
</LinearLayout>
|
||||
@ -88,6 +88,13 @@
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"/>
|
||||
|
||||
|
||||
<org.autojs.autojs.ui.edit.debug.DebugBar
|
||||
android:id="@+id/debug_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.autojs.autojs.ui.widget.EWebView
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="28dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:background="?selectableItemBackground"
|
||||
android:paddingLeft="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/variable"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
tools:text="variable = value"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="2dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:src="@drawable/ic_delete_black_48dp"
|
||||
android:tint="@android:color/white"/>
|
||||
</LinearLayout>
|
||||
@ -94,6 +94,11 @@
|
||||
android:id="@+id/action_launch_debugger"
|
||||
android:title="@string/text_launch_debugger"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_remove_all_breakpoints"
|
||||
android:title="@string/text_remove_all_breakpoints"
|
||||
app:showAsAction="never"/>
|
||||
</menu>
|
||||
|
||||
</item>
|
||||
|
||||
@ -367,4 +367,15 @@
|
||||
<string name="text_debug_step_over">单步</string>
|
||||
<string name="text_debug_resume_script">继续</string>
|
||||
<string name="text_stop">停止</string>
|
||||
<string name="text_new_watching_variable">增加监视的变量或表达式</string>
|
||||
<string name="text_variable_or_expr">变量或表达式</string>
|
||||
<string name="text_variable">变量</string>
|
||||
<string name="text_remove_all_breakpoints">删除所有断点</string>
|
||||
<string name="hint_long_click_run_to_debug">长按\"运行\"图标也可以启动调试</string>
|
||||
<string name="format_debug_bar_title">调试 [%s]</string>
|
||||
<string name="text_copy_value">复制值</string>
|
||||
<string name="text_execute_code">执行代码</string>
|
||||
<string name="text_code">代码</string>
|
||||
<string name="text_result">结果</string>
|
||||
<string name="text_close">关闭</string>
|
||||
</resources>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
module.exports = function(){
|
||||
Object.observe||function(e,t,n,r){"use strict";var o,i,c=["add","update","delete","reconfigure","setPrototype","preventExtensions"],a=t.isArray||function(e){return function(t){return"[object Array]"===e.call(t)}}(e.prototype.toString),f=t.prototype.indexOf?t.indexOf||function(e,n,r){return t.prototype.indexOf.call(e,n,r)}:function(e,t,n){for(var r=n||0;r<e.length;r++)if(e[r]===t)return r;return-1},s=n.Map!==r&&Map.prototype.forEach?function(){return new Map}:function(){var e=[],t=[];return{size:0,has:function(t){return f(e,t)>-1},get:function(n){return t[f(e,n)]},set:function(n,r){var o=f(e,n);-1===o?(e.push(n),t.push(r),this.size++):t[o]=r},"delete":function(n){var r=f(e,n);r>-1&&(e.splice(r,1),t.splice(r,1),this.size--)},forEach:function(n){for(var r=0;r<e.length;r++)n.call(arguments[1],t[r],e[r],this)}}},u=e.getOwnPropertyNames?function(){var t=e.getOwnPropertyNames;try{arguments.callee}catch(n){var r=(t(f).join(" ")+" ").replace(/prototype |length |name /g,"").slice(0,-1).split(" ");r.length&&(t=function(t){var n=e.getOwnPropertyNames(t);if("function"==typeof t)for(var o,i=0;i<r.length;)(o=f(n,r[i++]))>-1&&n.splice(o,1);return n})}return t}():function(t){var n,r,o=[];if("hasOwnProperty"in t)for(n in t)t.hasOwnProperty(n)&&o.push(n);else{r=e.hasOwnProperty;for(n in t)r.call(t,n)&&o.push(n)}return a(t)&&o.push("length"),o},p=n.requestAnimationFrame||n.webkitRequestAnimationFrame||function(){var e=+new Date,t=e;return function(n){return setTimeout(function(){n((t=+new Date)-e)},17)}}(),l=function(e,t,n){var r=o.get(e);r?(v(r,e),g(e,r,t,n)):(r=h(e),g(e,r,t,n),1===o.size&&p(d))},h=function(e,t){for(var n=u(e),r=[],i=0,t={handlers:s(),properties:n,values:r,notifier:b(e,t)};i<n.length;)r[i]=e[n[i++]];return o.set(e,t),t},v=function(e,t,n){if(e.handlers.size){var r,o,i,c,a,s,p,l=e.values,h=0;for(r=e.properties.slice(),o=r.length,i=u(t);h<i.length;)a=i[h++],c=f(r,a),s=t[a],-1===c?(w(t,e,{name:a,type:"add",object:t},n),e.properties.push(a),l.push(s)):(p=l[c],r[c]=null,o--,(p===s?0===p&&1/p!==1/s:p===p||s===s)&&(w(t,e,{name:a,type:"update",object:t,oldValue:p},n),e.values[c]=s));for(h=r.length;o&&h--;)null!==r[h]&&(w(t,e,{name:r[h],type:"delete",object:t,oldValue:l[h]},n),e.properties.splice(h,1),e.values.splice(h,1),o--)}},d=function(){o.size&&(o.forEach(v),i.forEach(y),p(d))},y=function(e,t){var n=e.changeRecords;n.length&&(e.changeRecords=[],t(n))},b=function(e,t){return arguments.length<2&&(t=o.get(e)),t&&t.notifier||{notify:function(t){t.type;var n=o.get(e);if(n){var r,i={object:e};for(r in t)"object"!==r&&(i[r]=t[r]);w(e,n,i)}},performChange:function(t,n){if("string"!=typeof t)throw new TypeError("Invalid non-string changeType");if("function"!=typeof n)throw new TypeError("Cannot perform non-function");var i,c,a=o.get(e),f=arguments[2],s=f===r?n():n.call(f);if(a&&v(a,e,t),a&&s&&"object"==typeof s){c={object:e,type:t};for(i in s)"object"!==i&&"type"!==i&&(c[i]=s[i]);w(e,a,c)}}}},g=function(e,t,n,r){var o=i.get(n);o||i.set(n,o={observed:s(),changeRecords:[]}),o.observed.set(e,{acceptList:r.slice(),data:t}),t.handlers.set(n,o)},w=function(e,t,n,r){t.handlers.forEach(function(t){var o=t.observed.get(e).acceptList;("string"!=typeof r||-1===f(o,r))&&f(o,n.type)>-1&&t.changeRecords.push(n)})};o=s(),i=s(),e.observe=function(t,n,o){if(!t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.observe cannot observe non-object");if("function"!=typeof n)throw new TypeError("Object.observe cannot deliver to non-function");if(e.isFrozen&&e.isFrozen(n))throw new TypeError("Object.observe cannot deliver to a frozen function object");if(o===r)o=c;else if(!o||"object"!=typeof o)throw new TypeError("Third argument to Object.observe must be an array of strings.");return l(t,n,o),t},e.unobserve=function(e,t){if(null===e||"object"!=typeof e&&"function"!=typeof e)throw new TypeError("Object.unobserve cannot unobserve non-object");if("function"!=typeof t)throw new TypeError("Object.unobserve cannot deliver to non-function");var n,r=i.get(t);return r&&(n=r.observed.get(e))&&(r.observed.forEach(function(e,t){v(e.data,t)}),p(function(){y(r,t)}),1===r.observed.size&&r.observed.has(e)?i["delete"](t):r.observed["delete"](e),1===n.data.handlers.size?o["delete"](e):n.data.handlers["delete"](t)),e},e.getNotifier=function(t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.getNotifier cannot getNotifier non-object");return e.isFrozen&&e.isFrozen(t)?null:b(t)},e.deliverChangeRecords=function(e){if("function"!=typeof e)throw new TypeError("Object.deliverChangeRecords cannot deliver to non-function");var t=i.get(e);t&&(t.observed.forEach(function(e,t){v(e.data,t)}),y(t,e))}}(Object,Array,this);
|
||||
Object.observe||function(e,t,n,r){var o,i,c=["add","update","delete","reconfigure","setPrototype","preventExtensions"],a=t.isArray||function(e){return function(t){return"[object Array]"===e.call(t)}}(e.prototype.toString),f=t.prototype.indexOf?t.indexOf||function(e,n,r){return t.prototype.indexOf.call(e,n,r)}:function(e,t,n){for(var r=n||0;r<e.length;r++)if(e[r]===t)return r;return-1},s=n.Map!==r&&Map.prototype.forEach?function(){return new Map}:function(){var e=[],t=[];return{size:0,has:function(t){return f(e,t)>-1},get:function(n){return t[f(e,n)]},set:function(n,r){var o=f(e,n);-1===o?(e.push(n),t.push(r),this.size++):t[o]=r},"delete":function(n){var r=f(e,n);r>-1&&(e.splice(r,1),t.splice(r,1),this.size--)},forEach:function(n){for(var r=0;r<e.length;r++)n.call(arguments[1],t[r],e[r],this)}}},u=e.getOwnPropertyNames?function(){var t=e.getOwnPropertyNames;try{arguments.callee}catch(n){var r=(t(f).join(" ")+" ").replace(/prototype |length |name /g,"").slice(0,-1).split(" ");r.length&&(t=function(t){var n=e.getOwnPropertyNames(t);if("function"==typeof t)for(var o,i=0;i<r.length;)(o=f(n,r[i++]))>-1&&n.splice(o,1);return n})}return t}():function(t){var n,r,o=[];if("hasOwnProperty"in t)for(n in t)t.hasOwnProperty(n)&&o.push(n);else{r=e.hasOwnProperty;for(n in t)r.call(t,n)&&o.push(n)}return a(t)&&o.push("length"),o},p=n.requestAnimationFrame||n.webkitRequestAnimationFrame||function(){var e=+new Date,t=e;return function(n){return setTimeout(function(){n((t=+new Date)-e)},17)}}(),l=function(e,t,n){var r=o.get(e);r?(v(r,e),g(e,r,t,n)):(r=h(e),g(e,r,t,n),1===o.size&&p(d))},h=function(e,t){for(var n=u(e),r=[],i=0,t={handlers:s(),properties:n,values:r,notifier:b(e,t)};i<n.length;)r[i]=e[n[i++]];return o.set(e,t),t},v=function(e,t,n){if(e.handlers.size){var r,o,i,c,a,s,p,l=e.values,h=0;for(r=e.properties.slice(),o=r.length,i=u(t);h<i.length;)a=i[h++],c=f(r,a),s=t[a],-1===c?(w(t,e,{name:a,type:"add",object:t},n),e.properties.push(a),l.push(s)):(p=l[c],r[c]=null,o--,(p===s?0===p&&1/p!==1/s:p===p||s===s)&&(w(t,e,{name:a,type:"update",object:t,oldValue:p},n),e.values[c]=s));for(h=r.length;o&&h--;)null!==r[h]&&(w(t,e,{name:r[h],type:"delete",object:t,oldValue:l[h]},n),e.properties.splice(h,1),e.values.splice(h,1),o--)}},d=function(){o.size&&(o.forEach(v),i.forEach(y),p(d))},y=function(e,t){var n=e.changeRecords;n.length&&(e.changeRecords=[],t(n))},b=function(e,t){return arguments.length<2&&(t=o.get(e)),t&&t.notifier||{notify:function(t){t.type;var n=o.get(e);if(n){var r,i={object:e};for(r in t)"object"!==r&&(i[r]=t[r]);w(e,n,i)}},performChange:function(t,n){if("string"!=typeof t)throw new TypeError("Invalid non-string changeType");if("function"!=typeof n)throw new TypeError("Cannot perform non-function");var i,c,a=o.get(e),f=arguments[2],s=f===r?n():n.call(f);if(a&&v(a,e,t),a&&s&&"object"==typeof s){c={object:e,type:t};for(i in s)"object"!==i&&"type"!==i&&(c[i]=s[i]);w(e,a,c)}}}},g=function(e,t,n,r){var o=i.get(n);o||i.set(n,o={observed:s(),changeRecords:[]}),o.observed.set(e,{acceptList:r.slice(),data:t}),t.handlers.set(n,o)},w=function(e,t,n,r){t.handlers.forEach(function(t){var o=t.observed.get(e).acceptList;("string"!=typeof r||-1===f(o,r))&&f(o,n.type)>-1&&t.changeRecords.push(n)})};o=s(),i=s(),e.observe=function(t,n,o){if(!t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.observe cannot observe non-object");if("function"!=typeof n)throw new TypeError("Object.observe cannot deliver to non-function");if(e.isFrozen&&e.isFrozen(n))throw new TypeError("Object.observe cannot deliver to a frozen function object");if(o===r)o=c;else if(!o||"object"!=typeof o)throw new TypeError("Third argument to Object.observe must be an array of strings.");return l(t,n,o),t},e.unobserve=function(e,t){if(null===e||"object"!=typeof e&&"function"!=typeof e)throw new TypeError("Object.unobserve cannot unobserve non-object");if("function"!=typeof t)throw new TypeError("Object.unobserve cannot deliver to non-function");var n,r=i.get(t);return r&&(n=r.observed.get(e))&&(r.observed.forEach(function(e,t){v(e.data,t)}),p(function(){y(r,t)}),1===r.observed.size&&r.observed.has(e)?i["delete"](t):r.observed["delete"](e),1===n.data.handlers.size?o["delete"](e):n.data.handlers["delete"](t)),e},e.getNotifier=function(t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.getNotifier cannot getNotifier non-object");return e.isFrozen&&e.isFrozen(t)?null:b(t)},e.deliverChangeRecords=function(e){if("function"!=typeof e)throw new TypeError("Object.deliverChangeRecords cannot deliver to non-function");var t=i.get(e);t&&(t.observed.forEach(function(e,t){v(e.data,t)}),y(t,e))}}(Object,Array,this);
|
||||
}
|
||||
@ -78,7 +78,7 @@ public class Dim {
|
||||
/**
|
||||
* The ContextFactory to listen to for debugging information.
|
||||
*/
|
||||
private ContextFactory contextFactory;
|
||||
private volatile ContextFactory contextFactory;
|
||||
|
||||
private ScriptEngineService scriptEngineService;
|
||||
|
||||
@ -222,7 +222,7 @@ public class Dim {
|
||||
detach();
|
||||
this.contextFactory = factory;
|
||||
this.scriptEngineService = scriptEngineService;
|
||||
this.listener = new DimIProxy(this, IPROXY_LISTEN);
|
||||
this.listener = new DimIProxy(IPROXY_LISTEN);
|
||||
scriptEngineService.registerEngineLifecycleCallback(this.listener);
|
||||
}
|
||||
|
||||
@ -517,6 +517,10 @@ public class Dim {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAttached() {
|
||||
return contextFactory != null && scriptEngineService != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current ContextData object.
|
||||
*/
|
||||
@ -585,7 +589,7 @@ public class Dim {
|
||||
* Compiles the given script.
|
||||
*/
|
||||
public void compileScript(String url, String text) {
|
||||
DimIProxy action = new DimIProxy(this, IPROXY_COMPILE_SCRIPT);
|
||||
DimIProxy action = new DimIProxy(IPROXY_COMPILE_SCRIPT);
|
||||
action.url = url;
|
||||
action.text = text;
|
||||
action.withContext();
|
||||
@ -595,7 +599,7 @@ public class Dim {
|
||||
* Evaluates the given script.
|
||||
*/
|
||||
public void evalScript(final String url, final String text) {
|
||||
DimIProxy action = new DimIProxy(this, IPROXY_EVAL_SCRIPT);
|
||||
DimIProxy action = new DimIProxy(IPROXY_EVAL_SCRIPT);
|
||||
action.url = url;
|
||||
action.text = text;
|
||||
action.withContext();
|
||||
@ -605,7 +609,7 @@ public class Dim {
|
||||
* Converts the given script object to a string.
|
||||
*/
|
||||
public String objectToString(Object object) {
|
||||
DimIProxy action = new DimIProxy(this, IPROXY_OBJECT_TO_STRING);
|
||||
DimIProxy action = new DimIProxy(IPROXY_OBJECT_TO_STRING);
|
||||
action.object = object;
|
||||
action.withContext();
|
||||
return action.stringResult;
|
||||
@ -615,7 +619,7 @@ public class Dim {
|
||||
* Returns whether the given string is syntactically valid script.
|
||||
*/
|
||||
public boolean stringIsCompilableUnit(String str) {
|
||||
DimIProxy action = new DimIProxy(this, IPROXY_STRING_IS_COMPILABLE);
|
||||
DimIProxy action = new DimIProxy(IPROXY_STRING_IS_COMPILABLE);
|
||||
action.text = str;
|
||||
action.withContext();
|
||||
return action.booleanResult;
|
||||
@ -625,7 +629,7 @@ public class Dim {
|
||||
* Returns the value of a property on the given script object.
|
||||
*/
|
||||
public Object getObjectProperty(Object object, Object id) {
|
||||
DimIProxy action = new DimIProxy(this, IPROXY_OBJECT_PROPERTY);
|
||||
DimIProxy action = new DimIProxy(IPROXY_OBJECT_PROPERTY);
|
||||
action.object = object;
|
||||
action.id = id;
|
||||
action.withContext();
|
||||
@ -636,7 +640,7 @@ public class Dim {
|
||||
* Returns an array of the property names on the given script object.
|
||||
*/
|
||||
public Object[] getObjectIds(Object object) {
|
||||
DimIProxy action = new DimIProxy(this, IPROXY_OBJECT_IDS);
|
||||
DimIProxy action = new DimIProxy(IPROXY_OBJECT_IDS);
|
||||
action.object = object;
|
||||
action.withContext();
|
||||
return action.objectArrayResult;
|
||||
@ -894,11 +898,6 @@ public class Dim {
|
||||
private class DimIProxy
|
||||
implements ContextAction, ScriptEngineManager.EngineLifecycleCallback, Debugger {
|
||||
|
||||
/**
|
||||
* The debugger.
|
||||
*/
|
||||
private Dim dim;
|
||||
|
||||
/**
|
||||
* The interface implementation type. One of the IPROXY_* constants
|
||||
* defined in {@link Dim}.
|
||||
@ -948,8 +947,7 @@ public class Dim {
|
||||
/**
|
||||
* Creates a new DimIProxy.
|
||||
*/
|
||||
private DimIProxy(Dim dim, int type) {
|
||||
this.dim = dim;
|
||||
private DimIProxy(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@ -966,8 +964,8 @@ public class Dim {
|
||||
|
||||
case IPROXY_EVAL_SCRIPT: {
|
||||
Scriptable scope = null;
|
||||
if (dim.scopeProvider != null) {
|
||||
scope = dim.scopeProvider.getScope();
|
||||
if (scopeProvider != null) {
|
||||
scope = scopeProvider.getScope();
|
||||
}
|
||||
if (scope == null) {
|
||||
scope = new ImporterTopLevel(cx);
|
||||
@ -993,11 +991,11 @@ public class Dim {
|
||||
break;
|
||||
|
||||
case IPROXY_OBJECT_PROPERTY:
|
||||
objectResult = dim.getObjectPropertyImpl(cx, object, id);
|
||||
objectResult = getObjectPropertyImpl(cx, object, id);
|
||||
break;
|
||||
|
||||
case IPROXY_OBJECT_IDS:
|
||||
objectArrayResult = dim.getObjectIdsImpl(cx, object);
|
||||
objectArrayResult = getObjectIdsImpl(cx, object);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1011,7 +1009,7 @@ public class Dim {
|
||||
* {@link ContextFactory}.
|
||||
*/
|
||||
private void withContext() {
|
||||
dim.contextFactory.call(this);
|
||||
contextFactory.call(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1024,7 +1022,7 @@ public class Dim {
|
||||
|
||||
Context cx = ((RhinoJavaScriptEngine) engine).getContext();
|
||||
ContextData contextData = new ContextData();
|
||||
Debugger debugger = new DimIProxy(dim, IPROXY_DEBUG);
|
||||
Debugger debugger = new DimIProxy(IPROXY_DEBUG);
|
||||
cx.setDebugger(debugger, contextData);
|
||||
cx.setGeneratingDebug(true);
|
||||
cx.setOptimizationLevel(-1);
|
||||
@ -1044,12 +1042,12 @@ public class Dim {
|
||||
public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript) {
|
||||
if (type != IPROXY_DEBUG) Kit.codeBug();
|
||||
|
||||
FunctionSource item = dim.getFunctionSource(fnOrScript);
|
||||
FunctionSource item = getFunctionSource(fnOrScript);
|
||||
if (item == null) {
|
||||
// Can not debug if source is not available
|
||||
return null;
|
||||
}
|
||||
return new StackFrame(cx, dim, item);
|
||||
return new StackFrame(cx, Dim.this, item);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1063,7 +1061,7 @@ public class Dim {
|
||||
if (!fnOrScript.isTopLevel()) {
|
||||
return;
|
||||
}
|
||||
dim.registerTopScript(fnOrScript, source);
|
||||
registerTopScript(fnOrScript, source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user