mirror of
https://github.com/processing/processing4.git
synced 2026-02-04 06:09:17 +01:00
ECS: clean up problem handling, move editor functions to JavaEditor
This commit is contained in:
@@ -5,6 +5,7 @@ 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;
|
||||
@@ -31,7 +32,6 @@ import processing.mode.java.debug.LineID;
|
||||
import processing.mode.java.pdex.ASTGenerator;
|
||||
import processing.mode.java.pdex.ErrorCheckerService;
|
||||
import processing.mode.java.pdex.ImportStatement;
|
||||
import processing.mode.java.pdex.LineMarker;
|
||||
import processing.mode.java.pdex.JavaTextArea;
|
||||
import processing.mode.java.pdex.Problem;
|
||||
import processing.mode.java.pdex.SourceUtils;
|
||||
@@ -72,6 +72,8 @@ public class JavaEditor extends Editor {
|
||||
|
||||
protected ErrorCheckerService errorCheckerService;
|
||||
|
||||
protected List<Problem> problems = Collections.emptyList();
|
||||
|
||||
|
||||
protected JavaEditor(Base base, String path, EditorState state,
|
||||
Mode mode) throws EditorException {
|
||||
@@ -160,7 +162,7 @@ public class JavaEditor extends Editor {
|
||||
|
||||
textarea.addCaretListener(new CaretListener() {
|
||||
public void caretUpdate(CaretEvent e) {
|
||||
errorCheckerService.updateEditorStatus();
|
||||
updateEditorStatus();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -210,6 +212,9 @@ public class JavaEditor extends Editor {
|
||||
if (errorCheckerService != null) {
|
||||
if (hasJavaTabsChanged) {
|
||||
errorCheckerService.handleHasJavaTabsChange(hasJavaTabs);
|
||||
if (hasJavaTabs) {
|
||||
setProblemList(Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
int currentTabCount = sketch.getCodeCount();
|
||||
@@ -2512,31 +2517,106 @@ public class JavaEditor extends Editor {
|
||||
// }
|
||||
|
||||
|
||||
public void updateErrorBar(List<Problem> problems) {
|
||||
public void setProblemList(List<Problem> problems) {
|
||||
this.problems = problems;
|
||||
boolean hasErrors = problems.stream().anyMatch(Problem::isError);
|
||||
updateErrorTable(problems);
|
||||
errorColumn.updateErrorPoints(problems);
|
||||
textarea.repaint();
|
||||
updateErrorToggle(hasErrors);
|
||||
updateEditorStatus();
|
||||
}
|
||||
|
||||
|
||||
public List<LineMarker> getErrorPoints() {
|
||||
return errorColumn.getErrorPoints();
|
||||
/**
|
||||
* Updates the error table in the Error Window.
|
||||
*/
|
||||
public void updateErrorTable(List<Problem> problems) {
|
||||
errorTable.clearRows();
|
||||
|
||||
for (Problem p : problems) {
|
||||
String message = p.getMessage();
|
||||
if (Preferences.getBoolean(JavaMode.SUGGEST_IMPORTS_PREF) &&
|
||||
p.getImportSuggestions() != null &&
|
||||
p.getImportSuggestions().length > 0) {
|
||||
message += " (double-click for suggestions)";
|
||||
}
|
||||
|
||||
errorTable.addRow(p, message,
|
||||
sketch.getCode(p.getTabIndex()).getPrettyName(),
|
||||
Integer.toString(p.getLineNumber() + 1));
|
||||
// Added +1 because lineNumbers internally are 0-indexed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void highlight(Problem p) {
|
||||
if (p != null) {
|
||||
highlight(p.getTabIndex(), p.getStartOffset(), p.getStartOffset());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void highlight(int tabIndex, int startOffset, int stopOffset) {
|
||||
// Switch to tab
|
||||
toFront();
|
||||
sketch.setCurrentCode(tabIndex);
|
||||
|
||||
// Make sure offsets are in bounds
|
||||
int length = textarea.getDocumentLength();
|
||||
startOffset = PApplet.constrain(startOffset, 0, length);
|
||||
stopOffset = PApplet.constrain(stopOffset, 0, length);
|
||||
|
||||
// Highlight the code
|
||||
textarea.select(startOffset, stopOffset);
|
||||
|
||||
// Scroll to error line
|
||||
textarea.scrollToCaret();
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
public List<Problem> getProblems() {
|
||||
return problems;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates editor status bar, depending on whether the caret is on an error
|
||||
* line or not
|
||||
*/
|
||||
public void updateEditorStatus() {
|
||||
if (JavaMode.errorCheckEnabled) {
|
||||
Problem problem = findError(textarea.getCaretLine());
|
||||
if (problem != null) {
|
||||
int type = problem.isError() ?
|
||||
EditorStatus.CURSOR_LINE_ERROR : EditorStatus.CURSOR_LINE_WARNING;
|
||||
statusMessage(problem.getMessage(), type);
|
||||
} else {
|
||||
switch (getStatusMode()) {
|
||||
case EditorStatus.CURSOR_LINE_ERROR:
|
||||
case EditorStatus.CURSOR_LINE_WARNING:
|
||||
statusEmpty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the LineMarker for the first error or warning on 'line'
|
||||
*/
|
||||
public LineMarker findError(int line) {
|
||||
List<LineMarker> errorPoints = getErrorPoints();
|
||||
public Problem findError(int line) {
|
||||
JavaTextArea textArea = getJavaTextArea();
|
||||
int currentTab = getSketch().getCurrentCodeIndex();
|
||||
for (LineMarker emarker : errorPoints) {
|
||||
if (emarker.getProblem().getTabIndex() != currentTab) continue;
|
||||
Problem p = emarker.getProblem();
|
||||
for (Problem p : problems) {
|
||||
if (p.getTabIndex() != currentTab) continue;
|
||||
int pStartLine = p.getLineNumber();
|
||||
int pEndOffset = p.getStopOffset();
|
||||
int pEndLine = textArea.getLineOfOffset(pEndOffset);
|
||||
if (line >= pStartLine && line <= pEndLine) {
|
||||
return emarker;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -2573,8 +2653,7 @@ public class JavaEditor extends Editor {
|
||||
|
||||
|
||||
public void errorTableClick(Object item) {
|
||||
Problem p = (Problem) item;
|
||||
errorCheckerService.scrollToErrorLine(p);
|
||||
highlight((Problem) item);
|
||||
}
|
||||
|
||||
|
||||
@@ -2598,6 +2677,8 @@ public class JavaEditor extends Editor {
|
||||
// showImportSuggestion(temp, evt.getXOnScreen(), evt.getYOnScreen() - 3 * getFont().getSize());
|
||||
Point mouse = MouseInfo.getPointerInfo().getLocation();
|
||||
showImportSuggestion(temp, mouse.x, mouse.y);
|
||||
} else {
|
||||
errorTableClick(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2759,6 +2840,7 @@ public class JavaEditor extends Editor {
|
||||
Messages.log("Applying prefs");
|
||||
// trigger it once to refresh UI
|
||||
errorCheckerService.handlePreferencesChange();
|
||||
setProblemList(Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ public class MarkerColumn extends JPanel {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
g.drawImage(editor.getJavaTextArea().getGutterGradient(),
|
||||
0, 0, getWidth(), getHeight(), this);
|
||||
@@ -109,17 +110,11 @@ public class MarkerColumn extends JPanel {
|
||||
}
|
||||
|
||||
|
||||
public List<LineMarker> getErrorPoints() {
|
||||
return errorPoints;
|
||||
}
|
||||
|
||||
|
||||
public void updateErrorPoints(final List<Problem> problems) {
|
||||
errorPoints = problems.stream()
|
||||
.map(problem -> new LineMarker(problem, problem.isError()))
|
||||
.map(LineMarker::new)
|
||||
.collect(Collectors.toList());
|
||||
repaint();
|
||||
editor.getErrorChecker().updateEditorStatus();
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +123,7 @@ public class MarkerColumn extends JPanel {
|
||||
try {
|
||||
LineMarker m = findClosestMarker(y);
|
||||
if (m != null) {
|
||||
editor.getErrorChecker().scrollToErrorLine(m.getProblem());
|
||||
editor.highlight(m.getProblem());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
|
||||
@@ -2583,12 +2583,20 @@ public class ASTGenerator {
|
||||
handleShowUsage(ps, binding);
|
||||
} else {
|
||||
Messages.log("found declaration, offset " + decl.getStartPosition() + ", name: " + declName);
|
||||
ecs.highlightNode(ps, declName);
|
||||
highlightNode(ps, declName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void highlightNode(PreprocessedSketch ps, ASTNode node) {
|
||||
SketchInterval si = ps.mapJavaToSketch(node);
|
||||
EventQueue.invokeLater(() -> {
|
||||
editor.highlight(si.tabIndex, si.startTabOffset, si.stopTabOffset);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// GUI ----------------------------------------------------------------------
|
||||
|
||||
@@ -2760,9 +2768,7 @@ public class ASTGenerator {
|
||||
|
||||
if (tnode.getUserObject() instanceof ShowUsageTreeNode) {
|
||||
ShowUsageTreeNode node = (ShowUsageTreeNode) tnode.getUserObject();
|
||||
astGen.ecs.highlightTabRange(node.tabIndex,
|
||||
node.startTabOffset,
|
||||
node.stopTabOffset);
|
||||
editor.highlight(node.tabIndex, node.startTabOffset, node.stopTabOffset);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2963,7 +2969,7 @@ public class ASTGenerator {
|
||||
if (tnode.getUserObject() instanceof ASTNode) {
|
||||
ASTNode node = (ASTNode) tnode.getUserObject();
|
||||
|
||||
astGen.ecs.acceptWhenDone(ps1 -> astGen.ecs.highlightNode(ps1, node));
|
||||
astGen.ecs.acceptWhenDone(ps1 -> astGen.highlightNode(ps1, node));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ import javax.swing.text.Document;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.compiler.IProblem;
|
||||
import org.eclipse.jdt.core.dom.AST;
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.ASTParser;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
|
||||
@@ -68,9 +67,6 @@ import processing.app.Sketch;
|
||||
import processing.app.SketchCode;
|
||||
import processing.app.SketchException;
|
||||
import processing.app.Util;
|
||||
import processing.app.ui.EditorStatus;
|
||||
import processing.app.ui.ErrorTable;
|
||||
import processing.core.PApplet;
|
||||
import processing.data.IntList;
|
||||
import processing.data.StringList;
|
||||
import processing.mode.java.JavaEditor;
|
||||
@@ -130,7 +126,7 @@ public class ErrorCheckerService {
|
||||
complete(null); // initialization block
|
||||
}};
|
||||
|
||||
private final Consumer<PreprocessedSketch> errorHandlerListener = this::handleSketchErrors;
|
||||
private final Consumer<PreprocessedSketch> errorHandlerListener = this::handleSketchProblems;
|
||||
|
||||
private volatile boolean isEnabled = true;
|
||||
private volatile boolean isContinuousCheckEnabled = true;
|
||||
@@ -466,7 +462,7 @@ public class ErrorCheckerService {
|
||||
}
|
||||
|
||||
|
||||
private void handleSketchErrors(PreprocessedSketch ps) {
|
||||
private void handleSketchProblems(PreprocessedSketch ps) {
|
||||
// Process problems
|
||||
final List<Problem> problems = ps.problems.stream()
|
||||
// Filter Warnings if they are not enabled
|
||||
@@ -519,9 +515,6 @@ public class ErrorCheckerService {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean hasErrors = ps.hasSyntaxErrors ||
|
||||
ps.hasCompilationErrors;
|
||||
|
||||
if (scheduledUiUpdate != null) {
|
||||
scheduledUiUpdate.cancel(true);
|
||||
}
|
||||
@@ -531,7 +524,7 @@ public class ErrorCheckerService {
|
||||
if (nextUiUpdate > 0 && System.currentTimeMillis() >= nextUiUpdate) {
|
||||
EventQueue.invokeLater(() -> {
|
||||
if (isContinuousCheckEnabled) {
|
||||
setProblemList(problems, hasErrors);
|
||||
editor.setProblemList(problems);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -541,14 +534,6 @@ 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();
|
||||
@@ -768,110 +753,6 @@ public class ErrorCheckerService {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the error table in the Error Window.
|
||||
*/
|
||||
protected void updateErrorTable(List<Problem> problems) {
|
||||
try {
|
||||
ErrorTable table = editor.getErrorTable();
|
||||
table.clearRows();
|
||||
|
||||
Sketch sketch = editor.getSketch();
|
||||
for (Problem p : problems) {
|
||||
String message = p.getMessage();
|
||||
if (Preferences.getBoolean(JavaMode.SUGGEST_IMPORTS_PREF) &&
|
||||
p.getImportSuggestions() != null &&
|
||||
p.getImportSuggestions().length > 0) {
|
||||
message += " (double-click for suggestions)";
|
||||
}
|
||||
|
||||
table.addRow(p, message,
|
||||
sketch.getCode(p.getTabIndex()).getPrettyName(),
|
||||
Integer.toString(p.getLineNumber() + 1));
|
||||
// Added +1 because lineNumbers internally are 0-indexed
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Messages.loge("Exception at updateErrorTable()", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates editor status bar, depending on whether the caret is on an error
|
||||
* line or not
|
||||
*/
|
||||
public void updateEditorStatus() {
|
||||
// if (editor.getStatusMode() == EditorStatus.EDIT) return;
|
||||
|
||||
// editor.statusNotice("Position: " +
|
||||
// editor.getTextArea().getCaretLine());
|
||||
if (isContinuousCheckEnabled) {
|
||||
LineMarker errorMarker = editor.findError(editor.getTextArea().getCaretLine());
|
||||
if (errorMarker != null) {
|
||||
if (errorMarker.getType() == LineMarker.WARNING) {
|
||||
editor.statusMessage(errorMarker.getProblem().getMessage(),
|
||||
EditorStatus.CURSOR_LINE_WARNING);
|
||||
} else {
|
||||
editor.statusMessage(errorMarker.getProblem().getMessage(),
|
||||
EditorStatus.CURSOR_LINE_ERROR);
|
||||
}
|
||||
} else {
|
||||
switch (editor.getStatusMode()) {
|
||||
case EditorStatus.CURSOR_LINE_ERROR:
|
||||
case EditorStatus.CURSOR_LINE_WARNING:
|
||||
editor.statusEmpty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // This line isn't an error line anymore, so probably just clear it
|
||||
// if (editor.statusMessageType == JavaEditor.STATUS_COMPILER_ERR) {
|
||||
// editor.statusEmpty();
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// TODO: does this belong here?
|
||||
// Thread: EDT
|
||||
public void scrollToErrorLine(Problem p) {
|
||||
if (p == null) return;
|
||||
highlightTabRange(p.getTabIndex(), p.getStartOffset(), p.getStopOffset());
|
||||
}
|
||||
|
||||
// TODO: does this belong here?
|
||||
// Thread: EDT
|
||||
public void highlightTabRange(int tabIndex, int startTabOffset, int stopTabOffset) {
|
||||
if (editor == null) return;
|
||||
|
||||
// Switch to tab
|
||||
editor.toFront();
|
||||
editor.getSketch().setCurrentCode(tabIndex);
|
||||
|
||||
// Make sure offsets are in bounds
|
||||
int length = editor.getTextArea().getDocumentLength();
|
||||
startTabOffset = PApplet.constrain(startTabOffset, 0, length);
|
||||
stopTabOffset = PApplet.constrain(stopTabOffset, 0, length);
|
||||
|
||||
// Highlight the code
|
||||
editor.getTextArea().select(startTabOffset, stopTabOffset);
|
||||
|
||||
// Scroll to error line
|
||||
editor.getTextArea().scrollToCaret();
|
||||
editor.repaint();
|
||||
}
|
||||
|
||||
|
||||
public void highlightNode(PreprocessedSketch ps, ASTNode node) {
|
||||
SketchInterval si = ps.mapJavaToSketch(node);
|
||||
EventQueue.invokeLater(() -> {
|
||||
highlightTabRange(si.tabIndex, si.startTabOffset, si.stopTabOffset);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if import statements in the sketch have changed. If they have,
|
||||
* compiler classpath needs to be updated.
|
||||
@@ -899,7 +780,6 @@ public class ErrorCheckerService {
|
||||
notifySketchChanged();
|
||||
} else {
|
||||
Messages.log(editor.getSketch().getName() + " Error Checker disabled.");
|
||||
setProblemList(Collections.emptyList(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -910,7 +790,6 @@ public class ErrorCheckerService {
|
||||
notifySketchChanged();
|
||||
} else {
|
||||
preprocessingTask.cancel(false);
|
||||
setProblemList(Collections.emptyList(), false);
|
||||
if (astGenerator.getGui().showUsageBinding != null) {
|
||||
astGenerator.getGui().showUsageWindow.setVisible(false);
|
||||
}
|
||||
|
||||
@@ -300,10 +300,8 @@ public class JavaTextAreaPainter extends TextAreaPainter
|
||||
* @param x
|
||||
*/
|
||||
protected void paintErrorLine(Graphics gfx, int line, int x) {
|
||||
LineMarker marker = getJavaEditor().findError(line);
|
||||
if (marker != null) {
|
||||
Problem problem = marker.getProblem();
|
||||
|
||||
Problem problem = getJavaEditor().findError(line);
|
||||
if (problem != null) {
|
||||
int startOffset = problem.getStartOffset();
|
||||
int stopOffset = problem.getStopOffset();
|
||||
|
||||
@@ -347,7 +345,7 @@ public class JavaTextAreaPainter extends TextAreaPainter
|
||||
x2 += Editor.LEFT_GUTTER;
|
||||
|
||||
gfx.setColor(errorUnderlineColor);
|
||||
if (marker.getType() == LineMarker.WARNING) {
|
||||
if (problem.isWarning()) {
|
||||
gfx.setColor(warningUnderlineColor);
|
||||
}
|
||||
paintSquiggle(gfx, y1, x1, x2);
|
||||
@@ -388,10 +386,8 @@ public class JavaTextAreaPainter extends TextAreaPainter
|
||||
public String getToolTipText(MouseEvent evt) {
|
||||
int line = evt.getY() / getFontMetrics().getHeight() + textArea.getFirstLine();
|
||||
if (line >= 0 || line < textArea.getLineCount()) {
|
||||
LineMarker marker = getJavaEditor().findError(line);
|
||||
if (marker != null) {
|
||||
Problem problem = marker.getProblem();
|
||||
|
||||
Problem problem = getJavaEditor().findError(line);
|
||||
if (problem != null) {
|
||||
int lineStart = textArea.getLineStartOffset(line);
|
||||
int lineEnd = textArea.getLineStopOffset(line);
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@ public class LineMarker {
|
||||
private Problem problem;
|
||||
|
||||
|
||||
public LineMarker(Problem problem, boolean error) {
|
||||
public LineMarker(Problem problem) {
|
||||
this.problem = problem;
|
||||
this.type = error ? ERROR : WARNING;
|
||||
this.type = problem.isError() ? ERROR : WARNING;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -157,10 +157,7 @@ public class Problem implements ErrorTable.Entry {
|
||||
importSuggestions = a;
|
||||
}
|
||||
|
||||
private static Pattern pattern;
|
||||
private static Matcher matcher;
|
||||
|
||||
private static final String tokenRegExp = "\\b token\\b";
|
||||
private static final Pattern tokenRegExp = Pattern.compile("\\b token\\b");
|
||||
|
||||
public static String process(IProblem problem) {
|
||||
return process(problem.getMessage());
|
||||
@@ -178,8 +175,7 @@ public class Problem implements ErrorTable.Entry {
|
||||
// Remove all instances of token
|
||||
// "Syntax error on token 'blah', delete this token"
|
||||
if(message == null) return null;
|
||||
pattern = Pattern.compile(tokenRegExp);
|
||||
matcher = pattern.matcher(message);
|
||||
Matcher matcher = tokenRegExp.matcher(message);
|
||||
message = matcher.replaceAll("");
|
||||
|
||||
return message;
|
||||
|
||||
Reference in New Issue
Block a user