Пакет jdk.jshell
Предоставляет интерфейсы для создания инструментов, таких как цикл Read-Eval-Print Loop (REPL), которые интерактивно оценивают "фрагменты" кода языка программирования Java. Где "фрагмент" представляет собой единственное выражение, оператор или объявление. Данная функциональность может использоваться для повышения функциональности инструментов, таких как IDE, или может быть использована как самостоятельный инструмент.
JShell — это центральный класс. Экземпляр JShell хранит состояние оценки, которое включает как текущий набор исходных фрагментов, так и состояние выполнения, которое они произвели.
Каждый исходный фрагмент представлен экземпляром подкласса Snippet. Например, оператор представлен экземпляром StatementSnippet, а объявление метода — экземпляром MethodSnippet. Фрагменты создаются при вызове JShell.eval(String) с вводом, который включает один или несколько фрагментов кода.
Любое изменение статуса компиляции фрагмента сообщается с помощью SnippetEvent. Существует три основных типа изменений состояния фрагмента: он может быть создан с помощью eval, он может быть исключён из активного состояния источника с помощью JShell.drop(jdk.jshell.Snippet), и его состояние может быть обновлено в результате изменения состояния другого фрагмента. Например: учитывая js, экземпляр JShell, выполнение js.eval("int x = 5;") добавит переменную x в состояние источника и сгенерирует событие, описывающее создание VarSnippet для x. Затем выполнение js.eval("int timesx(int val) { return val * x; }") добавит метод в состояние источника и сгенерирует событие, описывающее создание MethodSnippet для timesx. Предположим, что varx хранит фрагмент, созданный первым вызовом eval, выполнение js.drop(varx) сгенерирует два события: одно для изменения состояния фрагмента переменной на DROPPED и одно для обновления фрагмента метода (который теперь имеет неразрешённую ссылку на x).
Конечно, для любого общего применения API ввод не будет фиксированными строками, а будет поступать от пользователя. Ниже приведён сильно упрощённый пример того, как API может быть использован для реализации REPL.
import java.io.ByteArrayInputStream;
import java.io.Console;
import java.util.List;
import jdk.jshell.*;
import jdk.jshell.Snippet.Status;
class ExampleJShell {
public static void main(String[] args) {
Console console = System.console();
try (JShell js = JShell.create()) {
do {
System.out.print("Enter some Java code: ");
String input = console.readLine();
if (input == null) {
break;
}
List<SnippetEvent> events = js.eval(input);
for (SnippetEvent e : events) {
StringBuilder sb = new StringBuilder();
if (e.causeSnippet == null) {
// We have a snippet creation event
switch (e.status) {
case VALID:
sb.append("Successful ");
break;
case RECOVERABLE_DEFINED:
sb.append("With unresolved references ");
break;
case RECOVERABLE_NOT_DEFINED:
sb.append("Possibly reparable, failed ");
break;
case REJECTED:
sb.append("Failed ");
break;
}
if (e.previousStatus == Status.NONEXISTENT) {
sb.append("addition");
} else {
sb.append("modification");
}
sb.append(" of ");
sb.append(e.snippet.source());
System.out.println(sb);
if (e.value != null) {
System.out.printf("Value is: %s\n", e.value);
}
System.out.flush();
}
}
} while (true);
}
System.out.println("\nGoodbye");
}
}
Для регистрации на события изменения состояния используйте JShell.onSnippetEvent(java.util.function.Consumer). Эти события генерируются только eval и drop, значения возврата этих методов — список событий, сгенерированных этим вызовом. Таким образом, как в примере выше, события могут быть использованы без регистрации на получение событий.
Если вы поэкспериментируете с этим примером, вы увидите, что отказ от завершения оператора или объявления переменной с использованием точки с запятой просто приведёт к ошибке. Незавершенная запись (например, желаемый многострочный метод) также просто завершится ошибкой после одной строки. Утилиты в SourceCodeAnalysis предоставляют анализ границ и полноты источника для решения подобных случаев. SourceCodeAnalysis также предоставляет предлагаемые завершения ввода, что может быть использовано в автозаполнении (tab-completion).
- Since:
- 9
| Интерфейс | Описание |
|---|---|
| SourceCodeAnalysis.CompletionInfo | Результат |
| SourceCodeAnalysis.Documentation | Документация для кандидата на продолжение ввода пользователя. |
| SourceCodeAnalysis.SnippetWrapper | Оборачивание фрагмента Java-исходного кода в допустимый исходный код Java верхнего уровня. |
| SourceCodeAnalysis.Suggestion | Кандидат на продолжение ввода пользователя. |
| Класс | Описание |
|---|---|
| DeclarationSnippet | Группа всех фрагментов объявления: объявления переменных ( |
| Diag | Диагностическая информация для фрагмента. |
| ErroneousSnippet | Фрагмент кода, который не является допустимым кодом языка программирования Java. |
| ExpressionSnippet | Фрагмент для присваивания или выражения значения переменной. |
| ImportSnippet | Фрагмент для объявления импорта. |
| JShell | Двигатель состояния оценки JShell. |
| JShell.Builder | Библиотека для создания экземпляров |
| MethodSnippet | Фрагмент для определения метода. |
| PersistentSnippet | Группа фрагментов, которые сохраняются и влияют на будущий код. |
| Snippet | Фрагмент представляет собой фрагмент исходного кода Java, переданный |
| SnippetEvent | Описание изменения фрагмента. |
| SourceCodeAnalysis | Предоставляет утилиты анализа для входных данных исходного кода. |
| SourceCodeAnalysis.QualifiedNames | Список возможных квалифицированных имён. |
| StatementSnippet | Фрагмент для оператора. |
| TypeDeclSnippet | Фрагмент для определения типа (класса, интерфейса, перечисления или аннотационного интерфейса). |
| VarSnippet | Фрагмент для объявления переменной. |
| Перечисление | Описание |
|---|---|
| Snippet.Kind | Описание общего типа фрагмента. |
| Snippet.Status | Описание текущего состояния фрагмента. |
| Snippet.SubKind | Детальный вид фрагмента. |
| SourceCodeAnalysis.Completeness | Описание полноты входных данных. |
| Исключение | Описание |
|---|---|
| EvalException | Оборачивает исключение, брошенное в клиентском приложении. |
| JShellException | Базовый класс для исключений, сгенерированных JShell. |
| UnresolvedReferenceException | Исключение, сообщённое при попытке выполнить фрагмент |
© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/11/docs/api/jdk.jshell/jdk/jshell/package-summary.html