Skip to content

Commit fe42826

Browse files
authored
Pop error or exception to PDE (#85)
* *: Add exception handler Signed-off-by: Ce Gao <[email protected]> * coala: Reformat Signed-off-by: Ce Gao <[email protected]> * PApplet: Add log Signed-off-by: Ce Gao <[email protected]> * Runner: Fix the bad code because of rebase Signed-off-by: Ce Gao <[email protected]> * *: Move Transfer code to RSketchError Signed-off-by: Ce Gao <[email protected]> * RSketchError: Transfer the exception Signed-off-by: Ce Gao <[email protected]> * SketchError: Add TODO Signed-off-by: Ce Gao <[email protected]>
1 parent dd9a382 commit fe42826

File tree

4 files changed

+159
-36
lines changed

4 files changed

+159
-36
lines changed

src/rprocessing/RLangPApplet.java

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.awt.Window;
55
import java.awt.event.ComponentAdapter;
66
import java.awt.event.ComponentEvent;
7+
import java.lang.Thread.UncaughtExceptionHandler;
78
import java.lang.reflect.Method;
89
import java.util.Arrays;
910
import java.util.concurrent.CountDownLatch;
@@ -27,6 +28,7 @@
2728
import processing.opengl.PSurfaceJOGL;
2829
import rprocessing.applet.BuiltinApplet;
2930
import rprocessing.exception.NotFoundException;
31+
import rprocessing.exception.RSketchError;
3032
import rprocessing.util.Constant;
3133
import rprocessing.util.Printer;
3234
import rprocessing.util.RScriptReader;
@@ -55,6 +57,8 @@ public class RLangPApplet extends BuiltinApplet {
5557

5658
private final CountDownLatch finishedLatch = new CountDownLatch(1);
5759

60+
private RSketchError terminalException = null;
61+
5862
/**
5963
* Mode for Processing.
6064
*
@@ -79,8 +83,12 @@ public RLangPApplet(final String programText, final Printer stdout) throws NotFo
7983
this.mode = this.detectMode();
8084
}
8185

82-
public void evaluateCoreCode() throws ScriptException {
83-
this.renjinEngine.eval(CORE_TEXT);
86+
public void evaluateCoreCode() throws RSketchError {
87+
try {
88+
this.renjinEngine.eval(CORE_TEXT);
89+
} catch (final ScriptException se) {
90+
throw RSketchError.toSketchException(se);
91+
}
8492
}
8593

8694
/**
@@ -129,18 +137,18 @@ public void addPAppletToRContext() {
129137
this.renjinEngine.put("stdout", stdout);
130138
}
131139

132-
public void runBlock(final String[] arguments) {
140+
public void runBlock(final String[] arguments) throws RSketchError {
133141
log("runBlock");
134142
PApplet.runSketch(arguments, this);
135143
try {
136144
finishedLatch.await();
137-
log("Down");
145+
log("RunSketch done.");
138146
} catch (final InterruptedException interrupted) {
139147
// Treat an interruption as a request to the applet to terminate.
140148
exit();
141149
try {
142150
finishedLatch.await();
143-
log("Down");
151+
log("RunSketch interrupted.");
144152
} catch (final InterruptedException exception) {
145153
log(exception.toString());
146154
}
@@ -167,9 +175,11 @@ public void runBlock(final String[] arguments) {
167175
surface.setVisible(false);
168176
}
169177
}
170-
// if (terminalException != null) {
171-
// throw terminalException;
172-
// }
178+
// log(terminalException.toString());
179+
if (terminalException != null) {
180+
log("Throw the exception to PDE.");
181+
throw terminalException;
182+
}
173183
}
174184

175185
private static void macosxFullScreenToggle(final Window window) {
@@ -227,6 +237,29 @@ public void exitActual() {
227237
finishedLatch.countDown();
228238
}
229239

240+
/**
241+
* @see processing.core.PApplet#start()
242+
*/
243+
@Override
244+
public void start() {
245+
// I want to quit on runtime exceptions.
246+
// Processing just sits there by default.
247+
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
248+
@Override
249+
public void uncaughtException(final Thread t, final Throwable e) {
250+
terminalException = RSketchError.toSketchException(e);
251+
try {
252+
log("There is an unexpected exception.");
253+
handleMethods("dispose");
254+
} catch (final Exception noop) {
255+
// give up
256+
}
257+
finishedLatch.countDown();
258+
}
259+
});
260+
super.start();
261+
}
262+
230263
/**
231264
* @see processing.core.PApplet#settings()
232265
*/
@@ -253,9 +286,14 @@ public void setup() {
253286
wrapProcessingVariables();
254287
if (this.mode == Mode.STATIC) {
255288
try {
289+
log("The mode is static, run the program directly.");
256290
this.renjinEngine.eval(this.programText);
257-
} catch (ScriptException exception) {
291+
log("Evaluate the code in static mode.");
292+
} catch (final Exception exception) {
293+
log("There is exception when evaluate the code in static mode.");
258294
log(exception.toString());
295+
terminalException = RSketchError.toSketchException(exception);
296+
exitActual();
259297
}
260298
} else if (this.mode == Mode.ACTIVE) {
261299
Object obj = this.renjinEngine.get(Constant.SETUP_NAME);
@@ -265,6 +303,7 @@ public void setup() {
265303
} else {
266304
System.out.println("The program is in mix mode now.");
267305
}
306+
log("Setup done");
268307
}
269308

270309
/**

src/rprocessing/Runner.java

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@
99

1010
import javax.script.ScriptException;
1111

12-
import org.renjin.eval.EvalException;
13-
1412
import processing.core.PApplet;
1513
import processing.core.PConstants;
1614
import rprocessing.exception.NotFoundException;
17-
import rprocessing.exception.REvalException;
15+
import rprocessing.exception.RSketchError;
1816
import rprocessing.lancher.StandaloneSketch;
1917
import rprocessing.mode.library.LibraryImporter;
2018
import rprocessing.util.Printer;
@@ -76,15 +74,13 @@ public static void main(final String[] args) throws Exception {
7674
}
7775

7876
public static synchronized void runSketchBlocking(final RunnableSketch sketch,
79-
final Printer stdout, final Printer stderr)
80-
throws REvalException, NotFoundException, ScriptException {
77+
final Printer stdout, final Printer stderr) throws NotFoundException, RSketchError {
8178
runSketchBlocking(sketch, stdout, stderr, null);
8279
}
8380

8481
public static synchronized void runSketchBlocking(final RunnableSketch sketch,
8582
final Printer stdout, final Printer stderr,
86-
final SketchPositionListener sketchPositionListener)
87-
throws REvalException, NotFoundException, ScriptException {
83+
final SketchPositionListener sketchPositionListener) throws NotFoundException, RSketchError {
8884
final String[] args = sketch.getPAppletArguments();
8985

9086
log("Tring to initialize RLangPApplet.");
@@ -95,21 +91,19 @@ public static synchronized void runSketchBlocking(final RunnableSketch sketch,
9591

9692
final List<File> libDirs = sketch.getLibraryDirectories();
9793
if (libDirs != null) {
98-
LibraryImporter libraryImporter = new LibraryImporter(libDirs, rp.getRenjinEngine());
99-
final Set<String> libs = new HashSet<>();
100-
for (final File dir : libDirs) {
101-
searchForExtraStuff(dir, libs);
94+
try {
95+
LibraryImporter libraryImporter = new LibraryImporter(libDirs, rp.getRenjinEngine());
96+
final Set<String> libs = new HashSet<>();
97+
for (final File dir : libDirs) {
98+
searchForExtraStuff(dir, libs);
99+
}
100+
libraryImporter.injectIntoScope();
101+
} catch (ScriptException se) {
102+
throw RSketchError.toSketchException(se);
102103
}
103-
libraryImporter.injectIntoScope();
104104
}
105105

106-
try {
107-
// Run Sketch.
108-
rp.runBlock(args);
109-
log("Down");
110-
} catch (EvalException ee) {
111-
throw new REvalException(ee.getMessage());
112-
}
106+
rp.runBlock(args);
113107
}
114108

115109
/**
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package rprocessing.exception;
2+
3+
import org.renjin.eval.EvalException;
4+
5+
/**
6+
* Error type for Processing.R
7+
*
8+
* @author github.com/gaocegege
9+
*/
10+
public class RSketchError extends Exception {
11+
12+
private static final long serialVersionUID = 6563629093797155634L;
13+
public final String fileName;
14+
public final int line;
15+
public final int column;
16+
17+
private static final boolean VERBOSE = Boolean.parseBoolean(System.getenv("VERBOSE_RLANG_MODE"));
18+
19+
private static void log(String msg) {
20+
if (!VERBOSE) {
21+
return;
22+
}
23+
System.err.println(RSketchError.class.getSimpleName() + ": " + msg);
24+
}
25+
26+
public RSketchError(final String message) {
27+
this(message, null);
28+
}
29+
30+
public RSketchError(final String message, final String fileName) {
31+
this(message, fileName, -1, -1);
32+
}
33+
34+
public RSketchError(final String message, final String fileName, final int line) {
35+
this(message, fileName, line, 0);
36+
}
37+
38+
public RSketchError(final String message, final String fileName, final int line,
39+
final int column) {
40+
super(message);
41+
42+
this.fileName = fileName;
43+
this.line = line;
44+
this.column = column;
45+
}
46+
47+
@Override
48+
public String toString() {
49+
if (fileName == null) {
50+
return getMessage();
51+
}
52+
if (line == -1) {
53+
return getMessage() + " in " + fileName;
54+
}
55+
if (column == -1) {
56+
return getMessage() + " at line " + line + " of " + fileName;
57+
}
58+
return getMessage() + " at " + line + ":" + column + " in " + fileName;
59+
}
60+
61+
// TODO: Support the line and column.
62+
public static RSketchError toSketchException(Throwable t) {
63+
log(t.getClass().toString());
64+
if (t instanceof RuntimeException && t.getCause() != null) {
65+
t = t.getCause();
66+
}
67+
if (t instanceof RSketchError) {
68+
return (RSketchError) t;
69+
}
70+
if (t instanceof EvalException) {
71+
final RSketchError e = new RSketchError(t.getMessage());
72+
log(e.toString());
73+
return e;
74+
}
75+
if (t instanceof ClassCastException) {
76+
final RSketchError e = (RSketchError) t;
77+
return e;
78+
}
79+
if (t instanceof NullPointerException) {
80+
final RSketchError e = (RSketchError) ((NullPointerException) t).getCause();
81+
log(e.toString());
82+
return e;
83+
}
84+
log("No exception type detected.");
85+
final RSketchError e = new RSketchError(t.getMessage());
86+
return e;
87+
}
88+
}

src/rprocessing/mode/run/SketchRunner.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import rprocessing.SketchPositionListener;
1111
import rprocessing.exception.REvalException;
1212
import rprocessing.exception.RMIRuntimeException;
13+
import rprocessing.exception.RSketchError;
1314
import rprocessing.mode.RLangMode;
1415
import rprocessing.mode.run.RMIUtils.RMIProblem;
1516
import rprocessing.util.Printer;
@@ -124,15 +125,16 @@ public void sketchMoved(final Point leftTop) {
124125
}
125126
}
126127
};
128+
log("Run the sketch.");
127129
Runner.runSketchBlocking(sketch, stdout, stderr, sketchPositionListener);
128-
} catch (final REvalException exception) {
130+
} catch (final RSketchError exception) {
129131
log("Sketch runner caught " + exception);
130-
modeService.handleSketchException(id,
131-
convertREvalError(exception, sketch.codeFileNames));
132+
modeService.handleSketchException(id, exception);
132133
} catch (final Exception exception) {
134+
log("Sketch runner caught Exception:" + exception);
133135
if (exception.getCause() != null && exception.getCause() instanceof REvalException) {
134136
modeService.handleSketchException(id,
135-
convertREvalError((REvalException) exception.getCause(), sketch.codeFileNames));
137+
convertREvalError((REvalException) exception.getCause()));
136138
} else {
137139
modeService.handleSketchException(id, exception);
138140
}
@@ -141,6 +143,7 @@ public void sketchMoved(final Point leftTop) {
141143
modeService.handleSketchStopped(id);
142144
}
143145
} catch (final RemoteException exception) {
146+
log("Sketch runner caught RemoteException:" + exception);
144147
log(exception.toString());
145148
}
146149
// Exiting; no need to interrupt and join it later.
@@ -225,8 +228,8 @@ private static void startSketchRunner(final String id) throws RMIRuntimeExceptio
225228
}
226229
}
227230

228-
private static void launch(final String id, final ModeService modeService)
229-
throws RMIProblem, RemoteException {
231+
private static void launch(final String id, final ModeService modeService) throws RMIProblem,
232+
RemoteException {
230233
final SketchRunner sketchRunner = new SketchRunner(id, modeService);
231234
final SketchService stub = (SketchService) RMIUtils.export(sketchRunner);
232235
log("Calling mode's handleReady().");
@@ -244,8 +247,7 @@ public void run() {
244247
}));
245248
}
246249

247-
private SketchException convertREvalError(final REvalException exception,
248-
final String[] fileNames) {
250+
private SketchException convertREvalError(final REvalException exception) {
249251
return new SketchException(exception.getMessage());
250252
}
251253
}

0 commit comments

Comments
 (0)