diff --git a/build.gradle b/build.gradle index da67b39dae..81332a0b83 100644 --- a/build.gradle +++ b/build.gradle @@ -73,4 +73,7 @@ shadowJar { run { standardInput = System.in + // Java ignores assert statements unless told otherwise, so turn them on when + // running the app from Gradle. Tests already run with assertions on. + enableAssertions = true } diff --git a/src/main/java/ted/MainWindow.java b/src/main/java/ted/MainWindow.java index 3ded5d5653..8658e605ba 100644 --- a/src/main/java/ted/MainWindow.java +++ b/src/main/java/ted/MainWindow.java @@ -59,6 +59,7 @@ public void setTed(Ted ted) { */ @FXML private void handleUserInput() { + assert ted != null : "Main calls setTed before showing the window, so input always has a Ted"; String input = userInput.getText(); String response = ted.getResponse(input); if (response.isEmpty()) { diff --git a/src/main/java/ted/Parser.java b/src/main/java/ted/Parser.java index 5740763887..7817ce3e3d 100644 --- a/src/main/java/ted/Parser.java +++ b/src/main/java/ted/Parser.java @@ -59,6 +59,8 @@ private Parser() { * @throws TedException if the command is unknown or its details are unusable. */ public static Command parse(String input) throws TedException { + assert !input.isBlank() : "Ted skips blank input, so it never reaches the parser"; + // Splitting into at most two parts keeps the command word exact, so that // "todos" is not mistaken for "todo", while leaving the rest untouched. String[] parts = input.split(" ", 2); diff --git a/src/main/java/ted/Storage.java b/src/main/java/ted/Storage.java index 2a01d32fba..adf6606cf8 100644 --- a/src/main/java/ted/Storage.java +++ b/src/main/java/ted/Storage.java @@ -139,6 +139,8 @@ public int getSkippedLineCount() { * @return the rebuilt task, or {@code null} if the line is not in the expected format. */ private static Task parseLine(String line) { + assert !line.isBlank() : "load() skips blank lines, so they are never parsed"; + // A first, unlimited split just to read the type icon safely: even a // corrupted line must have at least its icon before anything can be parsed. String icon = line.split(FIELD_SEPARATOR_REGEX)[0]; @@ -172,7 +174,7 @@ private static Task parseLine(String line) { parseSavedDateTime(fields[3])), isDone); default: - // Unreachable: fieldCountFor accepts only T, D and E. + assert false : "unreachable, as fieldCountFor accepts only T, D and E"; return null; } } catch (DateTimeParseException e) { diff --git a/src/main/java/ted/Ted.java b/src/main/java/ted/Ted.java index 53b347989b..0e16f88082 100644 --- a/src/main/java/ted/Ted.java +++ b/src/main/java/ted/Ted.java @@ -123,6 +123,7 @@ public String getResponse(String input) { return ui.flush(); } + assert tasks != null : "the constructor sets up a task list even when loading fails"; try { command.execute(tasks, ui, storage); } catch (TedException e) { diff --git a/src/main/java/ted/task/TaskList.java b/src/main/java/ted/task/TaskList.java index d3ba0b7cc2..dd3c4dae67 100644 --- a/src/main/java/ted/task/TaskList.java +++ b/src/main/java/ted/task/TaskList.java @@ -28,6 +28,7 @@ public TaskList() { * @param tasks the tasks to start with. */ public TaskList(List tasks) { + assert tasks.stream().allMatch(task -> task != null) : "Storage.load() never adds null"; this.tasks = new ArrayList<>(tasks); }