I'm using the JShell API to run Java code. However, I got an error when I run a whole code.
For example:
import jdk.jshell.JShell;
var code= """
void hello(){
System.out.println("Hello world");
}
hello();
""";
JShell shell = JShell.create();
List<SnippetEvent> snippets = shell.eval(code);
After evaluation, I see the error in output snippet.
cannot find symbol
symbol: method hello()
location: class
What is the problem here ?
eval
is not designed to handle code like that. The code you showed is actually 2 "complete snippets" that needs to be broken up before you pass into eval
. From the docs:
The input should be exactly one complete snippet of source code, that is, one expression, statement, variable declaration, method declaration, class declaration, or import. To break arbitrary input into individual complete snippets, use
SourceCodeAnalysis.analyzeCompletion(String)
.
The "real" JShell command line program probably uses the SourceCodeAnalysis.analyzeCompletion(String)
method to break up your input into two complete snippets, and passes each of them into eval
.
Here is how to use SourceCodeAnalysis.analyzeCompletion(String)
:
var code = "...";
JShell jshell = JShell.create();
SourceCodeAnalysis.CompletionInfo completionInfo = jshell.sourceCodeAnalysis().analyzeCompletion(code);
// this is the shortest complete code
System.out.println(completionInfo.source());
// this is what remains after removing the shortest complete code
// you'd probably want to analyze the completion of this recursively
System.out.println(completionInfo.remaining());
hello();
fails to compile for the same reason that
class Foo {
void hello() {
}
hello();
}
doesn't compile.
If you look at the diagnostics:
JShell shell = JShell.create();
List<SnippetEvent> events = shell.eval(code);
shell.diagnostics(events.get(0).snippet()).forEach(x -> System.out.println(x.getMessage(Locale.ENGLISH)));
You get:
Invalid method declaration; return type required
That is the exact error message you get if you put a method call at class level.
Anyway, to make your code work, simply eval
the method declaration first, then eval
the hello();
call.