From 02d9dcef45ac6cc67b71c671c877057e6880397f Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Sat, 26 Mar 2016 14:55:34 +0100 Subject: [PATCH] ECS: fix error mapping --- java/src/processing/mode/java/JavaEditor.java | 2 +- .../mode/java/pdex/ASTGenerator.java | 28 +-- .../mode/java/pdex/ErrorCheckerService.java | 225 ++++++------------ .../mode/java/pdex/JavaTextAreaPainter.java | 12 +- .../processing/mode/java/pdex/Problem.java | 18 +- 5 files changed, 95 insertions(+), 190 deletions(-) diff --git a/java/src/processing/mode/java/JavaEditor.java b/java/src/processing/mode/java/JavaEditor.java index 82baf65d8..3a8c27b95 100644 --- a/java/src/processing/mode/java/JavaEditor.java +++ b/java/src/processing/mode/java/JavaEditor.java @@ -2519,7 +2519,7 @@ public class JavaEditor extends Editor { for (LineMarker emarker : errorPoints) { Problem p = emarker.getProblem(); int pStartLine = p.getLineNumber(); - int pEndOffset = textArea.getLineStartOffset(pStartLine) + p.getPDELineStopOffset() + 1; + int pEndOffset = p.getStopOffset(); int pEndLine = textArea.getLineOfOffset(pEndOffset); if (line >= pStartLine && line <= pEndLine) { return emarker; diff --git a/java/src/processing/mode/java/pdex/ASTGenerator.java b/java/src/processing/mode/java/pdex/ASTGenerator.java index 54661805f..64ee6d29c 100644 --- a/java/src/processing/mode/java/pdex/ASTGenerator.java +++ b/java/src/processing/mode/java/pdex/ASTGenerator.java @@ -99,6 +99,7 @@ import processing.app.Util; import processing.app.syntax.JEditTextArea; import processing.app.ui.EditorStatus; import processing.app.ui.Toolkit; +import processing.core.PApplet; import processing.mode.java.JavaEditor; import processing.mode.java.preproc.PdePreprocessor; @@ -134,7 +135,6 @@ public class ASTGenerator { /** * Used for searching for package declaration of a class */ - // TODO: get this from Error checker result protected ClassPath classPath; @@ -1348,10 +1348,11 @@ public class ASTGenerator { } // Base.loge(getNodeAsString(awrap.getNode()) + ", T:" + pdeOffsets[i][0] // + ", L:" + pdeOffsets[i][1] + ", O:" + pdeOffsets[i][2]); - highlightPDECode(pdeOffsets[i][0], + // TODO: fix this line after fixing offsets in node wrapper + /*highlightPDECode(pdeOffsets[i][0], pdeOffsets[i][1], pdeOffsets[i][2] + off, awrap.getNode() - .toString().length()); + .toString().length());*/ //int k = JOptionPane.showConfirmDialog(new JFrame(), "Rename?","", JOptionPane.INFORMATION_MESSAGE); editor.getTextArea().setSelectedText(newName); } @@ -3195,27 +3196,6 @@ public class ASTGenerator { return -1; } - - /** - * Highlights text in the editor - * @param tab - * @param lineNumber - * @param lineStartWSOffset - line start offset including initial white space - * @param length - */ - public void highlightPDECode(int tab, int lineNumber, int lineStartWSOffset, - int length) { - Messages.log("* highlightPDECode"); - -// log("ASTGen.highlightPDECode: T " + tab + ",L: " + lineNumber + ",LSO: " -// + lineStartWSOffset + ",Len: " + length); - editor.toFront(); - editor.getSketch().setCurrentCode(tab); - lineStartWSOffset += editor.getTextArea().getLineStartOffset(lineNumber); - editor.getTextArea().select(lineStartWSOffset, lineStartWSOffset + length); - } - - /** * Converts pde line number to java line number * @param pdeLineNum - pde line number diff --git a/java/src/processing/mode/java/pdex/ErrorCheckerService.java b/java/src/processing/mode/java/pdex/ErrorCheckerService.java index 422155454..e1bb97815 100644 --- a/java/src/processing/mode/java/pdex/ErrorCheckerService.java +++ b/java/src/processing/mode/java/pdex/ErrorCheckerService.java @@ -54,6 +54,7 @@ import javax.swing.text.Element; import javax.swing.text.PlainDocument; import javax.swing.tree.DefaultMutableTreeNode; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; @@ -83,6 +84,7 @@ import processing.app.Util; import processing.app.ui.Editor; 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.JavaMode; @@ -222,8 +224,8 @@ public class ErrorCheckerService { public void run() { synchronized (astGenerator) { astGenerator.updateAST(latestResult.compilationUnit, tree); + astGenerator.classPath = result.classPath; } - calcPdeOffsetsForProbList(result); updateErrorTable(result.problems); editor.updateErrorBar(result.problems); editor.getTextArea().repaint(); @@ -358,9 +360,6 @@ public class ErrorCheckerService { final List programImports = new ArrayList<>(); final List coreAndDefaultImports = new ArrayList<>(); final List codeFolderImports = new ArrayList<>(); - - - } protected PreprocessedSketch checkCode() { @@ -377,7 +376,6 @@ public class ErrorCheckerService { StringBuilder workBuffer = new StringBuilder(); - // Combine code into one buffer IntList tabStartsList = new IntList(); for (SketchCode sc : sketch.getCode()) { @@ -453,6 +451,8 @@ public class ErrorCheckerService { syntaxMapping.addAll(SourceUtils.replaceHexLiterals(workBuffer)); syntaxMapping.addAll(SourceUtils.wrapSketch(mode, className, workBuffer.length())); + // TODO: all imports are parsed now, check if they need to be filtered somehow + // Transform code syntaxStage = syntaxMapping.apply(pdeStage); @@ -475,7 +475,7 @@ public class ErrorCheckerService { }} - if (result.hasSyntaxErrors) { + if (!result.hasSyntaxErrors) { {{ // COMPILATION CHECK @@ -549,44 +549,70 @@ public class ErrorCheckerService { }} } - if (!syntaxProblems.isEmpty()) { - for (IProblem problem : syntaxProblems) { + List mappedSyntaxProblems = + mapProblems(syntaxProblems, result.tabStarts, result.pdeCode, + result.syntaxMapping); - // Hide a useless error which is produced when a line ends with - // an identifier without a semicolon. "Missing a semicolon" is - // also produced and is preferred over this one. - // (Syntax error, insert ":: IdentifierOrNew" to complete Expression) - // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=405780 - if (problem.getMessage().contains("Syntax error, insert \":: IdentifierOrNew\"")) { - continue; - } + List mappedCompilationProblems = + mapProblems(compilationProblems, result.tabStarts, result.pdeCode, + result.compilationMapping, result.syntaxMapping); - int start = problem.getSourceStart(); - int end = problem.getSourceEnd() - 1; + result.problems.addAll(mappedSyntaxProblems); + result.problems.addAll(mappedCompilationProblems); - int mappedStart = result.syntaxMapping.getInputOffset(start); - int mappedEnd = result.syntaxMapping.getInputOffset(end); + return result; + } - int tab = Arrays.binarySearch(result.tabStarts, mappedStart); - if (tab < 0) { - tab = -(tab + 1) - 1; - } - int tabStart = result.tabStarts[tab]; + protected static List mapProblems(List problems, + int[] tabStarts, String pdeCode, + SourceMapping... mappings) { - int line = Util.countLines(result.pdeCode.substring(tabStart, mappedStart)); + List result = new ArrayList<>(); - Problem p = new Problem(problem, tab, line - 1); - if (p.isWarning() && !JavaMode.warningsEnabled) { - continue; - } - result.problems.add(p); + for (IProblem problem : problems) { + if (problem.isWarning() && !JavaMode.warningsEnabled) continue; + + // Hide a useless error which is produced when a line ends with + // an identifier without a semicolon. "Missing a semicolon" is + // also produced and is preferred over this one. + // (Syntax error, insert ":: IdentifierOrNew" to complete Expression) + // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=405780 + if (problem.getMessage().contains("Syntax error, insert \":: IdentifierOrNew\"")) { + continue; } + + int start = problem.getSourceStart(); + int stop = problem.getSourceEnd(); // inclusive + + for (SourceMapping mapping : mappings) { + start = mapping.getInputOffset(start); + stop = mapping.getInputOffset(stop); + } + + int pdeStart = PApplet.constrain(start, 0, pdeCode.length()-1); + int pdeStop = PApplet.constrain(stop + 1, 1, pdeCode.length()); // +1 for exclusive end + + // TODO: maybe optimize this, some people use tons of tabs + int tab = Arrays.binarySearch(tabStarts, pdeStart); + if (tab < 0) { + tab = -(tab + 1) - 1; + } + + int tabStart = tabStarts[tab]; + + // TODO: quick hack; make it smart, fast & beautiful later + int line = Util.countLines(pdeCode.substring(tabStart, pdeStart)) - 1; + + Problem p = new Problem(problem, tab, line); + p.setPDEOffsets(pdeStart - tabStart, pdeStop - tabStart); + result.add(p); } return result; } + protected static CompilationUnit makeAST(ASTParser parser, char[] source, Map options) { @@ -598,13 +624,11 @@ public class ErrorCheckerService { return (CompilationUnit) parser.createAST(null); } + public boolean hasSyntaxErrors(){ return latestResult.hasSyntaxErrors; } - public boolean hasErrors(){ - return latestResult.hasSyntaxErrors || latestResult.hasCompilationErrors; - } /** * Performs compiler error check. @@ -652,68 +676,6 @@ public class ErrorCheckerService { } - /** - * Calculates PDE Offsets from Java Offsets for Problems - */ - private void calcPdeOffsetsForProbList(PreprocessedSketch preprocessedSketch) { - try { - PlainDocument javaSource = new PlainDocument(); - - javaSource.insertString(0, preprocessedSketch.preprocessedCode, null); - // Code in pde tabs stored as PlainDocument - List pdeTabs = new ArrayList<>(); - for (SketchCode sc : editor.getSketch().getCode()) { - PlainDocument tab = new PlainDocument(); - if (editor.getSketch().getCurrentCode().equals(sc)) { - tab.insertString(0, sc.getDocumentText(), null); - } else { - tab.insertString(0, sc.getProgram(), null); - } - pdeTabs.add(tab); - } - - for (Problem p : preprocessedSketch.problems) { - int prbStart = p.getIProblem().getSourceStart(); - int prbEnd = p.getIProblem().getSourceEnd(); - int javaLineNumber = p.getSourceLineNumber() - 1; - Element lineElement = - javaSource.getDefaultRootElement().getElement(javaLineNumber); - if (lineElement == null) { - Messages.log("calcPDEOffsetsForProbList(): " + - "Couldn't fetch Java line number " + - javaLineNumber + "\nProblem: " + p); - p.setPDEOffsets(-1, -1); - continue; - } - int lineStart = lineElement.getStartOffset(); - int lineLength = lineElement.getEndOffset() - lineStart; - String javaLine = javaSource.getText(lineStart, lineLength); - - Document doc = pdeTabs.get(p.getTabIndex()); - Element pdeLineElement = - doc.getDefaultRootElement().getElement(p.getLineNumber()); - if (pdeLineElement == null) { - Messages.log("calcPDEOffsetsForProbList(): " + - "Couldn't fetch pde line number " + - javaLineNumber + "\nProblem: " + p); - p.setPDEOffsets(-1,-1); - continue; - } - int pdeLineStart = pdeLineElement.getStartOffset(); - int pdeLineLength = pdeLineElement.getEndOffset() - pdeLineStart; - String pdeLine = - pdeTabs.get(p.getTabIndex()).getText(pdeLineStart, pdeLineLength); - OffsetMatcher ofm = new OffsetMatcher(pdeLine, javaLine); - int pdeOffset = - ofm.getPdeOffForJavaOff(prbStart - lineStart, prbEnd - prbStart + 1); - p.setPDEOffsets(pdeOffset, pdeOffset + prbEnd - prbStart); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public CompilationUnit getLatestCU() { return latestResult.compilationUnit; } @@ -1161,22 +1123,6 @@ public class ErrorCheckerService { } - /** - * Returns line number of corresponding java source - */ - protected int getJavaLineNumFromPDElineNum(int tab, int pdeLineNum){ - return 0; - - /*int jLineNum = programImports.size() + 1; - for (int i = 0; i < tab; i++) { - SketchCode sc = editor.getSketch().getCode(i); - int len = Util.countLines(sc.getProgram()) + 1; - jLineNum += len; - } - return jLineNum;*/ - } - - /** * Now defunct. * The super method that highlights any ASTNode in the pde editor =D @@ -1209,45 +1155,28 @@ public class ErrorCheckerService { } + // TODO: does this belong here? + // Thread: EDT public void scrollToErrorLine(Problem p) { - if (editor == null) { - return; - } - if (p == null) - return; - try { - if(p.getPDELineStartOffset() == -1 || p.getPDELineStopOffset() == -1){ - // bad offsets, don't highlight, just scroll. - editor.toFront(); - editor.getSketch().setCurrentCode(p.getTabIndex()); - } - else { - astGenerator.highlightPDECode(p.getTabIndex(), - p.getLineNumber(), - p.getPDELineStartOffset(), - (p.getPDELineStopOffset() - - p.getPDELineStartOffset() + 1)); - } + if (editor == null) return; + if (p == null) return; - // scroll, but within boundaries - // It's also a bit silly that if parameters to scrollTo() are out of range, - // a BadLocation Exception is thrown internally and caught in JTextArea AND - // even the stack trace gets printed! W/o letting me catch it later! SMH - // That's because 1) you can prevent it by not causing the BLE, - // and 2) there are so many JEditSyntax bugs that actually throwing the - // exception all the time would cause the editor to shut down over - // trivial/recoverable quirks. It's the least bad option. [fry] - final Document doc = editor.getTextArea().getDocument(); - final int lineCount = countLines(doc.getText(0, doc.getLength())); - if (p.getLineNumber() < lineCount && p.getLineNumber() >= 0) { - editor.getTextArea().scrollTo(p.getLineNumber(), 0); - } - editor.repaint(); + // Switch to tab + editor.toFront(); + editor.getSketch().setCurrentCode(p.getTabIndex()); - } catch (Exception e) { - Messages.loge("Error while selecting text in scrollToErrorLine(), for problem: " + p, e); - } - // log("---"); + // Highlight the code + int startOffset = p.getStartOffset(); + int stopOffset = p.getStopOffset(); + + int length = editor.getTextArea().getDocumentLength(); + startOffset = PApplet.constrain(startOffset, 0, length); + stopOffset = PApplet.constrain(stopOffset, 0, length); + editor.getTextArea().select(startOffset, stopOffset); + + // Scroll to error line + editor.getTextArea().scrollToCaret(); + editor.repaint(); } /** diff --git a/java/src/processing/mode/java/pdex/JavaTextAreaPainter.java b/java/src/processing/mode/java/pdex/JavaTextAreaPainter.java index 42dfaf757..c8124e291 100644 --- a/java/src/processing/mode/java/pdex/JavaTextAreaPainter.java +++ b/java/src/processing/mode/java/pdex/JavaTextAreaPainter.java @@ -360,10 +360,8 @@ public class JavaTextAreaPainter extends TextAreaPainter if (marker != null) { Problem problem = marker.getProblem(); - int offset = textArea.getLineStartOffset(problem.getLineNumber()); - - int startOffset = offset + problem.getPDELineStartOffset(); - int stopOffset = offset + problem.getPDELineStopOffset() + 1; + int startOffset = problem.getStartOffset(); + int stopOffset = problem.getStopOffset(); int lineOffset = textArea.getLineStartOffset(line); @@ -450,13 +448,11 @@ public class JavaTextAreaPainter extends TextAreaPainter if (marker != null) { Problem problem = marker.getProblem(); - int lineOffset = textArea.getLineStartOffset(problem.getLineNumber()); - int lineStart = textArea.getLineStartOffset(line); int lineEnd = textArea.getLineStopOffset(line); - int errorStart = lineOffset + problem.getPDELineStartOffset(); - int errorEnd = lineOffset + problem.getPDELineStopOffset() + 1; + int errorStart = problem.getStartOffset(); + int errorEnd = problem.getStopOffset() + 1; int startOffset = Math.max(errorStart, lineStart) - lineStart; int stopOffset = Math.min(errorEnd, lineEnd) - lineStart; diff --git a/java/src/processing/mode/java/pdex/Problem.java b/java/src/processing/mode/java/pdex/Problem.java index 157c500c2..89d3f4a61 100644 --- a/java/src/processing/mode/java/pdex/Problem.java +++ b/java/src/processing/mode/java/pdex/Problem.java @@ -46,9 +46,9 @@ public class Problem implements ErrorTable.Entry { */ private int lineNumber; - private int lineStartOffset; + private int startOffset; - private int lineStopOffset; + private int stopOffset; /** * Error Message. Processed form of IProblem.getMessage() @@ -89,21 +89,21 @@ public class Problem implements ErrorTable.Entry { } public void setPDEOffsets(int startOffset, int stopOffset){ - lineStartOffset = startOffset; - lineStopOffset = stopOffset; + this.startOffset = startOffset; + this.stopOffset = stopOffset; } - public int getPDELineStartOffset() { - return lineStartOffset; + public int getStartOffset() { + return startOffset; } - public int getPDELineStopOffset() { - return lineStopOffset; + public int getStopOffset() { + return stopOffset; } public String toString() { return new String("TAB " + tabIndex + ",LN " + lineNumber + "LN START OFF: " - + lineStartOffset + ",LN STOP OFF: " + lineStopOffset + ",PROB: " + + startOffset + ",LN STOP OFF: " + stopOffset + ",PROB: " + message); }