Skip to content

Commit

Permalink
Cleanup of JShellWrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
surajkumar committed May 19, 2024
1 parent aede716 commit 4b6da72
Showing 1 changed file with 84 additions and 68 deletions.
152 changes: 84 additions & 68 deletions JShellWrapper/src/main/java/JShellWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,73 +43,87 @@ public void run(Config config, InputStream in, PrintStream processOut) {

private void verifyStartupEval(EvalResult result) {
JShellEvalAbortion abortion = result.abortion();
if (abortion == null) return;
SnippetEvent event = result.events().get(result.events().size() - 1);
// TODO Replace with switch
if (abortion.cause() instanceof JShellEvalAbortionCause.TimeoutAbortionCause) {
throw new RuntimeException("Timeout exceeded.");
} else if (abortion.cause()
instanceof JShellEvalAbortionCause.UnhandledExceptionAbortionCause) {
throw new RuntimeException(
"Following startup script resulted in an exception : "
+ sanitize(abortion.sourceCause()),
event.exception());
} else if (abortion.cause()
instanceof JShellEvalAbortionCause.CompileTimeErrorAbortionCause) {
throw new RuntimeException(
"Following startup script was REJECTED : " + sanitize(abortion.sourceCause()));
} else if (abortion.cause() instanceof JShellEvalAbortionCause.SyntaxErrorAbortionCause) {
throw new RuntimeException(
"Following startup script has a syntax error : "
+ sanitize(abortion.sourceCause()));
} else throw new AssertionError();
if (abortion == null) {
return;
}

JShellEvalAbortionCause cause = abortion.cause();

String message = switch (cause) {
case JShellEvalAbortionCause.TimeoutAbortionCause ignored ->
"Timeout exceeded.";
case JShellEvalAbortionCause.UnhandledExceptionAbortionCause ignored ->
"Following startup script resulted in an exception: " + sanitize(abortion.sourceCause());
case JShellEvalAbortionCause.CompileTimeErrorAbortionCause ignored ->
"Following startup script was REJECTED: " + sanitize(abortion.sourceCause());
case JShellEvalAbortionCause.SyntaxErrorAbortionCause ignored ->
"Following startup script has a syntax error: " + sanitize(abortion.sourceCause());
};

if (cause instanceof JShellEvalAbortionCause.UnhandledExceptionAbortionCause) {
throw new RuntimeException(message, result.events().getLast().exception());
} else {
throw new RuntimeException(message);
}
}

private void ok(PrintStream processOut) {
processOut.println("OK");
processOut.flush();

private void ok(PrintStream output) {
output.println("OK");
output.flush();
}

private EvalResult eval(JShell shell, String code, AtomicBoolean hasStopped) {
List<SnippetEvent> resultEvents = new ArrayList<>();
JShellEvalAbortion abortion = null;

while (!code.isEmpty()) {
var completion = shell.sourceCodeAnalysis().analyzeCompletion(clean(code));
SourceCodeAnalysis.CompletionInfo completion = shell.sourceCodeAnalysis().analyzeCompletion(clean(code));

if (!completion.completeness().isComplete()) {
abortion =
new JShellEvalAbortion(
code, "", new JShellEvalAbortionCause.SyntaxErrorAbortionCause());
abortion = createSyntaxErrorAbortion(code);
break;
}

List<SnippetEvent> evalEvents = shell.eval(completion.source());
JShellEvalAbortionCause abortionCause = handleEvents(shell, evalEvents, resultEvents);

if (abortionCause != null) {
abortion =
new JShellEvalAbortion(
completion.source(), completion.remaining(), abortionCause);
abortion = new JShellEvalAbortion(completion.source(), completion.remaining(), abortionCause);
break;
}

if (hasStopped.get()) {
abortion =
new JShellEvalAbortion(
completion.source(),
completion.remaining(),
new JShellEvalAbortionCause.TimeoutAbortionCause());
abortion = createTimeoutAbortion(completion);
break;
}

code = completion.remaining();
}

return new EvalResult(resultEvents, abortion);
}

private JShellEvalAbortion createSyntaxErrorAbortion(String code) {
return new JShellEvalAbortion(code, "", new JShellEvalAbortionCause.SyntaxErrorAbortionCause());
}

private JShellEvalAbortion createTimeoutAbortion(SourceCodeAnalysis.CompletionInfo completion) {
return new JShellEvalAbortion(completion.source(), completion.remaining(), new JShellEvalAbortionCause.TimeoutAbortionCause());
}


private JShellEvalAbortionCause handleEvents(
JShell shell, List<SnippetEvent> evalEvents, List<SnippetEvent> resultEvents) {
for (SnippetEvent event : evalEvents) {
if (event.causeSnippet() == null) { // Only keep snippet creation events
resultEvents.add(event);
if (event.status() == Snippet.Status.REJECTED)
if (event.status() == Snippet.Status.REJECTED) {
return createCompileErrorCause(shell, event);
if (event.exception() != null) return createExceptionCause(event);
}
if (event.exception() != null) {
return createExceptionCause(event);
}
}
}
return null;
Expand All @@ -119,7 +133,8 @@ private JShellEvalAbortionCause.UnhandledExceptionAbortionCause createExceptionC
SnippetEvent event) {
if (event.exception() == null) {
return null;
} else if (event.exception() instanceof EvalException evalException) {
}
if (event.exception() instanceof EvalException evalException) {
return new JShellEvalAbortionCause.UnhandledExceptionAbortionCause(
evalException.getExceptionClassName(), evalException.getMessage());
} else {
Expand Down Expand Up @@ -159,7 +174,7 @@ private void eval(
PrintStream processOut,
Config config,
JShell shell,
StringOutputStream jshellOut) {
StringOutputStream jShellOutput) {
AtomicBoolean hasStopped = new AtomicBoolean();
TimeoutWatcher watcher =
new TimeoutWatcher(
Expand All @@ -175,49 +190,50 @@ private void eval(
EvalResult result = eval(shell, code, hasStopped);
watcher.stop();

List<String> outBuffer = writeEvalResult(result, jshellOut);
List<String> outBuffer = writeEvalResult(result, jShellOutput);
for (String line : outBuffer) {
processOut.println(line);
}
}

private List<String> writeEvalResult(EvalResult result, StringOutputStream jshellOut) {
private List<String> writeEvalResult(EvalResult result, StringOutputStream jShellOutput) {
List<SnippetEvent> events = result.events();
List<String> outBuffer = new ArrayList<>();
outBuffer.add(String.valueOf(events.size()));
List<String> buffer = new ArrayList<>();

buffer.add(String.valueOf(events.size()));
for (SnippetEvent event : events) {
writeEvalSnippetEvent(outBuffer, event);
writeEvalSnippetEvent(buffer, event);
}

JShellEvalAbortion abortion = result.abortion();
if (abortion != null) {
// TODO replace with switch
if (abortion.cause() instanceof JShellEvalAbortionCause.TimeoutAbortionCause) {
outBuffer.add("TIMEOUT");
} else if (abortion.cause()
instanceof JShellEvalAbortionCause.UnhandledExceptionAbortionCause c) {
outBuffer.add("UNCAUGHT_EXCEPTION");
outBuffer.add(getExceptionFromCause(c));
} else if (abortion.cause()
instanceof JShellEvalAbortionCause.CompileTimeErrorAbortionCause c) {
outBuffer.add("COMPILE_TIME_ERROR");
outBuffer.add(String.valueOf(c.errors().size()));
outBuffer.addAll(c.errors());
} else if (abortion.cause()
instanceof JShellEvalAbortionCause.SyntaxErrorAbortionCause c) {
outBuffer.add("SYNTAX_ERROR");
} else throw new AssertionError();
outBuffer.add(sanitize(abortion.sourceCause()));
outBuffer.add(sanitize(abortion.remainingSource()));
} else {
outBuffer.add("");
var cause = abortion.cause();
switch (cause) {
case JShellEvalAbortionCause.TimeoutAbortionCause ignored1 -> buffer.add("TIMEOUT");
case JShellEvalAbortionCause.UnhandledExceptionAbortionCause c -> {
buffer.add("UNCAUGHT_EXCEPTION");
buffer.add(getExceptionFromCause(c));
}
case JShellEvalAbortionCause.CompileTimeErrorAbortionCause c -> {
buffer.add("COMPILE_TIME_ERROR");
buffer.add(String.valueOf(c.errors().size()));
buffer.addAll(c.errors());
}
case JShellEvalAbortionCause.SyntaxErrorAbortionCause ignored -> buffer.add("SYNTAX_ERROR");
default -> throw new AssertionError();
}
buffer.add(sanitize(abortion.sourceCause()));
buffer.add(sanitize(abortion.remainingSource()));
}

StringOutputStream.Result out = jshellOut.readAll();
outBuffer.add(String.valueOf(out.isOverflow()));
outBuffer.add(sanitize(out.content()));
return outBuffer;
StringOutputStream.Result out = jShellOutput.readAll();
buffer.add(String.valueOf(out.isOverflow()));
buffer.add(sanitize(out.content()));

return buffer;
}


/**
* Output format :<br>
* <code>
Expand Down

0 comments on commit 4b6da72

Please sign in to comment.