ECS: handle java tabs and preference changes better

This commit is contained in:
Jakub Valtar
2016-04-30 17:41:25 +02:00
parent 59b4fb2b7f
commit e3296c48de
3 changed files with 70 additions and 67 deletions

View File

@@ -5,7 +5,6 @@ import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -204,9 +203,15 @@ public class JavaEditor extends Editor {
super.rebuild();
// after Rename and New Tab, we may have new .java tabs
hasJavaTabs = checkForJavaTabs();
boolean newHasJavaTabs = checkForJavaTabs();
boolean hasJavaTabsChanged = hasJavaTabs != newHasJavaTabs;
hasJavaTabs = newHasJavaTabs;
if (errorCheckerService != null) {
if (hasJavaTabsChanged) {
errorCheckerService.handleHasJavaTabsChange(hasJavaTabs);
}
int currentTabCount = sketch.getCodeCount();
if (currentTabCount != previousTabCount) {
previousTabCount = currentTabCount;
@@ -2753,7 +2758,7 @@ public class JavaEditor extends Editor {
jmode.loadPreferences();
Messages.log("Applying prefs");
// trigger it once to refresh UI
errorCheckerService.handleErrorCheckingToggle();
errorCheckerService.handlePreferencesChange();
}
}

View File

@@ -29,6 +29,7 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.JPanel;
@@ -114,12 +115,9 @@ public class MarkerColumn extends JPanel {
public void updateErrorPoints(final List<Problem> problems) {
errorPoints.clear();
// Each problem.getSourceLine() will have an extra line added because
// of class declaration in the beginning as well as default imports
for (Problem problem : problems) {
errorPoints.add(new LineMarker(problem, problem.isError()));
}
errorPoints = problems.stream()
.map(problem -> new LineMarker(problem, problem.isError()))
.collect(Collectors.toList());
repaint();
editor.getErrorChecker().updateEditorStatus();
}
@@ -166,7 +164,6 @@ public class MarkerColumn extends JPanel {
private void recalculateMarkerPositions() {
List<LineMarker> errorPoints = getErrorPoints();
if (errorPoints != null && errorPoints.size() > 0) {
Sketch sketch = editor.getSketch();
SketchCode code = sketch.getCurrentCode();

View File

@@ -118,7 +118,6 @@ public class ErrorCheckerService {
private volatile long nextUiUpdate = 0;
private final Object requestLock = new Object();
private final Object serialCallbackLock = new Object();
private boolean needsCheck = false;
private CompletableFuture<PreprocessedSketch> preprocessingTask =
@@ -126,20 +125,23 @@ public class ErrorCheckerService {
complete(PreprocessedSketch.empty()); // initialization block
}};
private CompletableFuture<?> lastErrorCheckTask =
new CompletableFuture() {{
complete(null); // initalization block
}};
private CompletableFuture<?> lastCallback =
new CompletableFuture() {{
complete(null); // initialization block
}};
private final Consumer<PreprocessedSketch> errorHandlerListener = this::handleSketchErrors;
private volatile boolean isEnabled = true;
private volatile boolean isContinuousCheckEnabled = true;
public ErrorCheckerService(JavaEditor editor) {
this.editor = editor;
astGenerator = new ASTGenerator(editor, this);
isEnabled = !editor.hasJavaTabs();
isContinuousCheckEnabled = JavaMode.errorCheckEnabled;
registerDoneListener(errorHandlerListener);
}
@@ -202,24 +204,14 @@ public class ErrorCheckerService {
public void notifySketchChanged() {
if (editor.hasJavaTabs()) return;
if (!isEnabled) return;
synchronized (requestLock) {
if (preprocessingTask.isDone()) {
preprocessingTask = new CompletableFuture<>();
lastErrorCheckTask = preprocessingTask
// Run error handler after both preprocessing
// task and previous error handler completed
.thenAcceptBothAsync(lastErrorCheckTask,
(ps, a) -> handleSketchErrors(ps))
// Make sure exception in error handler won't spoil the chain
.handleAsync((res, e) -> {
if (e != null) Messages.loge("problem during error handling", e);
return res;
});
// Fire listeners, don't trigger check
acceptWhenDone(this::fireDoneListeners, false);
// Register callback which executes all listeners
registerCallback(this::fireDoneListeners);
}
if (isContinuousCheckEnabled()) {
if (isContinuousCheckEnabled) {
// Continuous check enabled, request
nextUiUpdate = System.currentTimeMillis() + errorCheckInterval;
requestQueue.offer(Boolean.TRUE);
@@ -231,24 +223,9 @@ public class ErrorCheckerService {
}
public void acceptWhenDone(Consumer<PreprocessedSketch> callback) {
// Public version always triggers check
acceptWhenDone(callback, true);
}
private void acceptWhenDone(Consumer<PreprocessedSketch> callback, boolean triggerCheck) {
if (editor.hasJavaTabs()) return;
if (triggerCheck) {
// Continuous check not enabled, request check now
synchronized (requestLock) {
if (!isContinuousCheckEnabled() && needsCheck) {
needsCheck = false;
requestQueue.offer(Boolean.TRUE);
}
}
}
synchronized (serialCallbackLock) {
private void registerCallback(Consumer<PreprocessedSketch> callback) {
if (!isEnabled) return;
synchronized (requestLock) {
lastCallback = preprocessingTask
// Run callback after both preprocessing task and previous callback
.thenAcceptBothAsync(lastCallback, (ps, a) -> callback.accept(ps))
@@ -261,6 +238,19 @@ public class ErrorCheckerService {
}
public void acceptWhenDone(Consumer<PreprocessedSketch> callback) {
if (!isEnabled) return;
synchronized (requestLock) {
// Continuous check not enabled, request check now
if (needsCheck && !isContinuousCheckEnabled) {
needsCheck = false;
requestQueue.offer(Boolean.TRUE);
}
registerCallback(callback);
}
}
/// LISTENERS ----------------------------------------------------------------
@@ -529,7 +519,7 @@ public class ErrorCheckerService {
}
}
final boolean updateErrorToggle = ps.hasSyntaxErrors ||
final boolean hasErrors = ps.hasSyntaxErrors ||
ps.hasCompilationErrors;
if (scheduledUiUpdate != null) {
@@ -540,11 +530,8 @@ public class ErrorCheckerService {
Runnable uiUpdater = () -> {
if (nextUiUpdate > 0 && System.currentTimeMillis() >= nextUiUpdate) {
EventQueue.invokeLater(() -> {
if (JavaMode.errorCheckEnabled) {
updateErrorTable(problems);
editor.updateErrorBar(problems);
editor.getTextArea().repaint();
editor.updateErrorToggle(updateErrorToggle);
if (isContinuousCheckEnabled) {
setProblemList(problems, hasErrors);
}
});
}
@@ -554,6 +541,14 @@ public class ErrorCheckerService {
}
protected void setProblemList(List<Problem> problems, boolean hasErrors) {
updateErrorTable(problems);
editor.updateErrorBar(problems);
editor.getTextArea().repaint();
editor.updateErrorToggle(hasErrors);
}
protected String[] buildClassPath(List<ImportStatement> neededImports) {
JavaMode mode = (JavaMode) editor.getMode();
Sketch sketch = editor.getSketch();
@@ -811,7 +806,7 @@ public class ErrorCheckerService {
// editor.statusNotice("Position: " +
// editor.getTextArea().getCaretLine());
if (JavaMode.errorCheckEnabled) {
if (isContinuousCheckEnabled) {
LineMarker errorMarker = editor.findError(editor.getTextArea().getCaretLine());
if (errorMarker != null) {
if (errorMarker.getType() == LineMarker.WARNING) {
@@ -897,22 +892,28 @@ public class ErrorCheckerService {
}
private static boolean isContinuousCheckEnabled() {
return JavaMode.errorCheckEnabled;
public void handlePreferencesChange() {
isContinuousCheckEnabled = JavaMode.errorCheckEnabled;
if (isContinuousCheckEnabled) {
Messages.log(editor.getSketch().getName() + " Error Checker enabled.");
notifySketchChanged();
} else {
Messages.log(editor.getSketch().getName() + " Error Checker disabled.");
setProblemList(Collections.emptyList(), false);
}
}
public void handleErrorCheckingToggle() {
if (!JavaMode.errorCheckEnabled) {
Messages.log(editor.getSketch().getName() + " Error Checker disabled.");
editor.getErrorPoints().clear();
updateErrorTable(Collections.emptyList());
updateEditorStatus();
editor.getTextArea().repaint();
editor.repaintErrorBar();
} else {
Messages.log(editor.getSketch().getName() + " Error Checker enabled.");
public void handleHasJavaTabsChange(boolean hasJavaTabs) {
isEnabled = !hasJavaTabs;
if (isEnabled) {
notifySketchChanged();
} else {
preprocessingTask.cancel(false);
setProblemList(Collections.emptyList(), false);
if (astGenerator.getGui().showUsageBinding != null) {
astGenerator.getGui().showUsageWindow.setVisible(false);
}
}
}