From b6f1a3a29d79c8a0277cdaa707f5f40d3ddccabc Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 00:54:30 +0530 Subject: [PATCH 001/193] attention to detail :P --- Todo, GSoC 2013.txt | 4 ++-- .../mode/experimental/ASTGenerator.java | 20 +++++++++++++++---- .../mode/experimental/DebugEditor.java | 8 ++++---- .../mode/experimental/ExperimentalMode.java | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 83602d2..05384a0 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -132,5 +132,5 @@ General Stuff x Add option for toggling debug output x On Run/Debug Console is visible(ProblemsList hidden) * Update wiki for Ctrl + H instead of Ctrl + J shortcuts -* update build.xml to produce dists -* Make this a contributed mode - mode.txt, github releases feature, version numbering, git tags, etc +x update build.xml to produce dists +x Make this a contributed mode - mode.txt, github releases feature, version numbering, git tags, etc diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 6a71610..810b9a9 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -170,7 +170,7 @@ private void setupGUI(){ btnListOccurrence = new JButton("Show Usage"); frmRename = new JFrame(); frmRename.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); - frmRename.setBounds(new Rectangle(680, 50, 250, 130)); + frmRename.setSize(250, 130); frmRename.setLayout(new BoxLayout(frmRename.getContentPane(), BoxLayout.Y_AXIS)); Toolkit.setIcon(frmRename); JPanel panelTop = new JPanel(), panelBottom = new JPanel(); @@ -192,13 +192,18 @@ private void setupGUI(){ panelTop.add(Box.createRigidArea(new Dimension(0, 10))); panelTop.add(lblRefactorOldName); frmRename.add(panelTop); - frmRename.add(panelBottom); - + frmRename.add(panelBottom); frmRename.setMinimumSize(frmRename.getSize()); + frmRename.setLocation(editor.getX() + + (editor.getWidth() - frmRename.getWidth()) / 2, + editor.getY() + + (editor.getHeight() - frmRename.getHeight()) + / 2); + frmOccurenceList = new JFrame(); frmOccurenceList.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); - frmOccurenceList.setBounds(new Rectangle(1100, 50, 350, 500)); + frmOccurenceList.setSize(300, 400); Toolkit.setIcon(frmOccurenceList); JScrollPane sp2 = new JScrollPane(); treeRename = new JTree(); @@ -1843,6 +1848,7 @@ private void refactorIt(){ treeRename.setModel(new DefaultTreeModel(defCU)); ((DefaultTreeModel) treeRename.getModel()).reload(); frmOccurenceList.setTitle("Usage of " + selText); + frmOccurenceList.setLocation(editor.getX() + editor.getWidth(),editor.getY()); frmOccurenceList.setVisible(true); int lineOffsetDisplacementConst = newName.length() - selText.length(); @@ -1917,6 +1923,7 @@ public void handleShowUsage(){ ((DefaultTreeModel) treeRename.getModel()).reload(); treeRename.setRootVisible(false); frmOccurenceList.setTitle("Usage of \"" + selText+ "\""); + frmOccurenceList.setLocation(editor.getX() + editor.getWidth(),editor.getY()); frmOccurenceList.setVisible(true); lastClickedWord = null; lastClickedWordNode = null; @@ -2168,6 +2175,11 @@ public void handleRefactor(){ return; } if (!frmRename.isVisible()){ + frmRename.setLocation(editor.getX() + + (editor.getWidth() - frmRename.getWidth()) / 2, + editor.getY() + + (editor.getHeight() - frmRename.getHeight()) + / 2); frmRename.setVisible(true); SwingUtilities.invokeLater(new Runnable() { @Override diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index ce341b7..aea75af 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -1251,14 +1251,14 @@ synchronized public boolean updateTable(final TableModel tableModel) { } private void handleRefactor() { - System.out.println("Caret at:"); - System.out.println(ta.getLineText(ta.getCaretLine())); + log("Caret at:"); + log(ta.getLineText(ta.getCaretLine())); errorCheckerService.astGenerator.handleRefactor(); } private void handleShowUsage() { - System.out.println("Caret at:"); - System.out.println(ta.getLineText(ta.getCaretLine())); + log("Caret at:"); + log(ta.getLineText(ta.getCaretLine())); errorCheckerService.astGenerator.handleShowUsage(); } diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 61d93d4..8619af0 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -43,7 +43,7 @@ public class ExperimentalMode extends JavaMode { public static final boolean VERBOSE_LOGGING = true; //public static final boolean VERBOSE_LOGGING = false; public static final int LOG_SIZE = 512 * 1024; // max log file size (in bytes) - public static boolean DEBUG = true; + public static boolean DEBUG = !true; public ExperimentalMode(Base base, File folder) { super(base, folder); From 33acd5e92bebbac335c663c713cf5066449e560f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 01:06:36 +0530 Subject: [PATCH 002/193] missed out the import frame --- src/processing/mode/experimental/ASTGenerator.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 810b9a9..034522b 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -3017,7 +3017,7 @@ private static ASTNode definedIn(ASTNode node, String name, } return null; } - JFrame frmImportSuggest; + protected JFrame frmImportSuggest; public void suggestImports(final String className){ if(frmImportSuggest != null) if(frmImportSuggest.isVisible()) @@ -3043,7 +3043,8 @@ public void suggestImports(final String className){ final JList classList = new JList(resources); classList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); frmImportSuggest = new JFrame(); - frmImportSuggest.setBounds(300, 300, 400, 300); + frmImportSuggest.setSize(350, 200); + Toolkit.setIcon(frmImportSuggest); frmImportSuggest.setLayout(new BoxLayout(frmImportSuggest .getContentPane(), BoxLayout.Y_AXIS)); ((JComponent) frmImportSuggest.getContentPane()).setBorder(BorderFactory @@ -3078,6 +3079,11 @@ public void actionPerformed(ActionEvent evt) { frmImportSuggest.add(jsp); frmImportSuggest.add(btnInsertImport); frmImportSuggest.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + frmImportSuggest.setLocation(editor.getX() + + (editor.getWidth() - frmImportSuggest.getWidth()) / 2, + editor.getY() + + (editor.getHeight() - frmImportSuggest.getHeight()) + / 2); frmImportSuggest.setVisible(true); } From ef343fcbe6bc20cd0769fdd4fdc534236671ad8f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 15:57:30 +0530 Subject: [PATCH 003/193] improving old code in ErrorBar/Error Marker --- .../mode/experimental/ErrorBar.java | 182 ++++++------------ .../experimental/ErrorCheckerService.java | 8 +- .../mode/experimental/ErrorMarker.java | 31 ++- .../mode/experimental/TextAreaPainter.java | 4 +- 4 files changed, 94 insertions(+), 131 deletions(-) diff --git a/src/processing/mode/experimental/ErrorBar.java b/src/processing/mode/experimental/ErrorBar.java index 3413813..a1c7ec3 100755 --- a/src/processing/mode/experimental/ErrorBar.java +++ b/src/processing/mode/experimental/ErrorBar.java @@ -35,6 +35,7 @@ import javax.swing.JPanel; import javax.swing.SwingWorker; +import javax.swing.text.BadLocationException; import processing.app.Base; import processing.app.SketchCode; @@ -109,12 +110,12 @@ public void paintComponent(Graphics g) { g.fillRect(0, 0, getWidth(), getHeight()); for (ErrorMarker emarker : errorPoints) { - if (emarker.type == ErrorMarker.Error) { + if (emarker.getType() == ErrorMarker.Error) { g.setColor(errorColor); } else { g.setColor(warningColor); } - g.fillRect(2, emarker.y, (getWidth() - 3), errorMarkerHeight); + g.fillRect(2, emarker.getY(), (getWidth() - 3), errorMarkerHeight); } } @@ -152,56 +153,46 @@ synchronized public void updateErrorPoints(final ArrayList problems) { final int fheight = this.getHeight(); SwingWorker worker = new SwingWorker() { - protected Object doInBackground() throws Exception { - return null; - } - - protected void done() { - int totalLines = 0; - int currentTab = 0; - for (SketchCode sc : editor.getSketch().getCode()) { - if (sc.isExtension("pde")) { - try { - if (editor.getSketch().getCurrentCode().equals(sc)) { - // Adding + 1 to len because \n gets appended - // for each - // sketchcode extracted during processPDECode() - totalLines = Base.countLines(sc.getDocument() - .getText(0, - sc.getDocument().getLength())) + 1; - break; - } - } catch (Exception e) { - e.printStackTrace(); - } - } - currentTab++; - } - // System.out.println("Total lines: " + totalLines); - - errorPointsOld.clear(); - for (ErrorMarker marker : errorPoints) { - errorPointsOld.add(marker); - } - 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) { - if (problem.tabIndex == currentTab) { - // Ratio of error line to total lines + protected Object doInBackground() throws Exception { + SketchCode sc = editor.getSketch().getCurrentCode(); + int totalLines = 0, currentTab = editor.getSketch() + .getCurrentCodeIndex(); + try { + totalLines = Base.countLines(sc.getDocument() + .getText(0, sc.getDocument().getLength())) + 1; + } catch (BadLocationException e) { + e.printStackTrace(); + } + // System.out.println("Total lines: " + totalLines); + + errorPointsOld.clear(); + for (ErrorMarker marker : errorPoints) { + errorPointsOld.add(marker); + } + 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) { + if (problem.tabIndex == currentTab) { + // Ratio of error line to total lines float y = (problem.lineNumber - errorCheckerService.defaultImportsOffset) / ((float) totalLines); - // Ratio multiplied by height of the error bar - y *= fheight - 15; // -15 is just a vertical offset - errorPoints.add(new ErrorMarker(problem, (int) y, - problem.isError() ? ErrorMarker.Error - : ErrorMarker.Warning)); - // System.out.println("Y: " + y); - } - } + // Ratio multiplied by height of the error bar + y *= fheight - 15; // -15 is just a vertical offset + errorPoints + .add(new ErrorMarker(problem, (int) y, + problem.isError() ? ErrorMarker.Error + : ErrorMarker.Warning)); + // System.out.println("Y: " + y); + } + } + + return null; + } + protected void done() { repaint(); } }; @@ -229,7 +220,7 @@ public boolean errorPointsChanged() { else { for (int i = 0; i < errorPoints.size(); i++) { - if (errorPoints.get(i).y != errorPointsOld.get(i).y) { + if (errorPoints.get(i).getY() != errorPointsOld.get(i).getY()) { editor.getTextArea().repaint(); // System.out.println("3 Repaint " + // System.currentTimeMillis()); @@ -262,36 +253,14 @@ protected void done() { for (ErrorMarker eMarker : errorPoints) { // -2 and +2 are extra allowance, clicks in the // vicinity of the markers register that way - if (e.getY() >= eMarker.y - 2 - && e.getY() <= eMarker.y + 2 + if (e.getY() >= eMarker.getY() - 2 + && e.getY() <= eMarker.getY() + 2 + errorMarkerHeight) { - int currentTabErrorIndex = errorPoints - .indexOf(eMarker); - // System.out.println("Index: " + - // currentTabErrorIndex); - int currentTab = editor.getSketch() - .getCodeIndex( - editor.getSketch() - .getCurrentCode()); - - int totalErrorIndex = currentTabErrorIndex; - - for (int i = 0; i < errorCheckerService.problemsList - .size(); i++) { - Problem p = errorCheckerService.problemsList - .get(i); - if (p.tabIndex < currentTab) { - totalErrorIndex++; - } - if (p.tabIndex == currentTab) { - break; - } - } errorCheckerService - .scrollToErrorLine(totalErrorIndex); + .scrollToErrorLine(eMarker.getProblem()); + return; } } - } }; @@ -311,7 +280,7 @@ protected void done() { @SuppressWarnings("rawtypes") @Override - public void mouseMoved(final MouseEvent e) { + public void mouseMoved(final MouseEvent evt) { // System.out.println(e); SwingWorker worker = new SwingWorker() { @@ -319,51 +288,22 @@ protected Object doInBackground() throws Exception { return null; } - protected void done() { - - for (ErrorMarker eMarker : errorPoints) { - if (e.getY() >= eMarker.y - 2 - && e.getY() <= eMarker.y + 2 - + errorMarkerHeight) { - // System.out.println("Index: " + - // errorPoints.indexOf(y)); - int currentTab = editor.getSketch() - .getCodeIndex( - editor.getSketch() - .getCurrentCode()); - int currentTabErrorCount = 0; - - for (int i = 0; i < errorPoints.size(); i++) { - Problem p = errorPoints.get(i).problem; - if (p.tabIndex == currentTab) { - if (currentTabErrorCount == errorPoints - .indexOf(eMarker)) { - // System.out.println("Roger that."); - String msg = (p.isError() ? "Error: " - : "Warning: ") - + p.message; - setToolTipText(msg); - setCursor(Cursor - .getPredefinedCursor(Cursor.HAND_CURSOR)); - return; - } else { - currentTabErrorCount++; - // System.out.println("Still looking.."); - } - } - - } - } - // Reset cursor and tooltip - else { - setToolTipText(""); - setCursor(Cursor - .getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - - } + protected void done() { + for (ErrorMarker eMarker : errorPoints) { + if (evt.getY() >= eMarker.getY() - 2 + && evt.getY() <= eMarker.getY() + 2 + errorMarkerHeight) { + Problem p = eMarker.getProblem(); + String msg = (p.isError() ? "Error: " : "Warning: ") + + p.message; + setToolTipText(msg); + setCursor(Cursor + .getPredefinedCursor(Cursor.HAND_CURSOR)); + break; + } + } + } }; + try { worker.execute(); } catch (Exception exp) { diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 1203bda..377fcb0 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -787,15 +787,15 @@ public void updateEditorStatus() { // editor.statusNotice("Position: " + // editor.getTextArea().getCaretLine()); for (ErrorMarker emarker : editor.errorBar.errorPoints) { - if (emarker.problem.lineNumber == editor.getTextArea() + if (emarker.getProblem().lineNumber == editor.getTextArea() .getCaretLine() + 1) { - if (emarker.type == ErrorMarker.Warning) { - editor.statusNotice(emarker.problem.message); + if (emarker.getType() == ErrorMarker.Warning) { + editor.statusNotice(emarker.getProblem().message); //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); //TODO: this is temporary } else { - editor.statusError(emarker.problem.message); + editor.statusError(emarker.getProblem().message); //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); } return; diff --git a/src/processing/mode/experimental/ErrorMarker.java b/src/processing/mode/experimental/ErrorMarker.java index bc244f7..b3c7d94 100755 --- a/src/processing/mode/experimental/ErrorMarker.java +++ b/src/processing/mode/experimental/ErrorMarker.java @@ -6,14 +6,14 @@ * */ public class ErrorMarker { - /** + /** * y co-ordinate of the marker */ - public int y; + private int y; /** * Type of marker: Error or Warning? */ - public int type = -1; + private int type = -1; /** * Error Type constant */ @@ -26,11 +26,34 @@ public class ErrorMarker { * Problem that the error marker represents * @see Problem */ - public Problem problem; + private Problem problem; public ErrorMarker(Problem problem, int y, int type) { this.problem = problem; this.y = y; this.type = type; } + + /** + * y co-ordinate of the marker + */ + public int getY() { + return y; + } + + /** + * Type of marker: ErrorMarker.Error or ErrorMarker.Warning? + */ + public int getType() { + return type; + } + + /** + * Problem that the error marker represents + * @see Problem + */ + public Problem getProblem() { + return problem; + } + } \ No newline at end of file diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 89170ed..b5d1740 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -311,9 +311,9 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { // Check if current line contains an error. If it does, find if it's an // error or warning for (ErrorMarker emarker : errorCheckerService.getEditor().errorBar.errorPoints) { - if (emarker.problem.lineNumber == line + 1) { + if (emarker.getProblem().lineNumber == line + 1) { notFound = false; - if (emarker.type == ErrorMarker.Warning) { + if (emarker.getType() == ErrorMarker.Warning) { isWarning = true; } break; From c760beda53195583020935a5b6e476dfb3211004 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 16:02:45 +0530 Subject: [PATCH 004/193] improving old code in Problem --- .../mode/experimental/ErrorBar.java | 6 ++--- .../experimental/ErrorCheckerService.java | 24 +++++++++---------- src/processing/mode/experimental/Problem.java | 16 +++++++++---- .../mode/experimental/TextAreaPainter.java | 2 +- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/processing/mode/experimental/ErrorBar.java b/src/processing/mode/experimental/ErrorBar.java index a1c7ec3..d5f6c93 100755 --- a/src/processing/mode/experimental/ErrorBar.java +++ b/src/processing/mode/experimental/ErrorBar.java @@ -175,9 +175,9 @@ protected Object doInBackground() throws Exception { // because of // class declaration in the beginning as well as default imports for (Problem problem : problems) { - if (problem.tabIndex == currentTab) { + if (problem.getTabIndex() == currentTab) { // Ratio of error line to total lines - float y = (problem.lineNumber - errorCheckerService.defaultImportsOffset) + float y = (problem.getLineNumber() - errorCheckerService.defaultImportsOffset) / ((float) totalLines); // Ratio multiplied by height of the error bar y *= fheight - 15; // -15 is just a vertical offset @@ -294,7 +294,7 @@ protected void done() { && evt.getY() <= eMarker.getY() + 2 + errorMarkerHeight) { Problem p = eMarker.getProblem(); String msg = (p.isError() ? "Error: " : "Warning: ") - + p.message; + + p.getMessage(); setToolTipText(msg); setCursor(Cursor .getPredefinedCursor(Cursor.HAND_CURSOR)); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 377fcb0..428e988 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -717,15 +717,15 @@ synchronized public void updateErrorTable() { try { String[][] errorData = new String[problemsList.size()][3]; for (int i = 0; i < problemsList.size(); i++) { - errorData[i][0] = problemsList.get(i).message; ////TODO: this is temporary + errorData[i][0] = problemsList.get(i).getMessage(); ////TODO: this is temporary //+ " : " + errorMsgSimplifier.getIDName(problemsList.get(i).getIProblem().getID()); errorData[i][1] = editor.getSketch() - .getCode(problemsList.get(i).tabIndex).getPrettyName(); - errorData[i][2] = problemsList.get(i).lineNumber + ""; + .getCode(problemsList.get(i).getTabIndex()).getPrettyName(); + errorData[i][2] = problemsList.get(i).getLineNumber() + ""; //TODO: This is temporary if(tempErrorLog.size() < 200) - tempErrorLog.put(problemsList.get(i).message,problemsList.get(i).getIProblem()); + tempErrorLog.put(problemsList.get(i).getMessage(),problemsList.get(i).getIProblem()); } if (errorWindow != null) { @@ -787,15 +787,15 @@ public void updateEditorStatus() { // editor.statusNotice("Position: " + // editor.getTextArea().getCaretLine()); for (ErrorMarker emarker : editor.errorBar.errorPoints) { - if (emarker.getProblem().lineNumber == editor.getTextArea() + if (emarker.getProblem().getLineNumber() == editor.getTextArea() .getCaretLine() + 1) { if (emarker.getType() == ErrorMarker.Warning) { - editor.statusNotice(emarker.getProblem().message); + editor.statusNotice(emarker.getProblem().getMessage()); //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); //TODO: this is temporary } else { - editor.statusError(emarker.getProblem().message); + editor.statusError(emarker.getProblem().getMessage()); //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); } return; @@ -1172,16 +1172,16 @@ public void scrollToErrorLine(Problem p) { return; try { editor.toFront(); - editor.getSketch().setCurrentCode(p.tabIndex); + editor.getSketch().setCurrentCode(p.getTabIndex()); editor .setSelection(editor.getTextArea() - .getLineStartNonWhiteSpaceOffset(p.lineNumber - 1) + .getLineStartNonWhiteSpaceOffset(p.getLineNumber() - 1) + editor.getTextArea() - .getLineText(p.lineNumber - 1).trim().length(), + .getLineText(p.getLineNumber() - 1).trim().length(), editor.getTextArea() - .getLineStartNonWhiteSpaceOffset(p.lineNumber - 1)); - editor.getTextArea().scrollTo(p.lineNumber - 1, 0); + .getLineStartNonWhiteSpaceOffset(p.getLineNumber() - 1)); + editor.getTextArea().scrollTo(p.getLineNumber() - 1, 0); editor.repaint(); } catch (Exception e) { System.err.println(e diff --git a/src/processing/mode/experimental/Problem.java b/src/processing/mode/experimental/Problem.java index 60d0c0b..aaa8cca 100644 --- a/src/processing/mode/experimental/Problem.java +++ b/src/processing/mode/experimental/Problem.java @@ -44,21 +44,21 @@ public class Problem { /** * The tab number to which the error belongs to */ - public int tabIndex; + private int tabIndex; /** * Line number(pde code) of the error */ - public int lineNumber; + private int lineNumber; /** * Error Message. Processed form of IProblem.getMessage() */ - public String message; + private String message; /** * The type of error - WARNING or ERROR. */ - public int type; + private int type; public static final int ERROR = 1, WARNING = 2; @@ -101,6 +101,14 @@ public String getMessage(){ public IProblem getIProblem(){ return iProblem; } + + public int getTabIndex(){ + return tabIndex; + } + + public int getLineNumber(){ + return lineNumber; + } public void setType(int ProblemType){ if(ProblemType == ERROR) diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index b5d1740..f8db484 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -311,7 +311,7 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { // Check if current line contains an error. If it does, find if it's an // error or warning for (ErrorMarker emarker : errorCheckerService.getEditor().errorBar.errorPoints) { - if (emarker.getProblem().lineNumber == line + 1) { + if (emarker.getProblem().getLineNumber() == line + 1) { notFound = false; if (emarker.getType() == ErrorMarker.Warning) { isWarning = true; From 8b02b98d4a680019105363ee9d2b876c6c089c44 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 19:52:10 +0530 Subject: [PATCH 005/193] icons in completion list, loading icons only once --- .../mode/experimental/CompletionPanel.java | 49 ++++++++++++++++++- .../mode/experimental/ExperimentalMode.java | 19 ++++++- .../mode/experimental/SketchOutline.java | 19 ++----- .../mode/experimental/TextArea.java | 2 +- 4 files changed, 70 insertions(+), 19 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index f054ccf..0336c72 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -4,13 +4,18 @@ import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Dimension; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.io.File; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; @@ -31,10 +36,13 @@ public class CompletionPanel { private TextArea textarea; private JScrollPane scrollPane; + + protected DebugEditor editor; public CompletionPanel(JEditTextArea textarea, int position, String subWord, - DefaultListModel items, Point location) { + DefaultListModel items, Point location, DebugEditor dedit) { this.textarea = (TextArea) textarea; + editor = dedit; this.insertionPosition = position; if (subWord.indexOf('.') != -1) this.subWord = subWord.substring(subWord.lastIndexOf('.') + 1); @@ -80,6 +88,7 @@ public void mouseClicked(MouseEvent e) { } } }); + list.setCellRenderer(new CustomListRenderer()); return list; } @@ -189,4 +198,42 @@ private void selectIndex(int index) { // }; // }); } + + protected class CustomListRenderer extends + javax.swing.DefaultListCellRenderer { + //protected final ImageIcon classIcon, fieldIcon, methodIcon; + + public Component getListCellRendererComponent(JList list, Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + JLabel label = (JLabel) super.getListCellRendererComponent(list, value, + index, + isSelected, + cellHasFocus); + if (value instanceof CompletionCandidate) { + CompletionCandidate cc = (CompletionCandidate) value; + switch (cc.getType()) { + case CompletionCandidate.LOCAL_FIELD: + case CompletionCandidate.PREDEF_FIELD: + label.setIcon(editor.dmode.fieldIcon); + break; + case CompletionCandidate.LOCAL_METHOD: + case CompletionCandidate.PREDEF_METHOD: + label.setIcon(editor.dmode.methodIcon); + break; + case CompletionCandidate.LOCAL_CLASS: + case CompletionCandidate.PREDEF_CLASS: + label.setIcon(editor.dmode.classIcon); + break; + + default: + break; + } + + } + return label; + } + } + } \ No newline at end of file diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 8619af0..783eeeb 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -28,6 +28,9 @@ import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; + +import javax.swing.ImageIcon; + import processing.app.Base; import processing.app.Editor; import processing.app.EditorState; @@ -43,7 +46,7 @@ public class ExperimentalMode extends JavaMode { public static final boolean VERBOSE_LOGGING = true; //public static final boolean VERBOSE_LOGGING = false; public static final int LOG_SIZE = 512 * 1024; // max log file size (in bytes) - public static boolean DEBUG = !true; + public static boolean DEBUG = true; public ExperimentalMode(Base base, File folder) { super(base, folder); @@ -96,6 +99,7 @@ public ExperimentalMode(Base base, File folder) { // String titleAndVersion = p.getImplementationTitle() + " (v" + p.getImplementationVersion() + ")"; // //log(titleAndVersion); // Logger.getLogger(ExperimentalMode.class.getName()).log(Level.INFO, titleAndVersion); + loadIcons(); } @@ -156,6 +160,19 @@ public Color getThemeColor(String attribute, Color defaultValue) { Logger.getLogger(ExperimentalMode.class.getName()).log(Level.WARNING, "Error loading Color: {0}", attribute); return defaultValue; } + + protected ImageIcon classIcon, fieldIcon, methodIcon; + protected void loadIcons(){ + String iconPath = getContentFile("data") + .getAbsolutePath() + + File.separator + "icons"; + classIcon = new ImageIcon(iconPath + File.separator + "class_obj.png"); + methodIcon = new ImageIcon(iconPath + File.separator + + "methpub_obj.png"); + fieldIcon = new ImageIcon(iconPath + File.separator + + "field_protected_obj.png"); + log("Icons loaded"); + } public ClassLoader getJavaModeClassLoader() { diff --git a/src/processing/mode/experimental/SketchOutline.java b/src/processing/mode/experimental/SketchOutline.java index f753d15..a78a66f 100644 --- a/src/processing/mode/experimental/SketchOutline.java +++ b/src/processing/mode/experimental/SketchOutline.java @@ -346,19 +346,6 @@ public boolean isVisible(){ protected class CustomCellRenderer extends DefaultTreeCellRenderer { - protected final ImageIcon classIcon, fieldIcon, methodIcon; - - public CustomCellRenderer() { - String iconPath = editor.getMode().getContentFile("data") - .getAbsolutePath() - + File.separator + "icons"; - classIcon = new ImageIcon(iconPath + File.separator + "class_obj.png"); - methodIcon = new ImageIcon(iconPath + File.separator - + "methpub_obj.png"); - fieldIcon = new ImageIcon(iconPath + File.separator - + "field_protected_obj.png"); - } - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { @@ -378,11 +365,11 @@ public javax.swing.Icon getTreeIcon(Object o) { .getUserObject(); int type = awrap.getNode().getParent().getNodeType(); if (type == ASTNode.METHOD_DECLARATION) - return methodIcon; + return editor.dmode.methodIcon; if (type == ASTNode.TYPE_DECLARATION) - return classIcon; + return editor.dmode.classIcon; if (type == ASTNode.VARIABLE_DECLARATION_FRAGMENT) - return fieldIcon; + return editor.dmode.fieldIcon; } return null; } diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 00e1282..576b58e 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -711,7 +711,7 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { } if (suggestion == null) suggestion = new CompletionPanel(this, position, subWord, defListModel, - location); + location,editor); else suggestion.updateList(defListModel, subWord, position); suggestion.setVisible(true); From 586947b603c25c143fb75a8473ab5527762c8420 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 20:04:54 +0530 Subject: [PATCH 006/193] completion panel type bugfix --- .../mode/experimental/CompletionCandidate.java | 12 +++++++++--- .../mode/experimental/CompletionPanel.java | 7 +++++++ .../mode/experimental/ExperimentalMode.java | 4 +++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/processing/mode/experimental/CompletionCandidate.java b/src/processing/mode/experimental/CompletionCandidate.java index 5c3761d..bc29737 100644 --- a/src/processing/mode/experimental/CompletionCandidate.java +++ b/src/processing/mode/experimental/CompletionCandidate.java @@ -5,6 +5,7 @@ import java.util.List; import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.TypeDeclaration; @@ -27,7 +28,6 @@ public class CompletionCandidate implements Comparable{ public CompletionCandidate(Method method) { method.getDeclaringClass().getName(); elementName = method.getName(); - type = LOCAL_METHOD; StringBuffer label = new StringBuffer(method.getName() + "("); StringBuffer cstr = new StringBuffer(method.getName() + "("); for (int i = 0; i < method.getParameterTypes().length; i++) { @@ -53,14 +53,20 @@ public CompletionCandidate(Method method) { public CompletionCandidate(SingleVariableDeclaration svd) { completionString = svd.getName().toString(); elementName = svd.getName().toString(); - type = LOCAL_VAR; + if(svd.getParent() instanceof FieldDeclaration) + type = LOCAL_FIELD; + else + type = LOCAL_VAR; label = svd.getName() + " : " + svd.getType(); } public CompletionCandidate(VariableDeclarationFragment vdf) { completionString = vdf.getName().toString(); elementName = vdf.getName().toString(); - type = LOCAL_VAR; + if(vdf.getParent() instanceof FieldDeclaration) + type = LOCAL_FIELD; + else + type = LOCAL_VAR; label = vdf.getName() + " : " + ASTGenerator.extracTypeInfo2(vdf); } diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 0336c72..55e66c4 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -214,6 +214,9 @@ public Component getListCellRendererComponent(JList list, Object value, if (value instanceof CompletionCandidate) { CompletionCandidate cc = (CompletionCandidate) value; switch (cc.getType()) { + case CompletionCandidate.LOCAL_VAR: + label.setIcon(editor.dmode.localVarIcon); + break; case CompletionCandidate.LOCAL_FIELD: case CompletionCandidate.PREDEF_FIELD: label.setIcon(editor.dmode.fieldIcon); @@ -228,10 +231,14 @@ public Component getListCellRendererComponent(JList list, Object value, break; default: + log("(CustomListRenderer)Unknown CompletionCandidate type " + cc.getType()); break; } } + else + log("(CustomListRenderer)Unknown CompletionCandidate object " + value); + return label; } } diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 783eeeb..d5f0739 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -161,7 +161,7 @@ public Color getThemeColor(String attribute, Color defaultValue) { return defaultValue; } - protected ImageIcon classIcon, fieldIcon, methodIcon; + protected ImageIcon classIcon, fieldIcon, methodIcon, localVarIcon; protected void loadIcons(){ String iconPath = getContentFile("data") .getAbsolutePath() @@ -171,6 +171,8 @@ protected void loadIcons(){ + "methpub_obj.png"); fieldIcon = new ImageIcon(iconPath + File.separator + "field_protected_obj.png"); + localVarIcon = new ImageIcon(iconPath + File.separator + + "field_default_obj.png"); log("Icons loaded"); } From 2134398edee28be0679917c6d205fc97d6279f4d Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 20:16:31 +0530 Subject: [PATCH 007/193] jars loaded only on demand --- src/processing/mode/experimental/ErrorCheckerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 428e988..a3bf64b 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -399,7 +399,6 @@ private void syntaxCheck() { syntaxErrors.set(false); else syntaxErrors.set(true); - astGenerator.loadJars(); } protected URLClassLoader classLoader; private void compileCheck() { @@ -1250,6 +1249,8 @@ private void checkForChangedImports() { } } } + if(loadCompClass) + astGenerator.loadJars(); // log("load..? " + loadCompClass); } From 8865e28c97b7a86501e989938e77018e7c51bc0c Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 20:43:19 +0530 Subject: [PATCH 008/193] fixing regression --- .../mode/experimental/ASTGenerator.java | 29 ++++++++++--------- .../experimental/ErrorCheckerService.java | 8 ++++- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 034522b..24ca2be 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -269,13 +269,14 @@ protected Object doInBackground() throws Exception { protected void done() { if (codeTree != null) { -// if (jtree.hasFocus() || frame2.hasFocus()) -// return; -// jtree.setModel(new DefaultTreeModel(codeTree)); -// ((DefaultTreeModel) jtree.getModel()).reload(); -// if (!frame2.isVisible()) { -// frame2.setVisible(true); -// } + if (jtree.hasFocus() || frame2.hasFocus()) + return; + jtree.setModel(new DefaultTreeModel(codeTree)); + ((DefaultTreeModel) jtree.getModel()).reload(); + jtree.validate(); + if (!frame2.isVisible()) { + frame2.setVisible(true); + } // if (!frameAutoComp.isVisible()) { // // frameAutoComp.setVisible(true); @@ -293,7 +294,6 @@ protected void done() { // .getY(), 450, 600)); // jdocWindow.setVisible(true); // } -// jtree.validate(); } } }; @@ -1379,18 +1379,20 @@ else if (prop.isChildListProperty()) { } private static ASTNode findClosestNode(int lineNumber, ASTNode node) { + log("findClosestNode to line " + lineNumber); ASTNode parent = findClosestParentNode(lineNumber, node); + log("findClosestParentNode returned " + getNodeAsString(parent)); if (parent == null) return null; - if (getLineNumber(parent) == lineNumber) + if (getLineNumber(parent) == lineNumber){ + log(parent + "|PNode " + getLineNumber(parent) + ", lfor " + lineNumber ); return parent; + } List nodes = null; if (parent instanceof TypeDeclaration) { - nodes = (List) ((TypeDeclaration) parent) - .getStructuralProperty(TypeDeclaration.BODY_DECLARATIONS_PROPERTY); + nodes = (List) ((TypeDeclaration) parent).bodyDeclarations(); } else if (parent instanceof Block) { - nodes = (List) ((Block) parent) - .getStructuralProperty(Block.STATEMENTS_PROPERTY); + nodes = (List) ((Block) parent).statements(); } else { System.err.println("THIS CONDITION SHOULD NOT OCCUR - findClosestNode " + getNodeAsString(parent)); @@ -1401,6 +1403,7 @@ private static ASTNode findClosestNode(int lineNumber, ASTNode node) { ASTNode retNode = parent; for (int i = 0; i < nodes.size(); i++) { ASTNode cNode = nodes.get(i); + log(cNode + "|cNode " + getLineNumber(cNode) + ", lfor " + lineNumber ); if (getLineNumber(cNode) <= lineNumber) retNode = cNode; } diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index a3bf64b..22f7886 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -250,6 +250,11 @@ public void run() { checkCode(); if(!hasSyntaxErrors()) editor.showProblemListView(XQConsoleToggle.CONSOLE); + // Make sure astGen has at least one CU to start with + // This is when the loaded sketch already has syntax errors. + // Completion wouldn't be complete, but it'd be still something + // better than nothing + astGenerator.buildAST(cu); while (!stopThread) { try { // Take a nap. @@ -313,7 +318,7 @@ private boolean checkCode() { + mainClassOffset); // No syntax errors, proceed for compilation check, Stage 2. - astGenerator.buildAST(cu); + //if(hasSyntaxErrors()) astGenerator.buildAST(null); if (problems.length == 0 && editor.compilationCheckEnabled) { //mainClassOffset++; // just a hack. @@ -327,6 +332,7 @@ private boolean checkCode() { // log(sourceCode); // log("--------------------------"); compileCheck(); + astGenerator.buildAST(cu); log(editor.getSketch().getName() + "2 MCO " + mainClassOffset); } From c5c3a75479641fd4562f2edc8fab68e4dd70be3e Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 20:46:09 +0530 Subject: [PATCH 009/193] updated todo --- Todo, GSoC 2013.txt | 1 + .../mode/experimental/ASTGenerator.java | 16 ++++++++-------- .../mode/experimental/ExperimentalMode.java | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 05384a0..97c1fb2 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -129,6 +129,7 @@ x Working for local code General Stuff ============= +* Ensure all editor windows are closed when editor is closed. x Add option for toggling debug output x On Run/Debug Console is visible(ProblemsList hidden) * Update wiki for Ctrl + H instead of Ctrl + J shortcuts diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 24ca2be..4ede16a 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -269,14 +269,14 @@ protected Object doInBackground() throws Exception { protected void done() { if (codeTree != null) { - if (jtree.hasFocus() || frame2.hasFocus()) - return; - jtree.setModel(new DefaultTreeModel(codeTree)); - ((DefaultTreeModel) jtree.getModel()).reload(); - jtree.validate(); - if (!frame2.isVisible()) { - frame2.setVisible(true); - } +// if (jtree.hasFocus() || frame2.hasFocus()) +// return; +// jtree.setModel(new DefaultTreeModel(codeTree)); +// ((DefaultTreeModel) jtree.getModel()).reload(); +// jtree.validate(); +// if (!frame2.isVisible()) { +// frame2.setVisible(true); +// } // if (!frameAutoComp.isVisible()) { // // frameAutoComp.setVisible(true); diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index d5f0739..db5f793 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -46,7 +46,7 @@ public class ExperimentalMode extends JavaMode { public static final boolean VERBOSE_LOGGING = true; //public static final boolean VERBOSE_LOGGING = false; public static final int LOG_SIZE = 512 * 1024; // max log file size (in bytes) - public static boolean DEBUG = true; + public static boolean DEBUG = !true; public ExperimentalMode(Base base, File folder) { super(base, folder); From 3ebae816556029cf99dd8c8ab519b4eceb9bb8be Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 21:51:40 +0530 Subject: [PATCH 010/193] forgot to remove this line --- src/processing/mode/experimental/DebugEditor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index aea75af..f134e50 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -232,7 +232,8 @@ public void actionPerformed(ActionEvent e) { ta.setECSandThemeforTextArea(errorCheckerService, dmode); addXQModeUI(); //TODO: Remove this later - setBounds(160, 300, getWidth(), getHeight()); + if(ExperimentalMode.DEBUG) + setBounds(160, 300, getWidth(), getHeight()); } private void addXQModeUI(){ From d8acb3585406ea35b49eeadcdacabdc1af134564 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 22:07:47 +0530 Subject: [PATCH 011/193] updated todo --- Todo, GSoC 2013.txt | 1 + .../mode/experimental/ErrorCheckerService.java | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 97c1fb2..6c583fe 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -130,6 +130,7 @@ General Stuff ============= * Ensure all editor windows are closed when editor is closed. +* Add a red marker near Errors label in console toggle, to indicate errors present in sketch. x Add option for toggling debug output x On Run/Debug Console is visible(ProblemsList hidden) * Update wiki for Ctrl + H instead of Ctrl + J shortcuts diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 22f7886..15cc6d0 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -362,12 +362,22 @@ private boolean checkCode() { return false; } - private AtomicBoolean syntaxErrors; + protected AtomicBoolean syntaxErrors; public boolean hasSyntaxErrors(){ return syntaxErrors.get(); } + public boolean hasErrors(){ + synchronized (problemsList) { + for (Problem p : problemsList) { + if (p.isError()) + return false; + } + return false; + } + } + protected TreeMap tempErrorLog; private void syntaxCheck() { From 302b968eae54ad620e36550a119bcd223a68b6da Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 19 Aug 2013 22:56:28 +0530 Subject: [PATCH 012/193] indicator near error toggle button, dunno if a good idea. --- Todo, GSoC 2013.txt | 2 +- src/processing/mode/experimental/DebugEditor.java | 5 +++++ .../mode/experimental/ErrorCheckerService.java | 6 ++++-- .../mode/experimental/XQConsoleToggle.java | 14 +++++++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 6c583fe..4c8abef 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -130,7 +130,7 @@ General Stuff ============= * Ensure all editor windows are closed when editor is closed. -* Add a red marker near Errors label in console toggle, to indicate errors present in sketch. +x Add a red marker near Errors label in console toggle, to indicate errors present in sketch. x Add option for toggling debug output x On Run/Debug Console is visible(ProblemsList hidden) * Update wiki for Ctrl + H instead of Ctrl + J shortcuts diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index f134e50..8f17f94 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -1251,6 +1251,11 @@ synchronized public boolean updateTable(final TableModel tableModel) { return errorTable.updateTable(tableModel); } + public void updateErrorToggle(){ + btnShowErrors.updateMarker(errorCheckerService.hasErrors(), + errorBar.errorColor); + } + private void handleRefactor() { log("Caret at:"); log(ta.getLineText(ta.getCaretLine())); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 15cc6d0..09b9034 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -342,6 +342,7 @@ private boolean checkCode() { updateEditorStatus(); editor.getTextArea().repaint(); updatePaintedThingys(); + editor.updateErrorToggle(); int x = textModified.get(); //log("TM " + x); if (x >= 2) { @@ -371,8 +372,9 @@ public boolean hasSyntaxErrors(){ public boolean hasErrors(){ synchronized (problemsList) { for (Problem p : problemsList) { - if (p.isError()) - return false; + if (p.isError()){ + return true; + } } return false; } diff --git a/src/processing/mode/experimental/XQConsoleToggle.java b/src/processing/mode/experimental/XQConsoleToggle.java index 79d8516..9652e0a 100755 --- a/src/processing/mode/experimental/XQConsoleToggle.java +++ b/src/processing/mode/experimental/XQConsoleToggle.java @@ -90,10 +90,22 @@ public void paintComponent(Graphics g) { g.fillRect(0, 0, 4, this.getHeight()); g.setColor(Color.WHITE); } - + g.drawString(buttonName, getWidth() / 2 + 2 // + 2 is a offset - getFontMetrics(getFont()).stringWidth(buttonName) / 2, this.getHeight() - 6); + if(drawMarker){ + g.setColor(markerColor); + g.fillRect(4, 0, 2, this.getHeight()); + } + } + + boolean drawMarker = false; + protected Color markerColor; + public void updateMarker(boolean value, Color color){ + drawMarker = value; + markerColor = color; + repaint(); } @Override From 7f5ec9f34fc8cc4d8b26bbde248b14065ac7ba73 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 20 Aug 2013 02:30:56 +0530 Subject: [PATCH 013/193] added swingworker in processkeyevent --- build.properties | 4 ++-- src/processing/mode/experimental/TextArea.java | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/build.properties b/build.properties index 2c812c9..bdda74b 100644 --- a/build.properties +++ b/build.properties @@ -5,5 +5,5 @@ app.library.location=/home/quarkninja/Workspaces/processing-workspace/processing java.target.version=1.6 lib.name=ExperimentalMode dist=dist -release=2 -prettyVersion=1.1 \ No newline at end of file +release=3 +prettyVersion=1.1.1 diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 576b58e..d5caef4 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -34,6 +34,7 @@ import javax.swing.DefaultListModel; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import processing.app.syntax.JEditTextArea; import processing.app.syntax.TextAreaDefaults; @@ -179,10 +180,16 @@ public void processKeyEvent(KeyEvent evt) { super.processKeyEvent(evt); if (evt.getID() == KeyEvent.KEY_TYPED) { - errorCheckerService.runManualErrorCheck(); - log(" Typing: " + fetchPhrase(evt) + " " - + (evt.getKeyChar() == KeyEvent.VK_ENTER)); - + final KeyEvent evt2 = evt; + SwingWorker worker = new SwingWorker() { + protected Object doInBackground() throws Exception { + errorCheckerService.runManualErrorCheck(); + log(" Typing: " + fetchPhrase(evt2) + " " + + (evt2.getKeyChar() == KeyEvent.VK_ENTER)); + return null; + } + }; + worker.execute(); } From 3c0a3c60a0143f2c503255d72c0ad184185a001b Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 20 Aug 2013 02:39:32 +0530 Subject: [PATCH 014/193] removing swingworker in astgen showPred --- .../mode/experimental/ASTGenerator.java | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 4ede16a..b934b75 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -211,14 +211,14 @@ private void setupGUI(){ frmOccurenceList.add(sp2); //occurenceListFrame.setVisible(true); - frameAutoComp = new JFrame(); - frameAutoComp.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - frameAutoComp.setBounds(new Rectangle(1280, 100, 460, 620)); - Toolkit.setIcon(frameAutoComp); - tableAuto = new JTable(); - JScrollPane sp3 = new JScrollPane(); - sp3.setViewportView(tableAuto); - frameAutoComp.add(sp3); +// frameAutoComp = new JFrame(); +// frameAutoComp.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); +// frameAutoComp.setBounds(new Rectangle(1280, 100, 460, 620)); +// Toolkit.setIcon(frameAutoComp); +// tableAuto = new JTable(); +// JScrollPane sp3 = new JScrollPane(); +// sp3.setViewportView(tableAuto); +// frameAutoComp.add(sp3); // jdocWindow = new JFrame(); // jdocWindow.setTitle("P5 InstaHelp"); @@ -779,14 +779,15 @@ public void preparePredictions(final String word, final int line, final int line log("No predictions."); return; } - SwingWorker worker = new SwingWorker() { - - @Override - protected Object doInBackground() throws Exception { - return null; - } - - protected void done() { +// SwingWorker worker = new SwingWorker() { +// +// @Override +// protected Object doInBackground() throws Exception { +// return null; +// } +// +// protected void done() { + // If the parsed code contains pde enhancements, take 'em out. String word2 = ASTNodeWrapper.getJavaCode(word); @@ -987,31 +988,31 @@ protected void done() { showPredictions(word); - } - }; - - worker.execute(); +// } +// }; +// +// worker.execute(); } private void showPredictions(final String word) { if (sketchOutline != null) if (sketchOutline.isVisible()) return; Collections.sort(candidates); - CompletionCandidate[][] candi = new CompletionCandidate[candidates.size()][1]; +// CompletionCandidate[][] candi = new CompletionCandidate[candidates.size()][1]; DefaultListModel defListModel = new DefaultListModel(); - for (int i = 0; i < candi.length; i++) { - candi[i][0] = candidates.get(i); + for (int i = 0; i < candidates.size(); i++) { +// candi[i][0] = candidates.get(i); defListModel.addElement(candidates.get(i)); } log("Total preds = " + candidates.size()); - DefaultTableModel tm = new DefaultTableModel(candi, - new String[] { "Suggestions" }); - if (tableAuto.isVisible()) { - tableAuto.setModel(tm); - tableAuto.validate(); - tableAuto.repaint(); - } +// DefaultTableModel tm = new DefaultTableModel(candi, +// new String[] { "Suggestions" }); +// if (tableAuto.isVisible()) { +// tableAuto.setModel(tm); +// tableAuto.validate(); +// tableAuto.repaint(); +// } errorCheckerService.getEditor().textArea() .showSuggestion(defListModel, word); } From 52c856c69cef9d276dca232103c1c78020144ee8 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 20 Aug 2013 02:50:13 +0530 Subject: [PATCH 015/193] further swingworker stuff --- .../mode/experimental/ASTGenerator.java | 2 + .../mode/experimental/ErrorBar.java | 51 ++++++++----------- .../mode/experimental/SketchOutline.java | 12 ++--- 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index b934b75..ae5c272 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -775,6 +775,8 @@ private void trimCandidates(String newWord){ private String lastPredictedWord = " "; public void preparePredictions(final String word, final int line, final int lineStartNonWSOffset) { + // This method is called from TextArea.fetchPhrase, which is called via a SwingWorker instance + // in TextArea.processKeyEvent if(caretWithinLineComment()){ log("No predictions."); return; diff --git a/src/processing/mode/experimental/ErrorBar.java b/src/processing/mode/experimental/ErrorBar.java index d5f6c93..181cd3d 100755 --- a/src/processing/mode/experimental/ErrorBar.java +++ b/src/processing/mode/experimental/ErrorBar.java @@ -243,26 +243,21 @@ protected void addListeners() { @SuppressWarnings("rawtypes") @Override public void mouseClicked(final MouseEvent e) { - SwingWorker worker = new SwingWorker() { - - protected Object doInBackground() throws Exception { - return null; - } - - protected void done() { - for (ErrorMarker eMarker : errorPoints) { - // -2 and +2 are extra allowance, clicks in the - // vicinity of the markers register that way - if (e.getY() >= eMarker.getY() - 2 - && e.getY() <= eMarker.getY() + 2 - + errorMarkerHeight) { - errorCheckerService - .scrollToErrorLine(eMarker.getProblem()); - return; - } - } - } - }; + SwingWorker worker = new SwingWorker() { + + protected Object doInBackground() throws Exception { + for (ErrorMarker eMarker : errorPoints) { + // -2 and +2 are extra allowance, clicks in the + // vicinity of the markers register that way + if (e.getY() >= eMarker.getY() - 2 + && e.getY() <= eMarker.getY() + 2 + errorMarkerHeight) { + errorCheckerService.scrollToErrorLine(eMarker.getProblem()); + return null; + } + } + return null; + } + }; try { worker.execute(); @@ -281,14 +276,10 @@ protected void done() { @SuppressWarnings("rawtypes") @Override public void mouseMoved(final MouseEvent evt) { - // System.out.println(e); - SwingWorker worker = new SwingWorker() { - - protected Object doInBackground() throws Exception { - return null; - } + // System.out.println(e); + SwingWorker worker = new SwingWorker() { - protected void done() { + protected Object doInBackground() throws Exception { for (ErrorMarker eMarker : errorPoints) { if (evt.getY() >= eMarker.getY() - 2 && evt.getY() <= eMarker.getY() + 2 + errorMarkerHeight) { @@ -296,13 +287,13 @@ protected void done() { String msg = (p.isError() ? "Error: " : "Warning: ") + p.getMessage(); setToolTipText(msg); - setCursor(Cursor - .getPredefinedCursor(Cursor.HAND_CURSOR)); + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); break; } } + return null; } - }; + }; try { worker.execute(); diff --git a/src/processing/mode/experimental/SketchOutline.java b/src/processing/mode/experimental/SketchOutline.java index a78a66f..6577adf 100644 --- a/src/processing/mode/experimental/SketchOutline.java +++ b/src/processing/mode/experimental/SketchOutline.java @@ -199,13 +199,13 @@ public void changedUpdate(DocumentEvent e) { private void updateSelection(){ SwingWorker worker = new SwingWorker() { protected Object doInBackground() throws Exception { - return null; - } - - protected void done() { String text = searchField.getText().toLowerCase(); tempNode = new DefaultMutableTreeNode(); filterTree(text, tempNode, soNode); + return null; + } + + protected void done() { soTree.setModel(new DefaultTreeModel(tempNode)); ((DefaultTreeModel) soTree.getModel()).reload(); for (int i = 0; i < soTree.getRowCount(); i++) { @@ -249,10 +249,6 @@ protected void done() { } DefaultMutableTreeNode tnode = (DefaultMutableTreeNode) soTree .getLastSelectedPathComponent(); - if (tnode.getUserObject() == null) { - return; - } - if (tnode.getUserObject() instanceof ASTNodeWrapper) { ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject(); // log(awrap); From ad8850d56f2feebe211908b16c8920be7ce45f26 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 20 Aug 2013 02:57:50 +0530 Subject: [PATCH 016/193] some code cleanup --- .../mode/experimental/ASTGenerator.java | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index ae5c272..fd72de4 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1744,10 +1744,6 @@ protected void done() { } DefaultMutableTreeNode tnode = (DefaultMutableTreeNode) jtree .getLastSelectedPathComponent(); - if(tnode.getUserObject() == null){ - return; - } - if (tnode.getUserObject() instanceof ASTNodeWrapper) { ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject(); errorCheckerService.highlightNode(awrap); @@ -1817,9 +1813,6 @@ protected void done() { } DefaultMutableTreeNode tnode = (DefaultMutableTreeNode) treeRename .getLastSelectedPathComponent(); - if(tnode.getUserObject() == null){ - return; - } if (tnode.getUserObject() instanceof ASTNodeWrapper) { ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject(); @@ -1851,8 +1844,10 @@ private void refactorIt(){ //else log("New name looks K."); errorCheckerService.pauseThread(); - treeRename.setModel(new DefaultTreeModel(defCU)); - ((DefaultTreeModel) treeRename.getModel()).reload(); + if(treeRename.isVisible()){ + treeRename.setModel(new DefaultTreeModel(defCU)); + ((DefaultTreeModel) treeRename.getModel()).reload(); + } frmOccurenceList.setTitle("Usage of " + selText); frmOccurenceList.setLocation(editor.getX() + editor.getWidth(),editor.getY()); frmOccurenceList.setVisible(true); @@ -1892,11 +1887,10 @@ private void refactorIt(){ editor.ta.setSelectedText(newName); } errorCheckerService.resumeThread(); - errorCheckerService.runManualErrorCheck(); - for (Integer lineNum : lineOffsetDisplacement.keySet()) { - log(lineNum + "line, disp" - + lineOffsetDisplacement.get(lineNum)); - } +// for (Integer lineNum : lineOffsetDisplacement.keySet()) { +// log(lineNum + "line, disp" +// + lineOffsetDisplacement.get(lineNum)); +// } editor.getSketch().setModified(true); errorCheckerService.runManualErrorCheck(); frmOccurenceList.setVisible(false); From 5aab9b9d0bff67243d88b9dbf67ba35e9ce67e13 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 24 Aug 2013 15:23:00 +0530 Subject: [PATCH 017/193] added mode.properties, and minor changes in ECS --- mode.properties | 7 ++++ .../experimental/ErrorCheckerService.java | 42 ++++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 mode.properties diff --git a/mode.properties b/mode.properties new file mode 100644 index 0000000..5029f19 --- /dev/null +++ b/mode.properties @@ -0,0 +1,7 @@ +name=ExperimentalMode +authorList=[The Processing Foundation](http://processing.org) +url=https://github.com/processing/processing-experimental +sentence=The next generation of PDE +paragraph=Intelligent Code Completion, Live Error Checker, Debugger, Auto Refactor, etc. +version=@@version@@ +prettyVersion=@@pretty-version@@ diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 09b9034..658148a 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -193,6 +193,7 @@ public ErrorCheckerService(DebugEditor debugEditor) { pdePrepoc.getDefaultImports().length + 1; astGenerator = new ASTGenerator(this); syntaxErrors = new AtomicBoolean(true); + containsErrors = new AtomicBoolean(true); errorMsgSimplifier = new ErrorMessageSimplifier(); tempErrorLog = new TreeMap(); } @@ -337,6 +338,15 @@ private boolean checkCode() { + mainClassOffset); } + // Update error flag + containsErrors.set(false); + for (Problem p : problemsList) { + if (p.isError()){ + containsErrors.set(true); + break; + } + } + updateErrorTable(); editor.updateErrorBar(problemsList); updateEditorStatus(); @@ -363,31 +373,24 @@ private boolean checkCode() { return false; } - protected AtomicBoolean syntaxErrors; + protected AtomicBoolean syntaxErrors, containsErrors; public boolean hasSyntaxErrors(){ return syntaxErrors.get(); } public boolean hasErrors(){ - synchronized (problemsList) { - for (Problem p : problemsList) { - if (p.isError()){ - return true; - } - } - return false; - } + return containsErrors.get(); } protected TreeMap tempErrorLog; private void syntaxCheck() { syntaxErrors.set(true); + containsErrors.set(true); parser.setSource(sourceCode.toCharArray()); parser.setKind(ASTParser.K_COMPILATION_UNIT); - @SuppressWarnings("unchecked") Map options = JavaCore.getOptions(); JavaCore.setComplianceOptions(JavaCore.VERSION_1_6, options); @@ -413,25 +416,31 @@ private void syntaxCheck() { // log(p.toString()); } - if (problems.length == 0) + if (problems.length == 0) { syntaxErrors.set(false); - else + containsErrors.set(false); + } else { syntaxErrors.set(true); + containsErrors.set(true); + } } + protected URLClassLoader classLoader; + private void compileCheck() { // Currently (Sept, 2012) I'm using Java's reflection api to load the // CompilationChecker class(from CompilationChecker.jar) that houses the - // Eclispe JDT compiler and call its getErrorsAsObj method to obtain + // Eclispe JDT compiler, and call its getErrorsAsObj method to obtain // errors. This way, I'm able to add the paths of contributed libraries // to the classpath of CompilationChecker, dynamically. The eclipse compiler - // needs all referenced libraries in the classpath. + // needs all referenced libraries in the classpath. Totally a hack. If you find + // a better method, do let me know. try { // NOTE TO SELF: If classpath contains null Strings - // URLClassLoader gets angry. Drops NPE bombs. + // URLClassLoader shoots NPE bullets. // If imports have changed, reload classes with new classpath. if (loadCompClass) { @@ -451,7 +460,7 @@ private void compileCheck() { FileFilter fileFilter = new FileFilter() { public boolean accept(File file) { return (file.getName().endsWith(".jar") && !file - .getName().startsWith("ExperimentalMode")); + .getName().startsWith(editor.getMode().getClass().getSimpleName())); } }; @@ -526,6 +535,7 @@ public boolean accept(File file) { Problem p = new Problem(problem, a[0], a[1]); if ((Boolean) errorList[i][8]) { p.setType(Problem.ERROR); + containsErrors.set(true); // set flag } if ((Boolean) errorList[i][9]) { From a0273c57a05893d50f2b135f30362b9b685dc777 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 24 Aug 2013 16:32:57 +0530 Subject: [PATCH 018/193] thread synchronization stuff, kinda important --- .../mode/experimental/ASTGenerator.java | 8 +- .../mode/experimental/DebugEditor.java | 2 +- .../experimental/ErrorCheckerService.java | 250 +++++++++--------- 3 files changed, 134 insertions(+), 126 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index fd72de4..7bbcf32 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -346,9 +346,11 @@ public void run() { + File.separator + "rt.jar" + File.pathSeparatorChar); } if (errorCheckerService.classpathJars != null) { - for (URL jarPath : errorCheckerService.classpathJars) { - //log(jarPath.getPath()); - tehPath.append(jarPath.getPath() + File.pathSeparatorChar); + synchronized (errorCheckerService.classpathJars) { + for (URL jarPath : errorCheckerService.classpathJars) { + //log(jarPath.getPath()); + tehPath.append(jarPath.getPath() + File.pathSeparatorChar); + } } } diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 8f17f94..ad0936e 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -312,7 +312,7 @@ public void dispose() { dbg.stopDebug(); // remove var.inspector vi.dispose(); - + errorCheckerService.stopThread(); // original dispose super.dispose(); } diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 658148a..c9cdfdb 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -53,12 +53,12 @@ public class ErrorCheckerService implements Runnable{ /** * Used to indirectly stop the Error Checker Thread */ - public boolean stopThread = false; + protected AtomicBoolean stopThread; /** * If true, Error Checking is paused. Calls to checkCode() become useless. */ - private boolean pauseThread = false; + protected AtomicBoolean pauseThread; protected ErrorWindow errorWindow; @@ -185,6 +185,12 @@ public class ErrorCheckerService implements Runnable{ public ErrorCheckerService(DebugEditor debugEditor) { this.editor = debugEditor; + stopThread = new AtomicBoolean(false); + pauseThread = new AtomicBoolean(false); + + problemsList = new ArrayList(); + classpathJars = new ArrayList(); + initParser(); initializeErrorWindow(); xqpreproc = new XQPreprocessor(); @@ -246,7 +252,7 @@ public void run() { } public void run() { - stopThread = false; + stopThread.set(false); checkCode(); if(!hasSyntaxErrors()) @@ -256,7 +262,7 @@ public void run() { // Completion wouldn't be complete, but it'd be still something // better than nothing astGenerator.buildAST(cu); - while (!stopThread) { + while (!stopThread.get()) { try { // Take a nap. Thread.sleep(sleepTime); @@ -268,7 +274,7 @@ public void run() { updatePaintedThingys(); updateEditorStatus(); - if (pauseThread) + if (pauseThread.get()) continue; if(textModified.get() == 0) continue; @@ -337,16 +343,7 @@ private boolean checkCode() { log(editor.getSketch().getName() + "2 MCO " + mainClassOffset); } - - // Update error flag - containsErrors.set(false); - for (Problem p : problemsList) { - if (p.isError()){ - containsErrors.set(true); - break; - } - } - + updateErrorTable(); editor.updateErrorBar(problemsList); updateEditorStatus(); @@ -397,31 +394,41 @@ private void syntaxCheck() { options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6); options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); parser.setCompilerOptions(options); - cu = (CompilationUnit) parser.createAST(null); - - // Store errors returned by the ast parser - problems = cu.getProblems(); - // log("Problem Count: " + problems.length); - // Populate the probList - problemsList = new ArrayList(); - for (int i = 0; i < problems.length; i++) { - int a[] = calculateTabIndexAndLineNumber(problems[i]); - Problem p = new Problem(problems[i], a[0], a[1] + 1); - //TODO: ^Why do cheeky stuff? - problemsList.add(p); + + if (cu == null) + cu = (CompilationUnit) parser.createAST(null); + else { + synchronized (cu) { + cu = (CompilationUnit) parser.createAST(null); + } + } + + synchronized (problemsList) { + + // Store errors returned by the ast parser + problems = cu.getProblems(); + // log("Problem Count: " + problems.length); + // Populate the probList + problemsList = new ArrayList(); + for (int i = 0; i < problems.length; i++) { + int a[] = calculateTabIndexAndLineNumber(problems[i]); + Problem p = new Problem(problems[i], a[0], a[1] + 1); + //TODO: ^Why do cheeky stuff? + problemsList.add(p); // log(problems[i].getMessage()); // for (String j : problems[i].getArguments()) { // log("arg " + j); // } - // log(p.toString()); - } - - if (problems.length == 0) { - syntaxErrors.set(false); - containsErrors.set(false); - } else { - syntaxErrors.set(true); - containsErrors.set(true); + // log(p.toString()); + } + + if (problems.length == 0) { + syntaxErrors.set(false); + containsErrors.set(false); + } else { + syntaxErrors.set(true); + containsErrors.set(true); + } } } @@ -487,7 +494,6 @@ public boolean accept(File file) { // log("2."); compilationChecker = checkerClass.newInstance(); - astGenerator.loadJars(); // Update jar files for completition list loadCompClass = false; } @@ -586,52 +592,80 @@ private void prepareCompilerClasspath() { return; } - // log("1.."); - classpathJars = new ArrayList(); - String entry = ""; - boolean codeFolderChecked = false; - for (ImportStatement impstat : programImports) { - String item = impstat.getImportName(); - int dot = item.lastIndexOf('.'); - entry = (dot == -1) ? item : item.substring(0, dot); - - entry = entry.substring(6).trim(); - // log("Entry--" + entry); - if (ignorableImport(entry)) { - // log("Ignoring: " + entry); - continue; - } - Library library = null; - - // Try to get the library classpath and add it to the list - try { - library = editor.getMode().getLibrary(entry); - // log("lib->" + library.getClassPath() + "<-"); - String libraryPath[] = PApplet.split(library.getClassPath() - .substring(1).trim(), File.pathSeparatorChar); - for (int i = 0; i < libraryPath.length; i++) { - // log(entry + " ::" - // + new File(libraryPath[i]).toURI().toURL()); - classpathJars.add(new File(libraryPath[i]).toURI().toURL()); + synchronized (classpathJars) { + // log("1.."); + classpathJars = new ArrayList(); + String entry = ""; + boolean codeFolderChecked = false; + for (ImportStatement impstat : programImports) { + String item = impstat.getImportName(); + int dot = item.lastIndexOf('.'); + entry = (dot == -1) ? item : item.substring(0, dot); + + entry = entry.substring(6).trim(); + // log("Entry--" + entry); + if (ignorableImport(entry)) { + // log("Ignoring: " + entry); + continue; } - // log("-- "); - // classpath[count] = (new File(library.getClassPath() - // .substring(1))).toURI().toURL(); - // log(" found "); - // log(library.getClassPath().substring(1)); - } catch (Exception e) { - if (library == null && !codeFolderChecked) { - // log(1); - // Look around in the code folder for jar files - if (editor.getSketch().hasCodeFolder()) { - File codeFolder = editor.getSketch().getCodeFolder(); - - // get a list of .jar files in the "code" folder - // (class files in subfolders should also be picked up) - String codeFolderClassPath = Base - .contentsToClassPath(codeFolder); - codeFolderChecked = true; - if (codeFolderClassPath.equalsIgnoreCase("")) { + Library library = null; + + // Try to get the library classpath and add it to the list + try { + library = editor.getMode().getLibrary(entry); + // log("lib->" + library.getClassPath() + "<-"); + String libraryPath[] = PApplet.split(library.getClassPath() + .substring(1).trim(), File.pathSeparatorChar); + for (int i = 0; i < libraryPath.length; i++) { + // log(entry + " ::" + // + new File(libraryPath[i]).toURI().toURL()); + classpathJars.add(new File(libraryPath[i]).toURI().toURL()); + } + // log("-- "); + // classpath[count] = (new File(library.getClassPath() + // .substring(1))).toURI().toURL(); + // log(" found "); + // log(library.getClassPath().substring(1)); + } catch (Exception e) { + if (library == null && !codeFolderChecked) { + // log(1); + // Look around in the code folder for jar files + if (editor.getSketch().hasCodeFolder()) { + File codeFolder = editor.getSketch().getCodeFolder(); + + // get a list of .jar files in the "code" folder + // (class files in subfolders should also be picked up) + String codeFolderClassPath = Base + .contentsToClassPath(codeFolder); + codeFolderChecked = true; + if (codeFolderClassPath.equalsIgnoreCase("")) { + System.err.println("Experimental Mode: Yikes! Can't find \"" + + entry + + "\" library! Line: " + + impstat.getLineNumber() + + " in tab: " + + editor.getSketch().getCode(impstat.getTab()) + .getPrettyName()); + System.out + .println("Please make sure that the library is present in /libraries folder or in the code folder of your sketch"); + + } + String codeFolderPath[] = PApplet.split( + codeFolderClassPath.substring(1).trim(), + File.pathSeparatorChar); + try { + for (int i = 0; i < codeFolderPath.length; i++) { + classpathJars.add(new File(codeFolderPath[i]) + .toURI().toURL()); + } + + } catch (Exception e2) { + System.out + .println("Yikes! codefolder, prepareImports(): " + + e2); + } + } else { System.err.println("Experimental Mode: Yikes! Can't find \"" + entry + "\" library! Line: " @@ -642,47 +676,21 @@ private void prepareCompilerClasspath() { System.out .println("Please make sure that the library is present in /libraries folder or in the code folder of your sketch"); - - } - String codeFolderPath[] = PApplet.split( - codeFolderClassPath.substring(1).trim(), - File.pathSeparatorChar); - try { - for (int i = 0; i < codeFolderPath.length; i++) { - classpathJars.add(new File(codeFolderPath[i]) - .toURI().toURL()); - } - - } catch (Exception e2) { - System.out - .println("Yikes! codefolder, prepareImports(): " - + e2); } + } else { - System.err.println("Experimental Mode: Yikes! Can't find \"" - + entry - + "\" library! Line: " - + impstat.getLineNumber() - + " in tab: " - + editor.getSketch().getCode(impstat.getTab()) - .getPrettyName()); - System.out - .println("Please make sure that the library is present in /libraries folder or in the code folder of your sketch"); + System.err + .println("Yikes! There was some problem in prepareImports(): " + + e); + System.err.println("I was processing: " + entry); + + // e.printStackTrace(); } - - } else { - System.err - .println("Yikes! There was some problem in prepareImports(): " - + e); - System.err.println("I was processing: " + entry); - - // e.printStackTrace(); } + } - } - + astGenerator.loadJars(); // update jar file for completion lookup } /** @@ -1277,8 +1285,6 @@ private void checkForChangedImports() { } } } - if(loadCompClass) - astGenerator.loadJars(); // log("load..? " + loadCompClass); } @@ -1390,21 +1396,21 @@ public static String substituteUnicode(String program) { * Stops the Error Checker Service thread */ public void stopThread() { - stopThread = true; + stopThread.set(true); } /** * Pauses the Error Checker Service thread */ public void pauseThread() { - pauseThread = true; + pauseThread.set(true); } /** * Resumes the Error Checker Service thread */ public void resumeThread() { - pauseThread = false; + pauseThread.set(false); } public DebugEditor getEditor() { From ae9394ac2a34e8fc06540b8f9ab60f0b029c811c Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 24 Aug 2013 16:57:47 +0530 Subject: [PATCH 019/193] more synchronization --- Todo, GSoC 2013.txt | 13 +++ .../mode/experimental/ErrorBar.java | 27 +++--- .../experimental/ErrorCheckerService.java | 91 ++++++++++--------- .../mode/experimental/ExperimentalMode.java | 2 +- 4 files changed, 74 insertions(+), 59 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 4c8abef..56d8552 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -126,6 +126,19 @@ x Working for local code * Labels for predefined class objects * Chaining support for labels +Synchronization +=============== + +Gotta do it carefully between main thread, ECS Thread, and SwingWorker threads +Fields that are concurrently accessed: + +ECS members: +ArrayList problems - updated in ECS, accessed by ErrorBar.update() +ArrayList classpathJars - updated in ECS, accessed by ASTGenerator.loadJars() +hasErrors, syntaxErrors - Atomic Boolean +CompilationUnit cu - updated in ECS, accessed a zillion times in ASTGenerator :'( + + General Stuff ============= diff --git a/src/processing/mode/experimental/ErrorBar.java b/src/processing/mode/experimental/ErrorBar.java index 181cd3d..375201e 100755 --- a/src/processing/mode/experimental/ErrorBar.java +++ b/src/processing/mode/experimental/ErrorBar.java @@ -174,21 +174,22 @@ protected Object doInBackground() throws Exception { // 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) { - if (problem.getTabIndex() == currentTab) { - // Ratio of error line to total lines - float y = (problem.getLineNumber() - errorCheckerService.defaultImportsOffset) - / ((float) totalLines); - // Ratio multiplied by height of the error bar - y *= fheight - 15; // -15 is just a vertical offset - errorPoints - .add(new ErrorMarker(problem, (int) y, - problem.isError() ? ErrorMarker.Error - : ErrorMarker.Warning)); - // System.out.println("Y: " + y); + synchronized (problems) { + for (Problem problem : problems) { + if (problem.getTabIndex() == currentTab) { + // Ratio of error line to total lines + float y = (problem.getLineNumber() - errorCheckerService.defaultImportsOffset) + / ((float) totalLines); + // Ratio multiplied by height of the error bar + y *= fheight - 15; // -15 is just a vertical offset + errorPoints + .add(new ErrorMarker(problem, (int) y, + problem.isError() ? ErrorMarker.Error + : ErrorMarker.Warning)); + // System.out.println("Y: " + y); + } } } - return null; } diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index c9cdfdb..9542d88 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -510,51 +510,52 @@ public boolean accept(File file) { if (errorList == null) { return; } - - problems = new DefaultProblem[errorList.length]; - - for (int i = 0; i < errorList.length; i++) { - - // for (int j = 0; j < errorList[i].length; j++) - // System.out.print(errorList[i][j] + ", "); - - problems[i] = new DefaultProblem((char[]) errorList[i][0], - (String) errorList[i][1], - ((Integer) errorList[i][2]).intValue(), - (String[]) errorList[i][3], - ((Integer) errorList[i][4]).intValue(), - ((Integer) errorList[i][5]).intValue(), - ((Integer) errorList[i][6]).intValue(), - ((Integer) errorList[i][7]).intValue(), 0); - - // System.out - // .println("ECS: " + problems[i].getMessage() + "," - // + problems[i].isError() + "," - // + problems[i].isWarning()); - - IProblem problem = problems[i]; -// log(problem.getMessage()); -// for (String j : problem.getArguments()) { -// log("arg " + j); -// } - int a[] = calculateTabIndexAndLineNumber(problem); - Problem p = new Problem(problem, a[0], a[1]); - if ((Boolean) errorList[i][8]) { - p.setType(Problem.ERROR); - containsErrors.set(true); // set flag - } - - if ((Boolean) errorList[i][9]) { - p.setType(Problem.WARNING); - } - - // If warnings are disabled, skip 'em - if (p.isWarning() && !warningsEnabled) { - continue; + + synchronized (problemsList) { + problems = new DefaultProblem[errorList.length]; + + for (int i = 0; i < errorList.length; i++) { + + // for (int j = 0; j < errorList[i].length; j++) + // System.out.print(errorList[i][j] + ", "); + + problems[i] = new DefaultProblem((char[]) errorList[i][0], + (String) errorList[i][1], + ((Integer) errorList[i][2]).intValue(), + (String[]) errorList[i][3], + ((Integer) errorList[i][4]).intValue(), + ((Integer) errorList[i][5]).intValue(), + ((Integer) errorList[i][6]).intValue(), + ((Integer) errorList[i][7]).intValue(), 0); + + // System.out + // .println("ECS: " + problems[i].getMessage() + "," + // + problems[i].isError() + "," + // + problems[i].isWarning()); + + IProblem problem = problems[i]; + // log(problem.getMessage()); + // for (String j : problem.getArguments()) { + // log("arg " + j); + // } + int a[] = calculateTabIndexAndLineNumber(problem); + Problem p = new Problem(problem, a[0], a[1]); + if ((Boolean) errorList[i][8]) { + p.setType(Problem.ERROR); + containsErrors.set(true); // set flag + } + + if ((Boolean) errorList[i][9]) { + p.setType(Problem.WARNING); + } + + // If warnings are disabled, skip 'em + if (p.isWarning() && !warningsEnabled) { + continue; + } + problemsList.add(p); } - problemsList.add(p); } - } catch (ClassNotFoundException e) { System.err.println("Compiltation Checker files couldn't be found! " + e + " compileCheck() problem."); @@ -717,7 +718,7 @@ protected boolean ignorableImport(String packageName) { /** * Enable/Disable warnings from being shown */ - public boolean warningsEnabled = true; + volatile public boolean warningsEnabled = true; /** * Sets compiler options for JDT Compiler @@ -747,7 +748,7 @@ protected void prepareCompilerSetting() { /** * Updates the error table in the Error Window. */ - synchronized public void updateErrorTable() { + public void updateErrorTable() { try { String[][] errorData = new String[problemsList.size()][3]; diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index db5f793..d5f0739 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -46,7 +46,7 @@ public class ExperimentalMode extends JavaMode { public static final boolean VERBOSE_LOGGING = true; //public static final boolean VERBOSE_LOGGING = false; public static final int LOG_SIZE = 512 * 1024; // max log file size (in bytes) - public static boolean DEBUG = !true; + public static boolean DEBUG = true; public ExperimentalMode(Base base, File folder) { super(base, folder); From 542f6a4e100f116b04c18e1980d76d09fd381b26 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 24 Aug 2013 17:24:54 +0530 Subject: [PATCH 020/193] bit more work on threads, making sure all windows quite --- Todo, GSoC 2013.txt | 9 +++++---- .../mode/experimental/ASTGenerator.java | 13 +++++++++++++ .../mode/experimental/ErrorCheckerService.java | 15 ++++++++++----- src/processing/mode/experimental/ErrorWindow.java | 4 ++-- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 56d8552..54ca3a0 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -133,10 +133,11 @@ Gotta do it carefully between main thread, ECS Thread, and SwingWorker threads Fields that are concurrently accessed: ECS members: -ArrayList problems - updated in ECS, accessed by ErrorBar.update() -ArrayList classpathJars - updated in ECS, accessed by ASTGenerator.loadJars() -hasErrors, syntaxErrors - Atomic Boolean -CompilationUnit cu - updated in ECS, accessed a zillion times in ASTGenerator :'( +x ArrayList problems - updated in ECS, accessed by ErrorBar.update() +x ArrayList classpathJars - updated in ECS, accessed by ASTGenerator.loadJars() +x hasErrors, syntaxErrors - Atomic Boolean +x boolean warningsEnabled - made it volatile +* CompilationUnit cu - updated in ECS, accessed a zillion times in ASTGenerator :'( General Stuff diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 7bbcf32..ff15544 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -3090,6 +3090,19 @@ public void actionPerformed(ActionEvent evt) { } } + + public void disposeAllWindows(){ + disposeWindow(frame2); + disposeWindow(frameAutoComp); + disposeWindow(frmImportSuggest); + disposeWindow(frmOccurenceList); + disposeWindow(frmRename); + } + + public static void disposeWindow(JFrame f) { + if(f != null) + f.dispose(); + } public static final String ignoredImports[] = { "com.oracle.", "sun.", "sunw.", "com.sun.", "javax.", "sunw.", "org.ietf.", diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 9542d88..02d2e6c 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -282,6 +282,10 @@ public void run() { checkCode(); checkForMissingImports(); } + checkerClass = null; + astGenerator.disposeAllWindows(); + astGenerator = null; + logE("Thread stopped: " + editor.getSketch().getName()); } private void checkForMissingImports() { @@ -559,20 +563,20 @@ public boolean accept(File file) { } catch (ClassNotFoundException e) { System.err.println("Compiltation Checker files couldn't be found! " + e + " compileCheck() problem."); - stopThread(); + pauseThread(); } catch (MalformedURLException e) { System.err.println("Compiltation Checker files couldn't be found! " + e + " compileCheck() problem."); - stopThread(); + pauseThread(); } catch (Exception e) { System.err.println("compileCheck() problem." + e); e.printStackTrace(); - stopThread(); + pauseThread(); } catch (NoClassDefFoundError e) { System.err .println(e + " compileCheck() problem. Somebody tried to mess with Experimental Mode files."); - stopThread(); + pauseThread(); } // log("Compilecheck, Done."); } @@ -793,7 +797,7 @@ public void updateErrorTable() { } catch (Exception e) { log("Exception at updateErrorTable() " + e); e.printStackTrace(); - stopThread(); + pauseThread(); } } @@ -1397,6 +1401,7 @@ public static String substituteUnicode(String program) { * Stops the Error Checker Service thread */ public void stopThread() { + logE("Stopping thread: " + editor.getSketch().getName()); stopThread.set(true); } diff --git a/src/processing/mode/experimental/ErrorWindow.java b/src/processing/mode/experimental/ErrorWindow.java index db4e2a8..cc95f2e 100755 --- a/src/processing/mode/experimental/ErrorWindow.java +++ b/src/processing/mode/experimental/ErrorWindow.java @@ -183,7 +183,7 @@ public void windowDeiconified(WindowEvent e) { return; } - thisEditor.addWindowListener(new WindowAdapter() { + /*thisEditor.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { @@ -207,7 +207,7 @@ public void windowDeiconified(WindowEvent e) { thisErrorWindow.setExtendedState(Frame.NORMAL); } - }); + });*/ thisEditor.addComponentListener(new ComponentListener() { From 1b82fd61f63f7dcd765b0439c84fa28f6409cd88 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 24 Aug 2013 20:30:39 +0530 Subject: [PATCH 021/193] Getter for astgen --- src/processing/mode/experimental/CompletionPanel.java | 8 ++++---- src/processing/mode/experimental/DebugEditor.java | 6 +++--- src/processing/mode/experimental/ErrorCheckerService.java | 5 +++++ src/processing/mode/experimental/TextArea.java | 6 +++--- src/processing/mode/experimental/TextAreaPainter.java | 4 ++-- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 55e66c4..ff2b738 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -56,7 +56,7 @@ public CompletionPanel(JEditTextArea textarea, int position, String subWord, scrollPane.setViewportView(completionList = createSuggestionList(position, items)); popupMenu.add(scrollPane, BorderLayout.CENTER); popupMenu.setPopupSize(280, 250); //TODO: Eradicate this evil - this.textarea.errorCheckerService.astGenerator + this.textarea.errorCheckerService.getASTGenerator() .updateJavaDoc((CompletionCandidate) completionList.getSelectedValue()); popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y); @@ -145,7 +145,7 @@ public boolean insertSelection() { public void hideSuggestion() { popupMenu.setVisible(false); log("Suggestion hidden" + System.nanoTime()); - //textarea.errorCheckerService.astGenerator.jdocWindowVisible(false); + //textarea.errorCheckerService.getASTGenerator().jdocWindowVisible(false); } public void moveUp() { @@ -163,7 +163,7 @@ public void moveUp() { .getVerticalScrollBar() .getValue() - step); - textarea.errorCheckerService.astGenerator + textarea.errorCheckerService.getASTGenerator() .updateJavaDoc((CompletionCandidate) completionList.getSelectedValue()); } @@ -178,7 +178,7 @@ public void moveDown() { .getSize() - 1); selectIndex(index); } - textarea.errorCheckerService.astGenerator + textarea.errorCheckerService.getASTGenerator() .updateJavaDoc((CompletionCandidate) completionList.getSelectedValue()); int step = scrollPane.getVerticalScrollBar().getMaximum() / completionList.getModel().getSize(); diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index ad0936e..34e02d5 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -612,7 +612,7 @@ public void actionPerformed(ActionEvent ae) { toggleVariableInspector(); } else if (source.equals(showOutline)){ log("Show Outline :D"); - errorCheckerService.astGenerator.showSketchOutline(); + errorCheckerService.getASTGenerator().showSketchOutline(); } } @@ -1259,13 +1259,13 @@ public void updateErrorToggle(){ private void handleRefactor() { log("Caret at:"); log(ta.getLineText(ta.getCaretLine())); - errorCheckerService.astGenerator.handleRefactor(); + errorCheckerService.getASTGenerator().handleRefactor(); } private void handleShowUsage() { log("Caret at:"); log(ta.getLineText(ta.getCaretLine())); - errorCheckerService.astGenerator.handleShowUsage(); + errorCheckerService.getASTGenerator().handleShowUsage(); } /** diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 02d2e6c..8070b9b 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -302,6 +302,11 @@ private void checkForMissingImports() { } protected ASTGenerator astGenerator; + + public ASTGenerator getASTGenerator() { + return astGenerator; + } + /** * This thing acts as an event queue counter of sort. * Since error checking happens on demand, anytime this counter diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index d5caef4..4468951 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -251,7 +251,7 @@ else if (s.length() == 0) if (Character.isDigit(word.charAt(0))) return null; log("Mouse click, word: " + word.trim()); - errorCheckerService.astGenerator.setLastClickedWord(line + errorCheckerService.getASTGenerator().setLastClickedWord(line + errorCheckerService.mainClassOffset, word, xLS); return word.trim(); } @@ -302,7 +302,7 @@ else if (keyChar == KeyEvent.VK_ESCAPE) { if (word.endsWith(".")) word = word.substring(0, word.length() - 1); if(word.length() > 1) - errorCheckerService.astGenerator.preparePredictions(word, line + errorCheckerService.getASTGenerator().preparePredictions(word, line + errorCheckerService.mainClassOffset,0); return word; } @@ -380,7 +380,7 @@ else if (s.charAt(x1) == ']') { // word = word.substring(0, word.length() - 1); int lineStartNonWSOffset = 0; if(word.length() > 1) - errorCheckerService.astGenerator.preparePredictions(word, line + errorCheckerService.getASTGenerator().preparePredictions(word, line + errorCheckerService.mainClassOffset,lineStartNonWSOffset); //showSuggestionLater(); return word; diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index f8db484..3825012 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -143,7 +143,7 @@ else if (s.length() == 0) log(errorCheckerService.mainClassOffset + line + "|" + line + "| offset " + xLS + word + " <= \n"); - errorCheckerService.astGenerator.scrollToDeclaration(line + errorCheckerService.getASTGenerator().scrollToDeclaration(line + errorCheckerService.mainClassOffset, word, xLS); } } @@ -472,7 +472,7 @@ else if (s.length() == 0) } if (Character.isDigit(word.charAt(0))) return null; - String tooltipText = errorCheckerService.astGenerator + String tooltipText = errorCheckerService.getASTGenerator() .getLabelForASTNode(line + errorCheckerService.mainClassOffset, word, xLS); From b7557790acadfdb9c362b36cb2e0303c927bb55e Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 24 Aug 2013 20:34:10 +0530 Subject: [PATCH 022/193] access is now protected --- .../experimental/ErrorCheckerService.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 8070b9b..b41a1d4 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -39,7 +39,7 @@ public class ErrorCheckerService implements Runnable{ - private DebugEditor editor; + protected DebugEditor editor; /** * Error check happens every sleepTime milliseconds */ @@ -48,7 +48,7 @@ public class ErrorCheckerService implements Runnable{ /** * The amazing eclipse ast parser */ - private ASTParser parser; + protected ASTParser parser; /** * Used to indirectly stop the Error Checker Thread @@ -65,7 +65,7 @@ public class ErrorCheckerService implements Runnable{ /** * IProblem[] returned by parser stored in here */ - private IProblem[] problems; + protected IProblem[] problems; /** * Class name of current sketch @@ -114,7 +114,7 @@ public class ErrorCheckerService implements Runnable{ * If true, compilation checker will be reloaded with updated classpath * items. */ - private boolean loadCompClass = true; + protected boolean loadCompClass = true; /** * Compiler Checker class. Note that methods for compilation checking are @@ -136,14 +136,14 @@ public class ErrorCheckerService implements Runnable{ /** * Timestamp - for measuring total overhead */ - private long lastTimeStamp = System.currentTimeMillis(); + protected long lastTimeStamp = System.currentTimeMillis(); /** * Used for displaying the rotating slash on the Problem Window title bar */ - private String[] slashAnimation = { "|", "/", "--", "\\", "|", "/", "--", + protected String[] slashAnimation = { "|", "/", "--", "\\", "|", "/", "--", "\\" }; - private int slashAnimationIndex = 0; + protected int slashAnimationIndex = 0; /** * Used to detect if the current tab index has changed and thus repaint the @@ -155,7 +155,7 @@ public class ErrorCheckerService implements Runnable{ * Stores the current import statements in the program. Used to compare for * changed import statements and update classpath if needed. */ - private ArrayList programImports; + protected ArrayList programImports; /** * List of imports when sketch was last checked. Used for checking for @@ -207,7 +207,7 @@ public ErrorCheckerService(DebugEditor debugEditor) { /** * Initializes ASTParser */ - private void initParser() { + protected void initParser() { try { parser = ASTParser.newParser(AST.JLS4); } catch (Exception e) { @@ -288,7 +288,7 @@ public void run() { logE("Thread stopped: " + editor.getSketch().getName()); } - private void checkForMissingImports() { + protected void checkForMissingImports() { for (Problem p : problemsList) { if(p.getMessage().endsWith(" cannot be resolved to a type"));{ int idx = p.getMessage().indexOf(" cannot be resolved to a type"); @@ -322,7 +322,7 @@ public void runManualErrorCheck() { textModified.incrementAndGet(); } - private boolean checkCode() { + protected boolean checkCode() { //log("checkCode() " + textModified.get() ); log("checkCode() " + textModified.get()); lastTimeStamp = System.currentTimeMillis(); @@ -391,7 +391,7 @@ public boolean hasErrors(){ protected TreeMap tempErrorLog; - private void syntaxCheck() { + protected void syntaxCheck() { syntaxErrors.set(true); containsErrors.set(true); parser.setSource(sourceCode.toCharArray()); @@ -443,7 +443,7 @@ private void syntaxCheck() { protected URLClassLoader classLoader; - private void compileCheck() { + protected void compileCheck() { // Currently (Sept, 2012) I'm using Java's reflection api to load the // CompilationChecker class(from CompilationChecker.jar) that houses the @@ -597,7 +597,7 @@ public URLClassLoader getSketchClassLoader() { * messed up. * */ - private void prepareCompilerClasspath() { + protected void prepareCompilerClasspath() { if (!loadCompClass) { return; } @@ -1037,7 +1037,7 @@ public int[] calculateTabIndexAndLineNumber(IProblem problem) { * code is not yet compile ready. */ - private String preprocessCode(String pdeCode) { + protected String preprocessCode(String pdeCode) { programImports = new ArrayList(); @@ -1276,7 +1276,7 @@ public static boolean scrollToErrorLine(Editor edt, int tabIndex, int lineNoInTa * Checks if import statements in the sketch have changed. If they have, * compiler classpath needs to be updated. */ - private void checkForChangedImports() { + protected void checkForChangedImports() { // log("Imports: " + programImports.size() + // " Prev Imp: " // + previousImports.size()); @@ -1298,7 +1298,7 @@ private void checkForChangedImports() { // log("load..? " + loadCompClass); } - private int pdeImportsCount; + protected int pdeImportsCount; public int getPdeImportsCount() { return pdeImportsCount; @@ -1314,7 +1314,7 @@ public int getPdeImportsCount() { * - index of the tab * @return String - Tab code with imports replaced with white spaces */ - private String scrapImportStatements(String tabProgram, int tabNumber) { + protected String scrapImportStatements(String tabProgram, int tabNumber) { //TODO: Commented out imports are still detected as main imports. pdeImportsCount = 0; String tabSource = new String(tabProgram); From c425255807d231267c3e54eaf69fa8c51ae4db7f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 24 Aug 2013 20:36:58 +0530 Subject: [PATCH 023/193] also for astGen --- .../mode/experimental/ASTGenerator.java | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index ff15544..9ba2d3e 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -109,44 +109,44 @@ public class ASTGenerator { public DefaultMutableTreeNode codeTree = new DefaultMutableTreeNode(); - private DefaultMutableTreeNode currentParent = null; + protected DefaultMutableTreeNode currentParent = null; /** * AST Window */ - private JFrame frame2; + protected JFrame frame2; - private JFrame frameAutoComp; + protected JFrame frameAutoComp; /** * Swing component wrapper for AST, used for internal testing */ - private JTree jtree; + protected JTree jtree; /** * JTree used for testing refactoring operations */ - private JTree treeRename; + protected JTree treeRename; - private CompilationUnit compilationUnit; + protected CompilationUnit compilationUnit; - private JTable tableAuto; + protected JTable tableAuto; - private JEditorPane javadocPane; + protected JEditorPane javadocPane; - private JScrollPane scrollPane; + protected JScrollPane scrollPane; - private JFrame frmRename; + protected JFrame frmRename; - private JButton btnRename; + protected JButton btnRename; - private JButton btnListOccurrence; + protected JButton btnListOccurrence; - private JTextField txtRenameField; + protected JTextField txtRenameField; - private JFrame frmOccurenceList; + protected JFrame frmOccurenceList; - private JLabel lblRefactorOldName; + protected JLabel lblRefactorOldName; public ASTGenerator(ErrorCheckerService ecs) { this.errorCheckerService = ecs; @@ -156,7 +156,7 @@ public ASTGenerator(ErrorCheckerService ecs) { addListeners(); } - private void setupGUI(){ + protected void setupGUI(){ frame2 = new JFrame(); jtree = new JTree(); @@ -234,7 +234,7 @@ private void setupGUI(){ //// loadJars(); } - private DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { + protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { ASTParser parser = ASTParser.newParser(AST.JLS4); parser.setSource(source.toCharArray()); @@ -304,14 +304,14 @@ protected void done() { return codeTree; } - private ClassPathFactory factory; + protected ClassPathFactory factory; /** * Used for searching for package declaration of a class */ - private ClassPath classPath; + protected ClassPath classPath; - private JFrame jdocWindow; + protected JFrame jdocWindow; /** * Loads up .jar files and classes defined in it for completion lookup @@ -395,9 +395,9 @@ public void run() { t.start(); } - private TreeMap jdocMap; + protected TreeMap jdocMap; - private void loadJavaDoc() { + protected void loadJavaDoc() { // presently loading only p5 reference for PApplet Thread t = new Thread(new Runnable() { @@ -758,7 +758,7 @@ public static ASTNode getParentExpression(ASTNode expression) { return null; } - private void trimCandidates(String newWord){ + protected void trimCandidates(String newWord){ ArrayList newCandidate = new ArrayList(); newWord = newWord.toLowerCase(); for (CompletionCandidate comp : candidates) { @@ -773,8 +773,8 @@ private void trimCandidates(String newWord){ /** * List of CompletionCandidates */ - private ArrayList candidates; - private String lastPredictedWord = " "; + protected ArrayList candidates; + protected String lastPredictedWord = " "; public void preparePredictions(final String word, final int line, final int lineStartNonWSOffset) { // This method is called from TextArea.fetchPhrase, which is called via a SwingWorker instance @@ -998,7 +998,7 @@ public void preparePredictions(final String word, final int line, final int line // worker.execute(); } - private void showPredictions(final String word) { + protected void showPredictions(final String word) { if (sketchOutline != null) if (sketchOutline.isVisible()) return; Collections.sort(candidates); @@ -1153,7 +1153,7 @@ public ArrayList getMembersForType(ClassMember tehClass, * @param className * @return */ - private Class findClassIfExists(String className){ + protected Class findClassIfExists(String className){ if(className == null){ return null; } @@ -1224,7 +1224,7 @@ private Class findClassIfExists(String className){ return tehClass; } - private Class loadClass(String className){ + protected Class loadClass(String className){ Class tehClass = null; if(className instanceof String){ try { @@ -1343,7 +1343,7 @@ public void run() { } @SuppressWarnings("unchecked") - private static ASTNode findClosestParentNode(int lineNumber, ASTNode node) { + protected static ASTNode findClosestParentNode(int lineNumber, ASTNode node) { Iterator it = node .structuralPropertiesForType().iterator(); // logE("Props of " + node.getClass().getName()); @@ -1383,7 +1383,7 @@ else if (prop.isChildListProperty()) { return node; } - private static ASTNode findClosestNode(int lineNumber, ASTNode node) { + protected static ASTNode findClosestNode(int lineNumber, ASTNode node) { log("findClosestNode to line " + lineNumber); ASTNode parent = findClosestParentNode(lineNumber, node); log("findClosestParentNode returned " + getNodeAsString(parent)); @@ -1427,7 +1427,7 @@ public String getLabelForASTNode(int lineNumber, String name, int offset) { //return ""; } - private String getLabelIfType(ASTNodeWrapper node, SimpleName sn){ + protected String getLabelIfType(ASTNodeWrapper node, SimpleName sn){ ASTNode current = node.getNode().getParent(); String type = ""; StringBuffer fullName = new StringBuffer(); @@ -1633,7 +1633,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, * @param name - The name we're looking for. * @return SimpleName */ - private static ASTNode getNodeName(ASTNode node, String name){ + protected static ASTNode getNodeName(ASTNode node, String name){ List vdfs = null; switch (node.getNodeType()) { case ASTNode.TYPE_DECLARATION: @@ -1726,7 +1726,7 @@ public static void traversal2() { } } - private void addListeners(){ + protected void addListeners(){ jtree.addTreeSelectionListener(new TreeSelectionListener() { @Override @@ -1827,7 +1827,7 @@ protected void done() { }); } - private void refactorIt(){ + protected void refactorIt(){ String newName = txtRenameField.getText().trim(); String selText = lastClickedWord == null ? editor.ta.getSelectedText() : lastClickedWord; @@ -1944,7 +1944,7 @@ public void setLastClickedWord(int lineNumber, String lastClickedWord, int offse log("Last clicked node: " + lastClickedWordNode); } - private DefaultMutableTreeNode findAllOccurrences(){ + protected DefaultMutableTreeNode findAllOccurrences(){ log("Last clicked word:" + lastClickedWord); String selText = lastClickedWord == null ? editor.ta.getSelectedText() : lastClickedWord; @@ -2121,7 +2121,7 @@ public int javaCodeOffsetToLineStartOffset(int line, int jOffset){ return -1; } - private int PdeToJavaLineNumber(int lineNum){ + protected int PdeToJavaLineNumber(int lineNum){ int lineNumber = lineNum + errorCheckerService.getPdeImportsCount(); // Adjust line number for tabbed sketches int codeIndex = editor.getSketch().getCodeIndex(editor.getCurrentTab()); @@ -2134,7 +2134,7 @@ private int PdeToJavaLineNumber(int lineNum){ return lineNumber; } - private boolean isInstanceOfType(ASTNode node,ASTNode decl, String name){ + protected boolean isInstanceOfType(ASTNode node,ASTNode decl, String name){ if(node instanceof SimpleName){ SimpleName sn = (SimpleName) node; @@ -2232,7 +2232,7 @@ else if (prop.isChildListProperty()) { } @SuppressWarnings("unchecked") - private static ASTNode findLineOfNode(ASTNode node, int lineNumber, + protected static ASTNode findLineOfNode(ASTNode node, int lineNumber, int offset, String name) { CompilationUnit root = (CompilationUnit) node.getRoot(); @@ -2349,7 +2349,7 @@ public static ASTNode pinpointOnLine(ASTNode node, int offset, * @return */ @SuppressWarnings("unchecked") - private static ASTNode findDeclaration(Name findMe) { + protected static ASTNode findDeclaration(Name findMe) { // WARNING: You're entering the Rube Goldberg territory of Experimental Mode. // To debug this code, thou must take the Recursive Leap of Faith. @@ -2544,7 +2544,7 @@ else if (parent instanceof Expression) { * @param alternateParent * @return */ - private static ASTNode findDeclaration2(Name findMe, ASTNode alternateParent) { + protected static ASTNode findDeclaration2(Name findMe, ASTNode alternateParent) { ASTNode declaringClass = null; ASTNode parent = findMe.getParent(); ASTNode ret = null; @@ -2728,7 +2728,7 @@ private static ASTNode findDeclaration2(Name findMe, ASTNode alternateParent) { } - private List getCodeComments(){ + protected List getCodeComments(){ List commentList = compilationUnit.getCommentList(); // log("Total comments: " + commentList.size()); // int i = 0; @@ -2925,7 +2925,7 @@ public static Type extracTypeInfo2(ASTNode node) { } @SuppressWarnings("unchecked") - private static ASTNode definedIn(ASTNode node, String name, + protected static ASTNode definedIn(ASTNode node, String name, ArrayList constrains, ASTNode declaringClass) { if (node == null) @@ -3108,7 +3108,7 @@ public static void disposeWindow(JFrame f) { "com.oracle.", "sun.", "sunw.", "com.sun.", "javax.", "sunw.", "org.ietf.", "org.jcp.", "org.omg.", "org.w3c.", "org.xml.", "org.eclipse.", "com.ibm.", "org.netbeans.", "org.jsoup.", "org.junit.", "org.apache.", "antlr." }; - private boolean ignorableImport(String impName) { + protected boolean ignorableImport(String impName) { //TODO: Trie man. for (ImportStatement impS : errorCheckerService.getProgramImports()) { if(impName.startsWith(impS.getPackageName())) @@ -3172,7 +3172,7 @@ public int[] getASTNodeAllOffsets(ASTNode node){ - static private String getNodeAsString(ASTNode node) { + static protected String getNodeAsString(ASTNode node) { if (node == null) return "NULL"; String className = node.getClass().getName(); @@ -3224,7 +3224,7 @@ else if (className.endsWith("Type")) * @param node * @return */ - static private String getNodeAsString2(ASTNode node) { + static protected String getNodeAsString2(ASTNode node) { if (node == null) return "NULL"; String className = node.getClass().getName(); From 6dad1e63fae849abb35f7d08ae5654f36b1fa8c7 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 25 Aug 2013 18:06:50 +0530 Subject: [PATCH 024/193] did and then undid javadoc pane work. doesn't seem right. --- Todo, GSoC 2013.txt | 1 + .../mode/experimental/ASTGenerator.java | 80 ++++++++++--------- .../experimental/CompletionCandidate.java | 8 ++ 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 54ca3a0..10415a8 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -15,6 +15,7 @@ The big stuff: - Making very good progress here. The elegance of recurion - Hats off! - Many of the cases seem to have been covered, and I'm achieving more and more code unification as I'm working through the problem step by step - Looks almost complete now, nearly all cases covered(July 13th) +* After popup appears, the popup location is fixed for the current line. So if editor window is moved while staying in the same line, popup appears at the prev location. Need to ensure editor is still at last know location * Scope handling? Static/non static scope? * Disable completions on comment line * Trie implementation would be lower priority, "premature optimisation is pure evil". Get all features of CC working good enough and then plan this. diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 9ba2d3e..d20b6fc 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -153,7 +153,7 @@ public ASTGenerator(ErrorCheckerService ecs) { this.editor = ecs.getEditor(); setupGUI(); //addCompletionPopupListner(); - addListeners(); + addListeners(); loadJavaDoc(); } protected void setupGUI(){ @@ -220,18 +220,20 @@ protected void setupGUI(){ // sp3.setViewportView(tableAuto); // frameAutoComp.add(sp3); -// jdocWindow = new JFrame(); -// jdocWindow.setTitle("P5 InstaHelp"); +// frmJavaDoc = new JFrame(); +// frmJavaDoc.setTitle("P5 InstaHelp"); // //jdocWindow.setUndecorated(true); -// jdocWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); +// frmJavaDoc.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); // javadocPane = new JEditorPane(); // javadocPane.setContentType("text/html"); +// javadocPane.setText(" "); // javadocPane.setEditable(false); // scrollPane = new JScrollPane(); // scrollPane.setViewportView(javadocPane); -// jdocWindow.add(scrollPane); -// jdocMap = new TreeMap(); -//// loadJars(); +// frmJavaDoc.add(scrollPane); + //frmJavaDoc.setUndecorated(true); + + } protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { @@ -282,17 +284,16 @@ protected void done() { // frameAutoComp.setVisible(true); // // } -// if (!jdocWindow.isVisible()) { +// if (!frmJavaDoc.isVisible()) { // long t = System.currentTimeMillis(); -// loadJars(); // loadJavaDoc(); // log("Time taken: " // + (System.currentTimeMillis() - t)); -// jdocWindow.setBounds(new Rectangle(errorCheckerService.getEditor() +// frmJavaDoc.setBounds(new Rectangle(errorCheckerService.getEditor() // .getX() + errorCheckerService.getEditor().getWidth(), // errorCheckerService.getEditor() // .getY(), 450, 600)); -// jdocWindow.setVisible(true); +// frmJavaDoc.setVisible(true); // } } } @@ -311,7 +312,7 @@ protected void done() { */ protected ClassPath classPath; - protected JFrame jdocWindow; + //protected JFrame frmJavaDoc; /** * Loads up .jar files and classes defined in it for completion lookup @@ -398,7 +399,7 @@ public void run() { protected TreeMap jdocMap; protected void loadJavaDoc() { - + jdocMap = new TreeMap(); // presently loading only p5 reference for PApplet Thread t = new Thread(new Runnable() { @@ -763,7 +764,7 @@ protected void trimCandidates(String newWord){ newWord = newWord.toLowerCase(); for (CompletionCandidate comp : candidates) { if(comp.toString().toLowerCase().startsWith(newWord)){ - log("Adding " + comp); + // log("Adding " + comp); newCandidate.add(comp); } } @@ -1309,37 +1310,44 @@ public ClassMember definedIn3rdPartyClass(ClassMember tehClass,String memberName public void updateJavaDoc(final CompletionCandidate candidate) { //TODO: Work on this later. - return; - /*String methodmatch = candidate.toString(); + return; + /* String methodmatch = candidate.toString(); if (methodmatch.indexOf('(') != -1) { methodmatch = methodmatch.substring(0, methodmatch.indexOf('(')); } //log("jdoc match " + methodmatch); + String temp = " "; for (final String key : jdocMap.keySet()) { if (key.startsWith(methodmatch) && key.length() > 3) { log("Matched jdoc " + key); - - //visitRecur((ASTNode) compilationUnit.types().get(0), codeTree); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - - log("Class: " + candidate.getDefiningClass()); - if (candidate.getDefiningClass().equals("processing.core.PApplet")) { - javadocPane.setText(jdocMap.get(key)); - //jdocWindow.setVisible(true); - //editor.textArea().requestFocus() - } else - javadocPane.setText(""); - javadocPane.setCaretPosition(0); + if (candidate.getWrappedObject() != null) { + String definingClass = ""; + if (candidate.getWrappedObject() instanceof Field) + definingClass = ((Field) candidate.getWrappedObject()) + .getDeclaringClass().getName(); + else if (candidate.getWrappedObject() instanceof Method) + definingClass = ((Method) candidate.getWrappedObject()) + .getDeclaringClass().getName(); + if (definingClass.equals("processing.core.PApplet")) { + temp = (jdocMap.get(key)); + break; } - }); - break; + } } - }*/ - //jdocWindow.setVisible(false); - + } + + final String jdocString = temp; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + javadocPane.setText(jdocString); + scrollPane.getVerticalScrollBar().setValue(0); + //frmJavaDoc.setVisible(!jdocString.equals(" ")); + editor.toFront(); + editor.ta.requestFocus(); + } + }); +*/ } @SuppressWarnings("unchecked") @@ -3271,7 +3279,7 @@ else if (className.endsWith("Type")) } public void jdocWindowVisible(boolean visible) { - jdocWindow.setVisible(visible); + // frmJavaDoc.setVisible(visible); } public static String readFile(String path) { diff --git a/src/processing/mode/experimental/CompletionCandidate.java b/src/processing/mode/experimental/CompletionCandidate.java index bc29737..ef29d59 100644 --- a/src/processing/mode/experimental/CompletionCandidate.java +++ b/src/processing/mode/experimental/CompletionCandidate.java @@ -18,6 +18,8 @@ public class CompletionCandidate implements Comparable{ private String label; // the toString value private String completionString; + + private Object wrappedObject; private int type; @@ -48,8 +50,13 @@ public CompletionCandidate(Method method) { this.label = label.toString(); this.completionString = cstr.toString(); type = PREDEF_METHOD; + wrappedObject = method; } + public Object getWrappedObject() { + return wrappedObject; + } + public CompletionCandidate(SingleVariableDeclaration svd) { completionString = svd.getName().toString(); elementName = svd.getName().toString(); @@ -110,6 +117,7 @@ public CompletionCandidate(Field f) { label = f.getName() + " : " + f.getType().getSimpleName() + " - " + f.getDeclaringClass().getSimpleName(); completionString = elementName; + wrappedObject = f; } public CompletionCandidate(String name, String labelStr, String completionStr, int type) { From 1a9cd133160cedbbb634a4e66812d024db4eb0d9 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 25 Aug 2013 18:36:37 +0530 Subject: [PATCH 025/193] adding option for disabling completions, fixes #10 --- .../mode/experimental/ASTGenerator.java | 4 ++++ .../mode/experimental/DebugEditor.java | 16 ++++++++++++++++ src/processing/mode/experimental/TextArea.java | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index d20b6fc..ba6e330 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.Stack; import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; import javax.swing.BorderFactory; @@ -154,6 +155,7 @@ public ASTGenerator(ErrorCheckerService ecs) { setupGUI(); //addCompletionPopupListner(); addListeners(); loadJavaDoc(); + predictionsEnabled = new AtomicBoolean(true); } protected void setupGUI(){ @@ -776,8 +778,10 @@ protected void trimCandidates(String newWord){ */ protected ArrayList candidates; protected String lastPredictedWord = " "; + protected AtomicBoolean predictionsEnabled; public void preparePredictions(final String word, final int line, final int lineStartNonWSOffset) { + if(!predictionsEnabled.get()) return; // This method is called from TextArea.fetchPhrase, which is called via a SwingWorker instance // in TextArea.processKeyEvent if(caretWithinLineComment()){ diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 34e02d5..6506b6e 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -166,6 +166,11 @@ public class DebugEditor extends JavaEditor implements ActionListener { */ protected JCheckBoxMenuItem writeErrorLog; + /** + * Enable/Disable code completion + */ + protected JCheckBoxMenuItem completionsEnabled; + public DebugEditor(Base base, String path, EditorState state, Mode mode) { super(base, path, state, mode); @@ -521,6 +526,17 @@ public void actionPerformed(ActionEvent e) { }); debugMenu.add(showWarnings); + completionsEnabled = new JCheckBoxMenuItem("Code Completion Enabled"); + completionsEnabled.setSelected(true); + completionsEnabled.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + errorCheckerService.getASTGenerator().predictionsEnabled + .set(((JCheckBoxMenuItem) e.getSource()).isSelected()); + } + }); + debugMenu.add(completionsEnabled); + debugMessagesEnabled = new JCheckBoxMenuItem("Show Debug Messages"); debugMessagesEnabled.setSelected(ExperimentalMode.DEBUG); debugMessagesEnabled.addActionListener(new ActionListener() { diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 4468951..0d54ecd 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -179,7 +179,7 @@ public void processKeyEvent(KeyEvent evt) { } super.processKeyEvent(evt); - if (evt.getID() == KeyEvent.KEY_TYPED) { + if (evt.getID() == KeyEvent.KEY_TYPED && editor.errorCheckerService.getASTGenerator().predictionsEnabled.get()) { final KeyEvent evt2 = evt; SwingWorker worker = new SwingWorker() { protected Object doInBackground() throws Exception { From cb3b8aac6379b82110d09f7eb5b6171a2b6fa62a Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 25 Aug 2013 18:38:09 +0530 Subject: [PATCH 026/193] thread sync bug fix, again. '-_- --- .../mode/experimental/ErrorBar.java | 47 ++++++++++--------- .../experimental/ErrorCheckerService.java | 26 +++++----- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/processing/mode/experimental/ErrorBar.java b/src/processing/mode/experimental/ErrorBar.java index 375201e..974f3ab 100755 --- a/src/processing/mode/experimental/ErrorBar.java +++ b/src/processing/mode/experimental/ErrorBar.java @@ -164,29 +164,30 @@ protected Object doInBackground() throws Exception { e.printStackTrace(); } // System.out.println("Total lines: " + totalLines); - - errorPointsOld.clear(); - for (ErrorMarker marker : errorPoints) { - errorPointsOld.add(marker); - } - errorPoints.clear(); - - // Each problem.getSourceLine() will have an extra line added - // because of - // class declaration in the beginning as well as default imports - synchronized (problems) { - for (Problem problem : problems) { - if (problem.getTabIndex() == currentTab) { - // Ratio of error line to total lines - float y = (problem.getLineNumber() - errorCheckerService.defaultImportsOffset) - / ((float) totalLines); - // Ratio multiplied by height of the error bar - y *= fheight - 15; // -15 is just a vertical offset - errorPoints - .add(new ErrorMarker(problem, (int) y, - problem.isError() ? ErrorMarker.Error - : ErrorMarker.Warning)); - // System.out.println("Y: " + y); + synchronized (errorPoints) { + errorPointsOld.clear(); + for (ErrorMarker marker : errorPoints) { + errorPointsOld.add(marker); + } + errorPoints.clear(); + + // Each problem.getSourceLine() will have an extra line added + // because of + // class declaration in the beginning as well as default imports + synchronized (problems) { + for (Problem problem : problems) { + if (problem.getTabIndex() == currentTab) { + // Ratio of error line to total lines + float y = (problem.getLineNumber() - errorCheckerService.defaultImportsOffset) + / ((float) totalLines); + // Ratio multiplied by height of the error bar + y *= fheight - 15; // -15 is just a vertical offset + errorPoints + .add(new ErrorMarker(problem, (int) y, + problem.isError() ? ErrorMarker.Error + : ErrorMarker.Warning)); + // System.out.println("Y: " + y); + } } } } diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index b41a1d4..491ae15 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -831,19 +831,21 @@ public void updatePaintedThingys() { public void updateEditorStatus() { // editor.statusNotice("Position: " + // editor.getTextArea().getCaretLine()); - for (ErrorMarker emarker : editor.errorBar.errorPoints) { - if (emarker.getProblem().getLineNumber() == editor.getTextArea() - .getCaretLine() + 1) { - if (emarker.getType() == ErrorMarker.Warning) { - editor.statusNotice(emarker.getProblem().getMessage()); - //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); - //TODO: this is temporary - } - else { - editor.statusError(emarker.getProblem().getMessage()); - //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); + synchronized (editor.errorBar.errorPoints) { + for (ErrorMarker emarker : editor.errorBar.errorPoints) { + if (emarker.getProblem().getLineNumber() == editor.getTextArea() + .getCaretLine() + 1) { + if (emarker.getType() == ErrorMarker.Warning) { + editor.statusNotice(emarker.getProblem().getMessage()); + //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); + //TODO: this is temporary + } + else { + editor.statusError(emarker.getProblem().getMessage()); + //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); + } + return; } - return; } } if (editor.ta.getCaretLine() != lastCaretLine) { From 7b3bc66aac7adc00dddab08b9abac8e7d14c2454 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 25 Aug 2013 20:09:17 +0530 Subject: [PATCH 027/193] attempting something crazy. --- .../mode/experimental/DebugEditor.java | 32 +++++++++-- .../mode/experimental/DebugToolbar.java | 54 +++++++++++++++++- .../mode/experimental/Debugger.java | 28 +++++---- theme/buttons-2x.png | Bin 11521 -> 8418 bytes theme/buttons.png | Bin 6652 -> 5322 bytes 5 files changed, 99 insertions(+), 15 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 6506b6e..fc3d8ee 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -373,7 +373,7 @@ private void writeErrorsToFile(){ * * @return the sketch menu */ - @Override + /*@Override public JMenu buildSketchMenu() { JMenuItem runItem = Toolkit.newJMenuItemShift(DebugToolbar.getTitle(DebugToolbar.RUN, false), KeyEvent.VK_R); runItem.addActionListener(new ActionListener() { @@ -399,6 +399,19 @@ public void actionPerformed(ActionEvent e) { } }); return buildSketchMenu(new JMenuItem[]{runItem, presentItem, stopItem}); + }*/ + + boolean debugToolbarShown = false; + protected EditorToolbar javaToolbar, debugToolbar; + protected void switchToolbars(){ + if(debugToolbarShown){ + // switch to java + } + else{ + // switch to debug + if(debugToolbar == null) + debugToolbar = new DebugToolbar(this, getBase()); + } } /** @@ -410,7 +423,16 @@ public void actionPerformed(ActionEvent e) { protected JMenu buildDebugMenu() { debugMenu = new JMenu("Debug"); - debugMenuItem = Toolkit.newJMenuItem("Debug", KeyEvent.VK_R); + JCheckBoxMenuItem toggleDebugger = new JCheckBoxMenuItem("Show Debug Toolbar"); + toggleDebugger.setSelected(false); + toggleDebugger.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + + } + }); + debugMenu.add(toggleDebugger); + debugMenuItem = Toolkit.newJMenuItemAlt("Debug", KeyEvent.VK_R); debugMenuItem.addActionListener(this); continueMenuItem = Toolkit.newJMenuItem("Continue", KeyEvent.VK_U); continueMenuItem.addActionListener(this); @@ -921,7 +943,9 @@ public VariableInspector variableInspector() { } public DebugToolbar toolbar() { + if(toolbar instanceof DebugToolbar) return (DebugToolbar) toolbar; + return null; } /** @@ -1191,10 +1215,10 @@ public Document currentDocument() { * * @return the toolbar */ - @Override + /*@Override public EditorToolbar createToolbar() { return new DebugToolbar(this, base); - } + }*/ /** * Event Handler for double clicking in the left hand gutter area. diff --git a/src/processing/mode/experimental/DebugToolbar.java b/src/processing/mode/experimental/DebugToolbar.java index 3738b9d..67af287 100755 --- a/src/processing/mode/experimental/DebugToolbar.java +++ b/src/processing/mode/experimental/DebugToolbar.java @@ -17,12 +17,16 @@ */ package processing.mode.experimental; +import java.awt.Graphics; import java.awt.Image; import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; import java.util.logging.Level; import java.util.logging.Logger; import processing.app.Base; import processing.app.Editor; +import processing.app.Preferences; +import processing.app.Toolkit; import processing.mode.java.JavaToolbar; /** @@ -64,7 +68,55 @@ public class DebugToolbar extends JavaToolbar { public DebugToolbar(Editor editor, Base base) { super(editor, base); } - + public Image[][] loadImages() { + int res = Toolkit.highResDisplay() ? 2 : 1; + + String suffix = null; + Image allButtons = null; + // Some modes may not have a 2x version. If a mode doesn't have a 1x + // version, this will cause an error... they should always have 1x. + if (res == 2) { + suffix = "-2x.png"; + allButtons = mode.loadImage("theme/buttons-debug" + suffix); + if (allButtons == null) { + res = 1; // take him down a notch + } + } + if (res == 1) { + suffix = ".png"; + allButtons = mode.loadImage("theme/buttons-debug" + suffix); + if (allButtons == null) { + // use the old (pre-2.0b9) file name + suffix = ".gif"; + allButtons = mode.loadImage("theme/buttons-debug" + suffix); + } + } + /** Width of each toolbar button. */ + final int BUTTON_WIDTH = 27; + /** Height of each toolbar button. */ +// static final int BUTTON_HEIGHT = 32; + /** The amount of space between groups of buttons on the toolbar. */ + final int BUTTON_GAP = 5; + /** Size (both width and height) of the buttons in the source image. */ + final int BUTTON_IMAGE_SIZE = 33; + int count = allButtons.getWidth(this) / BUTTON_WIDTH*res; + final int GRID_SIZE = 32; + Image[][] buttonImages = new Image[count][3]; + + for (int i = 0; i < count; i++) { + for (int state = 0; state < 3; state++) { + Image image = new BufferedImage(BUTTON_WIDTH*res, GRID_SIZE*res, BufferedImage.TYPE_INT_ARGB); + Graphics g = image.getGraphics(); + g.drawImage(allButtons, + -(i*BUTTON_IMAGE_SIZE*res) - 3, + (state-2)*BUTTON_IMAGE_SIZE*res, null); + g.dispose(); + buttonImages[i][state] = image; + } + } + + return buttonImages; + } /** * Initialize buttons. Loads images and adds the buttons to the toolbar. diff --git a/src/processing/mode/experimental/Debugger.java b/src/processing/mode/experimental/Debugger.java index 758f6cf..50b5d98 100755 --- a/src/processing/mode/experimental/Debugger.java +++ b/src/processing/mode/experimental/Debugger.java @@ -168,7 +168,7 @@ public synchronized void startDebug() { // load edits into sketch obj, etc... editor.prepareRun(); - + if(editor.toolbar() != null) editor.toolbar().activate(DebugToolbar.DEBUG); // after prepareRun, since this removes highlights try { @@ -236,9 +236,11 @@ public synchronized void stopDebug() { } stopTrackingLineChanges(); started = false; - editor.toolbar().deactivate(DebugToolbar.DEBUG); - editor.toolbar().deactivate(DebugToolbar.CONTINUE); - editor.toolbar().deactivate(DebugToolbar.STEP); + if(editor.toolbar() != null){ + editor.toolbar().deactivate(DebugToolbar.DEBUG); + editor.toolbar().deactivate(DebugToolbar.CONTINUE); + editor.toolbar().deactivate(DebugToolbar.STEP); + } editor.statusEmpty(); } @@ -246,7 +248,8 @@ public synchronized void stopDebug() { * Resume paused debugging session. Resumes VM. */ public synchronized void continueDebug() { - editor.toolbar().activate(DebugToolbar.CONTINUE); + if(editor.toolbar() != null) + editor.toolbar().activate(DebugToolbar.CONTINUE); editor.variableInspector().lock(); //editor.clearSelection(); //clearHighlight(); @@ -271,7 +274,8 @@ protected void step(int stepDepth) { startDebug(); } else if (isPaused()) { editor.variableInspector().lock(); - editor.toolbar().activate(DebugToolbar.STEP); + if(editor.toolbar() != null) + editor.toolbar().activate(DebugToolbar.STEP); // use global to mark that there is a step request pending requestedStep = runtime.vm().eventRequestManager().createStepRequest(currentThread, StepRequest.STEP_LINE, stepDepth); @@ -588,8 +592,10 @@ public synchronized void vmEvent(EventSet es) { @Override public void run() { editor.setCurrentLine(newCurrentLine); - editor.toolbar().deactivate(DebugToolbar.STEP); - editor.toolbar().deactivate(DebugToolbar.CONTINUE); + if(editor.toolbar() != null){ + editor.toolbar().deactivate(DebugToolbar.STEP); + editor.toolbar().deactivate(DebugToolbar.CONTINUE); + } } }); @@ -616,8 +622,10 @@ public void run() { @Override public void run() { editor.setCurrentLine(newCurrentLine); - editor.toolbar().deactivate(DebugToolbar.STEP); - editor.toolbar().deactivate(DebugToolbar.CONTINUE); + if(editor.toolbar() != null){ + editor.toolbar().deactivate(DebugToolbar.STEP); + editor.toolbar().deactivate(DebugToolbar.CONTINUE); + } } }); diff --git a/theme/buttons-2x.png b/theme/buttons-2x.png index a63d28a67a340752122b0888a1dec539b35452a9..e82e968fc264b1fabad4c1ede9f68b44220ab1d4 100644 GIT binary patch delta 5754 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 G5b|GOkd4v+ delta 8882 zcmcJUc|26_`~RnSH$+CMR2YPitYzO#VYE%9#ZDz8`;r;PAv6-wP}!GEVPX`rWv66k zvhO=X_F*jHcZS}d&-?TFe82DCT;D8ZK+bija zhu0+iXSFmBGQP;pKgMyN7{a-Hvcuz`Sw{`A+`lR#%bLN25r25t*o=wa;N8QiGr`%+ z##v6Eq{>l&)r{N+?fm!7YV{qQtu*-SJ&{RD}sC*KWjDFmFbsNGLR;I9T!NPpW|=Rh$^{y zhbaP^4n7X?C2!y+atPV@MqQ;TipQK@p#;Tn=|G>71y97X_6IrSk(0!eMYwtXW^dIT z3Wp_6f2IAhTn^^@S45|+hD7Fl7OWFc#sFVjLbY!!vY$qohEanE9KKiPY>^3ihH|}( zPTUd8izPim7ZTHhJm8O@dPdljHxs$3}dH#7*FhQQf zOhi~R(m@WWKFs0CM!b6plgiz2AbWyejmliNxfhnE0?}x4imP6VCihl!h5W#Khf%ew zu)}<3VJ;UX(LFU&V@(SmvpH4nkMF5yuaM|q5iT*6=quR!=?qiD@JN0!->;PVja%GQ7vz?yZ=A-=JIcPv&%>@`h!W359MuI{1v zG5{)rdte?+9N%fnbKeBSO0@4dvxbK!;a?UEc_lg8Ow4Rn-7clbXra$1-wrUCxa5+~ z|GirCCO5OJUIAupDP4uJ*IN!AEm!v*4$dDP`0`ESvPP*-r-ieOzRdM5AU)URjRsne zZ7wcEWXKwPdUDj|w>SjHO1hm>- zRa=<(27XRu&%o9dWemz76Wvd`p(^M>bhBu6zg>)ROv7z@dtl-PjuPNrnD0eqtBYM} zvm579vg{&RTg}QGQy=v--Wo^2!(BTqac-)Hj$f=zWw#cqpJP@UT#~M@42?%(hkx>A zy1?j={S({6;;CA6-BPB2Ew zyWX>5x!d-(0#P_+U;K0lQ=@As=#77tB5v2x;Oqb6xIOkebg%Eo;HEFGP z>n%lvGey5@-o~3apZFZT*xPQJ$5~UY?-QL+n>ceBBjs}(_G}{X8f*=ImX)dFWo?pb zY{WxC)(q2F61&Azir77dI2mitCHNtW z3O`@PyAP%;mKP^P9d1Tt3>A-K0-{;=xg#ulY`>urT!C&kY5h{J@R%MOOczX~o|Ji^!uXZAcFy?0il*#1HD$|==jWx=>Amt@Rs7>`5D#GOiw zRKZIpl(%yQBDkE5v(r&Yg$BWnRE=+w$blK(ijio4uJ|}bKv{S2o`A+o&Pv$sLW;te zC$z7@hEzO!6(gEg3R`ee1s!i5b-2l8)F&B-Q^nr!gfe_xfl5vl-by-oUV7F0U1YW& zqncLHt&Gn&#((S|`5+9_#2!9O>d(6G_d8s4v0LD}sPZa{yWbH$l^E#xEswLZT2%}% z704?#fIX9@@R#?BoP{4!AG6DS8igouQMX`RsqQ%NhOZskZOn;Sj>+|13?)Dp=hfyG zdJD=dhBaO4)fR^N-qNkgGq7{zy{ceU4z5`1U3Ikd1b++8LIei6h8PR`BqP%^_L>$% z0DXty;S0euxeto%?0H3TJm;yOfVWwuF-8g#Zpolq&&V*{D*B8Iv@1=I0Cka*PI=&XT%AAOScm-- zAo#Vzy<%;v9Z>I81O>%ld+1-oNyTGsu0Dy;5f%>GaRgxlPqG@^!0b9>g8>@$i)Vc= z`Jw@uDSz{k$~n8&msM5Nmzvnk3ZJwyZ0?1mKdlLK#V!xaB2xt8q^35e$B!YNFwk8; z0Q&w~D9~Gdr`Ri_FEpZ?QJ&KU&RMN2*6l3FISFtYDu=+4rm%U_@9W26{$a? za=!Bo8g|*}8tfoF?n<3wQ~EWVMVJsQw*MKc_Apd@pF2n(SwyW5Z-lpU(-~%Fr?Q9@ zB%DX&EXP&vjiM7Wm&7wox4h<;eE{4_uvPG2=m)xkZGeZJEO#V<~pWU>8u`+7P~h}V32)M>{JZTQi<@k`^mL(=JC^t@U1 zT3e;}#`#s8vpXq|za1d~uP}vrFx_K>&xa-8uxb$;r%`(39V+}jAohLsA$4Dn?f%k6 z0<1zwWIE)Q-Stz%J|fdxQr`kK8{Q32pXvKL2QG&_hwc^Hvlr$ebwZ??yJa#2446j+ zdFhI z7wtE8H^(!G(1{zeSBQT67x3Oi^8aTozz*U6OLu(Y(4Jo-M4~ZGUW^h+SR0?PLEgZ# z$!=pWlHU^!AZ_up$ig4LdO4L8Me3XzKJ(OOofAkRp0& zFpVe44m4+Qv}zi>=2B#=B@&-_2D0yM=s?7%U3+cm2>a63(>%q`3G>a|^La6msR*kw z$gd2uG?=YJq$);m3T|E?d%`6n9_B8aX3wyE>*34y1BgV4J73%iDxt{3u;WzZI^(hr z6f!9eRdsOCCfnjA_I0iZ3JY$20j(P=V$&D)BbALv#9SfcEDcD)+~^((!`Ue4J#6sq z9>%&!xCz{8kF+)G zJ#;--|4Xn3x!wirEBYDF>6ikGaTUQ%d2EGaX&FKW25ELNo>(Y)e=g6_9T>?W@Cp_m zbV^Y8USGNPPORU3v1{z2M`srcTxJPkVQcYbI)Gy!a~pxD*4In!oAJebS4WvPPa-ea z8b?qw2xCkeGSi7fqC;JlalDZNrVgF+MYiiK2N?NCoU@4jV zo^HKzD)FJxeMjs4QY^58E0+C;AGcZ&{@^yLV!bhk_1bK)7SgC?xyaf0FsCu<=9P2R zt0_JkWqaWBK2Q~Z=FyGy$0IL~m zM?9Ws^Dc)-5Rp#bAiJ}Tr4#<(RraQhND8*CSAMWM$7SDGt>sd03(uo8XbSSO+`QR9 zA{m=3tyR&i-blKwu&2#DrlMYtMNiBqwIP5fDTbWUxl2>!@8ByNLlkuAoiNNig@4I= zsLm>-aPCKJZLWn33fNPblx3%E6oo)vB3r!SX?GJxo(}pHEJ>Y~-&Sr-ZTlO<|69Tb zb`gJIdtBY?g<*rI`?#CuORsupYTO!YcRvBj5J_!*5E_~ClJhLwt6^hWfoz`p)TE=X z4ox7-UfMS)*`?soJx6tG&AqH_WPo#SUnWc!zTTfk;(c)^WXqenJ?HJ!M@#*0DIfSx z%&-5YRSL8XJYg>IuUVKn`en1}p>iHi5;d3IzJ>AmLh8*v#?ZF~yzBNqqEza$mx?_c z!oK=2Y=9j7<9JT74UAcOjDLvxlWBWpsrTXyp4HOrnF|NzWIJp#558LX{(QO+EBd6> zenKuszA6|2yt6H9tO=PuhbwMutL3g0r461dY+I{hdNrl9H03Qg5e_b~P|CFrqD^)) z^rgAEpJz0PE|y1d{?qY9QzK8^-`EfBKv7ncTE1W=SLbWqLokO= zGl$zWmf9uuhK)p9j_~nQt|g+1?fPSjNXY!5t|&UM%k6EwVhdvib~o8#n4`VE0 z2zxfZlRiMs!(L&JNBzXGr8R*gDVn&K@|A76ijkFr7VIGT^o8fGB6`*izz^LcBc2po zd!QodUEA~Mz*(I0gm(qg&lj0o5}N6-oB|2(?Pwh`1KJ~j=Fw<8D7BEN_#nZUK z2^yz*{*mVo_@TSqh^m5XpqIzgDn~$lQj?s&-#H#N<6P%?f&5%TSv=_EH_wvu%!obBv~Vmm^Bc(cN+74Z9KfIV&Ss4{laQ~zT&cN9xqE$!UKh|e(A9H&*y z&iS?aeZakT;T5N`n5iX93h&bR>-MCgp~a+wX#FYevKb6>#6hoKrlJ|nkX(9FQv*sd z1=m^;9x#acnM+Rz7ZZQ!kxh^~Uw%s6P0a71drJUB(M{;eL9(VTOs(QxNWR?6pU4?-_ zK3K>InwS-PTqcVmg@f0(3KhSF4MJcZpm0~=zo-e_*8vnHW220MaDAoLIBNGR1|Glx zK~BNLPq=P^%2M<5<><$tuhdR$sd-lM@5&McF_Kt0Cvg#^f$49Jl;rWwyXNiSxaw}+ zR9y&3K2v87ClY0*`G>bI(VpEIsBMxoG1&UK_^!Nz0p5L<)Z%aJ91WOn#9a5!RA0gmZ56C233&r=e_Ub0sNqw(PJgB%R5_rA z=?^P#&tZQEv(f+-6~QG4M0LUkXV?3h>ORaeo-uyRUbwsTIMmXhKa}T`u+}>;Cw}o8 z(wQQ7@oT7^pibNTh7*e7&+V}0re&vP>ZiIG>( zgjzHc=aJe{xsUgBgShGqw(Gs)-nF=i86pwDqyNf7zHUed-Su04O#zy1^r0gu1sVP| z&tOepv;NH^4Sp?Z+6jrExCddZ4LxIf&T1l^aCVWlKkLhhV&CEDip;Y%{d7ode=^F( zn+Sf7KWJf^X31AkbS~{5E_~GNt?;&mOW>#w@K?<_nbtVIN|efEJ7xB!{rzPv39g)` zb>?yYAw|nB;p-h*X45+=D=Tg2f6Mtb;OlKkGv@r~FU9(0Lj@*YS|)tdXTcJ8gzH0e ztWRWsq96eM>R)7b-7|`) zq#$`rVTd#OUevQ9vp*-vdZGh4lqtI9m6+mWNQUA21M{zP-ygRC9co@&I?4EJWuxhQ zSQM1Wh~Xn)L_@l3Air+`U zTv#Sv-!uLWO8!+_khvb{l6U23z{NRT{Oio3F;)F>*R7u8Z(m4kKI(PI-7XL_aX??S z&3W3b=|^IdtCr*OP&ZIu!X}xR6zGZHzy1$_g8l3zlYDApa*Li%1m|ms*qix(ps|i` z6~C$f(F;J?=!`tbe~E9Pqm=7K`sxXb8tF?{p6Y3jKV1r_co&yP<1pKNU&l0dFvRr8 zgSfK|pPurGL6ao1K8W2;3#gw;vdMllH5B7e3X@(ulmnmSWLMsK{Pf0)Huu>>B3EmM zin9+2aodH;GRAS&i^u-xtxz=CPKf#B8r7@-|_kjI4hs$!prQ{etBCZ zJqfgR8e%_41zMJ=-bZ9m5`{nK#|BD16a=_@+V9=6?k=!;CudmRxhG~hED{uDA_cTn zM<1vAS(aMhQOMLw$R5RrZ2Zw*fgZQ7^I-m!it!J?Y5@st3P_}6<8pvo!A$2zuZ zhjGzpw+^!sDk)xdE#dF=?th12U{~+{n*8R#kqgrMk1tQUrwVSam2M4gaJ3a#S?%b& zUOwGXO}p|W5@t6Zh(3Xq9x3nW^9vO?@W8gyt+*&w=d?-XeV;9Sh+oR)6*C>Xo}BDg zZX#ADR|`QEJ#1=yA+T+7j`!k%%0t=dg1#bqN&Jg0$g*+_pxF~cHHWys4>cT|Hc@qT z#os$XJ7H!)b^)F>E;XqpkBK>;drT!PoQn#-+HYrf(Ga5gecA#bR&TUgewKml$MM}VeM3X_2}Dqac_VPQoM=d|Fz=%W$pGmm2pVV z^C5vMXIsE>gsono6b_0K_c9$%^zIB^ac=+4<3HL>M zkwT84b^5{YB87*piaZf4QY_@6LuFY(b|!pUa!}SP;IEdg+kb=@^OZ>lc0V|t+6Na= z`48^>6MF$i`@_rZjeeYw2xhxXE-X{HC$`4j#Oeo_i^w8Nox6q

+E5w0Kk+*jcb*Pwj&R6ZTy074C3jU^>%@Q@s(dQ;qASx-Vm7Ey?^IMgJH_-d>Bqs%i#_&q5yCF3&vsl)Alt+qovDjy zu}ryet;)k8JNn)Mr@Edl&GWos_;xSV3rY{{hkCoGYTMf3CvyR8u%RPqN9exX6P1dS zOCm2_IQtK?UwYM~H*5am zrf4H%pezlnz8!&7fNS`^u3{Vvj$#z+4p@+G@2>m%8LSKp?qZJ|&r8ZeMsPs5T(&gg9#|_SzFw-y2i6e7% zx?s#j_yHtdx$2{sPyJ`O{Y#{p#AB0>%B11mXQbko=t9`B6Hp%S#|C5&>a;%J#nL9?$m9NOZTirSfe|j0z+`f)(yi%4D zpfDg)LOj;5ljj68bb5t%L(UMTwbl;+BXt=<9tP!poFzfQBJ)^d=QGCd+%*$%qK75A zx^B(p(fQ2|=^$KU-v2Ok$o=i+?=TKA|CkR-MWguy`6Juyjc*$A>{&SVcIRFBV(6$a ze7@NQ234J%&m~+&s_Pa`qI;AVP{}o8ytR$u+&edd^?wK}TY^ADxG`A#ugEB0`K(=M zdWOsW`A&Jj<5+p%;hk=h_P!ImyrV|`Dt_{lr0wuH|Gi2(s`8)E0Nwiz8fs1b7I*>4 zf@jP7wF$-F66|Z9EY4OeInBBYE)YnukalA1{aa*dHqCY#J_LcrN;lh#r(}SFQn(eHL>}Bv&w1X@`_Jb*=e(cuJfG*~p6fn?h_kXZf(T0s zgFqmNiLt&l|L)`;tPq%ATTB5^1tLcnIQYp#A7lIH_$t-oI-Gfo*?hztntF0ja7I^3 z=!$W&fi4S?FD(^Bdsk@r6;)tWe`h!&UvMTn2#HoNb$wWP=1A_w>}CP<*@HWyNEi<6c`yB=U5NQ#PTmfl=$`Q{I zWw2G*R&c6QU|Web2je850-mPm(LWrZ2&(uw!CsB8Q5BUQJQz~AEaN(s956quWq9G| z19JP&1r?i`;Ax@A2oPWgs=e^*#e?d}y~+jSg0rC@N%Fec!IlG{h>6w~^C(D6+x5p+ z(I;FoL2HL1hsaZxqaduMvq?A7%IxOTx)p!>>{Y&C`CJ{z4*BCuJcl*N02hIt3yw>Sj;F<)y*_Y^G~3-@ zRkkOP5uja&-Kr=Jvr8HGjHE%j&Gt3J@}=$og?-P^SMg%YXQ>6l<*WB{OGDV)*NAXO zK!{PKV}CQV9R$$iYl23Jc==2TBF@Tv<8EIur_wDp|K=kkUPF?EjvB|cV@01zS6Z!f zcDNW30>6s0nznPEZ$}!+2*P)R?N`$N(Nnr;M3Kw?2scakYw>In|JkTb=gB?S(emNZ zk>IXx3|dM%-bxwKAwlJ1IPW}G0%^RRB3&OhBM9*B?R@ys`P99=GPcBhPhmDUp%KIO zX8p2SU-eg0-TtZ8oC}o9#>4Vf4mB}Un^_IqpYilc<(f&={<%Px+?L_AqBSn#nx}J_ zms5vb8E|+oGi@+RHc`&N3mUYzX_2hLvb&tqGZ$I7fQc+l0oc?dyxW#5uNCgqEki!S z2!LCqMJk$;7~uM6yo)CI*H`*pd-%q!ZVwgBO_KpN)7nXw#0ce*PlMQ4h6G8@7gbh$ zOzp~etg5{&&3rCUL+bMst6si3|CRq~8BxayCnswyL%+rp0fPRasYQh;;#ZV0Yy?q1 z!|j@c#2^SaTweg-zvXjp zRJRT{-0AF3Jr+(~C9P2mSKNhmkA<&~@%{7mVur7bXz<#^q_mX>CSWVOmKZ8Y{g7i8 z1wmq0ufQoq74^CK8@sG|PV5_SDuU=v2CXR~kV9=JkTYu}zZfgnzhm`eOuwljpsXyI z_JK=??=#^O8q98dIR;2-L!l=`FPOM!o>G$8?h3h!?^@U}hhK_ax9&cFA`?xvf@xFG zof3>dyAm$W03Q-SuOLt6ym!PKw|$tlh83H`Z4?};v0_)Q#oWAZOO=H({4$hgdS{VUM%4(;@!KCyI`+K%XvFd@18h-B zGaahRbnR$H*72oLYIlcfju6*7)*8;s)GXm7S8F^iBc@vqI$$H3c&B}7Jjp%Uo}f-x znC@#IXEXRvt99q^97?&9F~g@p++ao5WIPZhOc1CZBQvc4OIoG1-}F|1TPtI!*?ae1 znGeGz18t}-QojlJ%8%_18kX^sOE2L=uWW9&p9J~T>HG%aR|QGRqoREaSS_aSY|P`i z;yUOxf%o(U|HomFo|Ck&-Ku0j{Uexk rd=+;g+;io40#R>E|4e9@JlITnapgQD0 zV>=v~BHy5seIy*{JSXF8_NF2^=zJ-XNpIfJd6p#8JRaT};J$rSv-C&T<;bTzH}L^_?WmdaVQSEsM^7a)swo0GI}GHDTnWXb;n`F zRsq|EXST~wCX#`D(J5mhZUoq_C-i-^C<=&|WNOuI?QE~-Y4K^6Uof0G6fyAa*Bz?7 zhGNYShoM!C)XH$-m9vsw#`kNu>^Xv4mJMGEs)m8dq4F}ShQCWPrF!iAvNHb91)4Qo z>hf-p)F+B|6rHh$0x~gKSfao4!Tp$02%uS&W^F^{P3HK|U2fGiAwj4o$Dbl4$-7S! zzam?~?{my5AgBx56g2rN6qShRIMKP*UK^7d?(buE8;JP&0 zYf&c4G1$4qRq|p^S`t}A{?9#^83*Ay;o@6UA!S$otHdrHnb7Dq198pKsfO=iz;o}l z?I#Nlrzv_ZNV&z7vsL-JF{iJ~YVGv|sg#bCD{!8T=!h)!n%-!YG}k;5Q~ghQLd9nA`%+1-qyvx`_!Y)^&7SkrCRI!LhVfQ3 zY;TDWuN~r8q{xCYi7GVS~7cO$6cj?`^QMXftWfWR=Vd^BWhI7|11>&Z~w8ezRJ>^7ye*b0u(G!*Z(=K|( qC{GSdPvFODKK^|@kIwEL097n@{rtGazm5Mr1eq9E>eKW*qy7UIBneLd delta 3974 zcmbW)c|4TuzX$N~$S9`aM9iQpAri(QQmSdP%#bbHSjRTDEJKp58^b6|7(@25lk5>OxY4;34{=Q-zf&Oi5c|8c#p`+j||>v~_Gt4DT6S^Tb% zfzDwrAubRIbQq(1#RLRm!?NC;4uV*ykL3H<8X`oiF9| z`GkxH!+p7sQBTynB=FWQy43pzOYy7;auTO zATa1U$ddC7sETWfE4=UBk&;aRd}lFqKkP}a8E<1c-=u62n?9R*zVY&ra4it`Jx=W) z*yk(c^V_W!yDc%*;Fh)Sskl5Lu(WnP=d07RMD7~0~x?RR8$UUtZ;tyjH98zNdAO~MWy0+zqeKB+NA^GjUWSIJ9{iSd5rp2 ztFK-Qd5a(ud1Ho`FVWPtv0m5-9q8vGb6F%*h= zC{nG`%h0c|=rb{!FRZ1&m@gJvUZ2_i*3-!OwWS?R0mB4`t}WTHLp{N*4Iy`1b-hk~ z>v|>+QBEfsDxvL|k6mPO=`PurfzyH3u2hUa^{8zUb56|s!UXAVSe@@&J)jD?@b&fc zLAgi`EF;xd-HG?DW{Uc)Q+19Mnj0N+*5QrPLn>`brMVSQ=mL(Gg&ykfze$`JHvHO{9WK9Kx7FSPXcza~y-ICRfq<=~H-06{i~-M8?Jl-1odx9bZG#_p<>E?l^Qw3T9U?eKd+y)n(1 z?fkg2J#53#UldC?QE#>nFq+mh&+pF-BIN&V=(mstxPH$}Zi>3fynqt0>amz?7J6>J zNpcPEV(grT%Pj16dQs>_LG~O5S*5^HydVdv3&1viZ-R?m4))eK z`X*_r-z6~%Hp#sYrCq2&O%l{PoWQ4bF;O_P;egncJFF6ZrNzDMoQ*IXIIbzhtk7f6 z>;6bZ8Ew+1r}91o7>=R|MBQ$WoR0f&m(am3Owztvd6)FMKH9nfhfdRSVHuHm4&6RN0mV zS6=>h_)ZM?jFSHXSehqPqPVx@s|~Xb0Z}i5Lzb4MpaLYCyY=&|M|ixtQx)t^sRF0x zJhsHyrG}p2Vtl-AaIB|IrV_x1SeLX3hE85w(~(^>DYdbcLO!>^{&PjjMg$6QatAr^ z5_ra8F%{i1vg_9pSaWgp`pS46^G;By*~H^1Aw|fE8d>Bm=Qk?d-U%dRmg%tzk1|F3 z9GjmXgfxU1x8#o{uAZ+A^n7Y|tlvO>wMk5`8(-xKg|9C2*slX|@31>;%cgN8TwveW1ynK?fX=^l9^iZ!NlrGba-&z=#-CGrfH#d08 zzj1v+&MI~R0?;Bd1S-FlvFWeduwP>HWrU=(jQJBNEDyCY|B7M1jBISa+iyKpu&i#U z44!5=mX()F<@oFeD1{`8yOKR>gx2}ISWQFmf^~hncu8W#`JsqYNz>ct&lWH~jbGGA zVyy-`R@T;h%BH2m9G%iLk^mH}-F;XVOE)SvUq92nus{!~YBKi7wYEx*fK0&LsLn=k zra}VLy#eE4U#dKrxO2usiX9$`Fw&GxHDvgYKnWP0nkijut$#PD~CS3WuPK4y<(Uz@$~x^ z1PQ*$uRLq!ZIwoe#&u*!_N~?iXlJPC;QBe-ReYu^MS*YeQmk}PX4g_^C|X{{F!!D88x zaUv$>0FcvBr>yr$Bz&-@!A;64|6?94=O?o!33*=SPW8!?e@CD~v;WbT!E0XWX>yt) z;jNjps%5(wyqG6=93ssmzQ%|M%n^tiv(EnmfsFym8d1hT8b`MJhU9VKumiHpMQj$T z>tj61a#Md=?DR-14Ye^P2~A6!5LO^%QjO=9^O{U9Lr+39HuVqvTCHx`#Z5wlEOe;fxT=jQ ze&At4H}-Z6S!tHnp<9=)N(y%cJFpgA_f#@!P_j`K+H>6`;0M*?wo2UAfCOS;L+enS z$HkttcN699<^ky|Lnc@-$=1JX>Mm{gHkASd4WvhN^k0bQ_OE8y7ZU@nx#$#Mzz?ZK zj=mTnti03}OrG2$Ig61f5yG1klnb?FSLUzg4Hb3K8&X9ynwy3za+{2LoR;jXosKPPYW1}GnrAKKAQSRR{943uP zoqu32D#;FilAAIs7e5Gk{IIU|`;l5ToUJcij}^`$BCNC5h0ri^iIX9WJl~4gK~g{U zz6}UbS!QLo8+;_5`A4W-OJw&v%XY4=dWG9U$zsFov5vtnl(f>#U^Wr{<-uofzGmq@`G;Z@nUDl2Ym+ z0>jY{#`k`y%zk-C(5^yH2ybI#SpFv#QczY2{!TOUpPJ$Jd=JY3-uP)ehwJUzBBV*U z?ztw3Ck3-Mhhmh$4&%yqNkx8g((w3>Y$_l47&{gYF_fSFwF}`kNr!S%f!vq zua1ujN_nMxUua^(*LiElAbOsK`@j4ld+!2~_rFReF2w6jD2Bldrdc7NiNy&K{>b~S ziFP$`dSD5avl*CdT%iZL9F?waN#pc+&^cReIMwVk!Oi*q$#gWX$BCNd!cpXh6IKwg zhye_;xU2~cQnGaBF@R;t-M>D!E2KcOqQ)aLD}mFoI6^W;di=zvJq7b7i@YD;HZ+OH zaZX1^Y3nl|rJ;=Lwb^a%)<2A&#w)?HYqc72Twt;?I4d`ibAZpd2cpOfJr=8 zUalX%%2iwU2pdY<+@0*h{4b;d|GjBN!49wtbpvoBBvX2{oM=QyDQPV-T`R!R?+Zkr z>J+h-rox-Kog3crwI!{gMQJ8T*yl_%dHQ?IJJgAclL>J{Tl8^FA=jzxOrkY7N3@8CWp=*B7 From a7b6cdef6a93c3a7c5ca80ef49f406d29686f07e Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 25 Aug 2013 20:44:48 +0530 Subject: [PATCH 028/193] well now, that was easy. --- .../mode/experimental/DebugEditor.java | 28 +++++++++++++++++-- .../mode/experimental/DebugToolbar.java | 12 ++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index fc3d8ee..bf2f464 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -21,6 +21,7 @@ import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; +import java.awt.Component; import java.awt.EventQueue; import java.awt.Frame; import java.awt.event.ActionEvent; @@ -42,6 +43,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; import javax.swing.border.EtchedBorder; import javax.swing.table.TableModel; import javax.swing.text.Document; @@ -403,15 +405,36 @@ public void actionPerformed(ActionEvent e) { boolean debugToolbarShown = false; protected EditorToolbar javaToolbar, debugToolbar; + protected void switchToolbars(){ + final EditorToolbar nextToolbar; if(debugToolbarShown){ // switch to java + if(javaToolbar == null) + javaToolbar = createToolbar(); + nextToolbar = javaToolbar; + debugToolbarShown = false; + log("Switching to Java Mode Toolbar"); } else{ // switch to debug if(debugToolbar == null) debugToolbar = new DebugToolbar(this, getBase()); + nextToolbar = debugToolbar; + debugToolbarShown = true; + log("Switching to Debugger Toolbar"); } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + Box upper = (Box)splitPane.getComponent(0); + upper.remove(0); + upper.add(nextToolbar, 0); + upper.validate(); + nextToolbar.repaint(); + toolbar = nextToolbar; + } + }); } /** @@ -425,10 +448,9 @@ protected JMenu buildDebugMenu() { JCheckBoxMenuItem toggleDebugger = new JCheckBoxMenuItem("Show Debug Toolbar"); toggleDebugger.setSelected(false); - toggleDebugger.addActionListener(new ActionListener() { - + toggleDebugger.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - + switchToolbars(); } }); debugMenu.add(toggleDebugger); diff --git a/src/processing/mode/experimental/DebugToolbar.java b/src/processing/mode/experimental/DebugToolbar.java index 67af287..c9616e1 100755 --- a/src/processing/mode/experimental/DebugToolbar.java +++ b/src/processing/mode/experimental/DebugToolbar.java @@ -68,7 +68,7 @@ public class DebugToolbar extends JavaToolbar { public DebugToolbar(Editor editor, Base base) { super(editor, base); } - public Image[][] loadImages() { + public Image[][] loadDebugImages() { int res = Toolkit.highResDisplay() ? 2 : 1; String suffix = null; @@ -91,16 +91,16 @@ public Image[][] loadImages() { allButtons = mode.loadImage("theme/buttons-debug" + suffix); } } + + // The following three final fields were not accessible, so just copied the values here + // for the time being. TODO: inform Ben, make these fields public /** Width of each toolbar button. */ final int BUTTON_WIDTH = 27; - /** Height of each toolbar button. */ -// static final int BUTTON_HEIGHT = 32; - /** The amount of space between groups of buttons on the toolbar. */ - final int BUTTON_GAP = 5; /** Size (both width and height) of the buttons in the source image. */ final int BUTTON_IMAGE_SIZE = 33; int count = allButtons.getWidth(this) / BUTTON_WIDTH*res; final int GRID_SIZE = 32; + Image[][] buttonImages = new Image[count][3]; for (int i = 0; i < count; i++) { @@ -123,7 +123,7 @@ public Image[][] loadImages() { */ @Override public void init() { - Image[][] images = loadImages(); + Image[][] images = loadDebugImages(); for (int idx = 0; idx < buttonSequence.length; idx++) { int id = buttonId(idx); addButton(getTitle(id, false), getTitle(id, true), images[idx], id == NEW || id == TOGGLE_BREAKPOINT); From ed1c4f8bce13b9128d664c0a8ed6854fcecc73de Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 25 Aug 2013 21:06:10 +0530 Subject: [PATCH 029/193] updating keylistener too --- src/processing/mode/experimental/DebugEditor.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index bf2f464..bf62fa7 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -27,6 +27,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; @@ -433,6 +434,17 @@ public void run() { upper.validate(); nextToolbar.repaint(); toolbar = nextToolbar; + // The toolbar responds to shift down/up events + // in order to show the alt version of toolbar buttons. + // With toolbar switch, KeyListener has to be changed as well + for (KeyListener kl : textarea.getKeyListeners()) { + if(kl instanceof EditorToolbar) + { + textarea.removeKeyListener(kl); + textarea.addKeyListener(toolbar); + break; + } + } } }); } From e052729788748c80829652a867adc696d9d3e021 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 25 Aug 2013 21:32:44 +0530 Subject: [PATCH 030/193] forgot to add the images --- .../mode/experimental/ASTGenerator.java | 3 ++- .../mode/experimental/ExperimentalMode.java | 2 +- theme/buttons-debug-2x.png | Bin 0 -> 11521 bytes theme/buttons-debug.png | Bin 0 -> 6652 bytes 4 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 theme/buttons-debug-2x.png create mode 100644 theme/buttons-debug.png diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index ba6e330..f933ba1 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -154,7 +154,8 @@ public ASTGenerator(ErrorCheckerService ecs) { this.editor = ecs.getEditor(); setupGUI(); //addCompletionPopupListner(); - addListeners(); loadJavaDoc(); + addListeners(); + //loadJavaDoc(); predictionsEnabled = new AtomicBoolean(true); } diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index d5f0739..db5f793 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -46,7 +46,7 @@ public class ExperimentalMode extends JavaMode { public static final boolean VERBOSE_LOGGING = true; //public static final boolean VERBOSE_LOGGING = false; public static final int LOG_SIZE = 512 * 1024; // max log file size (in bytes) - public static boolean DEBUG = true; + public static boolean DEBUG = !true; public ExperimentalMode(Base base, File folder) { super(base, folder); diff --git a/theme/buttons-debug-2x.png b/theme/buttons-debug-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a63d28a67a340752122b0888a1dec539b35452a9 GIT binary patch literal 11521 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 Date: Fri, 30 Aug 2013 15:26:33 +0530 Subject: [PATCH 031/193] Adding some pacakages to be ignored by code completion --- .../mode/experimental/ASTGenerator.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index f933ba1..c8ae679 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -952,9 +952,10 @@ public void preparePredictions(final String word, final int line, final int line matchedClass2 = matchedClass2.replace('/', '.'); String matchedClass = matchedClass2.substring(0, matchedClass2 .length() - 6); - if (ignorableImport(matchedClass2)) - continue; int d = matchedClass.lastIndexOf('.'); + if (ignorableImport(matchedClass2,matchedClass.substring(d + 1))) + continue; + matchedClass = matchedClass.substring(d + 1); candidates .add(new CompletionCandidate(matchedClass, matchedClass @@ -3121,17 +3122,19 @@ public static void disposeWindow(JFrame f) { "com.oracle.", "sun.", "sunw.", "com.sun.", "javax.", "sunw.", "org.ietf.", "org.jcp.", "org.omg.", "org.w3c.", "org.xml.", "org.eclipse.", "com.ibm.", "org.netbeans.", "org.jsoup.", "org.junit.", "org.apache.", "antlr." }; - protected boolean ignorableImport(String impName) { + public static final String allowedImports[] = {"java.lang.", "java.util.", "java.io.", + "java.math.", "processing.core.", "processing.data.", "processing.event.", "processing.opengl."}; + protected boolean ignorableImport(String impName, String className) { //TODO: Trie man. for (ImportStatement impS : errorCheckerService.getProgramImports()) { if(impName.startsWith(impS.getPackageName())) return false; } - for (String impS : ignoredImports) { - if(impName.startsWith(impS)) - return true; + for (String impS : allowedImports) { + if(impName.startsWith(impS) && className.indexOf('.') == -1) + return false; } - return false; + return true; } public static boolean isAddableASTNode(ASTNode node) { From 9815b99a619a672b71330cd2f8c87bf3df018c0f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 30 Aug 2013 15:30:13 +0530 Subject: [PATCH 032/193] lol, I'd really done this --- src/processing/mode/experimental/TextArea.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 0d54ecd..7c1c5c4 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -179,13 +179,15 @@ public void processKeyEvent(KeyEvent evt) { } super.processKeyEvent(evt); - if (evt.getID() == KeyEvent.KEY_TYPED && editor.errorCheckerService.getASTGenerator().predictionsEnabled.get()) { + if (evt.getID() == KeyEvent.KEY_TYPED) { final KeyEvent evt2 = evt; SwingWorker worker = new SwingWorker() { protected Object doInBackground() throws Exception { errorCheckerService.runManualErrorCheck(); - log(" Typing: " + fetchPhrase(evt2) + " " - + (evt2.getKeyChar() == KeyEvent.VK_ENTER)); + // Provide completions only if it's enabled + if(editor.errorCheckerService.getASTGenerator().predictionsEnabled.get()) + log(" Typing: " + fetchPhrase(evt2) + " " + + (evt2.getKeyChar() == KeyEvent.VK_ENTER)); return null; } }; From b3546aadd089f5686a285377fe85059bde9a1a76 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 1 Sep 2013 20:35:51 +0530 Subject: [PATCH 033/193] renaming mode menu, todo updates --- Todo, GSoC 2013.txt | 4 ++-- src/processing/mode/experimental/DebugEditor.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 10415a8..ca0338e 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -42,8 +42,8 @@ Finer details * printStuff(int,float,String) - completion endings have to be appropriate. Right now it's just printStuff(,,). Cursor positioning also needs to be taken care of(done). Argument list as tooltip if possible? *! p5 enhanced stuff in java, how does it fit in with everything else, and edge cases. Possibly add support for them. Offset handling improvements should help here. * Diamond operator isn't supported for now. Bummer. -* Icons for completions? Or overkill right now? +x Icons for completions? Or overkill right now? x 'Show Usage' menu item added x Show declaring class for completions x! Ignore String case while finding completion candidates @@ -144,7 +144,7 @@ x boolean warningsEnabled - made it volatile General Stuff ============= -* Ensure all editor windows are closed when editor is closed. +x Ensure all editor windows are closed when editor is closed. x Add a red marker near Errors label in console toggle, to indicate errors present in sketch. x Add option for toggling debug output x On Run/Debug Console is visible(ProblemsList hidden) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index bf62fa7..a2f07ef 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -456,7 +456,8 @@ public void run() { * @return The debug menu */ protected JMenu buildDebugMenu() { - debugMenu = new JMenu("Debug"); + //debugMenu = new JMenu("Debug"); + debugMenu = new JMenu("PDE X"); JCheckBoxMenuItem toggleDebugger = new JCheckBoxMenuItem("Show Debug Toolbar"); toggleDebugger.setSelected(false); From 27e44b9d0101524f3f9fe28c48c431192fbd42d2 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 1 Sep 2013 21:21:05 +0530 Subject: [PATCH 034/193] breakpoint markers hidden when Debugger not active --- Todo, GSoC 2013.txt | 1 + .../mode/experimental/DebugEditor.java | 14 ++++----- .../mode/experimental/TextArea.java | 6 ++++ .../mode/experimental/TextAreaPainter.java | 29 +++++++++---------- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index ca0338e..0b772dd 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -144,6 +144,7 @@ x boolean warningsEnabled - made it volatile General Stuff ============= +x Hide breakpoint markers when Debugger isn't active x Ensure all editor windows are closed when editor is closed. x Add a red marker near Errors label in console toggle, to indicate errors present in sketch. x Add option for toggling debug output diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index a2f07ef..663b278 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -34,6 +34,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; @@ -239,9 +240,7 @@ public void actionPerformed(ActionEvent e) { initializeErrorChecker(); ta.setECSandThemeforTextArea(errorCheckerService, dmode); addXQModeUI(); - //TODO: Remove this later - if(ExperimentalMode.DEBUG) - setBounds(160, 300, getWidth(), getHeight()); + debugToolbarEnabled = new AtomicBoolean(false); } private void addXQModeUI(){ @@ -404,17 +403,17 @@ public void actionPerformed(ActionEvent e) { return buildSketchMenu(new JMenuItem[]{runItem, presentItem, stopItem}); }*/ - boolean debugToolbarShown = false; + AtomicBoolean debugToolbarEnabled; protected EditorToolbar javaToolbar, debugToolbar; protected void switchToolbars(){ final EditorToolbar nextToolbar; - if(debugToolbarShown){ + if(debugToolbarEnabled.get()){ // switch to java if(javaToolbar == null) javaToolbar = createToolbar(); nextToolbar = javaToolbar; - debugToolbarShown = false; + debugToolbarEnabled.set(false); log("Switching to Java Mode Toolbar"); } else{ @@ -422,7 +421,7 @@ protected void switchToolbars(){ if(debugToolbar == null) debugToolbar = new DebugToolbar(this, getBase()); nextToolbar = debugToolbar; - debugToolbarShown = true; + debugToolbarEnabled.set(true); log("Switching to Debugger Toolbar"); } @@ -445,6 +444,7 @@ public void run() { break; } } + ta.repaint(); } }); } diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 7c1c5c4..77e26b5 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -396,6 +396,9 @@ else if (s.charAt(x1) == ']') { * @return gutter width in pixels */ protected int getGutterWidth() { + if(editor.debugToolbarEnabled == null || !editor.debugToolbarEnabled.get()){ + return 0; + } FontMetrics fm = painter.getFontMetrics(); // log("fm: " + (fm == null)); // log("editor: " + (editor == null)); @@ -413,6 +416,9 @@ protected int getGutterWidth() { * @return margins in pixels */ protected int getGutterMargins() { + if(editor.debugToolbarEnabled == null || !editor.debugToolbarEnabled.get()){ + return 0; + } return gutterPadding; } diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 3825012..07c04ab 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -172,19 +172,19 @@ private void loadTheme(ExperimentalMode mode) { @Override protected void paintLine(Graphics gfx, TokenMarker tokenMarker, int line, int x) { - - // paint gutter - paintGutterBg(gfx, line, x); - - paintLineBgColor(gfx, line, x + ta.getGutterWidth()); - - paintGutterLine(gfx, line, x); - - // paint gutter symbol - paintGutterText(gfx, line, x); - + if(ta.editor.debugToolbarEnabled != null && ta.editor.debugToolbarEnabled.get()){ + // paint gutter + paintGutterBg(gfx, line, x); + + paintLineBgColor(gfx, line, x + ta.getGutterWidth()); + + paintGutterLine(gfx, line, x); + + // paint gutter symbol + paintGutterText(gfx, line, x); + } + paintErrorLine(gfx, line, x); - super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth()); } @@ -296,7 +296,6 @@ protected void paintLineBgColor(Graphics gfx, int line, int x) { * @param x */ protected void paintErrorLine(Graphics gfx, int line, int x) { - if (errorCheckerService == null) { return; } @@ -354,8 +353,8 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { int rw = fm.stringWidth(linetext.trim()); // real width int x1 = 0 + (aw - rw), y1 = y + fm.getHeight() - 2, x2 = x1 + rw; // Adding offsets for the gutter - x1 += 20; - x2 += 20; + x1 += ta.getGutterWidth(); + x2 += ta.getGutterWidth(); // gfx.fillRect(x1, y, rw, height); From 3abd079f1dae32ac45c1b61d6527f65b869585f0 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 15 Sep 2013 02:42:47 +0530 Subject: [PATCH 035/193] prediction length added --- src/processing/mode/experimental/ASTGenerator.java | 4 +++- src/processing/mode/experimental/TextArea.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index c8ae679..ede894e 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -780,9 +780,11 @@ protected void trimCandidates(String newWord){ protected ArrayList candidates; protected String lastPredictedWord = " "; protected AtomicBoolean predictionsEnabled; + protected int predictionMinLength = 3; public void preparePredictions(final String word, final int line, final int lineStartNonWSOffset) { if(!predictionsEnabled.get()) return; + if(word.length() < predictionMinLength) return; // This method is called from TextArea.fetchPhrase, which is called via a SwingWorker instance // in TextArea.processKeyEvent if(caretWithinLineComment()){ @@ -809,7 +811,7 @@ public void preparePredictions(final String word, final int line, final int line noCompare = true; } - if (word2.length() > 2 && !noCompare + if (word2.length() >= predictionMinLength && !noCompare && word2.length() > lastPredictedWord.length()) { if (word2.startsWith(lastPredictedWord)) { log(word + " starts with " + lastPredictedWord); diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 77e26b5..6b2dd7a 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -303,7 +303,7 @@ else if (keyChar == KeyEvent.VK_ESCAPE) { word = word.trim(); if (word.endsWith(".")) word = word.substring(0, word.length() - 1); - if(word.length() > 1) + errorCheckerService.getASTGenerator().preparePredictions(word, line + errorCheckerService.mainClassOffset,0); return word; From ce40cd775cfb47b0a90bdfa22a6c90b1830455d1 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 15 Sep 2013 03:18:03 +0530 Subject: [PATCH 036/193] todo updates --- Todo, GSoC 2013.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 0b772dd..a22e4c0 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -16,6 +16,7 @@ The big stuff: - Many of the cases seem to have been covered, and I'm achieving more and more code unification as I'm working through the problem step by step - Looks almost complete now, nearly all cases covered(July 13th) * After popup appears, the popup location is fixed for the current line. So if editor window is moved while staying in the same line, popup appears at the prev location. Need to ensure editor is still at last know location +* Keyboard Shortcut for completion popup - Ctrl + Space * Scope handling? Static/non static scope? * Disable completions on comment line * Trie implementation would be lower priority, "premature optimisation is pure evil". Get all features of CC working good enough and then plan this. @@ -144,7 +145,9 @@ x boolean warningsEnabled - made it volatile General Stuff ============= +* Consult Ben on where to save preferences - main preferences.txt or custom one x Hide breakpoint markers when Debugger isn't active +x Ensure gutter mouse handler is taken care of when hiding Debugger breakpoint bar. x Ensure all editor windows are closed when editor is closed. x Add a red marker near Errors label in console toggle, to indicate errors present in sketch. x Add option for toggling debug output From c9313e570fbafc3d63b9c9486bd12da70cc507b2 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 15 Sep 2013 21:14:45 +0530 Subject: [PATCH 037/193] prefs work --- .../mode/experimental/ASTGenerator.java | 4 +- .../mode/experimental/DebugEditor.java | 20 +++++----- .../experimental/ErrorCheckerService.java | 7 +--- .../mode/experimental/ExperimentalMode.java | 39 +++++++++++++++++++ .../mode/experimental/TextArea.java | 1 - 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index ede894e..b0a47eb 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -779,11 +779,11 @@ protected void trimCandidates(String newWord){ */ protected ArrayList candidates; protected String lastPredictedWord = " "; - protected AtomicBoolean predictionsEnabled; + //protected AtomicBoolean predictionsEnabled; protected int predictionMinLength = 3; public void preparePredictions(final String word, final int line, final int lineStartNonWSOffset) { - if(!predictionsEnabled.get()) return; + if(!ExperimentalMode.codeCompletionsEnabled) return; if(word.length() < predictionMinLength) return; // This method is called from TextArea.fetchPhrase, which is called via a SwingWorker instance // in TextArea.processKeyEvent diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 663b278..23d42fa 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -326,12 +326,10 @@ public void dispose() { // Added temporarily to dump error log. TODO: Remove this later public void internalCloseRunner(){ - if(enableErrorLogging) writeErrorsToFile(); + if(ExperimentalMode.errorLogsEnabled) writeErrorsToFile(); super.internalCloseRunner(); } - protected boolean enableErrorLogging = false; - private void writeErrorsToFile(){ if (errorCheckerService.tempErrorLog.size() == 0) return; @@ -525,12 +523,12 @@ public void actionPerformed(ActionEvent e) { JCheckBoxMenuItem item; final DebugEditor thisEditor = this; item = new JCheckBoxMenuItem("Error Checker Enabled"); - item.setSelected(true); + item.setSelected(ExperimentalMode.errorCheckEnabled); item.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - + ExperimentalMode.errorCheckEnabled = ((JCheckBoxMenuItem) e.getSource()).isSelected(); if (!((JCheckBoxMenuItem) e.getSource()).isSelected()) { // unticked Menu Item errorCheckerService.pauseThread(); @@ -571,12 +569,12 @@ public void actionPerformed(ActionEvent e) { debugMenu.add(problemWindowMenuCB); showWarnings = new JCheckBoxMenuItem("Warnings Enabled"); - showWarnings.setSelected(true); + showWarnings.setSelected(ExperimentalMode.warningsEnabled); showWarnings.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - errorCheckerService.warningsEnabled = ((JCheckBoxMenuItem) e + ExperimentalMode.warningsEnabled = ((JCheckBoxMenuItem) e .getSource()).isSelected(); errorCheckerService.runManualErrorCheck(); } @@ -588,8 +586,8 @@ public void actionPerformed(ActionEvent e) { completionsEnabled.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - errorCheckerService.getASTGenerator().predictionsEnabled - .set(((JCheckBoxMenuItem) e.getSource()).isSelected()); + ExperimentalMode.codeCompletionsEnabled = (((JCheckBoxMenuItem) e + .getSource()).isSelected()); } }); debugMenu.add(completionsEnabled); @@ -610,11 +608,11 @@ public void actionPerformed(ActionEvent e) { debugMenu.add(showOutline); writeErrorLog = new JCheckBoxMenuItem("Write Errors to Log"); - writeErrorLog.setSelected(enableErrorLogging); + writeErrorLog.setSelected(ExperimentalMode.errorLogsEnabled); writeErrorLog.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - enableErrorLogging = !enableErrorLogging; + ExperimentalMode.errorLogsEnabled = !ExperimentalMode.errorLogsEnabled; } }); debugMenu.add(writeErrorLog); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 491ae15..262265f 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -559,7 +559,7 @@ public boolean accept(File file) { } // If warnings are disabled, skip 'em - if (p.isWarning() && !warningsEnabled) { + if (p.isWarning() && !ExperimentalMode.warningsEnabled) { continue; } problemsList.add(p); @@ -724,11 +724,6 @@ protected boolean ignorableImport(String packageName) { @SuppressWarnings("rawtypes") protected Map compilerSettings; - /** - * Enable/Disable warnings from being shown - */ - volatile public boolean warningsEnabled = true; - /** * Sets compiler options for JDT Compiler */ diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index db5f793..b530782 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -35,6 +35,7 @@ import processing.app.Editor; import processing.app.EditorState; import processing.app.Mode; +import processing.app.Preferences; import processing.mode.java.JavaMode; @@ -114,6 +115,44 @@ public File[] getKeywordFiles() { Base.getContentFile("modes/java/keywords.txt") }; } + + volatile public static boolean errorCheckEnabled = true, warningsEnabled = true, + codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false; + + public final String prefErrorCheck = "pdex.errorCheckEnabled", + prefWarnings = "pdex.warningsEnabled", + prefCodeCompletionEnabled = "pdex.ccEnabled", + prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs"; + + public void loadPreferences(){ + ensurePrefsExist(); + errorCheckEnabled = Preferences.getBoolean(prefErrorCheck); + warningsEnabled = Preferences.getBoolean(prefWarnings); + codeCompletionsEnabled = Preferences.getBoolean(prefCodeCompletionEnabled); + debugOutputEnabled = Preferences.getBoolean(prefDebugOP); + errorCheckEnabled = Preferences.getBoolean(prefErrorLogs); + } + + public void savePreferences(){ + Preferences.setBoolean(prefErrorCheck, errorCheckEnabled); + Preferences.setBoolean(prefWarnings, warningsEnabled); + Preferences.setBoolean(prefCodeCompletionEnabled, codeCompletionsEnabled); + Preferences.setBoolean(prefDebugOP, debugOutputEnabled); + Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); + } + + public void ensurePrefsExist(){ + if(Preferences.get(prefErrorCheck) == null) + Preferences.setBoolean(prefErrorCheck,errorCheckEnabled); + if(Preferences.get(prefWarnings) == null) + Preferences.setBoolean(prefWarnings,warningsEnabled); + if(Preferences.get(prefCodeCompletionEnabled) == null) + Preferences.setBoolean(prefCodeCompletionEnabled,codeCompletionsEnabled); + if(Preferences.get(prefDebugOP) == null) + Preferences.setBoolean(prefDebugOP,debugOutputEnabled); + if(Preferences.get(prefErrorLogs) == null) + Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); + } /** diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 6b2dd7a..4a083e6 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -185,7 +185,6 @@ public void processKeyEvent(KeyEvent evt) { protected Object doInBackground() throws Exception { errorCheckerService.runManualErrorCheck(); // Provide completions only if it's enabled - if(editor.errorCheckerService.getASTGenerator().predictionsEnabled.get()) log(" Typing: " + fetchPhrase(evt2) + " " + (evt2.getKeyChar() == KeyEvent.VK_ENTER)); return null; From 02bdcff7ac367ac8ef7ea843d3a6bd19d8d1a2e6 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 15 Sep 2013 21:56:02 +0530 Subject: [PATCH 038/193] pde x prefs now saved to the main preferences.txt --- Todo, GSoC 2013.txt | 3 ++- .../mode/experimental/ASTGenerator.java | 1 - .../mode/experimental/DebugEditor.java | 25 ++++--------------- .../experimental/ErrorCheckerService.java | 22 ++++++++++++++++ .../mode/experimental/ExperimentalMode.java | 11 +++++--- .../mode/experimental/TextArea.java | 1 + 6 files changed, 37 insertions(+), 26 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index a22e4c0..94f0d75 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -145,7 +145,8 @@ x boolean warningsEnabled - made it volatile General Stuff ============= -* Consult Ben on where to save preferences - main preferences.txt or custom one +x Consult Ben on where to save preferences - main preferences.txt or custom one. - Main prefs file +x Save preferences to main preference.txt x Hide breakpoint markers when Debugger isn't active x Ensure gutter mouse handler is taken care of when hiding Debugger breakpoint bar. x Ensure all editor windows are closed when editor is closed. diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index b0a47eb..62b4e90 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -156,7 +156,6 @@ public ASTGenerator(ErrorCheckerService ecs) { //addCompletionPopupListner(); addListeners(); //loadJavaDoc(); - predictionsEnabled = new AtomicBoolean(true); } protected void setupGUI(){ diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 23d42fa..af738e7 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -326,6 +326,7 @@ public void dispose() { // Added temporarily to dump error log. TODO: Remove this later public void internalCloseRunner(){ + dmode.savePreferences(); if(ExperimentalMode.errorLogsEnabled) writeErrorsToFile(); super.internalCloseRunner(); } @@ -521,7 +522,6 @@ public void actionPerformed(ActionEvent e) { // XQMode menu items JCheckBoxMenuItem item; - final DebugEditor thisEditor = this; item = new JCheckBoxMenuItem("Error Checker Enabled"); item.setSelected(ExperimentalMode.errorCheckEnabled); item.addActionListener(new ActionListener() { @@ -529,23 +529,7 @@ public void actionPerformed(ActionEvent e) { @Override public void actionPerformed(ActionEvent e) { ExperimentalMode.errorCheckEnabled = ((JCheckBoxMenuItem) e.getSource()).isSelected(); - if (!((JCheckBoxMenuItem) e.getSource()).isSelected()) { - // unticked Menu Item - errorCheckerService.pauseThread(); - System.out.println(thisEditor.getSketch().getName() - + " - Error Checker paused."); - errorBar.errorPoints.clear(); - errorCheckerService.problemsList.clear(); - errorCheckerService.updateErrorTable(); - errorCheckerService.updateEditorStatus(); - getTextArea().repaint(); - errorBar.repaint(); - } else { - errorCheckerService.resumeThread(); - System.out.println(thisEditor.getSketch().getName() - + " - Error Checker resumed."); - errorCheckerService.runManualErrorCheck(); - } + errorCheckerService.handleErrorCheckingToggle(); } }); debugMenu.add(item); @@ -582,7 +566,7 @@ public void actionPerformed(ActionEvent e) { debugMenu.add(showWarnings); completionsEnabled = new JCheckBoxMenuItem("Code Completion Enabled"); - completionsEnabled.setSelected(true); + completionsEnabled.setSelected(ExperimentalMode.codeCompletionsEnabled); completionsEnabled.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -612,7 +596,8 @@ public void actionPerformed(ActionEvent e) { writeErrorLog.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - ExperimentalMode.errorLogsEnabled = !ExperimentalMode.errorLogsEnabled; + ExperimentalMode.errorLogsEnabled = ((JCheckBoxMenuItem) e + .getSource()).isSelected(); } }); debugMenu.add(writeErrorLog); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 262265f..cc66605 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -19,6 +19,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.swing.JCheckBoxMenuItem; import javax.swing.table.DefaultTableModel; import org.eclipse.jdt.core.JavaCore; @@ -262,6 +263,7 @@ public void run() { // Completion wouldn't be complete, but it'd be still something // better than nothing astGenerator.buildAST(cu); + handleErrorCheckingToggle(); while (!stopThread.get()) { try { // Take a nap. @@ -1399,6 +1401,26 @@ public static String substituteUnicode(String program) { return new String(p2, 0, index); } + public void handleErrorCheckingToggle(){ + if (!ExperimentalMode.errorCheckEnabled) { + // unticked Menu Item + pauseThread(); + log(editor.getSketch().getName() + + " - Error Checker paused."); + editor.errorBar.errorPoints.clear(); + problemsList.clear(); + updateErrorTable(); + updateEditorStatus(); + editor.getTextArea().repaint(); + editor.errorBar.repaint(); + } else { + resumeThread(); + log(editor.getSketch().getName() + + " - Error Checker resumed."); + runManualErrorCheck(); + } + } + /** * Stops the Error Checker Service thread */ diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index b530782..9417f94 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -100,6 +100,7 @@ public ExperimentalMode(Base base, File folder) { // String titleAndVersion = p.getImplementationTitle() + " (v" + p.getImplementationVersion() + ")"; // //log(titleAndVersion); // Logger.getLogger(ExperimentalMode.class.getName()).log(Level.INFO, titleAndVersion); + loadPreferences(); loadIcons(); } @@ -125,19 +126,21 @@ public File[] getKeywordFiles() { prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs"; public void loadPreferences(){ + log("Load PDEX prefs"); ensurePrefsExist(); errorCheckEnabled = Preferences.getBoolean(prefErrorCheck); warningsEnabled = Preferences.getBoolean(prefWarnings); codeCompletionsEnabled = Preferences.getBoolean(prefCodeCompletionEnabled); - debugOutputEnabled = Preferences.getBoolean(prefDebugOP); - errorCheckEnabled = Preferences.getBoolean(prefErrorLogs); + DEBUG = Preferences.getBoolean(prefDebugOP); + errorLogsEnabled = Preferences.getBoolean(prefErrorLogs); } public void savePreferences(){ + log("Saving PDEX prefs"); Preferences.setBoolean(prefErrorCheck, errorCheckEnabled); Preferences.setBoolean(prefWarnings, warningsEnabled); Preferences.setBoolean(prefCodeCompletionEnabled, codeCompletionsEnabled); - Preferences.setBoolean(prefDebugOP, debugOutputEnabled); + Preferences.setBoolean(prefDebugOP, DEBUG); Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); } @@ -149,7 +152,7 @@ public void ensurePrefsExist(){ if(Preferences.get(prefCodeCompletionEnabled) == null) Preferences.setBoolean(prefCodeCompletionEnabled,codeCompletionsEnabled); if(Preferences.get(prefDebugOP) == null) - Preferences.setBoolean(prefDebugOP,debugOutputEnabled); + Preferences.setBoolean(prefDebugOP,DEBUG); if(Preferences.get(prefErrorLogs) == null) Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); } diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 4a083e6..beb0846 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -185,6 +185,7 @@ public void processKeyEvent(KeyEvent evt) { protected Object doInBackground() throws Exception { errorCheckerService.runManualErrorCheck(); // Provide completions only if it's enabled + if(ExperimentalMode.codeCompletionsEnabled) log(" Typing: " + fetchPhrase(evt2) + " " + (evt2.getKeyChar() == KeyEvent.VK_ENTER)); return null; From 634483a710f89bf9a5f1fd9bc54f39ebd932a06b Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 16 Sep 2013 21:01:59 +0530 Subject: [PATCH 039/193] this should get rid of the TA paint line errors, hopefully --- src/processing/mode/experimental/TextAreaPainter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 07c04ab..aab49e9 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -182,10 +182,14 @@ protected void paintLine(Graphics gfx, TokenMarker tokenMarker, int line, // paint gutter symbol paintGutterText(gfx, line, x); + + paintErrorLine(gfx, line, x); + super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth()); + } + else { + paintErrorLine(gfx, line, x); + super.paintLine(gfx, tokenMarker, line, x); } - - paintErrorLine(gfx, line, x); - super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth()); } /** From 3868e547fe6e680d83d7ca02563a00b7c0dc7a47 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 16 Sep 2013 21:16:09 +0530 Subject: [PATCH 040/193] completion list now hidden on hitting space --- .../mode/experimental/CompletionPanel.java | 6 ++-- .../mode/experimental/TextArea.java | 33 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index ff2b738..a8f44d1 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -84,7 +84,7 @@ private JList createSuggestionList(final int position, public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { insertSelection(); - hideSuggestion(); + hide(); } } }); @@ -137,12 +137,12 @@ public boolean insertSelection() { } catch (BadLocationException e1) { e1.printStackTrace(); } - hideSuggestion(); + hide(); } return false; } - public void hideSuggestion() { + public void hide() { popupMenu.setVisible(false); log("Suggestion hidden" + System.nanoTime()); //textarea.errorCheckerService.getASTGenerator().jdocWindowVisible(false); diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index beb0846..9402673 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -173,11 +173,18 @@ public void processKeyEvent(KeyEvent evt) { case KeyEvent.VK_BACK_SPACE: log("BK Key"); break; + case KeyEvent.VK_SPACE: + if (suggestion != null) + if (suggestion.isVisible()) { + log("Space bar, hide completion list"); + suggestion.hide(); + } + break; default: break; } } - super.processKeyEvent(evt); + super.processKeyEvent(evt); if (evt.getID() == KeyEvent.KEY_TYPED) { final KeyEvent evt2 = evt; @@ -259,20 +266,14 @@ else if (s.length() == 0) } } private String fetchPhrase(KeyEvent evt) { - if (evt != null) { - char keyChar = evt.getKeyChar(); - if (keyChar == KeyEvent.VK_ENTER) { - //log("Enter keypress."); - return null; - } -// if (keyChar == KeyEvent.VK_BACK_SPACE || keyChar == KeyEvent.VK_DELETE) -// ; // accepted these keys - else if (keyChar == KeyEvent.VK_ESCAPE) { - //log("ESC keypress. fetchPhrase()"); - return null; - } else if (keyChar == KeyEvent.VK_TAB || keyChar == KeyEvent.CHAR_UNDEFINED) { - return null; - } + char keyChar = evt.getKeyChar(); + if (keyChar == KeyEvent.VK_ENTER) { + return null; + } else if (keyChar == KeyEvent.VK_ESCAPE) { + return null; + } else if (keyChar == KeyEvent.VK_SPACE || keyChar == KeyEvent.VK_TAB + || keyChar == KeyEvent.CHAR_UNDEFINED) { + return null; } int off = getCaretPosition(); log2("off " + off); @@ -741,7 +742,7 @@ public void run() { private void hideSuggestion() { if (suggestion != null) { - suggestion.hideSuggestion(); + suggestion.hide(); suggestion = null; } } From 1c027c3ddc4fc2097a7cec5bcaef60d61a6adb8e Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 16 Sep 2013 21:21:25 +0530 Subject: [PATCH 041/193] also hide completions when ctrl or other modifiers pressed --- .../mode/experimental/TextArea.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 9402673..38f891d 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -187,7 +187,18 @@ public void processKeyEvent(KeyEvent evt) { super.processKeyEvent(evt); if (evt.getID() == KeyEvent.KEY_TYPED) { - final KeyEvent evt2 = evt; + + char keyChar = evt.getKeyChar(); + if (keyChar == KeyEvent.VK_ENTER || keyChar == KeyEvent.VK_ESCAPE) { + return; + } else if (keyChar == KeyEvent.VK_SPACE || keyChar == KeyEvent.VK_TAB + || keyChar == KeyEvent.CHAR_UNDEFINED) { + return; + } + if(evt.isAltDown() || evt.isControlDown() || evt.isMetaDown()){ + return; + } + final KeyEvent evt2 = evt; SwingWorker worker = new SwingWorker() { protected Object doInBackground() throws Exception { errorCheckerService.runManualErrorCheck(); @@ -266,15 +277,7 @@ else if (s.length() == 0) } } private String fetchPhrase(KeyEvent evt) { - char keyChar = evt.getKeyChar(); - if (keyChar == KeyEvent.VK_ENTER) { - return null; - } else if (keyChar == KeyEvent.VK_ESCAPE) { - return null; - } else if (keyChar == KeyEvent.VK_SPACE || keyChar == KeyEvent.VK_TAB - || keyChar == KeyEvent.CHAR_UNDEFINED) { - return null; - } + int off = getCaretPosition(); log2("off " + off); if (off < 0) From 7553015c43b801d35a054559fe1a2159350d2324 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 16 Sep 2013 21:35:40 +0530 Subject: [PATCH 042/193] completion screen location update bug fix --- src/processing/mode/experimental/ASTGenerator.java | 2 +- src/processing/mode/experimental/CompletionPanel.java | 4 ++-- src/processing/mode/experimental/TextArea.java | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 62b4e90..c563c43 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -779,7 +779,7 @@ protected void trimCandidates(String newWord){ protected ArrayList candidates; protected String lastPredictedWord = " "; //protected AtomicBoolean predictionsEnabled; - protected int predictionMinLength = 3; + protected int predictionMinLength = 2; public void preparePredictions(final String word, final int line, final int lineStartNonWSOffset) { if(!ExperimentalMode.codeCompletionsEnabled) return; diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index a8f44d1..6e1f36e 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -92,7 +92,7 @@ public void mouseClicked(MouseEvent e) { return list; } - public boolean updateList(final DefaultListModel items, String newSubword, int position){ + public boolean updateList(final DefaultListModel items, String newSubword, Point location, int position){ scrollPane.getViewport().removeAll(); Dimension dimen = popupMenu.getSize(); completionList.setModel(items); @@ -101,7 +101,7 @@ public boolean updateList(final DefaultListModel items, String newSubword, int p scrollPane.setViewportView(completionList); scrollPane.validate(); popupMenu.setSize(dimen); - + popupMenu.setLocation(location); this.subWord = new String(newSubword); if (subWord.indexOf('.') != -1) this.subWord = subWord.substring(subWord.lastIndexOf('.') + 1); diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 38f891d..9183d98 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -720,6 +720,7 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { - getLineStartOffset(getCaretLine())); location.y = lineToY(getCaretLine()) + getPainter().getFontMetrics().getHeight(); + log("TA position: " + location); } catch (Exception e2) { e2.printStackTrace(); return; @@ -732,7 +733,9 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { suggestion = new CompletionPanel(this, position, subWord, defListModel, location,editor); else - suggestion.updateList(defListModel, subWord, position); + suggestion.updateList(defListModel, subWord, + new Point(getLocationOnScreen().x + location.x, + getLocationOnScreen().y + location.y), position); suggestion.setVisible(true); // requestFocusInWindow(); SwingUtilities.invokeLater(new Runnable() { From fbf59b1d21b244c9ad9f4b70b87912aa3ec4006a Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 16 Sep 2013 21:39:42 +0530 Subject: [PATCH 043/193] use show() instead --- src/processing/mode/experimental/CompletionPanel.java | 4 +++- src/processing/mode/experimental/TextArea.java | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 6e1f36e..39ce00d 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -101,12 +101,14 @@ public boolean updateList(final DefaultListModel items, String newSubword, Point scrollPane.setViewportView(completionList); scrollPane.validate(); popupMenu.setSize(dimen); - popupMenu.setLocation(location); + //popupMenu.setLocation(location); this.subWord = new String(newSubword); if (subWord.indexOf('.') != -1) this.subWord = subWord.substring(subWord.lastIndexOf('.') + 1); insertionPosition = position; log("Suggestion updated" + System.nanoTime()); + popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + + location.y); return true; } diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 9183d98..806e613 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -733,9 +733,8 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { suggestion = new CompletionPanel(this, position, subWord, defListModel, location,editor); else - suggestion.updateList(defListModel, subWord, - new Point(getLocationOnScreen().x + location.x, - getLocationOnScreen().y + location.y), position); + suggestion.updateList(defListModel, subWord, location, position); + suggestion.setVisible(true); // requestFocusInWindow(); SwingUtilities.invokeLater(new Runnable() { From 251fe7e7e3db5abc112f40dc245e88b81d3b0c03 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 01:02:14 +0530 Subject: [PATCH 044/193] giving up and adding try catch block. --- Todo, GSoC 2013.txt | 2 +- src/processing/mode/experimental/TextAreaPainter.java | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 94f0d75..2079b1b 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -15,7 +15,7 @@ The big stuff: - Making very good progress here. The elegance of recurion - Hats off! - Many of the cases seem to have been covered, and I'm achieving more and more code unification as I'm working through the problem step by step - Looks almost complete now, nearly all cases covered(July 13th) -* After popup appears, the popup location is fixed for the current line. So if editor window is moved while staying in the same line, popup appears at the prev location. Need to ensure editor is still at last know location +x After popup appears, the popup location is fixed for the current line. So if editor window is moved while staying in the same line, popup appears at the prev location. Need to ensure editor is still at last know location. Fixed. * Keyboard Shortcut for completion popup - Ctrl + Space * Scope handling? Static/non static scope? * Disable completions on comment line diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index aab49e9..065fcbf 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -183,12 +183,14 @@ protected void paintLine(Graphics gfx, TokenMarker tokenMarker, int line, // paint gutter symbol paintGutterText(gfx, line, x); - paintErrorLine(gfx, line, x); - super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth()); } - else { - paintErrorLine(gfx, line, x); + paintErrorLine(gfx, line, x); + try { + //TODO: This line is causing NPE's randomly ever since I added the toggle for + //Java Mode/Debugger toolbar. super.paintLine(gfx, tokenMarker, line, x); + } catch (NullPointerException e) { + log(e.getMessage()); } } From 97976cac8da3a054ef1d7e97e34185b87bc2a934 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 01:18:10 +0530 Subject: [PATCH 045/193] updated version. --- build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.properties b/build.properties index bdda74b..656dbd7 100644 --- a/build.properties +++ b/build.properties @@ -6,4 +6,4 @@ java.target.version=1.6 lib.name=ExperimentalMode dist=dist release=3 -prettyVersion=1.1.1 +prettyVersion=1.0.0b From a78c03fa434313fc401056cb8bb4f22df42f81bd Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 04:53:21 +0530 Subject: [PATCH 046/193] another shot at paintLine bug, adding keywords.txt --- build.xml | 3 + keywords.txt | 890 ++++++++++++++++++ .../mode/experimental/TextArea.java | 14 +- .../mode/experimental/TextAreaPainter.java | 4 +- 4 files changed, 902 insertions(+), 9 deletions(-) create mode 100644 keywords.txt diff --git a/build.xml b/build.xml index 1f06d8b..a3988d3 100644 --- a/build.xml +++ b/build.xml @@ -85,6 +85,9 @@ + + + diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..5ba33d3 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,890 @@ +# For an explanation of these tags, see Token.java +# trunk/processing/app/src/processing/app/syntax/Token.java + +ADD LITERAL2 blend_ +ALIGN_CENTER LITERAL2 +ALIGN_LEFT LITERAL2 +ALIGN_RIGHT LITERAL2 +ALPHA LITERAL2 +ALPHA_MASK LITERAL2 +ALT LITERAL2 +AMBIENT LITERAL2 +ARC LITERAL2 createShape_ +ARROW LITERAL2 cursor_ +ARGB LITERAL2 +BACKSPACE LITERAL2 keyCode +BASELINE LITERAL2 textAlign_ +BEVEL LITERAL2 strokeJoin_ +BLEND LITERAL2 blend_ +BLUE_MASK LITERAL2 +BLUR LITERAL2 filter_ +BOTTOM LITERAL2 textAlign_ +BOX LITERAL2 createShape_ +BURN LITERAL2 blend_ +CENTER LITERAL2 +CHATTER LITERAL2 +CHORD LITERAL2 arc_ +CLAMP LITERAL2 +CLICK LITERAL2 +CLOSE LITERAL2 +CMYK LITERAL2 +CODED LITERAL2 key +COMPLAINT LITERAL2 +COMPOSITE LITERAL2 +COMPONENT LITERAL2 +CONCAVE_POLYGON LITERAL2 +CONTROL LITERAL2 +CONVEX_POLYGON LITERAL2 +CORNER LITERAL2 textAlign_ +CORNERS LITERAL2 +CROSS LITERAL2 cursor_ +CUSTOM LITERAL2 +DARKEST LITERAL2 blend_ +DEGREES LITERAL2 +DEG_TO_RAD LITERAL2 +DELETE LITERAL2 +DIAMETER LITERAL2 +DIFFERENCE LITERAL2 blend_ +DIFFUSE LITERAL2 +DILATE LITERAL2 filter_ +DIRECTIONAL LITERAL2 +DISABLE_ACCURATE_2D LITERAL2 +DISABLE_DEPTH_MASK LITERAL2 +DISABLE_DEPTH_SORT LITERAL2 +DISABLE_DEPTH_TEST LITERAL2 +DISABLE_NATIVE_FONTS LITERAL2 +DISABLE_OPENGL_ERRORS LITERAL2 +DISABLE_PURE_STROKE LITERAL2 +DISABLE_TEXTURE_MIPMAPS LITERAL2 +DISABLE_TRANSFORM_CACHE LITERAL2 +DISABLE_STROKE_PERSPECTIVE LITERAL2 +DISABLED LITERAL2 +DODGE LITERAL2 blend_ +DOWN LITERAL2 keyCode +DRAG LITERAL2 +DXF LITERAL2 size_ +ELLIPSE LITERAL2 createShape_ +ENABLE_ACCURATE_2D LITERAL2 +ENABLE_DEPTH_MASK LITERAL2 +ENABLE_DEPTH_SORT LITERAL2 +ENABLE_DEPTH_TEST LITERAL2 +ENABLE_NATIVE_FONTS LITERAL2 +ENABLE_OPENGL_ERRORS LITERAL2 +ENABLE_PURE_STROKE LITERAL2 +ENABLE_TEXTURE_MIPMAPS LITERAL2 +ENABLE_TRANSFORM_CACHE LITERAL2 +ENABLE_STROKE_PERSPECTIVE LITERAL2 +ENTER LITERAL2 keyCode +EPSILON LITERAL2 +ERODE LITERAL2 filter_ +ESC LITERAL2 keyCode +EXCLUSION LITERAL2 blend_ +EXIT LITERAL2 +GIF LITERAL2 +GRAY LITERAL2 filter_ +GREEN_MASK LITERAL2 +GROUP LITERAL2 +HALF LITERAL2 +HALF_PI LITERAL2 HALF_PI +HAND LITERAL2 cursor_ +HARD_LIGHT LITERAL2 blend_ +HINT_COUNT LITERAL2 +HSB LITERAL2 colorMode_ +IMAGE LITERAL2 textureMode_ +INVERT LITERAL2 filter_ +JPEG LITERAL2 +LEFT LITERAL2 keyCode +LIGHTEST LITERAL2 blend_ +LINE LITERAL2 createShape_ +LINES LITERAL2 beginShape_ +LINUX LITERAL2 +MACOSX LITERAL2 +MAX_FLOAT LITERAL2 +MAX_INT LITERAL2 +MIN_FLOAT LITERAL2 +MIN_INT LITERAL2 +MITER LITERAL2 stokeJoin_ +MODEL LITERAL2 textMode_ +MOVE LITERAL2 cursor_ +MULTIPLY LITERAL2 blend_ +NORMAL LITERAL2 +NORMALIZED LITERAL2 textureMode_ +NO_DEPTH_TEST LITERAL2 +NTSC LITERAL2 +ONE LITERAL2 +OPAQUE LITERAL2 filter_ +OPEN LITERAL2 +ORTHOGRAPHIC LITERAL2 +OVERLAY LITERAL2 blend_ +PAL LITERAL2 +PDF LITERAL2 size_ +P2D LITERAL2 size_ +P3D LITERAL2 size_ +PERSPECTIVE LITERAL2 +PI LITERAL2 PI +PIE LITERAL2 +PIXEL_CENTER LITERAL2 +POINT LITERAL2 +POINTS LITERAL2 +POSTERIZE LITERAL2 filter_ +PRESS LITERAL2 +PROBLEM LITERAL2 +PROJECT LITERAL2 strokeCap_ +QUAD LITERAL2 createShape_ +QUAD_STRIP LITERAL2 beginShape_ +QUADS LITERAL2 beginShape_ +QUARTER_PI LITERAL2 QUARTER_PI +RAD_TO_DEG LITERAL2 +RADIUS LITERAL2 +RADIANS LITERAL2 +RECT LITERAL2 +RED_MASK LITERAL2 +RELEASE LITERAL2 +REPEAT LITERAL2 +REPLACE LITERAL2 +RETURN LITERAL2 +RGB LITERAL2 colorMode_ +RIGHT LITERAL2 keyCode +ROUND LITERAL2 strokeCap_ +SCREEN LITERAL2 blend_ +SECAM LITERAL2 +SHAPE LITERAL2 textMode_ +SHIFT LITERAL2 +SPECULAR LITERAL2 +SPHERE LITERAL2 createShape_ +SOFT_LIGHT LITERAL2 blend_ +SQUARE LITERAL2 strokeCap_ +SUBTRACT LITERAL2 blend_ +SVIDEO LITERAL2 +TAB LITERAL2 keyCode +TARGA LITERAL2 +TAU LITERAL2 TAU +TEXT LITERAL2 cursor_ +TFF LITERAL2 +THIRD_PI LITERAL2 +THRESHOLD LITERAL2 filter_ +TIFF LITERAL2 +TOP LITERAL2 textAlign_ +TRIANGLE LITERAL2 createShape_ +TRIANGLE_FAN LITERAL2 beginShape_ +TRIANGLES LITERAL2 beginShape_ +TRIANGLE_STRIP LITERAL2 beginShape_ +TUNER LITERAL2 +TWO LITERAL2 +TWO_PI LITERAL2 TWO_PI +UP LITERAL2 keyCode +WAIT LITERAL2 cursor_ +WHITESPACE LITERAL2 + + +# Java keywords (void, import, , etc.) + +abstract KEYWORD1 +assert KEYWORD1 +break KEYWORD1 break +case KEYWORD1 case +class KEYWORD1 class +continue KEYWORD1 continue +default KEYWORD1 default +enum KEYWORD1 +extends KEYWORD1 extends +false KEYWORD1 false +final KEYWORD1 final +finally KEYWORD1 +implements KEYWORD1 implements +import KEYWORD1 import +instanceof KEYWORD1 +interface KEYWORD1 +native KEYWORD1 +new KEYWORD1 new +null KEYWORD1 null +package KEYWORD1 +private KEYWORD1 private +protected KEYWORD1 +public KEYWORD1 public +return KEYWORD1 return +static KEYWORD1 static +strictfp KEYWORD1 +super KEYWORD1 super +this KEYWORD1 this +throw KEYWORD1 +throws KEYWORD1 +transient KEYWORD1 +true KEYWORD1 true +void KEYWORD1 void +volatile KEYWORD1 + + +# Datatypes + +Array KEYWORD5 Array +ArrayList KEYWORD5 ArrayList +Boolean KEYWORD5 +Byte KEYWORD5 +BufferedReader KEYWORD5 BufferedReader +Character KEYWORD5 +Class KEYWORD5 class +Double KEYWORD5 +Float KEYWORD5 +Integer KEYWORD5 +HashMap KEYWORD5 HashMap +PrintWriter KEYWORD5 PrintWriter +String KEYWORD5 String +StringBuffer KEYWORD5 +Thread KEYWORD5 +boolean KEYWORD5 boolean +byte KEYWORD5 byte +char KEYWORD5 char +color KEYWORD5 color_datatype +double KEYWORD5 double +float KEYWORD5 float +int KEYWORD5 int +long KEYWORD5 long +short KEYWORD5 + + +# Flow structures + +catch KEYWORD3 catch +do KEYWORD3 +for KEYWORD3 for +if KEYWORD3 if +else KEYWORD3 else +switch KEYWORD3 switch +synchronized KEYWORD3 +while KEYWORD3 while +try KEYWORD3 try + +catch FUNCTION3 catch +do FUNCTION3 +for FUNCTION3 for +if FUNCTION3 if +#else FUNCTION3 else +switch FUNCTION3 switch +synchronized FUNCTION3 +while FUNCTION3 while +#try FUNCTION3 try + + +# These items are a part of Processing but, but pages don't generate + +boolean FUNCTION1 booleanconvert_ +byte FUNCTION1 byteconvert_ +cache FUNCTION2 +char FUNCTION1 charconvert_ +start FUNCTION1 +stop FUNCTION1 +breakShape FUNCTION1 +createPath FUNCTION1 +float FUNCTION1 floatconvert_ +int FUNCTION1 intconvert_ +str FUNCTION1 strconvert_ +loadMatrix FUNCTION1 +parseBoolean FUNCTION1 +parseByte FUNCTION1 +parseChar FUNCTION1 +parseFloat FUNCTION1 +parseInt FUNCTION1 +saveFile FUNCTION1 +savePath FUNCTION1 +sketchFile FUNCTION1 +sketchPath FUNCTION1 + +readLine FUNCTION2 BufferedReader_readLine_ +close FUNCTION2 PrintWriter_close_ +flush FUNCTION2 PrintWriter_flush_ +print FUNCTION2 PrintWriter_print_ +println FUNCTION2 PrintWriter_println_ +charAt FUNCTION2 String_charAt_ +equals FUNCTION2 String_equals_ +indexOf FUNCTION2 String_indexOf_ +length FUNCTION2 String_length_ +substring FUNCTION2 String_substring_ +toLowerCase FUNCTION2 String_toLowerCase_ +toUpperCase FUNCTION2 String_toUpperCase_ + +length KEYWORD2 String + + +# Temporary additions 3 September 2012 as the reference is getting updated + +end FUNCTION1 +addChild FUNCTION1 + +# Operators are without KEYWORDS + ++= addassign ++ addition +[] arrayaccess += assign +& bitwiseAND +| bitwiseOR +, comma +// comment +? conditional +{} curlybraces +-- decrement +/ divide +/= divideassign +/** doccomment +. dot +== equality +> greaterthan +>= greaterthanorequalto +++ increment +!= inequality +<< leftshift +< lessthan +<= lessthanorequalto +&& logicalAND +! logicalNOT +|| logicalOR +- minus +% modulo +/* multilinecomment +* multiply +*= multiplyassign +() parentheses +>> rightshift +; semicolon +-= subtractassign + +# Suppressed from Generate to avoid conflicts with variables inside methods + +width KEYWORD4 width_ +height KEYWORD4 height_ + +PVector FUNCTION1 PVector +ArrayList FUNCTION1 ArrayList +HashMap FUNCTION1 HashMap + + +# THE TEXT ABOVE IS HAND-WRITTEN AND FOUND IN THE FILE "keywords_base.txt" +# THE TEXT BELOW IS AUTO-GENERATED +# +# SO DON'T +# TOUCH IT + + +abs FUNCTION1 abs_ +acos FUNCTION1 acos_ +alpha FUNCTION1 alpha_ +ambient FUNCTION1 ambient_ +ambientLight FUNCTION1 ambientLight_ +append FUNCTION1 append_ +applyMatrix FUNCTION1 applyMatrix_ +arc FUNCTION1 arc_ +arrayCopy FUNCTION1 arrayCopy_ +asin FUNCTION1 asin_ +atan FUNCTION1 atan_ +atan2 FUNCTION1 atan2_ +background FUNCTION1 background_ +beginCamera FUNCTION1 beginCamera_ +beginContour FUNCTION1 beginContour_ +beginRaw FUNCTION1 beginRaw_ +beginRecord FUNCTION1 beginRecord_ +beginShape FUNCTION1 beginShape_ +bezier FUNCTION1 bezier_ +bezierDetail FUNCTION1 bezierDetail_ +bezierPoint FUNCTION1 bezierPoint_ +bezierTangent FUNCTION1 bezierTangent_ +bezierVertex FUNCTION1 bezierVertex_ +binary FUNCTION1 binary_ +blend FUNCTION1 blend_ +blendColor FUNCTION1 blendColor_ +blendMode FUNCTION1 blendMode_ +blue FUNCTION1 blue_ +box FUNCTION1 box_ +brightness FUNCTION1 brightness_ +camera FUNCTION1 camera_ +ceil FUNCTION1 ceil_ +clear FUNCTION1 clear_ +clip FUNCTION1 clip_ +color FUNCTION1 color_ +colorMode FUNCTION1 colorMode_ +concat FUNCTION1 concat_ +constrain FUNCTION1 constrain_ +copy FUNCTION1 copy_ +cos FUNCTION1 cos_ +createFont FUNCTION1 createFont_ +createGraphics FUNCTION1 createGraphics_ +createImage FUNCTION1 createImage_ +createInput FUNCTION1 createInput_ +createOutput FUNCTION1 createOutput_ +createReader FUNCTION1 createReader_ +createShape FUNCTION1 createShape_ +createWriter FUNCTION1 createWriter_ +cursor FUNCTION1 cursor_ +curve FUNCTION1 curve_ +curveDetail FUNCTION1 curveDetail_ +curvePoint FUNCTION1 curvePoint_ +curveTangent FUNCTION1 curveTangent_ +curveTightness FUNCTION1 curveTightness_ +curveVertex FUNCTION1 curveVertex_ +day FUNCTION1 day_ +degrees FUNCTION1 degrees_ +directionalLight FUNCTION1 directionalLight_ +displayHeight KEYWORD4 displayHeight +displayWidth KEYWORD4 displayWidth +dist FUNCTION1 dist_ +draw FUNCTION4 draw +ellipse FUNCTION1 ellipse_ +ellipseMode FUNCTION1 ellipseMode_ +emissive FUNCTION1 emissive_ +endCamera FUNCTION1 endCamera_ +endContour FUNCTION1 endContour_ +endRaw FUNCTION1 endRaw_ +endRecord FUNCTION1 endRecord_ +endShape FUNCTION1 endShape_ +exit FUNCTION1 exit_ +exp FUNCTION1 exp_ +expand FUNCTION1 expand_ +fill FUNCTION1 fill_ +filter FUNCTION1 filter_ +FloatDict KEYWORD5 FloatDict +add FUNCTION2 FloatDict_add_ +clear FUNCTION2 FloatDict_clear_ +div FUNCTION2 FloatDict_div_ +get FUNCTION2 FloatDict_get_ +hasKey FUNCTION2 FloatDict_hasKey_ +keyArray FUNCTION2 FloatDict_keyArray_ +keys FUNCTION2 FloatDict_keys_ +mult FUNCTION2 FloatDict_mult_ +remove FUNCTION2 FloatDict_remove_ +set FUNCTION2 FloatDict_set_ +size FUNCTION2 FloatDict_size_ +sortKeys FUNCTION2 FloatDict_sortKeys_ +sortKeysReverse FUNCTION2 FloatDict_sortKeysReverse_ +sortValues FUNCTION2 FloatDict_sortValues_ +sortValuesReverse FUNCTION2 FloatDict_sortValuesReverse_ +sub FUNCTION2 FloatDict_sub_ +valueArray FUNCTION2 FloatDict_valueArray_ +values FUNCTION2 FloatDict_values_ +FloatList KEYWORD5 FloatList +add FUNCTION2 FloatList_add_ +append FUNCTION2 FloatList_append_ +array FUNCTION2 FloatList_array_ +clear FUNCTION2 FloatList_clear_ +div FUNCTION2 FloatList_div_ +get FUNCTION2 FloatList_get_ +hasValue FUNCTION2 FloatList_hasValue_ +max FUNCTION2 FloatList_max_ +min FUNCTION2 FloatList_min_ +mult FUNCTION2 FloatList_mult_ +remove FUNCTION2 FloatList_remove_ +reverse FUNCTION2 FloatList_reverse_ +set FUNCTION2 FloatList_set_ +shuffle FUNCTION2 FloatList_shuffle_ +size FUNCTION2 FloatList_size_ +sort FUNCTION2 FloatList_sort_ +sortReverse FUNCTION2 FloatList_sortReverse_ +sub FUNCTION2 FloatList_sub_ +floor FUNCTION1 floor_ +focused KEYWORD4 focused +frameCount KEYWORD4 frameCount +frameRate KEYWORD4 frameRate +frameRate FUNCTION1 frameRate_ +frustum FUNCTION1 frustum_ +get FUNCTION1 get_ +green FUNCTION1 green_ +HALF_PI LITERAL2 HALF_PI +hex FUNCTION1 hex_ +hint FUNCTION1 hint_ +hour FUNCTION1 hour_ +hue FUNCTION1 hue_ +image FUNCTION1 image_ +imageMode FUNCTION1 imageMode_ +IntDict KEYWORD5 IntDict +add FUNCTION2 IntDict_add_ +clear FUNCTION2 IntDict_clear_ +div FUNCTION2 IntDict_div_ +get FUNCTION2 IntDict_get_ +hasKey FUNCTION2 IntDict_hasKey_ +increment FUNCTION2 IntDict_increment_ +keyArray FUNCTION2 IntDict_keyArray_ +keys FUNCTION2 IntDict_keys_ +mult FUNCTION2 IntDict_mult_ +remove FUNCTION2 IntDict_remove_ +set FUNCTION2 IntDict_set_ +size FUNCTION2 IntDict_size_ +sortKeys FUNCTION2 IntDict_sortKeys_ +sortKeysReverse FUNCTION2 IntDict_sortKeysReverse_ +sortValues FUNCTION2 IntDict_sortValues_ +sortValuesReverse FUNCTION2 IntDict_sortValuesReverse_ +sub FUNCTION2 IntDict_sub_ +valueArray FUNCTION2 IntDict_valueArray_ +values FUNCTION2 IntDict_values_ +IntList KEYWORD5 IntList +add FUNCTION2 IntList_add_ +append FUNCTION2 IntList_append_ +array FUNCTION2 IntList_array_ +clear FUNCTION2 IntList_clear_ +div FUNCTION2 IntList_div_ +get FUNCTION2 IntList_get_ +hasValue FUNCTION2 IntList_hasValue_ +increment FUNCTION2 IntList_increment_ +max FUNCTION2 IntList_max_ +min FUNCTION2 IntList_min_ +mult FUNCTION2 IntList_mult_ +remove FUNCTION2 IntList_remove_ +reverse FUNCTION2 IntList_reverse_ +set FUNCTION2 IntList_set_ +shuffle FUNCTION2 IntList_shuffle_ +size FUNCTION2 IntList_size_ +sort FUNCTION2 IntList_sort_ +sortReverse FUNCTION2 IntList_sortReverse_ +sub FUNCTION2 IntList_sub_ +join FUNCTION1 join_ +JSONArray KEYWORD5 JSONArray +append FUNCTION2 JSONArray_append_ +getBoolean FUNCTION2 JSONArray_getBoolean_ +getFloat FUNCTION2 JSONArray_getFloat_ +getInt FUNCTION2 JSONArray_getInt_ +getIntArray FUNCTION2 JSONArray_getIntArray_ +getJSONArray FUNCTION2 JSONArray_getJSONArray_ +getJSONObject FUNCTION2 JSONArray_getJSONObject_ +getString FUNCTION2 JSONArray_getString_ +getStringArray FUNCTION2 JSONArray_getStringArray_ +remove FUNCTION2 JSONArray_remove_ +setBoolean FUNCTION2 JSONArray_setBoolean_ +setFloat FUNCTION2 JSONArray_setFloat_ +setInt FUNCTION2 JSONArray_setInt_ +getJSONArray FUNCTION2 JSONArray_setJSONArray_ +getJSONObject FUNCTION2 JSONArray_setJSONObject_ +setString FUNCTION2 JSONArray_setString_ +size FUNCTION2 JSONArray_size_ +JSONObject KEYWORD5 JSONObject +getBoolean FUNCTION2 JSONObject_getBoolean_ +getFloat FUNCTION2 JSONObject_getFloat_ +getInt FUNCTION2 JSONObject_getInt_ +getJSONArray FUNCTION2 JSONObject_getJSONArray_ +getJSONObject FUNCTION2 JSONObject_getJSONObject_ +getString FUNCTION2 JSONObject_getString_ +setBoolean FUNCTION2 JSONObject_setBoolean_ +setFloat FUNCTION2 JSONObject_setFloat_ +setInt FUNCTION2 JSONObject_setInt_ +setJSONArray FUNCTION2 JSONObject_setJSONArray_ +setJSONObject FUNCTION2 JSONObject_setJSONObject_ +setString FUNCTION2 JSONObject_setString_ +key KEYWORD4 key +keyCode KEYWORD4 keyCode +keyPressed FUNCTION4 keyPressed +keyPressed KEYWORD4 keyPressed +keyReleased FUNCTION4 keyReleased +keyTyped FUNCTION4 keyTyped +lerp FUNCTION1 lerp_ +lerpColor FUNCTION1 lerpColor_ +lightFalloff FUNCTION1 lightFalloff_ +lights FUNCTION1 lights_ +lightSpecular FUNCTION1 lightSpecular_ +line FUNCTION1 line_ +loadBytes FUNCTION1 loadBytes_ +loadFont FUNCTION1 loadFont_ +loadImage FUNCTION1 loadImage_ +loadJSONArray FUNCTION1 loadJSONArray_ +loadJSONObject FUNCTION1 loadJSONObject_ +loadPixels FUNCTION1 loadPixels_ +loadShader FUNCTION1 loadShader_ +loadShape FUNCTION1 loadShape_ +loadStrings FUNCTION1 loadStrings_ +loadTable FUNCTION1 loadTable_ +loadXML FUNCTION1 loadXML_ +log FUNCTION1 log_ +loop FUNCTION1 loop_ +mag FUNCTION1 mag_ +map FUNCTION1 map_ +match FUNCTION1 match_ +matchAll FUNCTION1 matchAll_ +max FUNCTION1 max_ +millis FUNCTION1 millis_ +min FUNCTION1 min_ +minute FUNCTION1 minute_ +modelX FUNCTION1 modelX_ +modelY FUNCTION1 modelY_ +modelZ FUNCTION1 modelZ_ +month FUNCTION1 month_ +mouseButton KEYWORD4 mouseButton +mouseClicked FUNCTION4 mouseClicked +mouseDragged FUNCTION4 mouseDragged +mouseMoved FUNCTION4 mouseMoved +mousePressed FUNCTION4 mousePressed +mousePressed KEYWORD4 mousePressed +mouseReleased FUNCTION1 mouseReleased_ +mouseWheel FUNCTION4 mouseWheel +mouseX KEYWORD4 mouseX +mouseY KEYWORD4 mouseY +nf FUNCTION1 nf_ +nfc FUNCTION1 nfc_ +nfp FUNCTION1 nfp_ +nfs FUNCTION1 nfs_ +noClip FUNCTION1 noClip_ +noCursor FUNCTION1 noCursor_ +noFill FUNCTION1 noFill_ +noise FUNCTION1 noise_ +noiseDetail FUNCTION1 noiseDetail_ +noiseSeed FUNCTION1 noiseSeed_ +noLights FUNCTION1 noLights_ +noLoop FUNCTION1 noLoop_ +norm FUNCTION1 norm_ +normal FUNCTION1 normal_ +noSmooth FUNCTION1 noSmooth_ +noStroke FUNCTION1 noStroke_ +noTint FUNCTION1 noTint_ +open FUNCTION1 open_ +ortho FUNCTION1 ortho_ +parseXML FUNCTION1 parseXML_ +perspective FUNCTION1 perspective_ +PFont KEYWORD5 PFont +list FUNCTION1 PFont_list_ +PGraphics KEYWORD5 PGraphics +beginDraw FUNCTION2 PGraphics_beginDraw_ +endDraw FUNCTION2 PGraphics_endDraw_ +PI LITERAL2 PI +PImage KEYWORD5 PImage +blend FUNCTION2 PImage_blend_ +copy FUNCTION2 PImage_copy_ +filter FUNCTION2 PImage_filter_ +get FUNCTION2 PImage_get_ +loadPixels FUNCTION2 PImage_loadPixels_ +mask FUNCTION2 PImage_mask_ +pixels KEYWORD2 PImage_pixels +resize FUNCTION2 PImage_resize_ +save FUNCTION2 PImage_save_ +set FUNCTION2 PImage_set_ +updatePixels FUNCTION2 PImage_updatePixels_ +pixels KEYWORD4 pixels +pmouseX KEYWORD4 pmouseX +pmouseY KEYWORD4 pmouseY +point FUNCTION1 point_ +pointLight FUNCTION1 pointLight_ +popMatrix FUNCTION1 popMatrix_ +popStyle FUNCTION1 popStyle_ +pow FUNCTION1 pow_ +print FUNCTION1 print_ +printCamera FUNCTION1 printCamera_ +println FUNCTION1 println_ +printMatrix FUNCTION1 printMatrix_ +printProjection FUNCTION1 printProjection_ +PShader KEYWORD5 PShader +PShader FUNCTION2 PShader_set_ +PShape KEYWORD5 PShape +addChild FUNCTION2 PShape_addChild_ +beginContour FUNCTION2 PShape_beginContour_ +disableStyle FUNCTION2 PShape_disableStyle_ +enableStyle FUNCTION2 PShape_enableStyle_ +endContour FUNCTION2 PShape_endContour_ +endShape FUNCTION2 PShape_endShape_ +getChild FUNCTION2 PShape_getChild_ +getChildCount FUNCTION2 PShape_getChildCount_ +getVertex FUNCTION2 PShape_getVertex_ +getVertexCount FUNCTION2 PShape_getVertexCount_ +isVisible FUNCTION2 PShape_isVisible_ +resetMatrix FUNCTION2 PShape_resetMatrix_ +rotate FUNCTION2 PShape_rotate_ +rotateX FUNCTION2 PShape_rotateX_ +rotateY FUNCTION2 PShape_rotateY_ +rotateZ FUNCTION2 PShape_rotateZ_ +scale FUNCTION2 PShape_scale_ +setVertex FUNCTION2 PShape_setVertex_ +setVisible FUNCTION2 PShape_setVisible_ +translate FUNCTION2 PShape_translate_ +pushMatrix FUNCTION1 pushMatrix_ +pushStyle FUNCTION1 pushStyle_ +PVector KEYWORD5 PVector +add FUNCTION2 PVector_add_ +angleBetween FUNCTION2 PVector_angleBetween_ +array FUNCTION2 PVector_array_ +copy FUNCTION2 PVector_copy_ +cross FUNCTION2 PVector_cross_ +dist FUNCTION2 PVector_dist_ +div FUNCTION2 PVector_div_ +dot FUNCTION2 PVector_dot_ +fromAngle FUNCTION2 PVector_fromAngle_ +get FUNCTION2 PVector_get_ +heading FUNCTION2 PVector_heading_ +lerp FUNCTION2 PVector_lerp_ +limit FUNCTION2 PVector_limit_ +mag FUNCTION2 PVector_mag_ +magSq FUNCTION2 PVector_magSq_ +mult FUNCTION2 PVector_mult_ +normalize FUNCTION2 PVector_normalize_ +random2D FUNCTION2 PVector_random2D_ +random3D FUNCTION2 PVector_random3D_ +rotate FUNCTION2 PVector_rotate_ +set FUNCTION2 PVector_set_ +setMag FUNCTION2 PVector_setMag_ +sub FUNCTION2 PVector_sub_ +quad FUNCTION1 quad_ +quadraticVertex FUNCTION1 quadraticVertex_ +QUARTER_PI LITERAL2 QUARTER_PI +radians FUNCTION1 radians_ +random FUNCTION1 random_ +randomGaussian FUNCTION1 randomGaussian_ +randomSeed FUNCTION1 randomSeed_ +rect FUNCTION1 rect_ +rectMode FUNCTION1 rectMode_ +red FUNCTION1 red_ +redraw FUNCTION1 redraw_ +requestImage FUNCTION1 requestImage_ +resetMatrix FUNCTION1 resetMatrix_ +resetShader FUNCTION1 resetShader_ +reverse FUNCTION1 reverse_ +rotate FUNCTION1 rotate_ +rotateX FUNCTION1 rotateX_ +rotateY FUNCTION1 rotateY_ +rotateZ FUNCTION1 rotateZ_ +round FUNCTION1 round_ +saturation FUNCTION1 saturation_ +save FUNCTION1 save_ +saveBytes FUNCTION1 saveBytes_ +saveFrame FUNCTION1 saveFrame_ +saveJSONArray FUNCTION1 saveJSONArray_ +saveJSONObject FUNCTION1 saveJSONObject_ +saveStream FUNCTION1 saveStream_ +saveStrings FUNCTION1 saveStrings_ +loadTable FUNCTION1 saveTable_ +saveXML FUNCTION1 saveXML_ +scale FUNCTION1 scale_ +screenX FUNCTION1 screenX_ +screenY FUNCTION1 screenY_ +screenZ FUNCTION1 screenZ_ +second FUNCTION1 second_ +selectFolder FUNCTION1 selectFolder_ +selectInput FUNCTION1 selectInput_ +selectOutput FUNCTION1 selectOutput_ +set FUNCTION1 set_ +setup FUNCTION4 setup +shader FUNCTION1 shader_ +shape FUNCTION1 shape_ +shapeMode FUNCTION1 shapeMode_ +shearX FUNCTION1 shearX_ +shearY FUNCTION1 shearY_ +shininess FUNCTION1 shininess_ +shorten FUNCTION1 shorten_ +sin FUNCTION1 sin_ +size FUNCTION1 size_ +smooth FUNCTION1 smooth_ +sort FUNCTION1 sort_ +specular FUNCTION1 specular_ +sphere FUNCTION1 sphere_ +sphereDetail FUNCTION1 sphereDetail_ +splice FUNCTION1 splice_ +split FUNCTION1 split_ +splitTokens FUNCTION1 splitTokens_ +spotLight FUNCTION1 spotLight_ +sq FUNCTION1 sq_ +sqrt FUNCTION1 sqrt_ +StringDict KEYWORD5 StringDict +clear FUNCTION2 StringDict_clear_ +get FUNCTION2 StringDict_get_ +hasKey FUNCTION2 StringDict_hasKey_ +keyArray FUNCTION2 StringDict_keyArray_ +keys FUNCTION2 StringDict_keys_ +remove FUNCTION2 StringDict_remove_ +set FUNCTION2 StringDict_set_ +size FUNCTION2 StringDict_size_ +sortKeys FUNCTION2 StringDict_sortKeys_ +sortKeysReverse FUNCTION2 StringDict_sortKeysReverse_ +sortValues FUNCTION2 StringDict_sortValues_ +sortValuesReverse FUNCTION2 StringDict_sortValuesReverse_ +valueArray FUNCTION2 StringDict_valueArray_ +values FUNCTION2 StringDict_values_ +StringList KEYWORD5 StringList +append FUNCTION2 StringList_append_ +array FUNCTION2 StringList_array_ +clear FUNCTION2 StringList_clear_ +get FUNCTION2 StringList_get_ +hasValue FUNCTION2 StringList_hasValue_ +lower FUNCTION2 StringList_lower_ +remove FUNCTION2 StringList_remove_ +reverse FUNCTION2 StringList_reverse_ +set FUNCTION2 StringList_set_ +shuffle FUNCTION2 StringList_shuffle_ +size FUNCTION2 StringList_size_ +sort FUNCTION2 StringList_sort_ +sortReverse FUNCTION2 StringList_sortReverse_ +upper FUNCTION2 StringList_upper_ +stroke FUNCTION1 stroke_ +strokeCap FUNCTION1 strokeCap_ +strokeJoin FUNCTION1 strokeJoin_ +strokeWeight FUNCTION1 strokeWeight_ +subset FUNCTION1 subset_ +Table KEYWORD5 Table +addColumn FUNCTION2 Table_addColumn_ +addRow FUNCTION2 Table_addRow_ +clearRows FUNCTION2 Table_clearRows_ +findRow FUNCTION2 Table_findRow_ +findRows FUNCTION2 Table_findRows_ +getColumnCount FUNCTION2 Table_getColumnCount_ +getFloat FUNCTION2 Table_getFloat_ +getInt FUNCTION2 Table_getInt_ +getRow FUNCTION2 Table_getRow_ +getRowCount FUNCTION2 Table_getRowCount_ +getString FUNCTION2 Table_getString_ +getStringColumn FUNCTION2 Table_getStringColumn_ +matchRow FUNCTION2 Table_matchRow_ +matchRows FUNCTION2 Table_matchRows_ +removeColumn FUNCTION2 Table_removeColumn_ +removeRow FUNCTION2 Table_removeRow_ +removeTokens FUNCTION2 Table_removeTokens_ +rows FUNCTION2 Table_rows_ +setFloat FUNCTION2 Table_setFloat_ +setInt FUNCTION2 Table_setInt_ +setString FUNCTION2 Table_setString_ +trim FUNCTION2 Table_trim_ +TableRow KEYWORD5 TableRow +getFloat FUNCTION2 TableRow_getFloat_ +getFloat FUNCTION2 TableRow_getInt_ +getString FUNCTION2 TableRow_getString_ +setFloat FUNCTION2 TableRow_setFloat_ +setInt FUNCTION2 TableRow_setInt_ +setString FUNCTION2 TableRow_setString_ +tan FUNCTION1 tan_ +TAU LITERAL2 TAU +text FUNCTION1 text_ +textAlign FUNCTION1 textAlign_ +textAscent FUNCTION1 textAscent_ +textDescent FUNCTION1 textDescent_ +textFont FUNCTION1 textFont_ +textLeading FUNCTION1 textLeading_ +textMode FUNCTION1 textMode_ +textSize FUNCTION1 textSize_ +texture FUNCTION1 texture_ +textureMode FUNCTION1 textureMode_ +textureWrap FUNCTION1 textureWrap_ +textWidth FUNCTION1 textWidth_ +tint FUNCTION1 tint_ +translate FUNCTION1 translate_ +triangle FUNCTION1 triangle_ +trim FUNCTION1 trim_ +TWO_PI LITERAL2 TWO_PI +unbinary FUNCTION1 unbinary_ +unhex FUNCTION1 unhex_ +updatePixels FUNCTION1 updatePixels_ +vertex FUNCTION1 vertex_ +XML KEYWORD5 XML +addChild FUNCTION2 XML_addChild_ +format FUNCTION2 XML_format_ +getAttributeCount FUNCTION2 XML_getAttributeCount_ +getChild FUNCTION2 XML_getChild_ +getChildren FUNCTION2 XML_getChildren_ +getContent FUNCTION2 XML_getContent_ +getFloat FUNCTION2 XML_getFloat_ +getContent FUNCTION2 XML_getFloatContent_ +getInt FUNCTION2 XML_getInt_ +getContent FUNCTION2 XML_getIntContent_ +getName FUNCTION2 XML_getName_ +getParent FUNCTION2 XML_getParent_ +getString FUNCTION2 XML_getString_ +hasAttribute FUNCTION2 XML_hasAttribute_ +hasChildren FUNCTION2 XML_hasChildren_ +listAttributes FUNCTION2 XML_listAttributes_ +listChildren FUNCTION2 XML_listChildren_ +removeChild FUNCTION2 XML_removeChild_ +setContent FUNCTION2 XML_setContent_ +setFloat FUNCTION2 XML_setFloat_ +setInt FUNCTION2 XML_setInt_ +setName FUNCTION2 XML_setName_ +setString FUNCTION2 XML_setString_ +toString FUNCTION2 XML_toString_ +year FUNCTION1 year_ diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 806e613..b7ba615 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -736,13 +736,13 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { suggestion.updateList(defListModel, subWord, location, position); suggestion.setVisible(true); -// requestFocusInWindow(); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - requestFocusInWindow(); - } - }); + requestFocusInWindow(); +// SwingUtilities.invokeLater(new Runnable() { +// @Override +// public void run() { +// requestFocusInWindow(); +// } +// }); } private void hideSuggestion() { diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 065fcbf..12fec47 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -188,8 +188,8 @@ protected void paintLine(Graphics gfx, TokenMarker tokenMarker, int line, try { //TODO: This line is causing NPE's randomly ever since I added the toggle for //Java Mode/Debugger toolbar. - super.paintLine(gfx, tokenMarker, line, x); - } catch (NullPointerException e) { + super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth()); + } catch (Exception e) { log(e.getMessage()); } } From d711e73cc05ad2fc1f647b70fd2836d68e43a3ca Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 04:54:58 +0530 Subject: [PATCH 047/193] save preferences everytime --- src/processing/mode/experimental/DebugEditor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index af738e7..ead7975 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -326,7 +326,6 @@ public void dispose() { // Added temporarily to dump error log. TODO: Remove this later public void internalCloseRunner(){ - dmode.savePreferences(); if(ExperimentalMode.errorLogsEnabled) writeErrorsToFile(); super.internalCloseRunner(); } @@ -530,6 +529,7 @@ public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) { ExperimentalMode.errorCheckEnabled = ((JCheckBoxMenuItem) e.getSource()).isSelected(); errorCheckerService.handleErrorCheckingToggle(); + dmode.savePreferences(); } }); debugMenu.add(item); @@ -561,6 +561,7 @@ public void actionPerformed(ActionEvent e) { ExperimentalMode.warningsEnabled = ((JCheckBoxMenuItem) e .getSource()).isSelected(); errorCheckerService.runManualErrorCheck(); + dmode.savePreferences(); } }); debugMenu.add(showWarnings); @@ -572,6 +573,7 @@ public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) { ExperimentalMode.codeCompletionsEnabled = (((JCheckBoxMenuItem) e .getSource()).isSelected()); + dmode.savePreferences(); } }); debugMenu.add(completionsEnabled); @@ -583,6 +585,7 @@ public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) { ExperimentalMode.DEBUG = ((JCheckBoxMenuItem) e .getSource()).isSelected(); + dmode.savePreferences(); } }); debugMenu.add(debugMessagesEnabled); @@ -598,6 +601,7 @@ public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) { ExperimentalMode.errorLogsEnabled = ((JCheckBoxMenuItem) e .getSource()).isSelected(); + dmode.savePreferences(); } }); debugMenu.add(writeErrorLog); From 40b8667fb77b0ed97c7106de1a0e30fb8ba832ae Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 05:30:06 +0530 Subject: [PATCH 048/193] search for missing imports in contrib libs --- .../mode/experimental/ASTGenerator.java | 24 +++++++++++++++---- .../experimental/ErrorCheckerService.java | 6 ++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index c563c43..ce466f7 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -94,6 +94,7 @@ import org.eclipse.jdt.core.dom.VariableDeclarationStatement; import processing.app.Base; +import processing.app.Library; import processing.app.SketchCode; import processing.app.Toolkit; import processing.mode.java.preproc.PdePreprocessor; @@ -3048,13 +3049,26 @@ public void suggestImports(final String className){ Pattern.CASE_INSENSITIVE)); String[] resources = classPath .findResources("", regf); - if(resources.length == 0){ - log("Couldn't find import for class " + className); - return; + ArrayList candidates = new ArrayList(); + for (String res : resources) { + candidates.add(res); + } + + // log("Couldn't find import for class " + className); + + for (Library lib : editor.dmode.contribLibraries) { + ClassPath cp = factory.createFromPath(lib.getClassPath()); + resources = cp.findResources("", regf); + for (String res : resources) { + candidates.add(res); + log("Res: " + res); + } } + + resources = new String[candidates.size()]; for (int i = 0; i < resources.length; i++) { - resources[i] = resources[i].replace('/', '.') - .substring(0, resources[i].length() - 6); + resources[i] = candidates.get(i).replace('/', '.') + .substring(0, candidates.get(i).length() - 6); } if (resources.length >= 1) { final JList classList = new JList(resources); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index cc66605..1697e41 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1276,9 +1276,9 @@ public static boolean scrollToErrorLine(Editor edt, int tabIndex, int lineNoInTa * compiler classpath needs to be updated. */ protected void checkForChangedImports() { - // log("Imports: " + programImports.size() + - // " Prev Imp: " - // + previousImports.size()); + log("Imports: " + programImports.size() + + " Prev Imp: " + + previousImports.size()); if (programImports.size() != previousImports.size()) { // log(1); loadCompClass = true; From 407356e5f3bb144a9aa223c09c60c4d1816a36ed Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 12:03:35 +0530 Subject: [PATCH 049/193] added doc listener finally. --- Todo, GSoC 2013.txt | 4 ++ .../experimental/ErrorCheckerService.java | 52 ++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 2079b1b..da4776a 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -119,6 +119,8 @@ Suggestion for missing imports 2. Find the class name via astGen, and suggest import as a popup. x Barebones functionality done. x Add imports only to beginning of first tab. +x Search within contributed libraries folder +* Search within code folder of sketch Labels for Java elements ======================== @@ -145,6 +147,8 @@ x boolean warningsEnabled - made it volatile General Stuff ============= +* Disabling Error Checking disables predictions as well! +x Added doc listener for text area updates x Consult Ben on where to save preferences - main preferences.txt or custom one. - Main prefs file x Save preferences to main preference.txt x Hide breakpoint markers when Debugger isn't active diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 1697e41..ba699cb 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -20,7 +20,10 @@ import java.util.regex.Pattern; import javax.swing.JCheckBoxMenuItem; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import javax.swing.table.DefaultTableModel; +import javax.swing.text.AbstractDocument; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.IProblem; @@ -35,6 +38,7 @@ import processing.app.Editor; import processing.app.Library; import processing.app.SketchCode; +import processing.app.syntax.SyntaxDocument; import processing.core.PApplet; import processing.mode.java.preproc.PdePreprocessor; @@ -203,6 +207,10 @@ public ErrorCheckerService(DebugEditor debugEditor) { containsErrors = new AtomicBoolean(true); errorMsgSimplifier = new ErrorMessageSimplifier(); tempErrorLog = new TreeMap(); + sketchChangedListener = new SketchChangedListener(); +// for (final SketchCode sc : editor.getSketch().getCode()) { +// sc.getDocument().addDocumentListener(sketchChangedListener); +// } } /** @@ -275,7 +283,7 @@ public void run() { updatePaintedThingys(); updateEditorStatus(); - + updateSketchCodeListeners(); if (pauseThread.get()) continue; if(textModified.get() == 0) @@ -290,6 +298,22 @@ public void run() { logE("Thread stopped: " + editor.getSketch().getName()); } + protected void updateSketchCodeListeners() { + for (final SketchCode sc : editor.getSketch().getCode()) { + boolean flag = false; + for (DocumentListener dl : ((SyntaxDocument)sc.getDocument()).getDocumentListeners()) { + if(dl.equals(sketchChangedListener)){ + flag = true; + break; + } + } + if(!flag){ + log("Adding doc listener to " + sc.getPrettyName()); + sc.getDocument().addDocumentListener(sketchChangedListener); + } + } + } + protected void checkForMissingImports() { for (Problem p : problemsList) { if(p.getMessage().endsWith(" cannot be resolved to a type"));{ @@ -323,6 +347,32 @@ public ASTGenerator getASTGenerator() { public void runManualErrorCheck() { textModified.incrementAndGet(); } + + protected SketchChangedListener sketchChangedListener; + protected class SketchChangedListener implements DocumentListener{ + + private SketchChangedListener(){ + } + + @Override + public void insertUpdate(DocumentEvent e) { + runManualErrorCheck(); + log("doc insert update, man error check.."); + } + + @Override + public void removeUpdate(DocumentEvent e) { + runManualErrorCheck(); + log("doc remove update, man error check.."); + } + + @Override + public void changedUpdate(DocumentEvent e) { + runManualErrorCheck(); + log("doc changed update, man error check.."); + } + + } protected boolean checkCode() { //log("checkCode() " + textModified.get() ); From a8b7a27aa3a3a667d83826519b55a0278e4b8f3b Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 12:18:21 +0530 Subject: [PATCH 050/193] fixed error check toggle. --- Todo, GSoC 2013.txt | 2 +- .../experimental/ErrorCheckerService.java | 43 ++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index da4776a..67638bb 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -147,7 +147,7 @@ x boolean warningsEnabled - made it volatile General Stuff ============= -* Disabling Error Checking disables predictions as well! +x Disabling Error Checking disables predictions as well! Fixed. x Added doc listener for text area updates x Consult Ben on where to save preferences - main preferences.txt or custom one. - Main prefs file x Save preferences to main preference.txt diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index ba699cb..c511eb7 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -345,6 +345,7 @@ public ASTGenerator getASTGenerator() { * Triggers error check */ public void runManualErrorCheck() { + log("Error Check."); textModified.incrementAndGet(); } @@ -356,20 +357,26 @@ private SketchChangedListener(){ @Override public void insertUpdate(DocumentEvent e) { - runManualErrorCheck(); - log("doc insert update, man error check.."); + if (ExperimentalMode.errorCheckEnabled){ + runManualErrorCheck(); + log("doc insert update, man error check.."); + } } @Override public void removeUpdate(DocumentEvent e) { - runManualErrorCheck(); - log("doc remove update, man error check.."); + if (ExperimentalMode.errorCheckEnabled){ + runManualErrorCheck(); + log("doc remove update, man error check.."); + } } @Override public void changedUpdate(DocumentEvent e) { - runManualErrorCheck(); - log("doc changed update, man error check.."); + if (ExperimentalMode.errorCheckEnabled){ + runManualErrorCheck(); + log("doc changed update, man error check.."); + } } } @@ -404,13 +411,18 @@ protected boolean checkCode() { log(editor.getSketch().getName() + "2 MCO " + mainClassOffset); } - - updateErrorTable(); - editor.updateErrorBar(problemsList); - updateEditorStatus(); - editor.getTextArea().repaint(); - updatePaintedThingys(); - editor.updateErrorToggle(); + if(ExperimentalMode.errorCheckEnabled){ + updateErrorTable(); + editor.updateErrorBar(problemsList); + updateEditorStatus(); + editor.getTextArea().repaint(); + updatePaintedThingys(); + editor.updateErrorToggle(); + } + else + { + log("Error Check disabled, so not updating UI."); + } int x = textModified.get(); //log("TM " + x); if (x >= 2) { @@ -878,6 +890,7 @@ public void updatePaintedThingys() { public void updateEditorStatus() { // editor.statusNotice("Position: " + // editor.getTextArea().getCaretLine()); + if(ExperimentalMode.errorCheckEnabled) synchronized (editor.errorBar.errorPoints) { for (ErrorMarker emarker : editor.errorBar.errorPoints) { if (emarker.getProblem().getLineNumber() == editor.getTextArea() @@ -1454,7 +1467,7 @@ public static String substituteUnicode(String program) { public void handleErrorCheckingToggle(){ if (!ExperimentalMode.errorCheckEnabled) { // unticked Menu Item - pauseThread(); + // pauseThread(); log(editor.getSketch().getName() + " - Error Checker paused."); editor.errorBar.errorPoints.clear(); @@ -1464,7 +1477,7 @@ public void handleErrorCheckingToggle(){ editor.getTextArea().repaint(); editor.errorBar.repaint(); } else { - resumeThread(); + //resumeThread(); log(editor.getSketch().getName() + " - Error Checker resumed."); runManualErrorCheck(); From c65031076f402d5ec9871d3abe99a41dccbb55aa Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 17:44:22 +0530 Subject: [PATCH 051/193] updated build.xml to produce dist zips --- build.properties | 1 + build.xml | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/build.properties b/build.properties index 656dbd7..3fbad5f 100644 --- a/build.properties +++ b/build.properties @@ -4,6 +4,7 @@ core.library.location=/home/quarkninja/Workspaces/processing-workspace/processin app.library.location=/home/quarkninja/Workspaces/processing-workspace/processing/app/ java.target.version=1.6 lib.name=ExperimentalMode +prettyName=PDE X dist=dist release=3 prettyVersion=1.0.0b diff --git a/build.xml b/build.xml index a3988d3..3feee8a 100644 --- a/build.xml +++ b/build.xml @@ -94,6 +94,14 @@ + + + + + From d1fb412a203ad6af77c9ea9290a5970d4cf77818 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 20:07:11 +0530 Subject: [PATCH 052/193] completion popup height now dynamic. --- Todo, GSoC 2013.txt | 1 + .../mode/experimental/CompletionPanel.java | 51 +++++++++++-------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 67638bb..f1752b2 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -44,6 +44,7 @@ Finer details *! p5 enhanced stuff in java, how does it fit in with everything else, and edge cases. Possibly add support for them. Offset handling improvements should help here. * Diamond operator isn't supported for now. Bummer. +x Completion popup height is now dynamic, decreases to fit. x Icons for completions? Or overkill right now? x 'Show Usage' menu item added x Show declaring class for completions diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 39ce00d..3b32a71 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -5,21 +5,19 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; -import java.awt.Dimension; +import java.awt.FontMetrics; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.io.File; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; -import javax.swing.Icon; -import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; import javax.swing.text.BadLocationException; import processing.app.syntax.JEditTextArea; @@ -39,8 +37,8 @@ public class CompletionPanel { protected DebugEditor editor; - public CompletionPanel(JEditTextArea textarea, int position, String subWord, - DefaultListModel items, Point location, DebugEditor dedit) { + public CompletionPanel(final JEditTextArea textarea, int position, String subWord, + DefaultListModel items, final Point location, DebugEditor dedit) { this.textarea = (TextArea) textarea; editor = dedit; this.insertionPosition = position; @@ -55,7 +53,7 @@ public CompletionPanel(JEditTextArea textarea, int position, String subWord, scrollPane = new JScrollPane(); scrollPane.setViewportView(completionList = createSuggestionList(position, items)); popupMenu.add(scrollPane, BorderLayout.CENTER); - popupMenu.setPopupSize(280, 250); //TODO: Eradicate this evil + popupMenu.setPopupSize(280, setHeight(items.getSize())); //TODO: Eradicate this evil this.textarea.errorCheckerService.getASTGenerator() .updateJavaDoc((CompletionCandidate) completionList.getSelectedValue()); popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) @@ -71,6 +69,14 @@ public void setVisible(boolean v){ log("Pred popup visible."); popupMenu.setVisible(v); } + + protected int setHeight(int itemCount){ + if(scrollPane.getHorizontalScrollBar().isVisible()) itemCount++; + FontMetrics fm = textarea.getFontMetrics(textarea.getFont()); + float h = (fm.getHeight() + fm.getDescent()*0.5f) * (itemCount + 1); + log("popup height " + Math.min(250,h)); + return Math.min(250,(int)h); // popup menu height + } private JList createSuggestionList(final int position, final DefaultListModel items) { @@ -92,23 +98,28 @@ public void mouseClicked(MouseEvent e) { return list; } - public boolean updateList(final DefaultListModel items, String newSubword, Point location, int position){ - scrollPane.getViewport().removeAll(); - Dimension dimen = popupMenu.getSize(); - completionList.setModel(items); - completionList.validate(); - completionList.setSelectedIndex(0); - scrollPane.setViewportView(completionList); - scrollPane.validate(); - popupMenu.setSize(dimen); - //popupMenu.setLocation(location); + public boolean updateList(final DefaultListModel items, String newSubword, + final Point location, int position) { this.subWord = new String(newSubword); if (subWord.indexOf('.') != -1) this.subWord = subWord.substring(subWord.lastIndexOf('.') + 1); insertionPosition = position; - log("Suggestion updated" + System.nanoTime()); - popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) - + location.y); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + scrollPane.getViewport().removeAll(); + completionList.setModel(items); + completionList.setSelectedIndex(0); + scrollPane.setViewportView(completionList); + popupMenu.setPopupSize(popupMenu.getSize().width, setHeight(items.getSize())); + log("Suggestion updated" + System.nanoTime()); + popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + + location.y); + completionList.validate(); + scrollPane.validate(); + popupMenu.validate(); + } + }); return true; } From 2f8ef70ef13ee83a491df46c8cffc932c81512e0 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 17 Sep 2013 23:45:04 +0530 Subject: [PATCH 053/193] Add GitHub link to PDE X Menu --- Todo, GSoC 2013.txt | 1 + src/processing/mode/experimental/DebugEditor.java | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index f1752b2..91c8af9 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -161,3 +161,4 @@ x On Run/Debug Console is visible(ProblemsList hidden) * Update wiki for Ctrl + H instead of Ctrl + J shortcuts x update build.xml to produce dists x Make this a contributed mode - mode.txt, github releases feature, version numbering, git tags, etc +x Add GitHub link to PDE X Menu diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index ead7975..644c67a 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -606,7 +606,16 @@ public void actionPerformed(ActionEvent e) { }); debugMenu.add(writeErrorLog); - + debugMenu.addSeparator(); + JMenuItem jitem = new JMenuItem("PDE X on GitHub"); + jitem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Base.openURL("https://github.com/processing/processing-experimental"); + } + }); + debugMenu.add(jitem); + return debugMenu; } From 51ba4024944d48863359255e7e85fdee018e202a Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 01:30:02 +0530 Subject: [PATCH 054/193] fix focus bug for Windows --- src/processing/mode/experimental/CompletionPanel.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 3b32a71..62c367d 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -56,6 +56,7 @@ public CompletionPanel(final JEditTextArea textarea, int position, String subWor popupMenu.setPopupSize(280, setHeight(items.getSize())); //TODO: Eradicate this evil this.textarea.errorCheckerService.getASTGenerator() .updateJavaDoc((CompletionCandidate) completionList.getSelectedValue()); + textarea.requestFocusInWindow(); popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y); log("Suggestion constructed" + System.nanoTime()); @@ -82,7 +83,7 @@ private JList createSuggestionList(final int position, final DefaultListModel items) { JList list = new JList(items); - list.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1)); + //list.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1)); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list.setSelectedIndex(0); list.addMouseListener(new MouseAdapter() { @@ -95,6 +96,7 @@ public void mouseClicked(MouseEvent e) { } }); list.setCellRenderer(new CustomListRenderer()); + list.setFocusable(false); return list; } @@ -113,6 +115,7 @@ public void run() { scrollPane.setViewportView(completionList); popupMenu.setPopupSize(popupMenu.getSize().width, setHeight(items.getSize())); log("Suggestion updated" + System.nanoTime()); + textarea.requestFocusInWindow(); popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y); completionList.validate(); From b130d8b1d12bb8a3834785c98b079d216bf2ee9d Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 01:31:10 +0530 Subject: [PATCH 055/193] lower suggestion window slightly --- src/processing/mode/experimental/TextArea.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index b7ba615..4abec78 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -719,7 +719,7 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { location.x = offsetToX(getCaretLine(), position - getLineStartOffset(getCaretLine())); location.y = lineToY(getCaretLine()) - + getPainter().getFontMetrics().getHeight(); + + getPainter().getFontMetrics().getHeight() + getPainter().getFontMetrics().getDescent(); log("TA position: " + location); } catch (Exception e2) { e2.printStackTrace(); From ff48f78daabba3a3211e2665302eb20ae8cadb4d Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 02:04:35 +0530 Subject: [PATCH 056/193] completion popup width dynamic fail --- Todo, GSoC 2013.txt | 1 + .../mode/experimental/CompletionPanel.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index 91c8af9..a9cd7c7 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -45,6 +45,7 @@ Finer details * Diamond operator isn't supported for now. Bummer. x Completion popup height is now dynamic, decreases to fit. +* Completion width can be dynamic, if really needed.. x Icons for completions? Or overkill right now? x 'Show Usage' menu item added x Show declaring class for completions diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 62c367d..08fc06a 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -9,6 +9,7 @@ import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.Iterator; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; @@ -78,6 +79,20 @@ protected int setHeight(int itemCount){ log("popup height " + Math.min(250,h)); return Math.min(250,(int)h); // popup menu height } + + /*TODO: Make width dynamic + protected int setWidth(){ + if(scrollPane.getVerticalScrollBar().isVisible()) return 280; + float min = 280; + FontMetrics fm = textarea.getFontMetrics(textarea.getFont()); + for (int i = 0; i < completionList.getModel().getSize(); i++) { + float h = fm.stringWidth(completionList.getModel().getElementAt(i).toString()); + min = Math.min(min, h); + } + min += fm.stringWidth(" "); + log("popup width " + Math.min(280,min)); + return Math.min(280,(int)min); // popup menu height + }*/ private JList createSuggestionList(final int position, final DefaultListModel items) { From d54cdb9f6d6de109bb1ac63600bd91b4715d7138 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 02:21:35 +0530 Subject: [PATCH 057/193] updated readme --- README.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4b944de..5f75d9e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,23 @@ -Experimental Mode for the PDE -========================= +PDE X +===== -This project is in the process of being moved out of the main project so that it can be developed in parallel with the PDE. Right now, it's in a messy state and not stable, forking isn't recommened. +PDE X is a [Processing](http://processing.org/) Mode that brings along powerful new features to the Processing Development Environment: -Stay tuned for updates. +* Intelligent Code Completion +* Quick Renaming(Refactoring) +* Quick Navigation +* Import Suggestions +* Live Error Checker +* Integrated Debugger + +Find out more at [Getting Started!](https://github.com/processing/processing-experimental/wiki/Getting-Started) + +####How to Install + +![Mode Button](http://i.imgur.com/cag1y10.png) + +Click on the down arrow besides the mode switch button, and select Add Mode. In the Mode Manager window, select PDE X and click 'Install'. Manindra Moharana -29 June 2013 +18 September 2013 From 9db39287dad7adb05a5bdc29e6c74dd0fc9de668 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 02:23:35 +0530 Subject: [PATCH 058/193] updated readme. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5f75d9e..7aca28b 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,6 @@ Click on the down arrow besides the mode switch button, and select Add Mode. In Manindra Moharana 18 September 2013 + +-- +PDE X is supported by [Google Summer of Code 2013](http://www.google-melange.com/gsoc/homepage/google/gsoc2013) \ No newline at end of file From 28271a26685c7bcdee6e0e873206de7c6c51ffdc Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 03:06:23 +0530 Subject: [PATCH 059/193] readme update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7aca28b..c4a28b8 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ PDE X is a [Processing](http://processing.org/) Mode that brings along powerful * Live Error Checker * Integrated Debugger -Find out more at [Getting Started!](https://github.com/processing/processing-experimental/wiki/Getting-Started) +Find out more at [Getting Started](https://github.com/processing/processing-experimental/wiki/Getting-Started) ####How to Install ![Mode Button](http://i.imgur.com/cag1y10.png) -Click on the down arrow besides the mode switch button, and select Add Mode. In the Mode Manager window, select PDE X and click 'Install'. +Click on the down arrow besides the mode switch button, and select Add Mode. In the Mode Manager window, select PDE X and click 'Install'. You'll need Processing 2.0.2 or higher. Manindra Moharana From f2e4ace79d139c5ef3d9d51dfe386c50e4b1cb23 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 15:23:04 +0530 Subject: [PATCH 060/193] a bit more work on import suggestions --- Todo, GSoC 2013.txt | 3 ++- mode.properties | 2 +- src/processing/mode/experimental/ASTGenerator.java | 14 ++++++++++++++ src/processing/mode/experimental/TextArea.java | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index a9cd7c7..f599eb4 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -122,7 +122,8 @@ Suggestion for missing imports x Barebones functionality done. x Add imports only to beginning of first tab. x Search within contributed libraries folder -* Search within code folder of sketch +x Hide suggestion list before showing import suggestions +x Search within code folder of sketch Labels for Java elements ======================== diff --git a/mode.properties b/mode.properties index 5029f19..b5ac007 100644 --- a/mode.properties +++ b/mode.properties @@ -1,4 +1,4 @@ -name=ExperimentalMode +name=PDE X authorList=[The Processing Foundation](http://processing.org) url=https://github.com/processing/processing-experimental sentence=The next generation of PDE diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index ce466f7..5e82877 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -3064,6 +3064,19 @@ public void suggestImports(final String className){ log("Res: " + res); } } + + if (editor.getSketch().hasCodeFolder()) { + File codeFolder = editor.getSketch().getCodeFolder(); + // get a list of .jar files in the "code" folder + // (class files in subfolders should also be picked up) + ClassPath cp = factory.createFromPath(Base + .contentsToClassPath(codeFolder)); + resources = cp.findResources("", regf); + for (String res : resources) { + candidates.add(res); + log("Res: " + res); + } + } resources = new String[candidates.size()]; for (int i = 0; i < resources.length; i++) { @@ -3115,6 +3128,7 @@ public void actionPerformed(ActionEvent evt) { editor.getY() + (editor.getHeight() - frmImportSuggest.getHeight()) / 2); + editor.ta.hideSuggestion(); frmImportSuggest.setVisible(true); } diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 4abec78..3e2a36f 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -745,7 +745,7 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { // }); } - private void hideSuggestion() { + protected void hideSuggestion() { if (suggestion != null) { suggestion.hide(); suggestion = null; From 3ea3ce1b5c380db7c2a7e68b3d2922ee13822880 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 16:07:17 +0530 Subject: [PATCH 061/193] improvements to import suggestions window --- Todo, GSoC 2013.txt | 2 +- .../mode/experimental/ASTGenerator.java | 47 ++++++++++++++----- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index f599eb4..cdd5026 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -75,7 +75,7 @@ Refactoring =========== * Undo misbehaves here, handle carefully. - +* Fails to rename the first defined global variable, if a javadoc comment precedes it. But owrds for single/multiline comments. Wth! x New Name is validated. x Ordered list in 'Show Usage' window x Add support for word select on right click and rename, mouse co-ordinates need to obtained carefully diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 5e82877..00ea002 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -3,14 +3,11 @@ import static processing.mode.experimental.ExperimentalMode.log; import static processing.mode.experimental.ExperimentalMode.logE; +import java.awt.BorderLayout; import java.awt.Dimension; -import java.awt.Point; import java.awt.Rectangle; -import java.awt.ScrollPane; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.WindowEvent; -import java.awt.event.WindowFocusListener; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -26,12 +23,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Stack; import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; import javax.swing.BorderFactory; @@ -51,13 +46,11 @@ import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.ListSelectionModel; -import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; -import javax.swing.table.DefaultTableModel; import javax.swing.text.BadLocationException; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; @@ -2208,6 +2201,7 @@ public void run() { + selText); lblRefactorOldName.setText("Current name: " + selText); + txtRenameField.setText(""); txtRenameField.requestFocus(); } }); @@ -3094,7 +3088,7 @@ public void suggestImports(final String className){ ((JComponent) frmImportSuggest.getContentPane()).setBorder(BorderFactory .createEmptyBorder(5, 5, 5, 5)); JLabel lbl = new JLabel("The class \"" + className - + "\" couldn't be determined, choose the import you need from the following list."); + + "\" couldn't be determined. You are probably missing one of the following imports:"); JScrollPane jsp = new JScrollPane(); jsp.setViewportView(classList); JButton btnInsertImport = new JButton("Insert import"); @@ -3118,11 +3112,38 @@ public void actionPerformed(ActionEvent evt) { } } }); - - frmImportSuggest.add(lbl); - frmImportSuggest.add(jsp); - frmImportSuggest.add(btnInsertImport); + + JButton btnCancel = new JButton("Cancel"); + btnCancel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + frmImportSuggest.setVisible(false); + } + }); + + JPanel panelTop = new JPanel(), panelBottom = new JPanel(), panelLabel = new JPanel(); + panelTop.setLayout(new BoxLayout(panelTop, BoxLayout.Y_AXIS)); + panelTop.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + panelLabel.setLayout(new BorderLayout()); + panelLabel.add(lbl,BorderLayout.CENTER); + panelTop.add(panelLabel); + panelTop.add(Box.createRigidArea(new Dimension(1, 5))); + panelTop.add(jsp); + panelBottom.setLayout(new BoxLayout(panelBottom, BoxLayout.X_AXIS)); + panelBottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + panelBottom .setLayout(new BoxLayout(panelBottom, BoxLayout.X_AXIS)); + panelBottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + panelBottom.add(Box.createHorizontalGlue()); + panelBottom.add(btnInsertImport); + panelBottom.add(Box.createRigidArea(new Dimension(15, 0))); + panelBottom.add(btnCancel); + +// frmImportSuggest.add(lbl); +// frmImportSuggest.add(jsp); +// frmImportSuggest.add(btnInsertImport); + frmImportSuggest.add(panelTop); + frmImportSuggest.add(panelBottom); frmImportSuggest.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + frmImportSuggest.setTitle("Import Suggestion"); frmImportSuggest.setLocation(editor.getX() + (editor.getWidth() - frmImportSuggest.getWidth()) / 2, editor.getY() From 378372cc9a90991871605eebfa18d6e3f29c7f75 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 16:08:16 +0530 Subject: [PATCH 062/193] updated mode.props --- mode.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode.properties b/mode.properties index b5ac007..e70030c 100644 --- a/mode.properties +++ b/mode.properties @@ -2,6 +2,6 @@ name=PDE X authorList=[The Processing Foundation](http://processing.org) url=https://github.com/processing/processing-experimental sentence=The next generation of PDE -paragraph=Intelligent Code Completion, Live Error Checker, Debugger, Auto Refactor, etc. +paragraph=Intelligent Code Completion, Quick Navigation, Refactoring, Live Error Checker, Debugger, etc. version=@@version@@ prettyVersion=@@pretty-version@@ From ff5d036916367c9917d7564c8ff2e97c18bb3861 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 23:29:44 +0530 Subject: [PATCH 063/193] reseting build props --- build.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.properties b/build.properties index 3fbad5f..4dfc002 100644 --- a/build.properties +++ b/build.properties @@ -1,7 +1,7 @@ -sketchbook.location=${user.home}/Documents/Processing -classpath.local.location=${user.home}/Documents/workspace/libs -core.library.location=/home/quarkninja/Workspaces/processing-workspace/processing/app/core/library -app.library.location=/home/quarkninja/Workspaces/processing-workspace/processing/app/ +sketchbook.location= +classpath.local.location= +core.library.location= +app.library.location= java.target.version=1.6 lib.name=ExperimentalMode prettyName=PDE X From 456e9963aa4bf2a8d00352334b95cafb09720bc7 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 23:30:33 +0530 Subject: [PATCH 064/193] ignoring build props --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 60f6819..e79cb31 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ bin mode/ExperimentalMode.jar dist +build.properties \ No newline at end of file From b83882aad824320b789a658399bf28e9fd5e43eb Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 18 Sep 2013 23:37:25 +0530 Subject: [PATCH 065/193] adding pdeX.txt --- pdeX.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 pdeX.txt diff --git a/pdeX.txt b/pdeX.txt new file mode 100644 index 0000000..08f2a61 --- /dev/null +++ b/pdeX.txt @@ -0,0 +1,7 @@ +name=PDE X +authorList=[The Processing Foundation](http://processing.org) +url=https://github.com/processing/processing-experimental +sentence=The next generation of PDE +paragraph=Intelligent Code Completion, Live Error Checker, Debugger, Auto Refactor, etc. +version=3 +prettyVersion=1.0.0b From 54efc33d4c6b0087b130e7ab74a77b8755bae8b2 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 25 Sep 2013 00:16:36 +0530 Subject: [PATCH 066/193] added FAQ link to readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c4a28b8..af8f5ef 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PDE X ===== -PDE X is a [Processing](http://processing.org/) Mode that brings along powerful new features to the Processing Development Environment: +PDE X is a [Processing](http://processing.org/) Mode that brings powerful new features to the Processing Development Environment: * Intelligent Code Completion * Quick Renaming(Refactoring) @@ -10,7 +10,7 @@ PDE X is a [Processing](http://processing.org/) Mode that brings along powerful * Live Error Checker * Integrated Debugger -Find out more at [Getting Started](https://github.com/processing/processing-experimental/wiki/Getting-Started) +Find out more at [Getting Started](https://github.com/processing/processing-experimental/wiki/Getting-Started). Or checkout the [FAQ](https://github.com/processing/processing-experimental/wiki/FAQ) ####How to Install @@ -20,7 +20,7 @@ Click on the down arrow besides the mode switch button, and select Add Mode. In Manindra Moharana -18 September 2013 +25 September 2013 -- PDE X is supported by [Google Summer of Code 2013](http://www.google-melange.com/gsoc/homepage/google/gsoc2013) \ No newline at end of file From fa259b09cb7a2f18a1268a39fb02aa0185d716c5 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 25 Sep 2013 02:42:12 +0530 Subject: [PATCH 067/193] Completion list now always recreated, fixes #19 --- .../mode/experimental/CompletionPanel.java | 1 + src/processing/mode/experimental/TextArea.java | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 08fc06a..a7fd9bb 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -115,6 +115,7 @@ public void mouseClicked(MouseEvent e) { return list; } + // possibly defunct public boolean updateList(final DefaultListModel items, String newSubword, final Point location, int position) { this.subWord = new String(newSubword); diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 3e2a36f..8025f96 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -708,9 +708,9 @@ public void run() { } protected void showSuggestion(DefaultListModel defListModel,String subWord) { + hideSuggestion(); if (defListModel.size() == 0) { log("TextArea: No suggestions to show."); - hideSuggestion(); return; } int position = getCaretPosition(); @@ -729,13 +729,13 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { if (subWord.length() < 2) { return; } - if (suggestion == null) - suggestion = new CompletionPanel(this, position, subWord, defListModel, - location,editor); - else - suggestion.updateList(defListModel, subWord, location, position); - - suggestion.setVisible(true); + //if (suggestion == null) + suggestion = new CompletionPanel(this, position, subWord, defListModel, + location,editor); +// else +// suggestion.updateList(defListModel, subWord, location, position); +// +// suggestion.setVisible(true); requestFocusInWindow(); // SwingUtilities.invokeLater(new Runnable() { // @Override @@ -748,6 +748,7 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { protected void hideSuggestion() { if (suggestion != null) { suggestion.hide(); + log("Suggestion hidden."); suggestion = null; } } From c5a6864a8d88e3a91aec910d24a6535b0e817f6a Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 25 Sep 2013 02:44:08 +0530 Subject: [PATCH 068/193] this should help in debugging --- src/processing/mode/experimental/DebugEditor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 644c67a..16d6350 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -241,6 +241,7 @@ public void actionPerformed(ActionEvent e) { ta.setECSandThemeforTextArea(errorCheckerService, dmode); addXQModeUI(); debugToolbarEnabled = new AtomicBoolean(false); + log("Sketch Path: " + path); } private void addXQModeUI(){ From 5a082c10ed333095a3377350c872f98d2922b7d7 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 25 Sep 2013 02:47:57 +0530 Subject: [PATCH 069/193] disabling those tiny rects, don't like 'em anymore --- .../mode/experimental/TextAreaPainter.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 12fec47..2e28125 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -365,12 +365,15 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { // gfx.fillRect(x1, y, rw, height); // Let the painting begin! - gfx.setColor(errorMarkerColor); - if (isWarning) { - gfx.setColor(warningMarkerColor); - } - gfx.fillRect(1, y + 2, 3, height - 2); + + // Little rect at starting of a line containing errors - disabling it for now +// gfx.setColor(errorMarkerColor); +// if (isWarning) { +// gfx.setColor(warningMarkerColor); +// } +// gfx.fillRect(1, y + 2, 3, height - 2); + gfx.setColor(errorColor); if (isWarning) { gfx.setColor(warningColor); From c1d1d189d5f8128620540ff984664420dbd969fe Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 25 Sep 2013 03:06:45 +0530 Subject: [PATCH 070/193] Adding a revisions file, to keep track of progress. --- revisions.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 revisions.txt diff --git a/revisions.txt b/revisions.txt new file mode 100644 index 0000000..8d68012 --- /dev/null +++ b/revisions.txt @@ -0,0 +1,17 @@ +PDE X v1.0.1b - 25 September, 2013 + +Bug fix + ++ Fixed a major issue where completion list was going blank. + https://github.com/processing/processing-experimental/issues/19 + +Changes + +- Removed the tiny markers shown at the start of error lines. Too. Much. Red. + + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + +PDE X v1.0.0b - 22 September, 2013 + +Boom! First Public Beta Release! + From 2b8c63ca79b5b87293c547d84b490b89ea142a70 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 25 Sep 2013 03:10:03 +0530 Subject: [PATCH 071/193] updated version no. --- pdeX.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdeX.txt b/pdeX.txt index 08f2a61..0b988f6 100644 --- a/pdeX.txt +++ b/pdeX.txt @@ -3,5 +3,5 @@ authorList=[The Processing Foundation](http://processing.org) url=https://github.com/processing/processing-experimental sentence=The next generation of PDE paragraph=Intelligent Code Completion, Live Error Checker, Debugger, Auto Refactor, etc. -version=3 -prettyVersion=1.0.0b +version=4 +prettyVersion=1.0.1b From e18c47b9fe03646cec27fbc93c3a5a71a9891c44 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 12 Oct 2013 11:09:42 +0530 Subject: [PATCH 072/193] Trying to solve the permgen out of memory problem --- Todo, GSoC 2013.txt | 4 ++++ .../experimental/ErrorCheckerService.java | 22 ++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index cdd5026..d2e5777 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -150,6 +150,10 @@ x boolean warningsEnabled - made it volatile General Stuff ============= +* [Critical] PermGen out of memory bug. Manually triggering GC after making the classloader null ensures permgen memory is reclaimed on editor exit. Max open window still limited by max permgen size. Also, added a classloadcounter in ECS to trigger GC periodically. +https://github.com/processing/processing-experimental/issues/1 +See: http://stackoverflow.com/questions/2095974/how-to-unload-a-already-loaded-class-in-java +I'm making the classLoader null, but what about the classes loaded by ASTGen? Investigate. x Disabling Error Checking disables predictions as well! Fixed. x Added doc listener for text area updates x Consult Ben on where to save preferences - main preferences.txt or custom one. - Main prefs file diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index c511eb7..1cc15d2 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -292,10 +292,14 @@ public void run() { checkCode(); checkForMissingImports(); } - checkerClass = null; + astGenerator.disposeAllWindows(); - astGenerator = null; + compilationChecker = null; + checkerClass = null; + classLoader = null; + System.gc(); logE("Thread stopped: " + editor.getSketch().getName()); + System.gc(); } protected void updateSketchCodeListeners() { @@ -558,7 +562,11 @@ public boolean accept(File file) { for (int i = 0; i < jarFiles.length; i++) { classpath[ii++] = jarFiles[i].toURI().toURL(); } - + + compilationChecker = null; + checkerClass = null; + classLoader = null; + System.gc(); // log("CP Len -- " + classpath.length); classLoader = new URLClassLoader(classpath); // log("1."); @@ -650,7 +658,15 @@ public boolean accept(File file) { // log("Compilecheck, Done."); } + private int loadClassCounter = 0; public URLClassLoader getSketchClassLoader() { + loadClassCounter++; + if(loadClassCounter > 100){ + loadClassCounter = 0; + classLoader = null; + System.gc(); + classLoader = new URLClassLoader(classpath); + } return classLoader; } From 0d62a27918f351f187f3e3865a86a8eb98fe4946 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 12 Oct 2013 11:21:50 +0530 Subject: [PATCH 073/193] completion gets hidden on editor losing focus. Fixes #21 --- src/processing/mode/experimental/DebugEditor.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 16d6350..953a4bf 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -28,6 +28,8 @@ import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; @@ -294,6 +296,16 @@ private void addXQModeUI(){ consoleProblemsPane.add(errorTableScrollPane, XQConsoleToggle.ERRORSLIST); consoleProblemsPane.add(console, XQConsoleToggle.CONSOLE); consolePanel.add(consoleProblemsPane, BorderLayout.CENTER); + + // ensure completion gets hidden on editor losing focus + addWindowFocusListener(new WindowFocusListener() { + public void windowLostFocus(WindowEvent e) { + ta.hideSuggestion(); + } + public void windowGainedFocus(WindowEvent e) { + + } + }); } // /** From 30da8611eef8374c291adf5ee0549a1a4ecf9603 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 12 Oct 2013 11:29:09 +0530 Subject: [PATCH 074/193] updated revisions.txt --- revisions.txt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/revisions.txt b/revisions.txt index 8d68012..6068571 100644 --- a/revisions.txt +++ b/revisions.txt @@ -1,3 +1,19 @@ + +PDE X v1.0.2b - October, 2013 + +Bug fixes + ++ Code completion window gets stuck when Processing loses focus + https://github.com/processing/processing-experimental/issues/21 + ++ Live-error checker in the experimental mode is inefficient with memory. + https://github.com/processing/processing-experimental/issues/1 + ++ Cmd + Left Click should be working again in OS X with Processing 2.1 + https://github.com/processing/processing-experimental/issues/11 + +. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + PDE X v1.0.1b - 25 September, 2013 Bug fix @@ -9,7 +25,7 @@ Changes - Removed the tiny markers shown at the start of error lines. Too. Much. Red. - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PDE X v1.0.0b - 22 September, 2013 From 68016c1b267f272e57852bbb9abc9ed76aee73fe Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 21 Oct 2013 11:56:41 +0530 Subject: [PATCH 075/193] updated painter to be 2.1 compatible --- revisions.txt | 2 ++ .../mode/experimental/TextAreaPainter.java | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/revisions.txt b/revisions.txt index 6068571..7f9f654 100644 --- a/revisions.txt +++ b/revisions.txt @@ -12,6 +12,8 @@ Bug fixes + Cmd + Left Click should be working again in OS X with Processing 2.1 https://github.com/processing/processing-experimental/issues/11 ++ TextAreaPainter updated for Processing 2.1 + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PDE X v1.0.1b - 25 September, 2013 diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 2e28125..4e8b888 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -172,26 +172,27 @@ private void loadTheme(ExperimentalMode mode) { @Override protected void paintLine(Graphics gfx, TokenMarker tokenMarker, int line, int x) { + try { + //TODO: This line is causing NPE's randomly ever since I added the toggle for + //Java Mode/Debugger toolbar. + super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth()); + } catch (Exception e) { + log(e.getMessage()); + } if(ta.editor.debugToolbarEnabled != null && ta.editor.debugToolbarEnabled.get()){ // paint gutter paintGutterBg(gfx, line, x); - paintLineBgColor(gfx, line, x + ta.getGutterWidth()); + // disabled line background after P5 2.1, since it adds highlight by default + //paintLineBgColor(gfx, line, x + ta.getGutterWidth()); paintGutterLine(gfx, line, x); // paint gutter symbol paintGutterText(gfx, line, x); - } + } paintErrorLine(gfx, line, x); - try { - //TODO: This line is causing NPE's randomly ever since I added the toggle for - //Java Mode/Debugger toolbar. - super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth()); - } catch (Exception e) { - log(e.getMessage()); - } } /** From 076e9d39d07d6a052ec0a78322a99c41023f3330 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 21 Oct 2013 12:50:54 +0530 Subject: [PATCH 076/193] release 1.0.2b --- build.xml | 2 +- pdeX.txt | 4 ++-- revisions.txt | 5 +++-- src/processing/mode/experimental/ErrorCheckerService.java | 5 +++++ 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/build.xml b/build.xml index 3feee8a..2fdfc8b 100644 --- a/build.xml +++ b/build.xml @@ -100,7 +100,7 @@ basedir="${dist}/" excludes="**/.DS_Store" /> - + diff --git a/pdeX.txt b/pdeX.txt index 0b988f6..803ecd0 100644 --- a/pdeX.txt +++ b/pdeX.txt @@ -3,5 +3,5 @@ authorList=[The Processing Foundation](http://processing.org) url=https://github.com/processing/processing-experimental sentence=The next generation of PDE paragraph=Intelligent Code Completion, Live Error Checker, Debugger, Auto Refactor, etc. -version=4 -prettyVersion=1.0.1b +version=5 +prettyVersion=1.0.2b diff --git a/revisions.txt b/revisions.txt index 7f9f654..ba37e8d 100644 --- a/revisions.txt +++ b/revisions.txt @@ -1,12 +1,13 @@ -PDE X v1.0.2b - October, 2013 +PDE X v1.0.2b - October 21, 2013 Bug fixes + Code completion window gets stuck when Processing loses focus https://github.com/processing/processing-experimental/issues/21 -+ Live-error checker in the experimental mode is inefficient with memory. ++ Live-error checker in the experimental mode is a bit more efficient with memory now. + You can have upto 7 editor windows open at a time with PDE X. https://github.com/processing/processing-experimental/issues/1 + Cmd + Left Click should be working again in OS X with Processing 2.1 diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 1cc15d2..b6b18e6 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -654,7 +654,12 @@ public boolean accept(File file) { .println(e + " compileCheck() problem. Somebody tried to mess with Experimental Mode files."); pauseThread(); + } catch(OutOfMemoryError e) { + System.err.println("Processing has used up its maximum alloted memory. Please close some Processing " + + " windows and then reopen this sketch."); + pauseThread(); } + // log("Compilecheck, Done."); } From f33f379cd48c23ec1c1064614cdb653d5725ff70 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 21 Oct 2013 15:04:47 +0530 Subject: [PATCH 077/193] added manual installation steps to ReadMe. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index af8f5ef..b536249 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,11 @@ Find out more at [Getting Started](https://github.com/processing/processing-expe Click on the down arrow besides the mode switch button, and select Add Mode. In the Mode Manager window, select PDE X and click 'Install'. You'll need Processing 2.0.2 or higher. +For installing it manually, download the latest version from [here](http://download.processing.org/pdeX.zip). Extract the zip contents into `/modes` folder. Restart Processing. + Manindra Moharana -25 September 2013 +21 October 2013 -- PDE X is supported by [Google Summer of Code 2013](http://www.google-melange.com/gsoc/homepage/google/gsoc2013) \ No newline at end of file From 56fd7d8ea45cfc830d898b7b97a1fa0ad0642d3b Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 21 Oct 2013 15:08:58 +0530 Subject: [PATCH 078/193] improved description --- revisions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/revisions.txt b/revisions.txt index ba37e8d..5581f04 100644 --- a/revisions.txt +++ b/revisions.txt @@ -6,7 +6,7 @@ Bug fixes + Code completion window gets stuck when Processing loses focus https://github.com/processing/processing-experimental/issues/21 -+ Live-error checker in the experimental mode is a bit more efficient with memory now. ++ Live-error checker is more efficient with memory now. You can have upto 7 editor windows open at a time with PDE X. https://github.com/processing/processing-experimental/issues/1 From 55ced1343a6eda579a6b54a09dd8e6a9ce4dca15 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 4 Dec 2013 02:05:44 +0530 Subject: [PATCH 079/193] Updated application folder, fixes #33 --- application/Info.plist.tmpl | 75 ++++++++++++++++++++++++++++++++++++ application/sketch.icns | Bin 0 -> 174666 bytes 2 files changed, 75 insertions(+) create mode 100644 application/Info.plist.tmpl create mode 100644 application/sketch.icns diff --git a/application/Info.plist.tmpl b/application/Info.plist.tmpl new file mode 100644 index 0000000..787f56e --- /dev/null +++ b/application/Info.plist.tmpl @@ -0,0 +1,75 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + @@sketch@@ + CFBundleIconFile + sketch.icns + CFBundleIdentifier + @@sketch@@ + CFBundleDisplayName + @@sketch@@ + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + @@sketch@@ + CFBundlePackageType + APPL + + + CFBundleShortVersionString + 1 + CFBundleVersion + 1 + CFBundleSignature + ???? + NSHumanReadableCopyright + Your copyright here + CFBundleGetInfoString + Created with Processing + + + JVMRuntime + @@jdk_folder@@ + + JVMMainClassName + @@sketch@@ + + LSMinimumSystemVersion + 10.7.3 + + NSHighResolutionCapable + + + LSArchitecturePriority + + x86_64 + + + LSEnvironment + + LC_CTYPE + UTF-8 + + + LSUIPresentationMode + @@lsuipresentationmode@@ + + JVMOptions + + @@jvm_options_list@@ + -Xdock:icon=Contents/Resources/sketch.icns + -Dapple.laf.useScreenMenuBar=true + -Dcom.apple.macos.use-file-dialog-packages=true + -Dcom.apple.macos.useScreenMenuBar=true + -Dcom.apple.mrj.application.apple.menu.about.name=@@sketch@@ + -Dcom.apple.smallTabs=true + + JVMArguments + + + + diff --git a/application/sketch.icns b/application/sketch.icns new file mode 100644 index 0000000000000000000000000000000000000000..2bdb4dfc22bf16a82544999627970c89d7d63939 GIT binary patch literal 174666 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�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

QXfc16$dVbe$MlV15l4Yvr8~)<% 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 z Date: Sat, 7 Dec 2013 02:56:12 +0530 Subject: [PATCH 080/193] bit of refactoring and tidying things up --- .../mode/experimental/ASTGenerator.java | 33 +++++++++++-------- .../mode/experimental/CompletionPanel.java | 6 ++-- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 00ea002..b026fb5 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -109,7 +109,7 @@ public class ASTGenerator { /** * AST Window */ - protected JFrame frame2; + protected JFrame frmASTView; protected JFrame frameAutoComp; @@ -153,14 +153,15 @@ public ASTGenerator(ErrorCheckerService ecs) { } protected void setupGUI(){ - frame2 = new JFrame(); + frmASTView = new JFrame(); jtree = new JTree(); - frame2.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); - frame2.setBounds(new Rectangle(680, 100, 460, 620)); + frmASTView.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + frmASTView.setBounds(new Rectangle(680, 100, 460, 620)); + frmASTView.setTitle("AST View - " + editor.getSketch().getName()); JScrollPane sp = new JScrollPane(); sp.setViewportView(jtree); - frame2.add(sp); + frmASTView.add(sp); btnRename = new JButton("Rename"); btnListOccurrence = new JButton("Show Usage"); @@ -231,6 +232,8 @@ protected void setupGUI(){ } + + public static final boolean SHOWAST = true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { @@ -267,14 +270,16 @@ protected Object doInBackground() throws Exception { protected void done() { if (codeTree != null) { -// if (jtree.hasFocus() || frame2.hasFocus()) -// return; -// jtree.setModel(new DefaultTreeModel(codeTree)); -// ((DefaultTreeModel) jtree.getModel()).reload(); -// jtree.validate(); -// if (!frame2.isVisible()) { -// frame2.setVisible(true); -// } + if(SHOWAST){ + if (jtree.hasFocus() || frmASTView.hasFocus()) + return; + jtree.setModel(new DefaultTreeModel(codeTree)); + ((DefaultTreeModel) jtree.getModel()).reload(); + jtree.validate(); + if (!frmASTView.isVisible()) { + frmASTView.setVisible(true); + } + } // if (!frameAutoComp.isVisible()) { // // frameAutoComp.setVisible(true); @@ -3156,7 +3161,7 @@ public void actionPerformed(ActionEvent e) { } public void disposeAllWindows(){ - disposeWindow(frame2); + disposeWindow(frmASTView); disposeWindow(frameAutoComp); disposeWindow(frmImportSuggest); disposeWindow(frmOccurenceList); diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index a7fd9bb..7973b76 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -60,7 +60,7 @@ public CompletionPanel(final JEditTextArea textarea, int position, String subWor textarea.requestFocusInWindow(); popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y); - log("Suggestion constructed" + System.nanoTime()); + //log("Suggestion constructed" + System.nanoTime()); } public boolean isVisible() { @@ -130,7 +130,7 @@ public void run() { completionList.setSelectedIndex(0); scrollPane.setViewportView(completionList); popupMenu.setPopupSize(popupMenu.getSize().width, setHeight(items.getSize())); - log("Suggestion updated" + System.nanoTime()); + //log("Suggestion updated" + System.nanoTime()); textarea.requestFocusInWindow(); popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y); @@ -176,7 +176,7 @@ public boolean insertSelection() { public void hide() { popupMenu.setVisible(false); - log("Suggestion hidden" + System.nanoTime()); + //log("Suggestion hidden" + System.nanoTime()); //textarea.errorCheckerService.getASTGenerator().jdocWindowVisible(false); } From bfcd4598cc8d4e7f9c379868c70bd24664adc5d1 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 7 Dec 2013 03:22:16 +0530 Subject: [PATCH 081/193] Isolated the problem --- src/processing/mode/experimental/ASTGenerator.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index b026fb5..25a260f 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -566,6 +566,9 @@ public ClassMember resolveExpression3rdParty(ASTNode nearestNode, case ASTNode.FIELD_ACCESS: FieldAccess fa = (FieldAccess) astNode; if (fa.getExpression() == null) { + + // TODO: Check for existence of 'new' keyword. Could be a ClassInstanceCreation + // Local code or belongs to super class log("FA,Not implemented."); return null; @@ -607,6 +610,7 @@ public ClassMember resolveExpression3rdParty(ASTNode nearestNode, return new ClassMember(extracTypeInfo(temp)); } if (mi.getExpression() == null) { +// if() //Local code or belongs to super class log("MI,Not implemented."); return null; @@ -864,7 +868,11 @@ public void preparePredictions(final String word, final int line, final int line ASTNode testnode = parser.createAST(null); //logE("PREDICTION PARSER PROBLEMS: " + parser); // Find closest ASTNode of the document to this word - logE("Typed: " + word2 + "|"); + logE("Typed: " + word2 + "|" + " temp Node type: " + testnode.getClass().getSimpleName()); + if(testnode instanceof MethodInvocation){ + MethodInvocation mi = (MethodInvocation)testnode; + System.out.println(mi.getName() + "," + mi.getExpression() + "," + mi.typeArguments().size()); + } nearestNode = findClosestNode(lineNumber, (ASTNode) compilationUnit.types() .get(0)); if (nearestNode == null) From 336d885cce64bdc6cf8c150ebf8389d44a1502fc Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Thu, 2 Jan 2014 11:33:48 +0530 Subject: [PATCH 082/193] Outline window width fixed. Fixes #31 --- src/processing/mode/experimental/ASTGenerator.java | 2 +- src/processing/mode/experimental/SketchOutline.java | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 25a260f..03343de 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -233,7 +233,7 @@ protected void setupGUI(){ } - public static final boolean SHOWAST = true; + public static final boolean SHOWAST = !true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { diff --git a/src/processing/mode/experimental/SketchOutline.java b/src/processing/mode/experimental/SketchOutline.java index 6577adf..13cb729 100644 --- a/src/processing/mode/experimental/SketchOutline.java +++ b/src/processing/mode/experimental/SketchOutline.java @@ -67,7 +67,8 @@ public SketchOutline(DefaultMutableTreeNode codeTree, ErrorCheckerService ecs) { //TODO: ^Absolute dimensions are bad bro - int minWidth = 200; + int minWidth = (int) (editor.getMinimumSize().width * 0.7f), + maxWidth = (int) (editor.getMinimumSize().width * 0.9f); frmOutlineView.setLayout(new BoxLayout(frmOutlineView.getContentPane(), BoxLayout.Y_AXIS)); JPanel panelTop = new JPanel(), panelBottom = new JPanel(); @@ -95,19 +96,20 @@ public SketchOutline(DefaultMutableTreeNode codeTree, ErrorCheckerService ecs) { jsp.setViewportView(soTree); jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - jsp.setMinimumSize(new Dimension(minWidth, 100)); + jsp.setMinimumSize(new Dimension(minWidth, editor.ta.getHeight() - 10)); + jsp.setMaximumSize(new Dimension(maxWidth, editor.ta.getHeight() - 10)); panelBottom.add(jsp); frmOutlineView.add(panelTop); frmOutlineView.add(panelBottom); frmOutlineView.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frmOutlineView.pack(); frmOutlineView.setBounds(tp.x + errorCheckerService.getEditor().ta .getWidth() - minWidth, tp.y, minWidth, - Math.min(editor.ta.getHeight(), 150)); + Math.min(editor.ta.getHeight(), frmOutlineView.getHeight())); frmOutlineView.setMinimumSize(new Dimension(minWidth, Math - .min(errorCheckerService.getEditor().ta.getHeight(), 150))); - frmOutlineView.pack(); + .min(errorCheckerService.getEditor().ta.getHeight(), frmOutlineView.getHeight()))); frmOutlineView.setLocation(tp.x + errorCheckerService.getEditor().ta .getWidth() - frmOutlineView.getWidth(), From 5a6fcf40e09dfd82700ab5c8ff567debfd1e5644 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 11 Jan 2014 20:28:31 +0530 Subject: [PATCH 083/193] Beginning auto save impl --- .../mode/experimental/AutoSaveUtil.java | 50 +++++++++++++++++++ .../mode/experimental/DebugEditor.java | 4 ++ 2 files changed, 54 insertions(+) create mode 100644 src/processing/mode/experimental/AutoSaveUtil.java diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java new file mode 100644 index 0000000..6e36c35 --- /dev/null +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -0,0 +1,50 @@ +package processing.mode.experimental; + +import java.util.Timer; +import java.util.TimerTask; + +public class AutoSaveUtil { + + private DebugEditor editor; + + private Timer timer; + + private int saveTime; + + /** + * + * @param dedit + * @param timeOut - in minutes + */ + public AutoSaveUtil(DebugEditor dedit, int timeOut){ + editor = dedit; + if (timeOut < 5) { + saveTime = -1; + throw new IllegalArgumentException(""); + } + else{ + saveTime = timeOut * 60 * 1000; + } + } + + public void init(){ + if(saveTime < 1000) return; + saveTime = 1000; + timer = new Timer(); + timer.schedule(new SaveTask(), saveTime, saveTime); + } + + private class SaveTask extends TimerTask{ + + @Override + public void run() { + ExperimentalMode.log("Saved " + editor.getSketch().getMainFilePath()); + } + + } + + public static void main(String[] args) { + + } + +} diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 953a4bf..dcbfa4d 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -177,6 +177,8 @@ public class DebugEditor extends JavaEditor implements ActionListener { */ protected JCheckBoxMenuItem completionsEnabled; + protected AutoSaveUtil autosaver; + public DebugEditor(Base base, String path, EditorState state, Mode mode) { super(base, path, state, mode); @@ -244,6 +246,8 @@ public void actionPerformed(ActionEvent e) { addXQModeUI(); debugToolbarEnabled = new AtomicBoolean(false); log("Sketch Path: " + path); + autosaver = new AutoSaveUtil(this, 5); + autosaver.init(); } private void addXQModeUI(){ From 13868a3528782837a9e70fcde184c35424defc80 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 11 Jan 2014 21:01:37 +0530 Subject: [PATCH 084/193] added save funtion --- .../mode/experimental/AutoSaveUtil.java | 146 +++++++++++++++++- 1 file changed, 144 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 6e36c35..d5a7285 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -1,8 +1,14 @@ package processing.mode.experimental; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; import java.util.Timer; import java.util.TimerTask; +import processing.app.Base; +import processing.app.Sketch; + public class AutoSaveUtil { private DebugEditor editor; @@ -29,16 +35,152 @@ public AutoSaveUtil(DebugEditor dedit, int timeOut){ public void init(){ if(saveTime < 1000) return; - saveTime = 1000; + saveTime = 3000; timer = new Timer(); timer.schedule(new SaveTask(), saveTime, saveTime); } + private boolean saveSketch() throws IOException{ + + Sketch sc = editor.getSketch(); + File autosaveDir = new File(sc.getFolder().getAbsolutePath() + File.separator + ".autosave"); + if(!autosaveDir.exists()){ + autosaveDir = new File(sc.getFolder().getAbsolutePath(), ".autosave"); + autosaveDir.mkdir(); + } + String newParentDir = autosaveDir + File.separator + sc.getName() + System.currentTimeMillis(); + String newName = sc.getName(); + + + // check on the sanity of the name + String sanitaryName = Sketch.checkName(newName); + File newFolder = new File(newParentDir, sanitaryName); + if (!sanitaryName.equals(newName) && newFolder.exists()) { + Base.showMessage("Cannot Save", + "A sketch with the cleaned name\n" + + "“" + sanitaryName + "” already exists."); + return false; + } + newName = sanitaryName; + +// String newPath = newFolder.getAbsolutePath(); +// String oldPath = folder.getAbsolutePath(); + +// if (newPath.equals(oldPath)) { +// return false; // Can't save a sketch over itself +// } + + // make sure there doesn't exist a tab with that name already + // but ignore this situation for the first tab, since it's probably being + // resaved (with the same name) to another location/folder. + for (int i = 1; i < sc.getCodeCount(); i++) { + if (newName.equalsIgnoreCase(sc.getCode()[i].getPrettyName())) { + Base.showMessage("Nope", + "You can't save the sketch as \"" + newName + "\"\n" + + "because the sketch already has a tab with that name."); + return false; + } + } + + + + // if the new folder already exists, then first remove its contents before + // copying everything over (user will have already been warned). + if (newFolder.exists()) { + Base.removeDir(newFolder); + } + // in fact, you can't do this on Windows because the file dialog + // will instead put you inside the folder, but it happens on OS X a lot. + + // now make a fresh copy of the folder + newFolder.mkdirs(); + + // grab the contents of the current tab before saving + // first get the contents of the editor text area + if (sc.getCurrentCode().isModified()) { + sc.getCurrentCode().setProgram(editor.getText()); + } + + File[] copyItems = sc.getFolder().listFiles(new FileFilter() { + public boolean accept(File file) { + String name = file.getName(); + // just in case the OS likes to return these as if they're legit + if (name.equals(".") || name.equals("..")) { + return false; + } + // list of files/folders to be ignored during "save as" + for (String ignorable : editor.getMode().getIgnorable()) { + if (name.equals(ignorable)) { + return false; + } + } + // ignore the extensions for code, since that'll be copied below + for (String ext : editor.getMode().getExtensions()) { + if (name.endsWith(ext)) { + return false; + } + } + // don't do screen captures, since there might be thousands. kind of + // a hack, but seems harmless. hm, where have i heard that before... + if (name.startsWith("screen-")) { + return false; + } + return true; + } + }); + // now copy over the items that make sense + for (File copyable : copyItems) { + if (copyable.isDirectory()) { + Base.copyDir(copyable, new File(newFolder, copyable.getName())); + } else { + Base.copyFile(copyable, new File(newFolder, copyable.getName())); + } + } + + // save the other tabs to their new location + for (int i = 1; i < sc.getCodeCount(); i++) { + File newFile = new File(newFolder, sc.getCode()[i].getFileName()); + sc.getCode()[i].saveAs(newFile); + } + + // While the old path to the main .pde is still set, remove the entry from + // the Recent menu so that it's not sticking around after the rename. + // If untitled, it won't be in the menu, so there's no point. +// if (!isUntitled()) { +// editor.removeRecent(); +// } + + // save the main tab with its new name + File newFile = new File(newFolder, newName + ".pde"); + sc.getCode()[0].saveAs(newFile); + +// updateInternal(newName, newFolder); +// +// // Make sure that it's not an untitled sketch +// setUntitled(false); +// +// // Add this sketch back using the new name +// editor.addRecent(); + + // let Editor know that the save was successful + return true; + } + private class SaveTask extends TimerTask{ @Override public void run() { - ExperimentalMode.log("Saved " + editor.getSketch().getMainFilePath()); + try { + saveSketch(); + ExperimentalMode.log("Saved " + editor.getSketch().getMainFilePath()); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + //editor + + } } From 49d5383af2af9915d27212bc76cf4e926549f26f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 11 Jan 2014 21:02:38 +0530 Subject: [PATCH 085/193] updated ignorable files --- src/processing/mode/experimental/ExperimentalMode.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 9417f94..2ac6ad3 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -253,4 +253,14 @@ public static final void log2(Object message){ if(ExperimentalMode.DEBUG) System.out.print(message); } + + public String[] getIgnorable() { + return new String[] { + "applet", + "application.macosx", + "application.windows", + "application.linux", + ".autosave" + }; + } } From 6c7fdbfebc2ae3de25adec0c0173ded13b8c613c Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 11 Jan 2014 21:14:25 +0530 Subject: [PATCH 086/193] only single backup remains --- .../mode/experimental/AutoSaveUtil.java | 21 ++++++++++++++++++- .../mode/experimental/DebugEditor.java | 3 ++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index d5a7285..6eacf79 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -40,15 +40,30 @@ public void init(){ timer.schedule(new SaveTask(), saveTime, saveTime); } + public void shutDown(){ + timer.cancel(); + } + private boolean saveSketch() throws IOException{ Sketch sc = editor.getSketch(); File autosaveDir = new File(sc.getFolder().getAbsolutePath() + File.separator + ".autosave"); + boolean deleteOldSave = false; + String oldSave = null; if(!autosaveDir.exists()){ autosaveDir = new File(sc.getFolder().getAbsolutePath(), ".autosave"); autosaveDir.mkdir(); } - String newParentDir = autosaveDir + File.separator + sc.getName() + System.currentTimeMillis(); + else + { + // delete the previous backup after saving current one. + String prevSaves[] = Base.listFiles(autosaveDir, false); + if(prevSaves.length > 0){ + deleteOldSave = true; + oldSave = prevSaves[0]; + } + } + String newParentDir = autosaveDir + File.separator + System.currentTimeMillis(); String newName = sc.getName(); @@ -163,6 +178,10 @@ public boolean accept(File file) { // editor.addRecent(); // let Editor know that the save was successful + + if(deleteOldSave) + Base.removeDir(new File(oldSave)); + return true; } diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index dcbfa4d..c949225 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -331,9 +331,10 @@ public void windowGainedFocus(WindowEvent e) { */ @Override public void dispose() { + autosaver.shutDown(); //System.out.println("window dispose"); // quit running debug session - dbg.stopDebug(); + dbg.stopDebug(); // remove var.inspector vi.dispose(); errorCheckerService.stopThread(); From a0edae8148142ec9b34a0bfcdd4054c74897417b Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 11 Jan 2014 21:34:28 +0530 Subject: [PATCH 087/193] further work on auto save --- .../mode/experimental/AutoSaveUtil.java | 21 +++++++++++++------ .../mode/experimental/DebugEditor.java | 2 +- .../mode/experimental/ExperimentalMode.java | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 6eacf79..5ed6f77 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -17,6 +17,9 @@ public class AutoSaveUtil { private int saveTime; + private File autosaveDir; + + private boolean isSaving; /** * * @param dedit @@ -31,27 +34,31 @@ public AutoSaveUtil(DebugEditor dedit, int timeOut){ else{ saveTime = timeOut * 60 * 1000; } + autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); } public void init(){ if(saveTime < 1000) return; - saveTime = 3000; + saveTime = 10 * 1000; timer = new Timer(); timer.schedule(new SaveTask(), saveTime, saveTime); + isSaving = false; } - public void shutDown(){ + public void stop(){ + while(isSaving); // save operation mustn't be interrupted timer.cancel(); + Base.removeDir(autosaveDir); } private boolean saveSketch() throws IOException{ - + isSaving = true; Sketch sc = editor.getSketch(); - File autosaveDir = new File(sc.getFolder().getAbsolutePath() + File.separator + ".autosave"); + boolean deleteOldSave = false; String oldSave = null; if(!autosaveDir.exists()){ - autosaveDir = new File(sc.getFolder().getAbsolutePath(), ".autosave"); + autosaveDir = new File(sc.getFolder().getAbsolutePath(), "_autosave"); autosaveDir.mkdir(); } else @@ -74,6 +81,7 @@ private boolean saveSketch() throws IOException{ Base.showMessage("Cannot Save", "A sketch with the cleaned name\n" + "“" + sanitaryName + "” already exists."); + isSaving = false; return false; } newName = sanitaryName; @@ -93,6 +101,7 @@ private boolean saveSketch() throws IOException{ Base.showMessage("Nope", "You can't save the sketch as \"" + newName + "\"\n" + "because the sketch already has a tab with that name."); + isSaving = false; return false; } } @@ -181,7 +190,7 @@ public boolean accept(File file) { if(deleteOldSave) Base.removeDir(new File(oldSave)); - + isSaving = false; return true; } diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index c949225..2fdfab0 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -331,7 +331,6 @@ public void windowGainedFocus(WindowEvent e) { */ @Override public void dispose() { - autosaver.shutDown(); //System.out.println("window dispose"); // quit running debug session dbg.stopDebug(); @@ -345,6 +344,7 @@ public void dispose() { // Added temporarily to dump error log. TODO: Remove this later public void internalCloseRunner(){ if(ExperimentalMode.errorLogsEnabled) writeErrorsToFile(); + autosaver.stop(); super.internalCloseRunner(); } diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 2ac6ad3..faccbd0 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -260,7 +260,7 @@ public String[] getIgnorable() { "application.macosx", "application.windows", "application.linux", - ".autosave" + "_autosave" }; } } From 751fa62bc382b486146a409a63cfc616ec5a5922 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 12 Jan 2014 19:23:03 +0530 Subject: [PATCH 088/193] load prev save if found --- .../mode/experimental/AutoSaveUtil.java | 17 +++++++++++++- .../mode/experimental/DebugEditor.java | 22 +++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 5ed6f77..35e7835 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -17,7 +17,7 @@ public class AutoSaveUtil { private int saveTime; - private File autosaveDir; + private File autosaveDir, pastSave; private boolean isSaving; /** @@ -37,6 +37,21 @@ public AutoSaveUtil(DebugEditor dedit, int timeOut){ autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); } + public boolean checkForPastSave(){ + if(autosaveDir.exists()){ + String prevSaves[] = Base.listFiles(autosaveDir, false); + if(prevSaves.length > 0){ + pastSave = new File(prevSaves[0]); + return true; + } + } + return false; + } + + public File getPastSave(){ + return pastSave; + } + public void init(){ if(saveTime < 1000) return; saveTime = 10 * 1000; diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 2fdfab0..2cd201b 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -246,8 +246,7 @@ public void actionPerformed(ActionEvent e) { addXQModeUI(); debugToolbarEnabled = new AtomicBoolean(false); log("Sketch Path: " + path); - autosaver = new AutoSaveUtil(this, 5); - autosaver.init(); + loadAutoSaver(); } private void addXQModeUI(){ @@ -870,6 +869,25 @@ public boolean handleSaveAs() { } return saved; } + + public void loadAutoSaver(){ + autosaver = new AutoSaveUtil(this, 5); + if(!autosaver.checkForPastSave()) { + autosaver.init(); + return; + } + + File pastSave = autosaver.getPastSave(); + int response = Base.showYesNoQuestion(this, "Unsaved backup found!", "An automatic backup of this " + + "sketch has been found. This may mean Processing quit unexpectedly last time.", + "Select YES to view it or NO to delete the backup."); + if(response == JOptionPane.YES_OPTION){ + handleOpenInternal(pastSave.getAbsolutePath()); + } + else{ + autosaver.init(); + } + } /** * Set text contents of a specific tab. Updates underlying document and text From 636b548523958d7dc77bde62ecc7e582153715ee Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 12 Jan 2014 19:52:33 +0530 Subject: [PATCH 089/193] load prev save better --- src/processing/mode/experimental/AutoSaveUtil.java | 7 ++++--- src/processing/mode/experimental/DebugEditor.java | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 35e7835..7120144 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -41,7 +41,8 @@ public boolean checkForPastSave(){ if(autosaveDir.exists()){ String prevSaves[] = Base.listFiles(autosaveDir, false); if(prevSaves.length > 0){ - pastSave = new File(prevSaves[0]); + File t = new File(Base.listFiles(new File(prevSaves[0]), false)[0]); + pastSave = new File(t.getAbsolutePath() + File.separator + t.getName() + ".pde"); return true; } } @@ -62,8 +63,8 @@ public void init(){ public void stop(){ while(isSaving); // save operation mustn't be interrupted - timer.cancel(); - Base.removeDir(autosaveDir); + if(timer != null) timer.cancel(); + //Base.removeDir(autosaveDir); } private boolean saveSketch() throws IOException{ diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 2cd201b..c4a16a5 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -883,10 +883,10 @@ public void loadAutoSaver(){ "Select YES to view it or NO to delete the backup."); if(response == JOptionPane.YES_OPTION){ handleOpenInternal(pastSave.getAbsolutePath()); + //log(getSketch().getMainFilePath()); + autosaver = new AutoSaveUtil(this, 5); } - else{ - autosaver.init(); - } + autosaver.init(); } /** From dcdffb9d1879d1e71bf36a79c05d31aeae599fab Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 12 Jan 2014 20:04:03 +0530 Subject: [PATCH 090/193] loading prev save and restore too? Decisions --- src/processing/mode/experimental/AutoSaveUtil.java | 6 +++--- src/processing/mode/experimental/DebugEditor.java | 13 +++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 7120144..954097c 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -55,7 +55,7 @@ public File getPastSave(){ public void init(){ if(saveTime < 1000) return; - saveTime = 10 * 1000; + saveTime = 10 * 1000; //TODO: remove timer = new Timer(); timer.schedule(new SaveTask(), saveTime, saveTime); isSaving = false; @@ -64,7 +64,7 @@ public void init(){ public void stop(){ while(isSaving); // save operation mustn't be interrupted if(timer != null) timer.cancel(); - //Base.removeDir(autosaveDir); + Base.removeDir(autosaveDir); } private boolean saveSketch() throws IOException{ @@ -216,7 +216,7 @@ private class SaveTask extends TimerTask{ public void run() { try { saveSketch(); - ExperimentalMode.log("Saved " + editor.getSketch().getMainFilePath()); + ExperimentalMode.log("Backup Saved " + editor.getSketch().getMainFilePath()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index c4a16a5..8bdfb92 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -245,8 +245,7 @@ public void actionPerformed(ActionEvent e) { ta.setECSandThemeforTextArea(errorCheckerService, dmode); addXQModeUI(); debugToolbarEnabled = new AtomicBoolean(false); - log("Sketch Path: " + path); - loadAutoSaver(); + log("Sketch Path: " + path); } private void addXQModeUI(){ @@ -735,6 +734,10 @@ protected boolean handleOpenInternal(String path) { clearBreakpointedLines(); // force clear breakpoint highlights variableInspector().reset(); // clear contents of variable inspector } + if(autosaver != null) + autosaver.stop(); + loadAutoSaver(); + //System.out.println("LOADDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"); return didOpen; } @@ -884,9 +887,11 @@ public void loadAutoSaver(){ if(response == JOptionPane.YES_OPTION){ handleOpenInternal(pastSave.getAbsolutePath()); //log(getSketch().getMainFilePath()); - autosaver = new AutoSaveUtil(this, 5); + return; + } + else{ + autosaver.init(); } - autosaver.init(); } /** From 021319a448a8eafb21a23cf863b6c98af3aba2bc Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 13 Jan 2014 20:12:08 +0530 Subject: [PATCH 091/193] auto saver work done, i guess. --- .../mode/experimental/AutoSaveUtil.java | 10 +++++++--- src/processing/mode/experimental/DebugEditor.java | 15 ++++++++++----- .../mode/experimental/ExperimentalMode.java | 7 ++++++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 954097c..f2e2ae4 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -33,6 +33,7 @@ public AutoSaveUtil(DebugEditor dedit, int timeOut){ } else{ saveTime = timeOut * 60 * 1000; + ExperimentalMode.log("AutoSaver Interval(mins): " + timeOut); } autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); } @@ -42,7 +43,8 @@ public boolean checkForPastSave(){ String prevSaves[] = Base.listFiles(autosaveDir, false); if(prevSaves.length > 0){ File t = new File(Base.listFiles(new File(prevSaves[0]), false)[0]); - pastSave = new File(t.getAbsolutePath() + File.separator + t.getName() + ".pde"); + pastSave = new File(t.getAbsolutePath() + File.separator + t.getName() + ".pde"); + if(pastSave.exists()) return true; } } @@ -55,10 +57,11 @@ public File getPastSave(){ public void init(){ if(saveTime < 1000) return; - saveTime = 10 * 1000; //TODO: remove + //saveTime = 10 * 1000; //TODO: remove timer = new Timer(); timer.schedule(new SaveTask(), saveTime, saveTime); isSaving = false; + ExperimentalMode.log("AutoSaver started"); } public void stop(){ @@ -204,8 +207,9 @@ public boolean accept(File file) { // let Editor know that the save was successful - if(deleteOldSave) + if(deleteOldSave){ Base.removeDir(new File(oldSave)); + } isSaving = false; return true; } diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 8bdfb92..a0336a4 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -342,7 +342,7 @@ public void dispose() { // Added temporarily to dump error log. TODO: Remove this later public void internalCloseRunner(){ if(ExperimentalMode.errorLogsEnabled) writeErrorsToFile(); - autosaver.stop(); + if(autosaver != null) autosaver.stop(); super.internalCloseRunner(); } @@ -874,18 +874,23 @@ public boolean handleSaveAs() { } public void loadAutoSaver(){ - autosaver = new AutoSaveUtil(this, 5); + autosaver = new AutoSaveUtil(this, dmode.autoSaveInterval); if(!autosaver.checkForPastSave()) { autosaver.init(); return; } File pastSave = autosaver.getPastSave(); - int response = Base.showYesNoQuestion(this, "Unsaved backup found!", "An automatic backup of this " + - "sketch has been found. This may mean Processing quit unexpectedly last time.", - "Select YES to view it or NO to delete the backup."); + int response = Base + .showYesNoQuestion(this, + "Unsaved backup found!", + "An automatic backup of " + + pastSave.getParentFile().getName() + + "sketch has been found. This may mean Processing quit unexpectedly last time.", + "Select YES to view it or NO to delete the backup."); if(response == JOptionPane.YES_OPTION){ handleOpenInternal(pastSave.getAbsolutePath()); + Base.showMessage("Save it", "Remember to save the backup to a specific location if you want to."); //log(getSketch().getMainFilePath()); return; } diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index faccbd0..4645984 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -119,11 +119,12 @@ public File[] getKeywordFiles() { volatile public static boolean errorCheckEnabled = true, warningsEnabled = true, codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false; + public int autoSaveInterval = 5; //in minutes public final String prefErrorCheck = "pdex.errorCheckEnabled", prefWarnings = "pdex.warningsEnabled", prefCodeCompletionEnabled = "pdex.ccEnabled", - prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs"; + prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs", prefAutoSaveInterval = "pdex.autoSaveInterval"; public void loadPreferences(){ log("Load PDEX prefs"); @@ -133,6 +134,7 @@ public void loadPreferences(){ codeCompletionsEnabled = Preferences.getBoolean(prefCodeCompletionEnabled); DEBUG = Preferences.getBoolean(prefDebugOP); errorLogsEnabled = Preferences.getBoolean(prefErrorLogs); + autoSaveInterval = Preferences.getInteger(prefAutoSaveInterval); } public void savePreferences(){ @@ -142,6 +144,7 @@ public void savePreferences(){ Preferences.setBoolean(prefCodeCompletionEnabled, codeCompletionsEnabled); Preferences.setBoolean(prefDebugOP, DEBUG); Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); + Preferences.setInteger(prefAutoSaveInterval,autoSaveInterval); } public void ensurePrefsExist(){ @@ -155,6 +158,8 @@ public void ensurePrefsExist(){ Preferences.setBoolean(prefDebugOP,DEBUG); if(Preferences.get(prefErrorLogs) == null) Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); + if(Preferences.get(prefAutoSaveInterval) == null) + Preferences.setInteger(prefAutoSaveInterval,autoSaveInterval); } From 5fdd88bed07260ecaa9088f8a2006584667c5f13 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 13 Jan 2014 20:18:22 +0530 Subject: [PATCH 092/193] oops, missed that case --- src/processing/mode/experimental/AutoSaveUtil.java | 5 +++++ src/processing/mode/experimental/DebugEditor.java | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index f2e2ae4..8811ed1 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -51,6 +51,11 @@ public boolean checkForPastSave(){ return false; } + public void reloadAutosaveDir(){ + while(isSaving); + autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); + } + public File getPastSave(){ return pastSave; } diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index a0336a4..5bcafd1 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -842,6 +842,8 @@ public void run() { }); } } + // if file location has changed, update autosaver + autosaver.reloadAutosaveDir(); return saved; } @@ -870,10 +872,15 @@ public boolean handleSaveAs() { // set new name of variable inspector vi.setTitle(getSketch().getName()); } + // if file location has changed, update autosaver + autosaver.reloadAutosaveDir(); return saved; } public void loadAutoSaver(){ + if(autosaver != null){ + autosaver.stop(); + } autosaver = new AutoSaveUtil(this, dmode.autoSaveInterval); if(!autosaver.checkForPastSave()) { autosaver.init(); From 6f52073887488d86c16651fd72e0b5c669a879e3 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 13 Jan 2014 20:43:48 +0530 Subject: [PATCH 093/193] fixes, tidying things up for auto save --- src/processing/mode/experimental/AutoSaveUtil.java | 7 ++++--- src/processing/mode/experimental/DebugEditor.java | 6 +++--- src/processing/mode/experimental/ExperimentalMode.java | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 8811ed1..54e883c 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -61,7 +61,7 @@ public File getPastSave(){ } public void init(){ - if(saveTime < 1000) return; + if(saveTime < 10000) saveTime = 10 * 1000; //saveTime = 10 * 1000; //TODO: remove timer = new Timer(); timer.schedule(new SaveTask(), saveTime, saveTime); @@ -76,6 +76,7 @@ public void stop(){ } private boolean saveSketch() throws IOException{ + if(!editor.getSketch().isModified()) return false; isSaving = true; Sketch sc = editor.getSketch(); @@ -224,8 +225,8 @@ private class SaveTask extends TimerTask{ @Override public void run() { try { - saveSketch(); - ExperimentalMode.log("Backup Saved " + editor.getSketch().getMainFilePath()); + if(saveSketch()) + ExperimentalMode.log("Backup Saved " + editor.getSketch().getMainFilePath()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 5bcafd1..9e9c306 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -245,7 +245,7 @@ public void actionPerformed(ActionEvent e) { ta.setECSandThemeforTextArea(errorCheckerService, dmode); addXQModeUI(); debugToolbarEnabled = new AtomicBoolean(false); - log("Sketch Path: " + path); + log("Sketch Path: " + path); } private void addXQModeUI(){ @@ -737,7 +737,6 @@ protected boolean handleOpenInternal(String path) { if(autosaver != null) autosaver.stop(); loadAutoSaver(); - //System.out.println("LOADDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"); return didOpen; } @@ -878,10 +877,11 @@ public boolean handleSaveAs() { } public void loadAutoSaver(){ + log("Load Auto Saver()"); if(autosaver != null){ autosaver.stop(); } - autosaver = new AutoSaveUtil(this, dmode.autoSaveInterval); + autosaver = new AutoSaveUtil(this, ExperimentalMode.autoSaveInterval); if(!autosaver.checkForPastSave()) { autosaver.init(); return; diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 4645984..87b190d 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -119,9 +119,9 @@ public File[] getKeywordFiles() { volatile public static boolean errorCheckEnabled = true, warningsEnabled = true, codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false; - public int autoSaveInterval = 5; //in minutes + public static int autoSaveInterval = 5; //in minutes - public final String prefErrorCheck = "pdex.errorCheckEnabled", + public static final String prefErrorCheck = "pdex.errorCheckEnabled", prefWarnings = "pdex.warningsEnabled", prefCodeCompletionEnabled = "pdex.ccEnabled", prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs", prefAutoSaveInterval = "pdex.autoSaveInterval"; From 0808e22f47fa4c8257eebd4a299f90c6bd3185e7 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 21 Jan 2014 16:25:18 +0530 Subject: [PATCH 094/193] last few minor touches --- src/processing/mode/experimental/DebugEditor.java | 7 ++++--- src/processing/mode/experimental/ExperimentalMode.java | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 9e9c306..5c7cf94 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -891,13 +891,14 @@ public void loadAutoSaver(){ int response = Base .showYesNoQuestion(this, "Unsaved backup found!", - "An automatic backup of " + "An automatic backup of \"" + pastSave.getParentFile().getName() - + "sketch has been found. This may mean Processing quit unexpectedly last time.", + + "\" sketch has been found. This may mean Processing " + + "was closed unexpectedly last time.", "Select YES to view it or NO to delete the backup."); if(response == JOptionPane.YES_OPTION){ handleOpenInternal(pastSave.getAbsolutePath()); - Base.showMessage("Save it", "Remember to save the backup to a specific location if you want to."); + Base.showMessage("Save it..", "Remember to save the backup sketch to a specific location if you want to."); //log(getSketch().getMainFilePath()); return; } diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 87b190d..a756700 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -119,7 +119,7 @@ public File[] getKeywordFiles() { volatile public static boolean errorCheckEnabled = true, warningsEnabled = true, codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false; - public static int autoSaveInterval = 5; //in minutes + public static int autoSaveInterval = 3; //in minutes public static final String prefErrorCheck = "pdex.errorCheckEnabled", prefWarnings = "pdex.warningsEnabled", From 77a37fb52abff717afb53ebdd6cf84f43b57edb9 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 21 Jan 2014 16:45:03 +0530 Subject: [PATCH 095/193] release notes --- pdeX.txt | 4 ++-- revisions.txt | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pdeX.txt b/pdeX.txt index 803ecd0..2cc551f 100644 --- a/pdeX.txt +++ b/pdeX.txt @@ -3,5 +3,5 @@ authorList=[The Processing Foundation](http://processing.org) url=https://github.com/processing/processing-experimental sentence=The next generation of PDE paragraph=Intelligent Code Completion, Live Error Checker, Debugger, Auto Refactor, etc. -version=5 -prettyVersion=1.0.2b +version=6 +prettyVersion=1.0.3b diff --git a/revisions.txt b/revisions.txt index 5581f04..3d99c4f 100644 --- a/revisions.txt +++ b/revisions.txt @@ -1,4 +1,22 @@ +PDE X v1.0.3b - January 21, 2014 + +New Feature + ++ PDE X now saves a backup of your sketch every 3 minutes(configurable in preferences.txt). +In case of an unexpected crash, this should save the day! +https://github.com/processing/processing-experimental/issues/36 + +Bug fixes + ++ Outline Window width is now fixed +https://github.com/processing/processing-experimental/issues/31 + ++ Export Application works again on OS X +https://github.com/processing/processing-experimental/issues/33 + +. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + PDE X v1.0.2b - October 21, 2013 Bug fixes From d371f01bb6a6d9ec26636390ce9090d3f1dadb61 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 21 Jan 2014 18:45:31 +0530 Subject: [PATCH 096/193] Major Blooper :( --- src/processing/mode/experimental/AutoSaveUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 54e883c..4586603 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -27,7 +27,7 @@ public class AutoSaveUtil { */ public AutoSaveUtil(DebugEditor dedit, int timeOut){ editor = dedit; - if (timeOut < 5) { + if (timeOut < 1) { // less than 1 minute not allowed! saveTime = -1; throw new IllegalArgumentException(""); } From e5683072b9eda168c69f8f5da175a03ed48eeb4a Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 31 Jan 2014 13:35:54 +0530 Subject: [PATCH 097/193] javadoc update for TextArea --- .../mode/experimental/TextArea.java | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 8025f96..b74d484 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Martin Leopold + * Copyright (C) 2012-14 Martin Leopold and Manindra Moharana * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software @@ -127,6 +127,10 @@ public void setECSandThemeforTextArea(ErrorCheckerService ecs, customPainter.setECSandTheme(ecs, mode); } + /** + * Handles KeyEvents for TextArea + * Code completion begins from here. + */ public void processKeyEvent(KeyEvent evt) { if(evt.getKeyCode() == KeyEvent.VK_ESCAPE){ @@ -215,7 +219,11 @@ protected Object doInBackground() throws Exception { } - + /** + * Retrieves the word on which the mouse pointer is present + * @param evt - the MouseEvent which triggered this method + * @return + */ private String fetchPhrase(MouseEvent evt) { log("--handle Mouse Right Click--"); int off = xyToOffset(evt.getX(), evt.getY()); @@ -276,6 +284,14 @@ else if (s.length() == 0) return word.trim(); } } + + /** + * Retrieves the current word typed just before the caret. + * Then triggers code completion for that word. + * + * @param evt - the KeyEvent which triggered this method + * @return + */ private String fetchPhrase(KeyEvent evt) { int off = getCaretPosition(); @@ -361,29 +377,29 @@ else if (s.charAt(x1) == ']') { break; } -// if (x2 >= 0 && x2 < s.length()) { -// if (Character.isLetterOrDigit(s.charAt(x2)) || s.charAt(x2) == '_' -// || s.charAt(x2) == '$') -// word = word + s.charAt(x2++); -// else -// x2 = -1; -// } else -// x2 = -1; - -// if (x1 < 0 )//&& x2 < 0 -// break; + // if (x2 >= 0 && x2 < s.length()) { + // if (Character.isLetterOrDigit(s.charAt(x2)) || s.charAt(x2) == '_' + // || s.charAt(x2) == '$') + // word = word + s.charAt(x2++); + // else + // x2 = -1; + // } else + // x2 = -1; + + // if (x1 < 0 )//&& x2 < 0 + // break; if (i > 200) { // time out! break; } } -// if (keyChar != KeyEvent.CHAR_UNDEFINED) + // if (keyChar != KeyEvent.CHAR_UNDEFINED) if (Character.isDigit(word.charAt(0))) return null; word = word.trim(); -// if (word.endsWith(".")) -// word = word.substring(0, word.length() - 1); + // if (word.endsWith(".")) + // word = word.substring(0, word.length() - 1); int lineStartNonWSOffset = 0; if(word.length() > 1) errorCheckerService.getASTGenerator().preparePredictions(word, line @@ -664,7 +680,7 @@ public void mouseMoved(MouseEvent me) { //JEditTextArea textarea; - // worthless + /* No longer used private void addCompletionPopupListner() { this.addKeyListener(new KeyListener() { @@ -695,7 +711,7 @@ public void keyReleased(KeyEvent e) { public void keyPressed(KeyEvent e) { } }); - } + }*/ public void showSuggestionLater(final DefaultListModel defListModel, final String word) { SwingUtilities.invokeLater(new Runnable() { @@ -707,6 +723,12 @@ public void run() { }); } + /** + * Calculates location of caret and displays the suggestion popup at the location. + * + * @param defListModel + * @param subWord + */ protected void showSuggestion(DefaultListModel defListModel,String subWord) { hideSuggestion(); if (defListModel.size() == 0) { @@ -745,6 +767,9 @@ protected void showSuggestion(DefaultListModel defListModel,String subWord) { // }); } + /** + * Hides suggestion popup + */ protected void hideSuggestion() { if (suggestion != null) { suggestion.hide(); From 505c55de52623e62b5f677dd69663d78e90d6d9f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 31 Jan 2014 13:50:19 +0530 Subject: [PATCH 098/193] javadoc update for ASTNodeWrapper --- .../mode/experimental/ASTNodeWrapper.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 9e99ad5..b980f15 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2012-14 Manindra Moharana + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + package processing.mode.experimental; import static processing.mode.experimental.ExperimentalMode.log; import static processing.mode.experimental.ExperimentalMode.log2; @@ -19,6 +37,11 @@ import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; import org.eclipse.jdt.core.dom.TypeDeclaration; +/** + * Wrapper class for ASTNode objects + * @author Manindra Moharana + * + */ public class ASTNodeWrapper { private ASTNode Node; @@ -142,7 +165,7 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { /** - * + * Finds the difference in pde and java code offsets * @param source * @param inpOffset * @param nodeLen @@ -354,6 +377,13 @@ public int[][] getOffsetMapping(String source){ return new int[][]{javaCodeMap,pdeCodeMap}; } + /** + * Gets offset mapping between java and pde code + * int[0][x] stores the java code offset and + * int[1][x] is the corresponding offset in pde code + * @param ecs + * @return int[0] - java code offset, int[1] - pde code offset + */ public int[][] getOffsetMapping(ErrorCheckerService ecs){ int pdeoffsets[] = getPDECodeOffsets(ecs); String pdeCode = ecs.getPDECodeAtLine(pdeoffsets[0],pdeoffsets[1] - 1).trim(); From f24ad4b03862e6b4f59c337322ef2799d9d7b3f0 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 31 Jan 2014 13:55:44 +0530 Subject: [PATCH 099/193] javadoc update for AutoSaveUtil --- .../mode/experimental/AutoSaveUtil.java | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 4586603..71b2245 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2012-14 Manindra Moharana + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + package processing.mode.experimental; import java.io.File; @@ -9,6 +27,13 @@ import processing.app.Base; import processing.app.Sketch; +/** + * Autosave utility for saving sketch backups in the background after + * certain intervals + * + * @author Manindra Moharana + * + */ public class AutoSaveUtil { private DebugEditor editor; @@ -20,10 +45,11 @@ public class AutoSaveUtil { private File autosaveDir, pastSave; private boolean isSaving; + /** * * @param dedit - * @param timeOut - in minutes + * @param timeOut - in minutes, how frequently should saves occur */ public AutoSaveUtil(DebugEditor dedit, int timeOut){ editor = dedit; @@ -38,6 +64,10 @@ public AutoSaveUtil(DebugEditor dedit, int timeOut){ autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); } + /** + * Check if any previous autosave exists + * @return + */ public boolean checkForPastSave(){ if(autosaveDir.exists()){ String prevSaves[] = Base.listFiles(autosaveDir, false); @@ -51,6 +81,9 @@ public boolean checkForPastSave(){ return false; } + /** + * Refresh autosave directory if current sketch location in the editor changes + */ public void reloadAutosaveDir(){ while(isSaving); autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); @@ -60,6 +93,9 @@ public File getPastSave(){ return pastSave; } + /** + * Start the auto save service + */ public void init(){ if(saveTime < 10000) saveTime = 10 * 1000; //saveTime = 10 * 1000; //TODO: remove @@ -69,12 +105,21 @@ public void init(){ ExperimentalMode.log("AutoSaver started"); } + /** + * Stop the autosave service + */ public void stop(){ while(isSaving); // save operation mustn't be interrupted if(timer != null) timer.cancel(); Base.removeDir(autosaveDir); } + /** + * Main function that performs the save operation + * Code reused from processing.app.Sketch.saveAs() + * @return + * @throws IOException + */ private boolean saveSketch() throws IOException{ if(!editor.getSketch().isModified()) return false; isSaving = true; @@ -220,6 +265,11 @@ public boolean accept(File file) { return true; } + /** + * Timertask used to perform the save operation every X minutes + * @author quarkninja + * + */ private class SaveTask extends TimerTask{ @Override @@ -228,19 +278,11 @@ public void run() { if(saveSketch()) ExperimentalMode.log("Backup Saved " + editor.getSketch().getMainFilePath()); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } - //editor - - } } - public static void main(String[] args) { - - } - } From efa62fc6ae8e9a708b00a8045dc470e98e8fabfc Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 31 Jan 2014 14:06:46 +0530 Subject: [PATCH 100/193] javadoc update for CompletionPanel --- .../mode/experimental/CompletionPanel.java | 77 ++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 7973b76..ab32e4b 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2012-14 Manindra Moharana + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + package processing.mode.experimental; import static processing.mode.experimental.ExperimentalMode.log; import static processing.mode.experimental.ExperimentalMode.logE; @@ -23,21 +41,51 @@ import processing.app.syntax.JEditTextArea; +/** + * Manages the actual suggestion popup that gets displayed + * @author Manindra Moharana + * + */ public class CompletionPanel { + + /** + * The completion list generated by ASTGenerator + */ private JList completionList; + /** + * The popup menu in which the suggestion list is shown + */ private JPopupMenu popupMenu; + /** + * Partial word which triggered the code completion and which needs to be completed + */ private String subWord; + /** + * Postion where the completion has to be inserted + */ private int insertionPosition; private TextArea textarea; + /** + * Scroll pane in which the completion list is displayed + */ private JScrollPane scrollPane; protected DebugEditor editor; + /** + * Triggers the completion popup + * @param textarea + * @param position - insertion position(caret pos) + * @param subWord - Partial word which triggered the code completion and which needs to be completed + * @param items - completion candidates + * @param location - Point location where popup list is to be displayed + * @param dedit + */ public CompletionPanel(final JEditTextArea textarea, int position, String subWord, DefaultListModel items, final Point location, DebugEditor dedit) { this.textarea = (TextArea) textarea; @@ -72,7 +120,7 @@ public void setVisible(boolean v){ popupMenu.setVisible(v); } - protected int setHeight(int itemCount){ + private int setHeight(int itemCount){ if(scrollPane.getHorizontalScrollBar().isVisible()) itemCount++; FontMetrics fm = textarea.getFontMetrics(textarea.getFont()); float h = (fm.getHeight() + fm.getDescent()*0.5f) * (itemCount + 1); @@ -94,6 +142,12 @@ protected int setWidth(){ return Math.min(280,(int)min); // popup menu height }*/ + /** + * Created the popup list to be displayed + * @param position + * @param items + * @return + */ private JList createSuggestionList(final int position, final DefaultListModel items) { @@ -142,6 +196,10 @@ public void run() { return true; } + /** + * Inserts the CompletionCandidate chosen from the suggestion list + * @return + */ public boolean insertSelection() { if (completionList.getSelectedValue() != null) { try { @@ -174,12 +232,18 @@ public boolean insertSelection() { return false; } + /** + * Hide the suggestion list + */ public void hide() { popupMenu.setVisible(false); //log("Suggestion hidden" + System.nanoTime()); //textarea.errorCheckerService.getASTGenerator().jdocWindowVisible(false); } + /** + * When up arrow key is pressed, moves the highlighted selection up in the list + */ public void moveUp() { if (completionList.getSelectedIndex() == 0) { scrollPane.getVerticalScrollBar().setValue(scrollPane.getVerticalScrollBar().getMaximum()); @@ -200,6 +264,9 @@ public void moveUp() { } + /** + * When down arrow key is pressed, moves the highlighted selection down in the list + */ public void moveDown() { if (completionList.getSelectedIndex() == completionList.getModel().getSize() - 1) { scrollPane.getVerticalScrollBar().setValue(0); @@ -231,7 +298,13 @@ private void selectIndex(int index) { // }); } - protected class CustomListRenderer extends + + /** + * Custom cell renderer to display icons along with the completion candidates + * @author Manindra Moharana + * + */ + private class CustomListRenderer extends javax.swing.DefaultListCellRenderer { //protected final ImageIcon classIcon, fieldIcon, methodIcon; From d9de9fa77cf85bfeee85f759f8a4ef2e0c7b6def Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 31 Jan 2014 14:11:55 +0530 Subject: [PATCH 101/193] javadoc update for DebugEditor --- .../mode/experimental/DebugEditor.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 5c7cf94..74f9abc 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -346,6 +346,10 @@ public void internalCloseRunner(){ super.internalCloseRunner(); } + /** + * Writes all error messages to a csv file. + * For analytics purposes only. + */ private void writeErrorsToFile(){ if (errorCheckerService.tempErrorLog.size() == 0) return; @@ -417,9 +421,16 @@ public void actionPerformed(ActionEvent e) { return buildSketchMenu(new JMenuItem[]{runItem, presentItem, stopItem}); }*/ + /** + * Whether debug toolbar is enabled + */ AtomicBoolean debugToolbarEnabled; + protected EditorToolbar javaToolbar, debugToolbar; + /** + * Toggles between java mode and debug mode toolbar + */ protected void switchToolbars(){ final EditorToolbar nextToolbar; if(debugToolbarEnabled.get()){ @@ -876,6 +887,11 @@ public boolean handleSaveAs() { return saved; } + /** + * Loads and starts the auto save service + * Also handles the case where an auto save backup is found. + * The user is asked to save the sketch to a new location + */ public void loadAutoSaver(){ log("Load Auto Saver()"); if(autosaver != null){ @@ -1376,17 +1392,27 @@ synchronized public boolean updateTable(final TableModel tableModel) { return errorTable.updateTable(tableModel); } + /** + * Handle whether the tiny red error indicator is shown near the error button + * at the bottom of the PDE + */ public void updateErrorToggle(){ btnShowErrors.updateMarker(errorCheckerService.hasErrors(), errorBar.errorColor); } + /** + * Handle refactor operation + */ private void handleRefactor() { log("Caret at:"); log(ta.getLineText(ta.getCaretLine())); errorCheckerService.getASTGenerator().handleRefactor(); } + /** + * Handle show usage operation + */ private void handleShowUsage() { log("Caret at:"); log(ta.getLineText(ta.getCaretLine())); From 1e0eddfbbceaef4d498acf0b738f6bb727284190 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 31 Jan 2014 14:13:00 +0530 Subject: [PATCH 102/193] javadoc update for DebugEditor2 --- src/processing/mode/experimental/DebugEditor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 74f9abc..02e698b 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Martin Leopold + * Copyright (C) 2012-14 Martin Leopold and Manindra Moharana * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software From 3b804caf25e4f75d53e24b6225bb1655a6974474 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 31 Jan 2014 14:14:02 +0530 Subject: [PATCH 103/193] javadoc update for ECS --- .../experimental/ErrorCheckerService.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index b6b18e6..71afef3 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2012-14 Manindra Moharana + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ package processing.mode.experimental; import static processing.mode.experimental.ExperimentalMode.log; @@ -42,6 +59,12 @@ import processing.core.PApplet; import processing.mode.java.preproc.PdePreprocessor; +/** + * The main error checking service + * + * @author Manindra Moharana <me@mkmoharana.com> + * + */ public class ErrorCheckerService implements Runnable{ protected DebugEditor editor; From 10c9afd13634f913317dd4ef383f41129f6ed379 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 2 Feb 2014 00:36:33 +0530 Subject: [PATCH 104/193] beginning work on race condition bug --- .../mode/experimental/ASTGenerator.java | 16 ++- .../mode/experimental/CompletionPanel.java | 121 +++++++++++++++++- .../mode/experimental/TextArea.java | 5 +- 3 files changed, 136 insertions(+), 6 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 03343de..4d7602e 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Stack; import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; import javax.swing.BorderFactory; @@ -150,6 +151,7 @@ public ASTGenerator(ErrorCheckerService ecs) { //addCompletionPopupListner(); addListeners(); //loadJavaDoc(); + predictionOngoing = new AtomicBoolean(false); } protected void setupGUI(){ @@ -784,15 +786,24 @@ protected void trimCandidates(String newWord){ //protected AtomicBoolean predictionsEnabled; protected int predictionMinLength = 2; + + private AtomicBoolean predictionOngoing; + public void preparePredictions(final String word, final int line, final int lineStartNonWSOffset) { + if(predictionOngoing.get()) return; + if(!ExperimentalMode.codeCompletionsEnabled) return; - if(word.length() < predictionMinLength) return; + if(word.length() < predictionMinLength) return; + + predictionOngoing.set(true); // This method is called from TextArea.fetchPhrase, which is called via a SwingWorker instance // in TextArea.processKeyEvent if(caretWithinLineComment()){ log("No predictions."); + predictionOngoing.set(false); return; } + // SwingWorker worker = new SwingWorker() { // // @Override @@ -826,6 +837,7 @@ public void preparePredictions(final String word, final int line, final int line } showPredictions(word); lastPredictedWord = word2; + predictionOngoing.set(false); return; } } @@ -1006,7 +1018,7 @@ public void preparePredictions(final String word, final int line, final int line } showPredictions(word); - + predictionOngoing.set(false); // } // }; // diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index ab32e4b..610be8c 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -18,6 +18,7 @@ package processing.mode.experimental; import static processing.mode.experimental.ExperimentalMode.log; +import static processing.mode.experimental.ExperimentalMode.log2; import static processing.mode.experimental.ExperimentalMode.logE; import java.awt.BorderLayout; @@ -25,6 +26,7 @@ import java.awt.Component; import java.awt.FontMetrics; import java.awt.Point; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Iterator; @@ -108,7 +110,7 @@ public CompletionPanel(final JEditTextArea textarea, int position, String subWor textarea.requestFocusInWindow(); popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y); - //log("Suggestion constructed" + System.nanoTime()); + log("Suggestion shown: " + System.currentTimeMillis()); } public boolean isVisible() { @@ -205,7 +207,7 @@ public boolean insertSelection() { try { String selectedSuggestion = ((CompletionCandidate) completionList .getSelectedValue()).getCompletionString().substring(subWord.length()); - logE(subWord+" <= subword,Inserting suggestion=> " + selectedSuggestion); + logE(subWord+" <= subword,Inserting suggestion=> " + selectedSuggestion + " Current sub: " + fetchPhrase()); textarea.getDocument().remove(insertionPosition-subWord.length(), subWord.length()); textarea.getDocument().insertString(insertionPosition-subWord.length(), ((CompletionCandidate) completionList @@ -223,6 +225,7 @@ public boolean insertSelection() { else { textarea.setCaretPosition(insertionPosition + selectedSuggestion.length()); } + log("Suggestion inserted: " + System.currentTimeMillis()); return true; } catch (BadLocationException e1) { e1.printStackTrace(); @@ -231,6 +234,120 @@ public boolean insertSelection() { } return false; } + + private String fetchPhrase() { + TextArea ta = editor.ta; + int off = ta.getCaretPosition(); + log2("off " + off); + if (off < 0) + return null; + int line = ta.getCaretLine(); + if (line < 0) + return null; + String s = ta.getLineText(line); + log2("lin " + line); + /* + * if (s == null) return null; else if (s.length() == 0) return null; + */ +// else { + //log2(s + " len " + s.length()); + + int x = ta.getCaretPosition() - ta.getLineStartOffset(line) - 1, x2 = x + 1, x1 = x - 1; + if(x >= s.length() || x < 0) + return null; //TODO: Does this check cause problems? Verify. + log2(" x char: " + s.charAt(x)); + //int xLS = off - getLineStartNonWhiteSpaceOffset(line); + + String word = (x < s.length() ? s.charAt(x) : "") + ""; + if (s.trim().length() == 1) { +// word = "" +// + (keyChar == KeyEvent.CHAR_UNDEFINED ? s.charAt(x - 1) : keyChar); + //word = (x < s.length()?s.charAt(x):"") + ""; + word = word.trim(); + if (word.endsWith(".")) + word = word.substring(0, word.length() - 1); + + return word; + } +// if (keyChar == KeyEvent.VK_BACK_SPACE || keyChar == KeyEvent.VK_DELETE) +// ; // accepted these keys +// else if (!(Character.isLetterOrDigit(keyChar) || keyChar == '_' || keyChar == '$')) +// return null; + int i = 0; + int closeB = 0; + + while (true) { + i++; + //TODO: currently works on single line only. "a. b()" won't be detected + if (x1 >= 0) { +// if (s.charAt(x1) != ';' && s.charAt(x1) != ',' && s.charAt(x1) != '(') + if (Character.isLetterOrDigit(s.charAt(x1)) || s.charAt(x1) == '_' + || s.charAt(x1) == '.' || s.charAt(x1) == ')' || s.charAt(x1) == ']') { + + if (s.charAt(x1) == ')') { + word = s.charAt(x1--) + word; + closeB++; + while (x1 >= 0 && closeB > 0) { + word = s.charAt(x1) + word; + if (s.charAt(x1) == '(') + closeB--; + if (s.charAt(x1) == ')') + closeB++; + x1--; + } + } + else if (s.charAt(x1) == ']') { + word = s.charAt(x1--) + word; + closeB++; + while (x1 >= 0 && closeB > 0) { + word = s.charAt(x1) + word; + if (s.charAt(x1) == '[') + closeB--; + if (s.charAt(x1) == ']') + closeB++; + x1--; + } + } + else { + word = s.charAt(x1--) + word; + } + } else { + break; + } + } else { + break; + } + + // if (x2 >= 0 && x2 < s.length()) { + // if (Character.isLetterOrDigit(s.charAt(x2)) || s.charAt(x2) == '_' + // || s.charAt(x2) == '$') + // word = word + s.charAt(x2++); + // else + // x2 = -1; + // } else + // x2 = -1; + + // if (x1 < 0 )//&& x2 < 0 + // break; + if (i > 200) { + // time out! + break; + } + } + // if (keyChar != KeyEvent.CHAR_UNDEFINED) + + if (Character.isDigit(word.charAt(0))) + return null; + word = word.trim(); + // if (word.endsWith(".")) + // word = word.substring(0, word.length() - 1); + if(word.length() > 1) + + //showSuggestionLater(); + return word; + else return ""; + //} + } /** * Hide the suggestion list diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index b74d484..6657353 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -205,11 +205,12 @@ public void processKeyEvent(KeyEvent evt) { final KeyEvent evt2 = evt; SwingWorker worker = new SwingWorker() { protected Object doInBackground() throws Exception { + log("[KeyEvent]" + evt2.getKeyChar() + " |Prediction started: " + System.currentTimeMillis()); errorCheckerService.runManualErrorCheck(); // Provide completions only if it's enabled if(ExperimentalMode.codeCompletionsEnabled) - log(" Typing: " + fetchPhrase(evt2) + " " - + (evt2.getKeyChar() == KeyEvent.VK_ENTER)); + log("Typing: " + fetchPhrase(evt2) + " " + + (evt2.getKeyChar() == KeyEvent.VK_ENTER) + " T: " + System.currentTimeMillis()); return null; } }; From 750a913aa66feb82145f9146c3f406b3d3d4608e Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 2 Feb 2014 01:23:38 +0530 Subject: [PATCH 105/193] hopefully fixes the tricky #38 --- .../mode/experimental/CompletionPanel.java | 94 ++++++------------- 1 file changed, 30 insertions(+), 64 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 610be8c..4eae592 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -199,31 +199,37 @@ public void run() { } /** - * Inserts the CompletionCandidate chosen from the suggestion list + * Inserts the CompletionCandidate chosen from the suggestion list + * * @return */ public boolean insertSelection() { if (completionList.getSelectedValue() != null) { try { + String currentSubword = fetchCurrentSubword(); String selectedSuggestion = ((CompletionCandidate) completionList - .getSelectedValue()).getCompletionString().substring(subWord.length()); - logE(subWord+" <= subword,Inserting suggestion=> " + selectedSuggestion + " Current sub: " + fetchPhrase()); - textarea.getDocument().remove(insertionPosition-subWord.length(), subWord.length()); - textarea.getDocument().insertString(insertionPosition-subWord.length(), - ((CompletionCandidate) completionList - .getSelectedValue()).getCompletionString(), null); - if(selectedSuggestion.endsWith(")")) - { - if(!selectedSuggestion.endsWith("()")){ + .getSelectedValue()).getCompletionString().substring(currentSubword + .length()); + logE(subWord + " <= subword,Inserting suggestion=> " + + selectedSuggestion + " Current sub: " + currentSubword); + textarea.getDocument().remove(insertionPosition + - currentSubword.length(), + currentSubword.length()); + textarea.getDocument() + .insertString(insertionPosition - currentSubword.length(), + ((CompletionCandidate) completionList + .getSelectedValue()).getCompletionString(), null); + if (selectedSuggestion.endsWith(")")) { + if (!selectedSuggestion.endsWith("()")) { int x = selectedSuggestion.indexOf('('); - if(x != -1){ + if (x != -1) { //log("X................... " + x); - textarea.setCaretPosition(insertionPosition + (x+1)); + textarea.setCaretPosition(insertionPosition + (x + 1)); } } - } - else { - textarea.setCaretPosition(insertionPosition + selectedSuggestion.length()); + } else { + textarea.setCaretPosition(insertionPosition + + selectedSuggestion.length()); } log("Suggestion inserted: " + System.currentTimeMillis()); return true; @@ -235,17 +241,17 @@ public boolean insertSelection() { return false; } - private String fetchPhrase() { + private String fetchCurrentSubword() { TextArea ta = editor.ta; int off = ta.getCaretPosition(); - log2("off " + off); + //log2("off " + off); if (off < 0) return null; int line = ta.getCaretLine(); if (line < 0) return null; String s = ta.getLineText(line); - log2("lin " + line); + //log2("lin " + line); /* * if (s == null) return null; else if (s.length() == 0) return null; */ @@ -255,7 +261,7 @@ private String fetchPhrase() { int x = ta.getCaretPosition() - ta.getLineStartOffset(line) - 1, x2 = x + 1, x1 = x - 1; if(x >= s.length() || x < 0) return null; //TODO: Does this check cause problems? Verify. - log2(" x char: " + s.charAt(x)); + //log2(" x char: " + s.charAt(x)); //int xLS = off - getLineStartNonWhiteSpaceOffset(line); String word = (x < s.length() ? s.charAt(x) : "") + ""; @@ -281,54 +287,16 @@ private String fetchPhrase() { //TODO: currently works on single line only. "a. b()" won't be detected if (x1 >= 0) { // if (s.charAt(x1) != ';' && s.charAt(x1) != ',' && s.charAt(x1) != '(') - if (Character.isLetterOrDigit(s.charAt(x1)) || s.charAt(x1) == '_' - || s.charAt(x1) == '.' || s.charAt(x1) == ')' || s.charAt(x1) == ']') { + if (Character.isLetterOrDigit(s.charAt(x1)) || s.charAt(x1) == '_') { + + word = s.charAt(x1--) + word; - if (s.charAt(x1) == ')') { - word = s.charAt(x1--) + word; - closeB++; - while (x1 >= 0 && closeB > 0) { - word = s.charAt(x1) + word; - if (s.charAt(x1) == '(') - closeB--; - if (s.charAt(x1) == ')') - closeB++; - x1--; - } - } - else if (s.charAt(x1) == ']') { - word = s.charAt(x1--) + word; - closeB++; - while (x1 >= 0 && closeB > 0) { - word = s.charAt(x1) + word; - if (s.charAt(x1) == '[') - closeB--; - if (s.charAt(x1) == ']') - closeB++; - x1--; - } - } - else { - word = s.charAt(x1--) + word; - } } else { break; } } else { break; } - - // if (x2 >= 0 && x2 < s.length()) { - // if (Character.isLetterOrDigit(s.charAt(x2)) || s.charAt(x2) == '_' - // || s.charAt(x2) == '$') - // word = word + s.charAt(x2++); - // else - // x2 = -1; - // } else - // x2 = -1; - - // if (x1 < 0 )//&& x2 < 0 - // break; if (i > 200) { // time out! break; @@ -339,13 +307,11 @@ else if (s.charAt(x1) == ']') { if (Character.isDigit(word.charAt(0))) return null; word = word.trim(); - // if (word.endsWith(".")) - // word = word.substring(0, word.length() - 1); - if(word.length() > 1) + if (word.endsWith(".")) + word = word.substring(0, word.length() - 1); //showSuggestionLater(); return word; - else return ""; //} } From 7bf09ba3ad4c7a74ea1a9ecd1e344d15d1d082d4 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 2 Feb 2014 19:35:58 +0530 Subject: [PATCH 106/193] revisions updated --- revisions.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/revisions.txt b/revisions.txt index 3d99c4f..5a2a1fd 100644 --- a/revisions.txt +++ b/revisions.txt @@ -1,4 +1,13 @@ +PDE X v1.0.4b - February , 2014 + +Bug fixes + ++ Autocompletion bug, column is sometimes off by 1 +https://github.com/processing/processing-experimental/issues/38 + +. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + PDE X v1.0.3b - January 21, 2014 New Feature From 63347c62841c0535cdff009bd5509d88f3d13e23 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 2 Feb 2014 19:58:51 +0530 Subject: [PATCH 107/193] completion popup height bug fix --- .../mode/experimental/CompletionPanel.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index 4eae592..cadc007 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -123,11 +123,15 @@ public void setVisible(boolean v){ } private int setHeight(int itemCount){ - if(scrollPane.getHorizontalScrollBar().isVisible()) itemCount++; - FontMetrics fm = textarea.getFontMetrics(textarea.getFont()); - float h = (fm.getHeight() + fm.getDescent()*0.5f) * (itemCount + 1); - log("popup height " + Math.min(250,h)); - return Math.min(250,(int)h); // popup menu height + FontMetrics fm = textarea.getFontMetrics(textarea.getFont()); + float h = (fm.getHeight() + (fm.getDescent()) * 0.5f) * (itemCount); + if (scrollPane.getHorizontalScrollBar().isVisible()) + h += scrollPane.getHorizontalScrollBar().getHeight() + fm.getHeight() + + (fm.getDescent() + fm.getAscent()) * 0.8f; + // 0.5f and 0.8f scaling give respectable results. + //log("popup height " + Math.min(250,h) + //+ scrollPane.getHorizontalScrollBar().isVisible()); + return Math.min(250, (int) h); // popup menu height } /*TODO: Make width dynamic From bdf6ee06bc4b6fe20b4b62094c226b112c727b1f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 23 Feb 2014 03:12:10 +0530 Subject: [PATCH 108/193] lookin into jdoc scroll bug, irritating one this --- .../mode/experimental/ASTGenerator.java | 5 +- .../mode/experimental/ASTNodeWrapper.java | 83 ++++++++++++++++++- .../experimental/ErrorCheckerService.java | 4 + 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 4d7602e..1d2a052 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -235,7 +235,10 @@ protected void setupGUI(){ } - public static final boolean SHOWAST = !true; + /** + * Toggle AST View window + */ + public static final boolean SHOWAST = true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index b980f15..340f956 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -29,6 +29,7 @@ import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.FieldDeclaration; +import org.eclipse.jdt.core.dom.Javadoc; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.QualifiedName; @@ -99,6 +100,7 @@ public ASTNodeWrapper(ASTNode node, String label){ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { int nodeOffset = Node.getStartPosition(), nodeLength = Node .getLength(); + log("0.nodeOffset " + nodeOffset); ASTNode thisNode = Node; while (thisNode.getParent() != null) { if (getLineNumber(thisNode.getParent()) == lineNumber) { @@ -119,8 +121,34 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { */ int altStartPos = thisNode.getStartPosition(); + log("1.Altspos " + altStartPos); thisNode = thisNode.getParent(); + int jdocOffset; Javadoc jd = null; + if(thisNode instanceof TypeDeclaration){ + jd = ((TypeDeclaration)thisNode).getJavadoc(); + log("Has t jdoc " + ((TypeDeclaration)thisNode).getJavadoc()); + } else if(thisNode instanceof MethodDeclaration){ + jd = ((MethodDeclaration)thisNode).getJavadoc(); + log("Has m jdoc " + jd); + } else if(thisNode instanceof FieldDeclaration){ + jd = ((FieldDeclaration)thisNode).getJavadoc(); + log("Has f jdoc " + ((FieldDeclaration)thisNode).getJavadoc()); + } + + if(jd != null){ + jdocOffset = jd.getLength(); + log("jdoc offset: " + jdocOffset); + while (thisNode.getParent() != null) { + if (getLineNumber2(thisNode.getParent()) == getLineNumber2(getNode())) { + thisNode = thisNode.getParent(); + } else { + break; + } + } + //thisNode = thisNode.getParent(); + } + log("Visiting children of node " + getNodeAsString(thisNode)); Iterator it = thisNode .structuralPropertiesForType().iterator(); boolean flag = true; @@ -130,15 +158,17 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { if (prop.isChildListProperty()) { List nodelist = (List) thisNode .getStructuralProperty(prop); + log("prop " + prop); for (ASTNode cnode : nodelist) { - if (getLineNumber(cnode) == lineNumber) { + log("Visiting node " + getNodeAsString(cnode)); + if (getLineNumber2(cnode) == lineNumber) { if (flag) { altStartPos = cnode.getStartPosition(); // log("multi..."); flag = false; } else { - if(cnode == Node){ + if (cnode == Node) { // loop only till the current node. break; } @@ -159,10 +189,36 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { if (vals != null) return new int[] { lineNumber, nodeOffset + vals[0] - altStartPos, vals[1] }; - else + else {// no offset mapping needed + log("joff[1] = " + (nodeOffset - altStartPos)); return new int[] { lineNumber, nodeOffset - altStartPos, nodeLength }; + } } + private boolean hasJavaDoc(ASTNode node){ + if(node != null){ + Iterator it = node + .structuralPropertiesForType().iterator(); + log("Checkin for javadoc in child node of " + getNodeAsString(node)); + while (it.hasNext()) { + StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it + .next(); + if (prop.isChildListProperty()) { + List nodelist = (List) node + .getStructuralProperty(prop); + log("prop " + prop); + for (ASTNode cnode : nodelist) { + log("Visiting node " + getNodeAsString(cnode)); + if(cnode instanceof Javadoc){ + log("Visiting jdoc " + cnode); + return true; + } + } + } + } + } + return false; + } /** * Finds the difference in pde and java code offsets @@ -492,6 +548,27 @@ private static int getLineNumber(ASTNode node) { return ((CompilationUnit) node.getRoot()).getLineNumber(node .getStartPosition()); } + + private static int getLineNumber2(ASTNode thisNode) { + int jdocOffset = 0; Javadoc jd = null; + if(thisNode instanceof TypeDeclaration){ + jd = ((TypeDeclaration)thisNode).getJavadoc(); + log("Has t jdoc " + ((TypeDeclaration)thisNode).getJavadoc()); + } else if(thisNode instanceof MethodDeclaration){ + jd = ((MethodDeclaration)thisNode).getJavadoc(); + log("Has m jdoc " + jd); + } else if(thisNode instanceof FieldDeclaration){ + jd = ((FieldDeclaration)thisNode).getJavadoc(); + log("Has f jdoc " + ((FieldDeclaration)thisNode).getJavadoc()); + } + if(jd != null){ + jdocOffset = 1+jd.getLength(); + } + log("ln 2 = " + ((CompilationUnit) thisNode.getRoot()).getLineNumber(thisNode + .getStartPosition() + jdocOffset)); + return ((CompilationUnit) thisNode.getRoot()).getLineNumber(thisNode + .getStartPosition() + jdocOffset); + } static private String getNodeAsString(ASTNode node) { if (node == null) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 71afef3..89f6538 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1278,9 +1278,13 @@ protected String preprocessCode(String pdeCode) { * @return true - if highlighting happened correctly. */ public boolean highlightNode(ASTNodeWrapper awrap){ + log("Highlighting: " + awrap); try { int pdeoffsets[] = awrap.getPDECodeOffsets(this); int javaoffsets[] = awrap.getJavaCodeOffsets(this); + log("offsets: " +pdeoffsets[0] + "," + + pdeoffsets[1]+ "," +javaoffsets[1]+ "," + + javaoffsets[2]); scrollToErrorLine(editor, pdeoffsets[0], pdeoffsets[1],javaoffsets[1], javaoffsets[2]); From 599eccc4cb4333cf9ca614e3b2496c5975d3f3c8 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 24 Feb 2014 00:48:57 +0530 Subject: [PATCH 109/193] Fixes #15 DIE BUG DIE --- .../mode/experimental/ASTNodeWrapper.java | 189 +++++++++++++----- 1 file changed, 140 insertions(+), 49 deletions(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 340f956..0f2ad87 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -36,7 +36,9 @@ import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; +import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; /** * Wrapper class for ASTNode objects @@ -127,31 +129,155 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { if(thisNode instanceof TypeDeclaration){ jd = ((TypeDeclaration)thisNode).getJavadoc(); + altStartPos = getLen((TypeDeclaration)thisNode); log("Has t jdoc " + ((TypeDeclaration)thisNode).getJavadoc()); } else if(thisNode instanceof MethodDeclaration){ + altStartPos = getLen((MethodDeclaration)thisNode); jd = ((MethodDeclaration)thisNode).getJavadoc(); log("Has m jdoc " + jd); } else if(thisNode instanceof FieldDeclaration){ - jd = ((FieldDeclaration)thisNode).getJavadoc(); - log("Has f jdoc " + ((FieldDeclaration)thisNode).getJavadoc()); + FieldDeclaration fd = ((FieldDeclaration)thisNode); + jd = fd.getJavadoc(); + log("Has f jdoc " + fd.getJavadoc()); + altStartPos = getLen(fd); + //nodeOffset = ((VariableDeclarationFragment)(fd.fragments().get(0))).getName().getStartPosition(); } if(jd != null){ - jdocOffset = jd.getLength(); - log("jdoc offset: " + jdocOffset); - while (thisNode.getParent() != null) { - if (getLineNumber2(thisNode.getParent()) == getLineNumber2(getNode())) { - thisNode = thisNode.getParent(); - } else { - break; +// jdocOffset = jd.getLength(); +// log("jdoc offset: " + jdocOffset); + //testForMultilineDecl(thisNode); + //thisNode = thisNode.getParent(); + } + else{ + log("Visiting children of node " + getNodeAsString(thisNode)); + Iterator it = thisNode + .structuralPropertiesForType().iterator(); + boolean flag = true; + while (it.hasNext()) { + StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it + .next(); + if (prop.isChildListProperty()) { + List nodelist = (List) thisNode + .getStructuralProperty(prop); + log("prop " + prop); + for (ASTNode cnode : nodelist) { + log("Visiting node " + getNodeAsString(cnode)); + if (getLineNumber(cnode) == lineNumber) { + if (flag) { + altStartPos = cnode.getStartPosition(); + // log("multi..."); + + flag = false; + } else { + if (cnode == Node) { + // loop only till the current node. + break; + } + // We've located the first node in the line. + // Now normalize offsets till Node + //altStartPos += normalizeOffsets(cnode); + + } + + } + } } } - //thisNode = thisNode.getParent(); + log("Altspos " + altStartPos); + } + + int pdeoffsets[] = getPDECodeOffsets(ecs); + String pdeCode = ecs.getPDECodeAtLine(pdeoffsets[0],pdeoffsets[1] - 1).trim(); + int vals[] = createOffsetMapping(pdeCode,nodeOffset - altStartPos,nodeLength); + if (vals != null) + return new int[] { + lineNumber, nodeOffset + vals[0] - altStartPos, vals[1] }; + else {// no offset mapping needed + log("joff[1] = " + (nodeOffset - altStartPos)); + return new int[] { lineNumber, nodeOffset - altStartPos, nodeLength }; } + } + + private int getLen(FieldDeclaration fd){ + List list= fd.modifiers(); + SimpleName sn = (SimpleName) getNode(); + + Type tp = fd.getType(); + int lineNum = getLineNumber(sn); + log("SN "+sn + ", " + lineNum); + for (ASTNode astNode : list) { + if(getLineNumber(astNode) == lineNum) + { + log("first node in that line " + astNode); + log("diff " + (sn.getStartPosition() - astNode.getStartPosition())); + return (astNode.getStartPosition()); + } + } + if(getLineNumber(fd.getType()) == lineNum) + { + log("first node in that line " + tp); + log("diff " + (sn.getStartPosition() - tp.getStartPosition())); + return (tp.getStartPosition()); + } + + + return 0; + } + + private int getLen(MethodDeclaration md) { + List list = md.modifiers(); + SimpleName sn = (SimpleName) getNode(); + int lineNum = getLineNumber(sn); + log("SN " + sn + ", " + lineNum); + + for (ASTNode astNode : list) { + if (getLineNumber(astNode) == lineNum) { + log("first node in that line " + astNode); + log("diff " + (sn.getStartPosition() - astNode.getStartPosition())); + return (astNode.getStartPosition()); + } + } + + if (!md.isConstructor()) { + Type tp = md.getReturnType2(); + if (getLineNumber(tp) == lineNum) { + log("first node in that line " + tp); + log("diff " + (sn.getStartPosition() - tp.getStartPosition())); + return (tp.getStartPosition()); + } + } + + return 0; + } + + private int getLen(TypeDeclaration td){ + List list= td.modifiers(); + list = td.modifiers(); + SimpleName sn = (SimpleName) getNode(); + + int lineNum = getLineNumber(sn); + log("SN "+sn + ", " + lineNum); + for (ASTNode astNode : list) { + if(getLineNumber(astNode) == lineNum) + { + log("first node in that line " + astNode); + log("diff " + (sn.getStartPosition() - astNode.getStartPosition())); + return (astNode.getStartPosition()); + } + } + + return 0; + } + + private void testForMultilineDecl(ASTNode thisNode){ + int minLineNum = lineNumber, maxLineNum = ((CompilationUnit) thisNode + .getRoot()).getLineNumber(thisNode.getStartPosition()); log("Visiting children of node " + getNodeAsString(thisNode)); Iterator it = thisNode .structuralPropertiesForType().iterator(); boolean flag = true; + int altStartPos = 0; while (it.hasNext()) { StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it .next(); @@ -161,7 +287,7 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { log("prop " + prop); for (ASTNode cnode : nodelist) { log("Visiting node " + getNodeAsString(cnode)); - if (getLineNumber2(cnode) == lineNumber) { + if (getLineNumber(cnode) >= minLineNum && getLineNumber(cnode) <= maxLineNum) { if (flag) { altStartPos = cnode.getStartPosition(); // log("multi..."); @@ -177,49 +303,14 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { //altStartPos += normalizeOffsets(cnode); } - + testForMultilineDecl(cnode); FieldDeclaration f; } } } } log("Altspos " + altStartPos); - int pdeoffsets[] = getPDECodeOffsets(ecs); - String pdeCode = ecs.getPDECodeAtLine(pdeoffsets[0],pdeoffsets[1] - 1).trim(); - int vals[] = createOffsetMapping(pdeCode,nodeOffset - altStartPos,nodeLength); - if (vals != null) - return new int[] { - lineNumber, nodeOffset + vals[0] - altStartPos, vals[1] }; - else {// no offset mapping needed - log("joff[1] = " + (nodeOffset - altStartPos)); - return new int[] { lineNumber, nodeOffset - altStartPos, nodeLength }; - } } - private boolean hasJavaDoc(ASTNode node){ - if(node != null){ - Iterator it = node - .structuralPropertiesForType().iterator(); - log("Checkin for javadoc in child node of " + getNodeAsString(node)); - while (it.hasNext()) { - StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it - .next(); - if (prop.isChildListProperty()) { - List nodelist = (List) node - .getStructuralProperty(prop); - log("prop " + prop); - for (ASTNode cnode : nodelist) { - log("Visiting node " + getNodeAsString(cnode)); - if(cnode instanceof Javadoc){ - log("Visiting jdoc " + cnode); - return true; - } - } - } - } - } - return false; - } - /** * Finds the difference in pde and java code offsets * @param source @@ -549,7 +640,7 @@ private static int getLineNumber(ASTNode node) { .getStartPosition()); } - private static int getLineNumber2(ASTNode thisNode) { + /*private static int getLineNumber2(ASTNode thisNode) { int jdocOffset = 0; Javadoc jd = null; if(thisNode instanceof TypeDeclaration){ jd = ((TypeDeclaration)thisNode).getJavadoc(); @@ -568,7 +659,7 @@ private static int getLineNumber2(ASTNode thisNode) { .getStartPosition() + jdocOffset)); return ((CompilationUnit) thisNode.getRoot()).getLineNumber(thisNode .getStartPosition() + jdocOffset); - } + }*/ static private String getNodeAsString(ASTNode node) { if (node == null) From 5df669c6ff58fee2664bcc12f5c97bfe9e44c536 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 1 Mar 2014 16:25:02 +0530 Subject: [PATCH 110/193] comments and cleanup --- .../mode/experimental/ASTNodeWrapper.java | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 0f2ad87..9e4a473 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -125,31 +125,33 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { int altStartPos = thisNode.getStartPosition(); log("1.Altspos " + altStartPos); thisNode = thisNode.getParent(); - int jdocOffset; Javadoc jd = null; + Javadoc jd = null; - if(thisNode instanceof TypeDeclaration){ - jd = ((TypeDeclaration)thisNode).getJavadoc(); - altStartPos = getLen((TypeDeclaration)thisNode); - log("Has t jdoc " + ((TypeDeclaration)thisNode).getJavadoc()); - } else if(thisNode instanceof MethodDeclaration){ - altStartPos = getLen((MethodDeclaration)thisNode); - jd = ((MethodDeclaration)thisNode).getJavadoc(); + /* + * There's another case that needs to be handled. If a TD, MD or FD + * contains javadoc comments(multi or single line) the starting position + * of the javadoc is treated as the beginning of the declaration by the AST parser. + * But that's clearly not what we need. The true decl begins after the javadoc ends. + * So this offset needs to be found carefully and stored in altStartPos + * + */ + if (thisNode instanceof TypeDeclaration) { + jd = ((TypeDeclaration) thisNode).getJavadoc(); + altStartPos = getLen((TypeDeclaration) thisNode); + log("Has t jdoc " + ((TypeDeclaration) thisNode).getJavadoc()); + } else if (thisNode instanceof MethodDeclaration) { + altStartPos = getLen((MethodDeclaration) thisNode); + jd = ((MethodDeclaration) thisNode).getJavadoc(); log("Has m jdoc " + jd); - } else if(thisNode instanceof FieldDeclaration){ - FieldDeclaration fd = ((FieldDeclaration)thisNode); + } else if (thisNode instanceof FieldDeclaration) { + FieldDeclaration fd = ((FieldDeclaration) thisNode); jd = fd.getJavadoc(); log("Has f jdoc " + fd.getJavadoc()); - altStartPos = getLen(fd); + altStartPos = getJavadocOffset(fd); //nodeOffset = ((VariableDeclarationFragment)(fd.fragments().get(0))).getName().getStartPosition(); } - if(jd != null){ -// jdocOffset = jd.getLength(); -// log("jdoc offset: " + jdocOffset); - //testForMultilineDecl(thisNode); - //thisNode = thisNode.getParent(); - } - else{ + if(jd == null){ log("Visiting children of node " + getNodeAsString(thisNode)); Iterator it = thisNode .structuralPropertiesForType().iterator(); @@ -199,7 +201,12 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { } } - private int getLen(FieldDeclaration fd){ + /** + * + * @param fd + * @return + */ + private int getJavadocOffset(FieldDeclaration fd){ List list= fd.modifiers(); SimpleName sn = (SimpleName) getNode(); From 93046ed302c1384f57b7e40d0b6d4932c6358ca4 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 1 Mar 2014 16:26:06 +0530 Subject: [PATCH 111/193] reafactored --- src/processing/mode/experimental/ASTNodeWrapper.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 9e4a473..45518b4 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -137,10 +137,10 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { */ if (thisNode instanceof TypeDeclaration) { jd = ((TypeDeclaration) thisNode).getJavadoc(); - altStartPos = getLen((TypeDeclaration) thisNode); + altStartPos = getJavadocOffset((TypeDeclaration) thisNode); log("Has t jdoc " + ((TypeDeclaration) thisNode).getJavadoc()); } else if (thisNode instanceof MethodDeclaration) { - altStartPos = getLen((MethodDeclaration) thisNode); + altStartPos = getJavadocOffset((MethodDeclaration) thisNode); jd = ((MethodDeclaration) thisNode).getJavadoc(); log("Has m jdoc " + jd); } else if (thisNode instanceof FieldDeclaration) { @@ -232,7 +232,7 @@ private int getJavadocOffset(FieldDeclaration fd){ return 0; } - private int getLen(MethodDeclaration md) { + private int getJavadocOffset(MethodDeclaration md) { List list = md.modifiers(); SimpleName sn = (SimpleName) getNode(); int lineNum = getLineNumber(sn); @@ -258,7 +258,7 @@ private int getLen(MethodDeclaration md) { return 0; } - private int getLen(TypeDeclaration td){ + private int getJavadocOffset(TypeDeclaration td){ List list= td.modifiers(); list = td.modifiers(); SimpleName sn = (SimpleName) getNode(); From 6831b5595f61213fcc4eca7b980ced45a0171fd5 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 1 Mar 2014 16:54:09 +0530 Subject: [PATCH 112/193] clean up --- .../mode/experimental/ASTNodeWrapper.java | 42 +------------------ 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 45518b4..6c6cbc6 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -259,6 +259,7 @@ private int getJavadocOffset(MethodDeclaration md) { } private int getJavadocOffset(TypeDeclaration td){ + // TODO: This is still broken. Hence no refactoring or highlighting on scroll works :\ List list= td.modifiers(); list = td.modifiers(); SimpleName sn = (SimpleName) getNode(); @@ -277,47 +278,6 @@ private int getJavadocOffset(TypeDeclaration td){ return 0; } - private void testForMultilineDecl(ASTNode thisNode){ - int minLineNum = lineNumber, maxLineNum = ((CompilationUnit) thisNode - .getRoot()).getLineNumber(thisNode.getStartPosition()); - log("Visiting children of node " + getNodeAsString(thisNode)); - Iterator it = thisNode - .structuralPropertiesForType().iterator(); - boolean flag = true; - int altStartPos = 0; - while (it.hasNext()) { - StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it - .next(); - if (prop.isChildListProperty()) { - List nodelist = (List) thisNode - .getStructuralProperty(prop); - log("prop " + prop); - for (ASTNode cnode : nodelist) { - log("Visiting node " + getNodeAsString(cnode)); - if (getLineNumber(cnode) >= minLineNum && getLineNumber(cnode) <= maxLineNum) { - if (flag) { - altStartPos = cnode.getStartPosition(); - // log("multi..."); - - flag = false; - } else { - if (cnode == Node) { - // loop only till the current node. - break; - } - // We've located the first node in the line. - // Now normalize offsets till Node - //altStartPos += normalizeOffsets(cnode); - - } - testForMultilineDecl(cnode); FieldDeclaration f; - } - } - } - } - log("Altspos " + altStartPos); - } - /** * Finds the difference in pde and java code offsets * @param source From cee31ad2e155c9df53560428d9e24843b3dbe484 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 2 Mar 2014 20:40:42 +0530 Subject: [PATCH 113/193] working on autosave --- .../mode/experimental/ASTGenerator.java | 6 +- .../mode/experimental/AutoSaveUtil.java | 30 +++++++++- .../mode/experimental/DebugEditor.java | 59 +++++++++++++++---- .../experimental/ErrorCheckerService.java | 6 +- 4 files changed, 81 insertions(+), 20 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 1d2a052..9d74fd4 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -238,7 +238,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = true; + public static final boolean SHOWAST = !true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { @@ -254,14 +254,14 @@ protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { compilationUnit = (CompilationUnit) parser.createAST(null); } else { compilationUnit = cu; - log("Other cu"); + //log("Other cu"); } // OutlineVisitor visitor = new OutlineVisitor(); // compilationUnit.accept(visitor); getCodeComments(); codeTree = new DefaultMutableTreeNode(new ASTNodeWrapper((ASTNode) compilationUnit .types().get(0))); - log("Total CU " + compilationUnit.types().size()); + //log("Total CU " + compilationUnit.types().size()); if(compilationUnit.types() == null || compilationUnit.types().isEmpty()){ logE("No CU found!"); } diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 71b2245..d02f510 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -46,6 +46,10 @@ public class AutoSaveUtil { private boolean isSaving; + private boolean isAutoSaveBackup; + + private File sketchFolder, sketchBackupFolder; + /** * * @param dedit @@ -62,8 +66,18 @@ public AutoSaveUtil(DebugEditor dedit, int timeOut){ ExperimentalMode.log("AutoSaver Interval(mins): " + timeOut); } autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); + sketchFolder = editor.getSketch().getFolder(); + checkIfBackup(); } + private void checkIfBackup(){ + + } + + public boolean isAutoSaveBackup() { + return isAutoSaveBackup; + } + /** * Check if any previous autosave exists * @return @@ -73,6 +87,7 @@ public boolean checkForPastSave(){ String prevSaves[] = Base.listFiles(autosaveDir, false); if(prevSaves.length > 0){ File t = new File(Base.listFiles(new File(prevSaves[0]), false)[0]); + sketchBackupFolder = t; pastSave = new File(t.getAbsolutePath() + File.separator + t.getName() + ".pde"); if(pastSave.exists()) return true; @@ -89,6 +104,18 @@ public void reloadAutosaveDir(){ autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); } + /** + * The folder of the original sketch + * @return + */ + public File getSketchFolder(){ + return sketchFolder; + } + + public File getSketchBackupFolder(){ + return sketchBackupFolder; + } + public File getPastSave(){ return pastSave; } @@ -98,7 +125,7 @@ public File getPastSave(){ */ public void init(){ if(saveTime < 10000) saveTime = 10 * 1000; - //saveTime = 10 * 1000; //TODO: remove + saveTime = 5 * 1000; //TODO: remove timer = new Timer(); timer.schedule(new SaveTask(), saveTime, saveTime); isSaving = false; @@ -112,6 +139,7 @@ public void stop(){ while(isSaving); // save operation mustn't be interrupted if(timer != null) timer.cancel(); Base.removeDir(autosaveDir); + ExperimentalMode.log("Stopping autosaver and deleting backup dir"); } /** diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 02e698b..42e6d23 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -245,7 +245,10 @@ public void actionPerformed(ActionEvent e) { ta.setECSandThemeforTextArea(errorCheckerService, dmode); addXQModeUI(); debugToolbarEnabled = new AtomicBoolean(false); - log("Sketch Path: " + path); + //log("Sketch Path: " + path); + + viewingAutosaveBackup = false; + log("DebugEdit constructed. Viewing auto save false " + viewingAutosaveBackup); } private void addXQModeUI(){ @@ -342,7 +345,10 @@ public void dispose() { // Added temporarily to dump error log. TODO: Remove this later public void internalCloseRunner(){ if(ExperimentalMode.errorLogsEnabled) writeErrorsToFile(); - if(autosaver != null) autosaver.stop(); + if(autosaver != null && !viewingAutosaveBackup) { + log("stopping autosaver in internalCloseRunner"); + autosaver.stop(); + } super.internalCloseRunner(); } @@ -738,6 +744,7 @@ public void handleStop() { */ @Override protected boolean handleOpenInternal(String path) { + log("handleOpenInternal, path: " + path); boolean didOpen = super.handleOpenInternal(path); if (didOpen && dbg != null) { // should already been stopped (open calls handleStop) @@ -745,9 +752,16 @@ protected boolean handleOpenInternal(String path) { clearBreakpointedLines(); // force clear breakpoint highlights variableInspector().reset(); // clear contents of variable inspector } - if(autosaver != null) - autosaver.stop(); - loadAutoSaver(); + + if(!viewingAutosaveBackup){ + log("Sketch isn't a backup"); + if(autosaver != null){ + log("stopping autosaver in handleOpenInternal"); + autosaver.stop(); + } + loadAutoSaver(); + } + log("handleOpenInternal, viewing autosave? " + viewingAutosaveBackup); return didOpen; } @@ -825,7 +839,25 @@ protected void addBreakpointComments(String tabFilename) { @Override public boolean handleSave(boolean immediately) { //System.out.println("handleSave " + immediately); - + + log("handleSave, viewing autosave? " + viewingAutosaveBackup); + /* If user wants to save a backup, the backup sketch should get + * copied to the main sketch directory, simply reload the main sketch. + */ + if(viewingAutosaveBackup){ + File files[] = autosaver.getSketchBackupFolder().listFiles(); + File src = autosaver.getSketchBackupFolder(), dst = autosaver + .getSketchFolder(); + for (File f : files) { + log("Copying " + f.getAbsolutePath() + " to " + dst.getAbsolutePath()); +// if(f.isFile()) + //Base.copyFile(f, new File(dst + File.separator + f.getName())); +// else +// Base.copyDir(f, new File(dst + File.separator + f.getName())); + } + //viewingAutosaveBackup = false; + } + // note modified tabs final List modified = new ArrayList(); for (int i = 0; i < getSketch().getCodeCount(); i++) { @@ -887,6 +919,8 @@ public boolean handleSaveAs() { return saved; } + private boolean viewingAutosaveBackup; + /** * Loads and starts the auto save service * Also handles the case where an auto save backup is found. @@ -894,15 +928,12 @@ public boolean handleSaveAs() { */ public void loadAutoSaver(){ log("Load Auto Saver()"); - if(autosaver != null){ - autosaver.stop(); - } - autosaver = new AutoSaveUtil(this, ExperimentalMode.autoSaveInterval); + autosaver = new AutoSaveUtil(this, ExperimentalMode.autoSaveInterval); if(!autosaver.checkForPastSave()) { autosaver.init(); return; } - + if(viewingAutosaveBackup) return; File pastSave = autosaver.getPastSave(); int response = Base .showYesNoQuestion(this, @@ -913,9 +944,11 @@ public void loadAutoSaver(){ "was closed unexpectedly last time.", "Select YES to view it or NO to delete the backup."); if(response == JOptionPane.YES_OPTION){ - handleOpenInternal(pastSave.getAbsolutePath()); - Base.showMessage("Save it..", "Remember to save the backup sketch to a specific location if you want to."); + viewingAutosaveBackup = true; + handleOpenInternal(pastSave.getAbsolutePath()); + // Base.showMessage("Save it..", "Remember to save the backup sketch to a specific location if you want to."); //log(getSketch().getMainFilePath()); + log("loadAutoSaver, viewing autosave? " + viewingAutosaveBackup); return; } else{ diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 89f6538..e855a33 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1387,9 +1387,9 @@ public static boolean scrollToErrorLine(Editor edt, int tabIndex, int lineNoInTa * compiler classpath needs to be updated. */ protected void checkForChangedImports() { - log("Imports: " + programImports.size() + - " Prev Imp: " - + previousImports.size()); +// log("Imports: " + programImports.size() + +// " Prev Imp: " +// + previousImports.size()); if (programImports.size() != previousImports.size()) { // log(1); loadCompClass = true; From 25f9db0edb75442288ff762d63bfa0dae2ccf639 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 2 Mar 2014 21:44:29 +0530 Subject: [PATCH 114/193] now going around in circles with autosave --- .../mode/experimental/AutoSaveUtil.java | 47 ++++++++++++++++--- .../mode/experimental/DebugEditor.java | 44 +++++++++-------- 2 files changed, 64 insertions(+), 27 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index d02f510..3141ed6 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -27,6 +27,8 @@ import processing.app.Base; import processing.app.Sketch; +import static processing.mode.experimental.ExperimentalMode.log; + /** * Autosave utility for saving sketch backups in the background after * certain intervals @@ -50,6 +52,8 @@ public class AutoSaveUtil { private File sketchFolder, sketchBackupFolder; + private static final String AUTOSAVEFOLDER = "__autosave__"; + /** * * @param dedit @@ -63,15 +67,36 @@ public AutoSaveUtil(DebugEditor dedit, int timeOut){ } else{ saveTime = timeOut * 60 * 1000; - ExperimentalMode.log("AutoSaver Interval(mins): " + timeOut); + log("AutoSaver Interval(mins): " + timeOut); } - autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); - sketchFolder = editor.getSketch().getFolder(); checkIfBackup(); + if(isAutoSaveBackup){ + sketchBackupFolder = sketchFolder; + } + else{ + autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + AUTOSAVEFOLDER); + sketchFolder = editor.getSketch().getFolder(); + sketchBackupFolder = autosaveDir; + } } + /** + * If the sketch path looks like ../__autosave__/../FooSketch + * then assume this is a backup sketch + */ private void checkIfBackup(){ - + File parent = sketchFolder.getParentFile().getParentFile(); + if(parent.isDirectory() && parent.getName().equals(AUTOSAVEFOLDER)){ + isAutoSaveBackup = true; + log("IS AUTOSAVE " + sketchFolder.getAbsolutePath()); + } + } + + public File getActualSketchFolder(){ + if(isAutoSaveBackup) + return sketchFolder.getParentFile().getParentFile().getParentFile(); + else + return sketchFolder; } public boolean isAutoSaveBackup() { @@ -101,7 +126,11 @@ public boolean checkForPastSave(){ */ public void reloadAutosaveDir(){ while(isSaving); - autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + "_autosave"); + autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + AUTOSAVEFOLDER); + } + + public File getAutoSaveDir(){ + return autosaveDir; } /** @@ -124,12 +153,16 @@ public File getPastSave(){ * Start the auto save service */ public void init(){ + if(isAutoSaveBackup) { + log("AutoSaver not started"); + return; + } if(saveTime < 10000) saveTime = 10 * 1000; saveTime = 5 * 1000; //TODO: remove timer = new Timer(); timer.schedule(new SaveTask(), saveTime, saveTime); isSaving = false; - ExperimentalMode.log("AutoSaver started"); + log("AutoSaver started"); } /** @@ -156,7 +189,7 @@ private boolean saveSketch() throws IOException{ boolean deleteOldSave = false; String oldSave = null; if(!autosaveDir.exists()){ - autosaveDir = new File(sc.getFolder().getAbsolutePath(), "_autosave"); + autosaveDir = new File(sc.getFolder().getAbsolutePath(), AUTOSAVEFOLDER); autosaveDir.mkdir(); } else diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 42e6d23..ee47350 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -246,9 +246,6 @@ public void actionPerformed(ActionEvent e) { addXQModeUI(); debugToolbarEnabled = new AtomicBoolean(false); //log("Sketch Path: " + path); - - viewingAutosaveBackup = false; - log("DebugEdit constructed. Viewing auto save false " + viewingAutosaveBackup); } private void addXQModeUI(){ @@ -744,7 +741,7 @@ public void handleStop() { */ @Override protected boolean handleOpenInternal(String path) { - log("handleOpenInternal, path: " + path); + log("handleOpenInternal, path: " + path); boolean didOpen = super.handleOpenInternal(path); if (didOpen && dbg != null) { // should already been stopped (open calls handleStop) @@ -752,16 +749,12 @@ protected boolean handleOpenInternal(String path) { clearBreakpointedLines(); // force clear breakpoint highlights variableInspector().reset(); // clear contents of variable inspector } - - if(!viewingAutosaveBackup){ - log("Sketch isn't a backup"); - if(autosaver != null){ - log("stopping autosaver in handleOpenInternal"); - autosaver.stop(); - } + //if(didOpen){ + loadAutoSaver(); - } - log("handleOpenInternal, viewing autosave? " + viewingAutosaveBackup); + viewingAutosaveBackup = autosaver.isAutoSaveBackup(); + log("handleOpenInternal, viewing autosave? " + viewingAutosaveBackup); + //} return didOpen; } @@ -845,17 +838,30 @@ public boolean handleSave(boolean immediately) { * copied to the main sketch directory, simply reload the main sketch. */ if(viewingAutosaveBackup){ + /* File files[] = autosaver.getSketchBackupFolder().listFiles(); File src = autosaver.getSketchBackupFolder(), dst = autosaver - .getSketchFolder(); + .getActualSketchFolder(); for (File f : files) { log("Copying " + f.getAbsolutePath() + " to " + dst.getAbsolutePath()); -// if(f.isFile()) - //Base.copyFile(f, new File(dst + File.separator + f.getName())); -// else -// Base.copyDir(f, new File(dst + File.separator + f.getName())); + try { + if (f.isFile()) { + f.delete(); + Base.copyFile(f, new File(dst + File.separator + f.getName())); + } else { + Base.removeDir(f); + Base.copyDir(f, new File(dst + File.separator + f.getName())); + } + } catch (IOException e) { + e.printStackTrace(); + } } + File sk = autosaver.getActualSketchFolder(); + Base.removeDir(autosaver.getAutoSaveDir()); + //handleOpenInternal(sk.getAbsolutePath() + File.separator + sk.getName() + ".pde"); + getBase().handleOpen(sk.getAbsolutePath() + File.separator + sk.getName() + ".pde"); //viewingAutosaveBackup = false; + */ } // note modified tabs @@ -933,7 +939,6 @@ public void loadAutoSaver(){ autosaver.init(); return; } - if(viewingAutosaveBackup) return; File pastSave = autosaver.getPastSave(); int response = Base .showYesNoQuestion(this, @@ -944,7 +949,6 @@ public void loadAutoSaver(){ "was closed unexpectedly last time.", "Select YES to view it or NO to delete the backup."); if(response == JOptionPane.YES_OPTION){ - viewingAutosaveBackup = true; handleOpenInternal(pastSave.getAbsolutePath()); // Base.showMessage("Save it..", "Remember to save the backup sketch to a specific location if you want to."); //log(getSketch().getMainFilePath()); From ad872d109a0bab22b8f8c7ac04551ccdebd80749 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 19 Mar 2014 13:50:50 +0530 Subject: [PATCH 115/193] diabling auto save, switching focus on other stuff for now --- src/processing/mode/experimental/AutoSaveUtil.java | 5 ++++- src/processing/mode/experimental/DebugEditor.java | 14 +++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/processing/mode/experimental/AutoSaveUtil.java b/src/processing/mode/experimental/AutoSaveUtil.java index 3141ed6..7efa14e 100644 --- a/src/processing/mode/experimental/AutoSaveUtil.java +++ b/src/processing/mode/experimental/AutoSaveUtil.java @@ -60,6 +60,7 @@ public class AutoSaveUtil { * @param timeOut - in minutes, how frequently should saves occur */ public AutoSaveUtil(DebugEditor dedit, int timeOut){ + /* editor = dedit; if (timeOut < 1) { // less than 1 minute not allowed! saveTime = -1; @@ -77,7 +78,7 @@ public AutoSaveUtil(DebugEditor dedit, int timeOut){ autosaveDir = new File(editor.getSketch().getFolder().getAbsolutePath() + File.separator + AUTOSAVEFOLDER); sketchFolder = editor.getSketch().getFolder(); sketchBackupFolder = autosaveDir; - } + }*/ } /** @@ -153,6 +154,7 @@ public File getPastSave(){ * Start the auto save service */ public void init(){ + /* if(isAutoSaveBackup) { log("AutoSaver not started"); return; @@ -163,6 +165,7 @@ public void init(){ timer.schedule(new SaveTask(), saveTime, saveTime); isSaving = false; log("AutoSaver started"); + */ } /** diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index ee47350..20206c1 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -342,10 +342,10 @@ public void dispose() { // Added temporarily to dump error log. TODO: Remove this later public void internalCloseRunner(){ if(ExperimentalMode.errorLogsEnabled) writeErrorsToFile(); - if(autosaver != null && !viewingAutosaveBackup) { - log("stopping autosaver in internalCloseRunner"); - autosaver.stop(); - } +// if(autosaver != null && !viewingAutosaveBackup) { +// log("stopping autosaver in internalCloseRunner"); +// autosaver.stop(); +// } super.internalCloseRunner(); } @@ -750,8 +750,8 @@ protected boolean handleOpenInternal(String path) { variableInspector().reset(); // clear contents of variable inspector } //if(didOpen){ - - loadAutoSaver(); + autosaver = new AutoSaveUtil(this, ExperimentalMode.autoSaveInterval); // this is used instead of loadAutosaver(), temp measure + //loadAutoSaver(); viewingAutosaveBackup = autosaver.isAutoSaveBackup(); log("handleOpenInternal, viewing autosave? " + viewingAutosaveBackup); //} @@ -932,7 +932,7 @@ public boolean handleSaveAs() { * Also handles the case where an auto save backup is found. * The user is asked to save the sketch to a new location */ - public void loadAutoSaver(){ + private void loadAutoSaver(){ log("Load Auto Saver()"); autosaver = new AutoSaveUtil(this, ExperimentalMode.autoSaveInterval); if(!autosaver.checkForPastSave()) { From 651e5c06e28ebf087d35bf5f4a325d074691946d Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 19 Mar 2014 23:48:05 +0530 Subject: [PATCH 116/193] fixes #45, application export --- application/Info.plist.tmpl | 3 +-- .../template.app/Contents/MacOS/JavaApplicationStub | Bin application/template.app/Contents/PkgInfo | 0 application/template.exe | Bin application/template.plist | 0 5 files changed, 1 insertion(+), 2 deletions(-) mode change 100644 => 100755 application/template.app/Contents/MacOS/JavaApplicationStub mode change 100644 => 100755 application/template.app/Contents/PkgInfo mode change 100644 => 100755 application/template.exe mode change 100644 => 100755 application/template.plist diff --git a/application/Info.plist.tmpl b/application/Info.plist.tmpl index 787f56e..28a2e02 100644 --- a/application/Info.plist.tmpl +++ b/application/Info.plist.tmpl @@ -32,8 +32,7 @@ Created with Processing - JVMRuntime - @@jdk_folder@@ + @@jvm_runtime@@ JVMMainClassName @@sketch@@ diff --git a/application/template.app/Contents/MacOS/JavaApplicationStub b/application/template.app/Contents/MacOS/JavaApplicationStub old mode 100644 new mode 100755 diff --git a/application/template.app/Contents/PkgInfo b/application/template.app/Contents/PkgInfo old mode 100644 new mode 100755 diff --git a/application/template.exe b/application/template.exe old mode 100644 new mode 100755 diff --git a/application/template.plist b/application/template.plist old mode 100644 new mode 100755 From e025d77d433e02b42002224b04ae404e576ab24f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 26 Mar 2014 19:31:48 +0530 Subject: [PATCH 117/193] trying to look into the breakpoint issue --- src/processing/mode/experimental/DebugEditor.java | 2 +- src/processing/mode/experimental/LineBreakpoint.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 20206c1..3e4041e 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -891,7 +891,7 @@ public void run() { } } // if file location has changed, update autosaver - autosaver.reloadAutosaveDir(); + // autosaver.reloadAutosaveDir(); return saved; } diff --git a/src/processing/mode/experimental/LineBreakpoint.java b/src/processing/mode/experimental/LineBreakpoint.java index 8d006fd..931ea9b 100755 --- a/src/processing/mode/experimental/LineBreakpoint.java +++ b/src/processing/mode/experimental/LineBreakpoint.java @@ -53,6 +53,7 @@ public LineBreakpoint(LineID line, Debugger dbg) { this.dbg = dbg; theClass = dbg.getClass(className()); // try to get the class immediately, may return null if not yet loaded set(); // activate the breakpoint (show highlight, attach if debugger is running) + Logger.getLogger(LineBreakpoint.class.getName()).log(Level.INFO, "LBP Created " +toString() + " class: " + theClass, new Object[]{}); } /** @@ -108,6 +109,7 @@ protected void attach() { return; } try { + Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "BPs of class: {0}", new Object[]{theClass}); List locations = theClass.locationsOfLine(javaLine.lineIdx() + 1); if (locations.isEmpty()) { Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "no location found for line {0} -> {1}", new Object[]{line, javaLine}); From 596897490c094b5d5d7674d9f4b1f3d670b9b1a3 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 30 Mar 2014 02:35:07 +0530 Subject: [PATCH 118/193] wasn't too tough after all.. Fixes #51 --- src/processing/mode/experimental/ASTGenerator.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 9d74fd4..9392fcb 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1618,7 +1618,13 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, log("FLON3 "+lineNode.getStartPosition() + " off " + offset + " alt off" + altOff); ASTNode simpName = pinpointOnLine(lineNode, altOff, lineNode.getStartPosition(), name); - log("+++> " + simpName); + + if(simpName == null){ //Added while fixing #51 + log("1+++> " + simpName); + simpName = pinpointOnLine(lineNode.getParent(), altOff, + lineNode.getStartPosition(), name); + } + log("2+++> " + simpName); if (simpName instanceof SimpleName) { nameOfNode = simpName.toString(); From f5b4b82e04901dde3d2805f94accd22f25ce757f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 30 Mar 2014 03:08:46 +0530 Subject: [PATCH 119/193] right click on classes with javadoc, related to #51 --- .../mode/experimental/ASTGenerator.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 9392fcb..325a98b 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -238,7 +238,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = !true; + public static final boolean SHOWAST = true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { @@ -1625,6 +1625,21 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, lineNode.getStartPosition(), name); } log("2+++> " + simpName); + if(simpName == null && lineNode instanceof SimpleName){ + switch (lineNode.getParent().getNodeType()) { + case ASTNode.TYPE_DECLARATION: + + case ASTNode.METHOD_DECLARATION: + + case ASTNode.FIELD_DECLARATION: + + case ASTNode.VARIABLE_DECLARATION_FRAGMENT: + decl = lineNode.getParent(); + return new ASTNodeWrapper(decl,""); + default: + break; + } + } if (simpName instanceof SimpleName) { nameOfNode = simpName.toString(); @@ -2339,7 +2354,7 @@ public static ASTNode pinpointOnLine(ASTNode node, int offset, if (node instanceof SimpleName) { SimpleName sn = (SimpleName) node; - log(offset+ "off,pol " + getNodeAsString(sn)); + //log(offset+ "off,pol " + getNodeAsString(sn)); if ((lineStartOffset + offset) >= sn.getStartPosition() && (lineStartOffset + offset) <= sn.getStartPosition() + sn.getLength()) { From 04d02057cd9eaeeaef8d3ab4fbdc61523813f3b6 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 1 Apr 2014 18:30:30 +0530 Subject: [PATCH 120/193] Fixes #45 for ever and ever --- src/processing/mode/experimental/ExperimentalMode.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index a756700..5b04896 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -117,6 +117,15 @@ public File[] getKeywordFiles() { }; } + public File getContentFile(String path) { + // workaround for #45 + if (path.startsWith("application" + File.separator)) { + return new File(Base.getContentFile("modes" + File.separator + "java") + .getAbsolutePath() + File.separator + path); + } + return new File(folder, path); + } + volatile public static boolean errorCheckEnabled = true, warningsEnabled = true, codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false; public static int autoSaveInterval = 3; //in minutes From 2dc6ee6d8d7a22f6b0f072d25bf92f963e8e5759 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 1 Apr 2014 19:35:14 +0530 Subject: [PATCH 121/193] Javadocs suck. Screwing the balance everywhere >.< --- .../mode/experimental/ASTNodeWrapper.java | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 6c6cbc6..eb35e22 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -202,6 +202,9 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { } /** + * When FD has javadoc attached, the beginning of FD is marked as the + * start of the javadoc. This kind of screws things when trying to locate + * the exact name of the FD. So, offset compensations... * * @param fd * @return @@ -232,6 +235,14 @@ private int getJavadocOffset(FieldDeclaration fd){ return 0; } + /** + * When MD has javadoc attached, the beginning of FD is marked as the + * start of the javadoc. This kind of screws things when trying to locate + * the exact name of the MD. So, offset compensations... + * + * @param md + * @return + */ private int getJavadocOffset(MethodDeclaration md) { List list = md.modifiers(); SimpleName sn = (SimpleName) getNode(); @@ -258,8 +269,16 @@ private int getJavadocOffset(MethodDeclaration md) { return 0; } + /** + * When TD has javadoc attached, the beginning of FD is marked as the + * start of the javadoc. This kind of screws things when trying to locate + * the exact name of the TD. So, offset compensations... + * + * @param td + * @return + */ private int getJavadocOffset(TypeDeclaration td){ - // TODO: This is still broken. Hence no refactoring or highlighting on scroll works :\ + // TODO: This isn't perfect yet. Class \n \n \n className still breaks it.. :'( List list= td.modifiers(); list = td.modifiers(); SimpleName sn = (SimpleName) getNode(); @@ -275,7 +294,13 @@ private int getJavadocOffset(TypeDeclaration td){ } } - return 0; + if(td.getJavadoc() != null){ + log("diff " + + (td.getJavadoc().getStartPosition() + td.getJavadoc().getLength() + 1)); + return (td.getJavadoc().getStartPosition() + td.getJavadoc().getLength() + 1); + } + log("getJavadocOffset(TypeDeclaration td) "+sn + ", found nothing. Meh."); + return 0; } /** From c842212b20dbb540008ac5951ceada7188d0dfa5 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 1 Apr 2014 19:59:52 +0530 Subject: [PATCH 122/193] This minor change was long due. --- .../mode/experimental/ErrorCheckerService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index e855a33..78af0fb 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -511,7 +511,7 @@ protected void syntaxCheck() { // Populate the probList problemsList = new ArrayList(); for (int i = 0; i < problems.length; i++) { - int a[] = calculateTabIndexAndLineNumber(problems[i]); + int a[] = calculateTabIndexAndLineNumber(problems[i].getSourceLineNumber()); Problem p = new Problem(problems[i], a[0], a[1] + 1); //TODO: ^Why do cheeky stuff? problemsList.add(p); @@ -642,7 +642,7 @@ public boolean accept(File file) { // for (String j : problem.getArguments()) { // log("arg " + j); // } - int a[] = calculateTabIndexAndLineNumber(problem); + int a[] = calculateTabIndexAndLineNumber(problem.getSourceLineNumber()); Problem p = new Problem(problem, a[0], a[1]); if ((Boolean) errorList[i][8]) { p.setType(Problem.ERROR); @@ -1055,16 +1055,16 @@ public String getPDECodeAtLine(int tab, int linenumber){ * - IProblem * @return int[0] - tab number, int[1] - line number */ - public int[] calculateTabIndexAndLineNumber(IProblem problem) { + public int[] calculateTabIndexAndLineNumber(int javalineNumber) { // String[] lines = {};// = PApplet.split(sourceString, '\n'); int codeIndex = 0; - int x = problem.getSourceLineNumber() - mainClassOffset; + int x = javalineNumber - mainClassOffset; if (x < 0) { // log("Negative line number " // + problem.getSourceLineNumber() + " , offset " // + mainClassOffset); - x = problem.getSourceLineNumber() - 2; // Another -1 for 0 index + x = javalineNumber - 2; // Another -1 for 0 index if (x < programImports.size() && x >= 0) { ImportStatement is = programImports.get(x); // log(is.importName + ", " + is.tab + ", " From e965f73725f784d6971391535d6fa328e5c6826e Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 5 Apr 2014 01:23:08 +0530 Subject: [PATCH 123/193] Further work on highlighting issue --- .../mode/experimental/ASTGenerator.java | 7 +- .../mode/experimental/ASTNodeWrapper.java | 76 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 325a98b..8a58ae2 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1678,7 +1678,12 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, ASTNode simpName2 = getNodeName(decl,nameOfNode); logE("FINAL String decl: " + getNodeAsString(decl)); logE("FINAL String label: " + getNodeAsString(simpName2)); - errorCheckerService.highlightNode(simpName2); + //errorCheckerService.highlightNode(simpName2); + ASTNodeWrapper declWrap = new ASTNodeWrapper(simpName2,nodeLabel); + errorCheckerService.highlightNode(declWrap); +// if (!declWrap.highlightNode(this)) { +// logE("Highlighting failed."); +// } } return new ASTNodeWrapper(decl,nodeLabel); diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index eb35e22..3ad8bb1 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -18,6 +18,7 @@ package processing.mode.experimental; import static processing.mode.experimental.ExperimentalMode.log; +import static processing.mode.experimental.ExperimentalMode.logE; import static processing.mode.experimental.ExperimentalMode.log2; import java.util.Iterator; import java.util.List; @@ -25,6 +26,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; +import javax.swing.text.PlainDocument; + import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ExpressionStatement; @@ -516,6 +521,77 @@ public int[][] getOffsetMapping(String source){ return new int[][]{javaCodeMap,pdeCodeMap}; } + public boolean highlightNode(ASTGenerator astGenerator){ + if(!(Node instanceof SimpleName)){ + return false; + } + SimpleName nodeName = (SimpleName) Node; + try { + int javaLineNumber = getLineNumber(nodeName); + int pdeOffs[] = astGenerator.errorCheckerService + .calculateTabIndexAndLineNumber(javaLineNumber); + PlainDocument javaSource = new PlainDocument(); + javaSource.insertString(0, astGenerator.errorCheckerService.sourceCode, null); + Element lineElement = javaSource.getDefaultRootElement() + .getElement(javaLineNumber-1); + if(lineElement == null) { + log(lineNumber + " line element null while highlighting " + nodeName); + return false; + } + + String javaLine = javaSource.getText(lineElement.getStartOffset(), + lineElement.getEndOffset() + - lineElement.getStartOffset()); + astGenerator.editor.getSketch().setCurrentCode(pdeOffs[0]); + String pdeLine = astGenerator.editor.getLineText(pdeOffs[1]); + String lookingFor = nodeName.toString(); + log(lookingFor + ", " + nodeName.getStartPosition()); + log("JL " + javaLine + " LSO " + lineElement.getStartOffset() + "," + + lineElement.getEndOffset()); + log("PL " + pdeLine); + if (!javaLine.contains(lookingFor) || !pdeLine.contains(lookingFor)) { + logE("Logical error in highLightNode(). Please file a bug report."); + return false; + } + Pattern toFind = Pattern.compile("\\b" + nodeName.toString() + "\\b"); + Matcher matcher = toFind.matcher(javaLine); + int lsto = lineElement.getStartOffset(); + while(matcher.find()){ + System.out.println(matcher.start() + lsto); + } + // find the count of the name in the java code + int count = 0, index = 0; + do { + index = javaLine.indexOf(lookingFor, index); + if (index != -1) { + count++; + index += lookingFor.length(); + } else + break; + } while (true); + log("count=" + count); + // find the offset of the name of that index in the pde code + index = 0; + while (count > 0) { + index = pdeLine.indexOf(lookingFor, index); + if (index != -1) { + count--; + index += lookingFor.length(); + } + } + log("pde lso " + (index - lookingFor.length())); + + int lso = astGenerator.editor.ta.getLineStartOffset(pdeOffs[1]); + astGenerator.editor.setSelection(lso + index - lookingFor.length(), lso + + index); + return true; + } catch (BadLocationException e) { + logE("BLE in highLightNode() for " + nodeName); + e.printStackTrace(); + } + return false; + } + /** * Gets offset mapping between java and pde code * int[0][x] stores the java code offset and From f8bcab9568f771b0428e26dc9ee393016d31a241 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 5 Apr 2014 02:14:41 +0530 Subject: [PATCH 124/193] does it work? Or does it not? idk --- .../mode/experimental/ASTGenerator.java | 38 +++++++++++++++++-- .../mode/experimental/ASTNodeWrapper.java | 26 +++++++------ .../experimental/ErrorCheckerService.java | 23 ++++++++++- 3 files changed, 71 insertions(+), 16 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 8a58ae2..1188b76 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -53,6 +53,8 @@ import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.text.BadLocationException; +import javax.swing.text.Element; +import javax.swing.text.PlainDocument; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; @@ -1680,10 +1682,10 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, logE("FINAL String label: " + getNodeAsString(simpName2)); //errorCheckerService.highlightNode(simpName2); ASTNodeWrapper declWrap = new ASTNodeWrapper(simpName2,nodeLabel); - errorCheckerService.highlightNode(declWrap); -// if (!declWrap.highlightNode(this)) { -// logE("Highlighting failed."); -// } + //errorCheckerService.highlightNode(declWrap); + if (!declWrap.highlightNode(this)) { + logE("Highlighting failed."); + } } return new ASTNodeWrapper(decl,nodeLabel); @@ -1812,6 +1814,34 @@ protected void done() { if (tnode.getUserObject() instanceof ASTNodeWrapper) { ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject(); errorCheckerService.highlightNode(awrap); + + //-- + try { + int javaLineNumber = getLineNumber(awrap.getNode()); + int pdeOffs[] = errorCheckerService + .calculateTabIndexAndLineNumber(javaLineNumber); + PlainDocument javaSource = new PlainDocument(); + javaSource.insertString(0, errorCheckerService.sourceCode, null); + Element lineElement = javaSource.getDefaultRootElement() + .getElement(javaLineNumber-1); + if(lineElement == null) { + return; + } + + String javaLine = javaSource.getText(lineElement.getStartOffset(), + lineElement.getEndOffset() + - lineElement.getStartOffset()); + editor.getSketch().setCurrentCode(pdeOffs[0]); + String pdeLine = editor.getLineText(pdeOffs[1]); + //String lookingFor = nodeName.toString(); + //log(lookingFor + ", " + nodeName.getStartPosition()); + log("JL " + javaLine + " LSO " + lineElement.getStartOffset() + "," + + lineElement.getEndOffset()); + log("PL " + pdeLine); + } catch (BadLocationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } } }; diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 3ad8bb1..c0cb491 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -546,29 +546,33 @@ public boolean highlightNode(ASTGenerator astGenerator){ String pdeLine = astGenerator.editor.getLineText(pdeOffs[1]); String lookingFor = nodeName.toString(); log(lookingFor + ", " + nodeName.getStartPosition()); - log("JL " + javaLine + " LSO " + lineElement.getStartOffset() + "," + log(javaLineNumber +" JL " + javaLine + " LSO " + lineElement.getStartOffset() + "," + lineElement.getEndOffset()); - log("PL " + pdeLine); + log(pdeOffs[1] + " PL " + pdeLine); if (!javaLine.contains(lookingFor) || !pdeLine.contains(lookingFor)) { logE("Logical error in highLightNode(). Please file a bug report."); return false; } Pattern toFind = Pattern.compile("\\b" + nodeName.toString() + "\\b"); Matcher matcher = toFind.matcher(javaLine); + int count = 0, index = 0; int lsto = lineElement.getStartOffset(); while(matcher.find()){ + count++; System.out.println(matcher.start() + lsto); + if(lsto + matcher.start() == nodeName.getStartPosition()) + break; } // find the count of the name in the java code - int count = 0, index = 0; - do { - index = javaLine.indexOf(lookingFor, index); - if (index != -1) { - count++; - index += lookingFor.length(); - } else - break; - } while (true); + +// do { +// index = javaLine.indexOf(lookingFor, index); +// if (index != -1) { +// count++; +// index += lookingFor.length(); +// } else +// break; +// } while (true); log("count=" + count); // find the offset of the name of that index in the pde code index = 0; diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 78af0fb..9a50c20 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -434,7 +434,7 @@ protected boolean checkCode() { // log(sourceCode); // log("--------------------------"); compileCheck(); - astGenerator.buildAST(cu); + //astGenerator.buildAST(cu); log(editor.getSketch().getName() + "2 MCO " + mainClassOffset); } @@ -535,6 +535,27 @@ protected void syntaxCheck() { protected URLClassLoader classLoader; protected void compileCheck() { + + // CU needs to be updated coz before compileCheck xqpreprocessor is run on the source code which makes some further changes + //TODO Check if this breaks things + + parser.setSource(sourceCode.toCharArray()); + parser.setKind(ASTParser.K_COMPILATION_UNIT); + + Map options = JavaCore.getOptions(); + + JavaCore.setComplianceOptions(JavaCore.VERSION_1_6, options); + options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6); + options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); + parser.setCompilerOptions(options); + + if (cu == null) + cu = (CompilationUnit) parser.createAST(null); + else { + synchronized (cu) { + cu = (CompilationUnit) parser.createAST(null); + } + } // Currently (Sept, 2012) I'm using Java's reflection api to load the // CompilationChecker class(from CompilationChecker.jar) that houses the From d0ddf3992498c61b136ed35a10ba262505eeaf4f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 5 Apr 2014 02:27:29 +0530 Subject: [PATCH 125/193] I guess this is the best that can be done.. --- src/processing/mode/experimental/ErrorCheckerService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 9a50c20..4544b8e 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -433,11 +433,11 @@ protected boolean checkCode() { // } // log(sourceCode); // log("--------------------------"); - compileCheck(); - //astGenerator.buildAST(cu); + compileCheck(); log(editor.getSketch().getName() + "2 MCO " + mainClassOffset); } + astGenerator.buildAST(cu); if(ExperimentalMode.errorCheckEnabled){ updateErrorTable(); editor.updateErrorBar(problemsList); From 72ecf76fae393e231be0594426064103dd82df6e Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 15 Apr 2014 02:28:39 +0530 Subject: [PATCH 126/193] Fixes #53 --- src/processing/mode/experimental/ErrorCheckerService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 4544b8e..00a5501 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -53,6 +53,7 @@ import processing.app.Base; import processing.app.Editor; +import processing.app.EditorStatus; import processing.app.Library; import processing.app.SketchCode; import processing.app.syntax.SyntaxDocument; @@ -947,12 +948,16 @@ public void updatePaintedThingys() { } } + protected int lastCaretLine = -1; + /** * 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(ExperimentalMode.errorCheckEnabled) From d286aff8326484b45a78cad73553787f18d1ad53 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 15 Apr 2014 02:39:12 +0530 Subject: [PATCH 127/193] Fixes #29 --- .../mode/experimental/ErrorCheckerService.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 00a5501..c422d33 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -978,10 +978,17 @@ public void updateEditorStatus() { } } } - if (editor.ta.getCaretLine() != lastCaretLine) { + + // This line isn't an error line anymore, so probably just clear it + if (editor.getStatusMode() == EditorStatus.ERR + || editor.getStatusMode() == EditorStatus.NOTICE) { editor.statusEmpty(); - lastCaretLine = editor.ta.getCaretLine(); + return; } +// if (editor.ta.getCaretLine() != lastCaretLine) { +// editor.statusEmpty(); +// lastCaretLine = editor.ta.getCaretLine(); +// } } /** From f288802233cf26a9586979b7f06e4c4eeb5a9677 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 15 Apr 2014 12:28:47 +0530 Subject: [PATCH 128/193] a bit of code cleanup --- .../mode/experimental/ASTGenerator.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 1188b76..ff3709c 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -240,7 +240,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = true; + public static final boolean SHOWAST = !true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { @@ -3239,17 +3239,16 @@ public void actionPerformed(ActionEvent e) { } - public void disposeAllWindows(){ - disposeWindow(frmASTView); - disposeWindow(frameAutoComp); - disposeWindow(frmImportSuggest); - disposeWindow(frmOccurenceList); - disposeWindow(frmRename); + public void disposeAllWindows() { + disposeWindow(frmASTView, frameAutoComp, frmImportSuggest, + frmOccurenceList, frmRename); } - public static void disposeWindow(JFrame f) { - if(f != null) - f.dispose(); + public static void disposeWindow(JFrame... f) { + for (JFrame jFrame : f) { + if(jFrame != null) + jFrame.dispose(); + } } public static final String ignoredImports[] = { From 7a09ebf20dab11169a214a1e9955b6a3117b2734 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 19 Apr 2014 23:22:14 +0530 Subject: [PATCH 129/193] Found another bug in refactoring --- .../mode/experimental/ASTNodeWrapper.java | 2 ++ .../mode/experimental/LineBreakpoint.java | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index c0cb491..2536e78 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -553,6 +553,7 @@ public boolean highlightNode(ASTGenerator astGenerator){ logE("Logical error in highLightNode(). Please file a bug report."); return false; } + //TODO: Asteriods example. Spaceship ship; wrong highlight Pattern toFind = Pattern.compile("\\b" + nodeName.toString() + "\\b"); Matcher matcher = toFind.matcher(javaLine); int count = 0, index = 0; @@ -583,6 +584,7 @@ public boolean highlightNode(ASTGenerator astGenerator){ index += lookingFor.length(); } } + log("pde lso " + (index - lookingFor.length())); int lso = astGenerator.editor.ta.getLineStartOffset(pdeOffs[1]); diff --git a/src/processing/mode/experimental/LineBreakpoint.java b/src/processing/mode/experimental/LineBreakpoint.java index 931ea9b..e35cea2 100755 --- a/src/processing/mode/experimental/LineBreakpoint.java +++ b/src/processing/mode/experimental/LineBreakpoint.java @@ -25,6 +25,10 @@ import java.util.logging.Level; import java.util.logging.Logger; +import static processing.mode.experimental.ExperimentalMode.log; +import static processing.mode.experimental.ExperimentalMode.logE; +import static processing.mode.experimental.ExperimentalMode.log2; + /** * Model/Controller of a line breakpoint. Can be set before or while debugging. * Adds a highlight using the debuggers view ({@link DebugEditor}). @@ -53,7 +57,7 @@ public LineBreakpoint(LineID line, Debugger dbg) { this.dbg = dbg; theClass = dbg.getClass(className()); // try to get the class immediately, may return null if not yet loaded set(); // activate the breakpoint (show highlight, attach if debugger is running) - Logger.getLogger(LineBreakpoint.class.getName()).log(Level.INFO, "LBP Created " +toString() + " class: " + theClass, new Object[]{}); + Logger.getLogger(LineBreakpoint.class.getName()).log(Level.INFO, "LBP Created " +toString() + " class: " + className(), new Object[]{}); } /** @@ -109,7 +113,7 @@ protected void attach() { return; } try { - Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "BPs of class: {0}", new Object[]{theClass}); + Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "BPs of class: {0} , line " + (javaLine.lineIdx() + 1), new Object[]{theClass}); List locations = theClass.locationsOfLine(javaLine.lineIdx() + 1); if (locations.isEmpty()) { Logger.getLogger(LineBreakpoint.class.getName()).log(Level.WARNING, "no location found for line {0} -> {1}", new Object[]{line, javaLine}); @@ -189,6 +193,7 @@ protected String className() { if (line.fileName().endsWith(".pde")) { // standard tab ReferenceType mainClass = dbg.getMainClass(); + //System.out.println(dbg.getMainClass().name()); if (mainClass == null) { return null; } @@ -212,9 +217,13 @@ protected String className() { @Override public void classLoaded(ReferenceType theClass) { // check if our class is being loaded + log("Class Loaded: " + theClass.name()); if (theClass.name().equals(className())) { this.theClass = theClass; attach(); } + for (ReferenceType ct : theClass.nestedTypes()) { + log("Nested " + ct.name()); + } } } From dfbfa580f67f624d9b7c68fca0bb6fc0991ccd98 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sat, 19 Apr 2014 23:27:43 +0530 Subject: [PATCH 130/193] Refactoring bug fix --- .../mode/experimental/ASTNodeWrapper.java | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 2536e78..3b03aa9 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -521,6 +521,12 @@ public int[][] getOffsetMapping(String source){ return new int[][]{javaCodeMap,pdeCodeMap}; } + /** + * Highlight the ASTNode in the editor, if it's of type + * SimpleName + * @param astGenerator + * @return - true if highlighting was successful + */ public boolean highlightNode(ASTGenerator astGenerator){ if(!(Node instanceof SimpleName)){ return false; @@ -553,7 +559,8 @@ public boolean highlightNode(ASTGenerator astGenerator){ logE("Logical error in highLightNode(). Please file a bug report."); return false; } - //TODO: Asteriods example. Spaceship ship; wrong highlight + + // First find the name in the java line, and marks its index Pattern toFind = Pattern.compile("\\b" + nodeName.toString() + "\\b"); Matcher matcher = toFind.matcher(javaLine); int count = 0, index = 0; @@ -564,27 +571,18 @@ public boolean highlightNode(ASTGenerator astGenerator){ if(lsto + matcher.start() == nodeName.getStartPosition()) break; } - // find the count of the name in the java code - -// do { -// index = javaLine.indexOf(lookingFor, index); -// if (index != -1) { -// count++; -// index += lookingFor.length(); -// } else -// break; -// } while (true); log("count=" + count); - // find the offset of the name of that index in the pde code index = 0; - while (count > 0) { - index = pdeLine.indexOf(lookingFor, index); - if (index != -1) { - count--; - index += lookingFor.length(); + // find the same name in the pde line by its index and get its offsets + matcher = toFind.matcher(pdeLine); + while(matcher.find()){ + count--; + if(count == 0){ + log("Found on pde line lso: " + matcher.start()); + index = matcher.end(); + break; } } - log("pde lso " + (index - lookingFor.length())); int lso = astGenerator.editor.ta.getLineStartOffset(pdeOffs[1]); From 3deb6e21cd347c11ab30f57b5e69e319f1ce5a35 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Thu, 1 May 2014 04:18:05 +0530 Subject: [PATCH 131/193] trying to get to the bottom of parameterized type bug --- .../mode/experimental/ASTGenerator.java | 18 +++++++++--------- .../mode/experimental/ErrorCheckerService.java | 8 +++++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index ff3709c..0650e86 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -240,7 +240,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = !true; + public static final boolean SHOWAST = true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { @@ -1545,7 +1545,7 @@ public void scrollToDeclaration(int lineNumber, String name, int offset) { public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, boolean scrollOnly) { - log("----getASTNodeAt----"); + log("----getASTNodeAt---- CU State: " + errorCheckerService.compilationUnitState); if (errorCheckerService != null) { editor = errorCheckerService.getEditor(); int codeIndex = editor.getSketch().getCodeIndex(editor.getCurrentTab()); @@ -1558,10 +1558,10 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } } - log("FLON: " + lineNumber); + log("FLON: Node line number " + lineNumber); ASTNode lineNode = findLineOfNode(compilationUnit, lineNumber, offset, name); - log("+> " + lineNode); + log("Node text +> " + lineNode); ASTNode decl = null; String nodeLabel = null; String nameOfNode = null; // The node name which is to be scrolled to @@ -1581,7 +1581,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } } } - log("FLON2: " + lineNumber + " LN spos " + log("FLON2: " + lineNumber + " LN start pos " + lineNode.getStartPosition() + " off " + offset + " alt off" + altOff); /* * Now I need to see if multiple statements exist with this same line number @@ -1617,16 +1617,16 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } } } - log("FLON3 "+lineNode.getStartPosition() + " off " + offset + " alt off" + altOff); + log("FLON3 new alt off: " + altOff); ASTNode simpName = pinpointOnLine(lineNode, altOff, lineNode.getStartPosition(), name); if(simpName == null){ //Added while fixing #51 - log("1+++> " + simpName); + log("pinpointOnLine 1+++> " + simpName); simpName = pinpointOnLine(lineNode.getParent(), altOff, lineNode.getStartPosition(), name); } - log("2+++> " + simpName); + log("pinpointOnLine 2+++> " + simpName); if(simpName == null && lineNode instanceof SimpleName){ switch (lineNode.getParent().getNodeType()) { case ASTNode.TYPE_DECLARATION: @@ -2386,7 +2386,7 @@ protected static ASTNode findLineOfNode(ASTNode node, int lineNumber, @SuppressWarnings("unchecked") public static ASTNode pinpointOnLine(ASTNode node, int offset, int lineStartOffset, String name) { - + //log("pinpointOnLine node class: " + node.getClass().getSimpleName()); if (node instanceof SimpleName) { SimpleName sn = (SimpleName) node; //log(offset+ "off,pol " + getNodeAsString(sn)); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index c422d33..19ac719 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -409,13 +409,15 @@ public void changedUpdate(DocumentEvent e) { } + public int compilationUnitState = 0; + protected boolean checkCode() { //log("checkCode() " + textModified.get() ); log("checkCode() " + textModified.get()); lastTimeStamp = System.currentTimeMillis(); try { sourceCode = preprocessCode(editor.getSketch().getMainProgram()); - + compilationUnitState = 0; syntaxCheck(); log(editor.getSketch().getName() + "1 MCO " + mainClassOffset); @@ -503,7 +505,7 @@ protected void syntaxCheck() { cu = (CompilationUnit) parser.createAST(null); } } - + compilationUnitState = 1; synchronized (problemsList) { // Store errors returned by the ast parser @@ -557,7 +559,7 @@ protected void compileCheck() { cu = (CompilationUnit) parser.createAST(null); } } - + compilationUnitState = 2; // Currently (Sept, 2012) I'm using Java's reflection api to load the // CompilationChecker class(from CompilationChecker.jar) that houses the // Eclispe JDT compiler, and call its getErrorsAsObj method to obtain From d5a766dfe73f1e9cf7840f81b40b75af3f0fe08d Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 4 May 2014 16:01:45 +0530 Subject: [PATCH 132/193] before attempting fix --- .../mode/experimental/ASTGenerator.java | 20 +++++++++++++++++++ .../mode/experimental/ASTNodeWrapper.java | 5 ++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 0650e86..67bca78 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1179,6 +1179,26 @@ public ArrayList getMembersForType(ClassMember tehClass, return candidates; } + public String getJavaSourceCodeline(int jLineNumber){ + try { + PlainDocument javaSource = new PlainDocument(); + javaSource.insertString(0, errorCheckerService.sourceCode, null); + Element lineElement = javaSource.getDefaultRootElement() + .getElement(jLineNumber-1); + if(lineElement == null) { + log("Couldn't fetch jlinenum " + jLineNumber); + return null; + } + String javaLine = javaSource.getText(lineElement.getStartOffset(), + lineElement.getEndOffset() + - lineElement.getStartOffset()); + return javaLine; + } catch (BadLocationException e) { + logE(e + " in getJavaSourceCodeline() for jinenum: " + jLineNumber); + } + return null; + } + /** * Searches for the particular class in the default list of imports as well as * the Sketch classpath diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 3b03aa9..542d0d8 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -377,7 +377,7 @@ public int[][] getOffsetMapping(String source){ * index correction needed. (2) Now all java conversions are applied after * marking the offsets. This ensures that the index order isn't disturbed by * one at a time conversions as done in preprocessCode() in ECS. Took me - * sometime to figure out this was a bug. (3) Next I create a tables(two + * sometime to figure out this was a bug. (3) Next I create a table(two * separate arrays) which allows me to look it up for matching any index * between pde or java version of the snippet. This also lets me find out * any difference in length between both versions. @@ -389,6 +389,8 @@ public int[][] getOffsetMapping(String source){ */ log("Src:" + source); + // Instead of converting pde into java, how can I simply extract the same source + // from the java code? Think. TODO String sourceAlt = new String(source); TreeMap offsetmap = new TreeMap(); @@ -533,6 +535,7 @@ public boolean highlightNode(ASTGenerator astGenerator){ } SimpleName nodeName = (SimpleName) Node; try { + //TODO: Redundant code. See ASTGenerator.getJavaSourceCodeline() int javaLineNumber = getLineNumber(nodeName); int pdeOffs[] = astGenerator.errorCheckerService .calculateTabIndexAndLineNumber(javaLineNumber); From 7b80247756c6993c93c4fdb6ad50e1cef038dc2b Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 5 May 2014 02:01:52 +0530 Subject: [PATCH 133/193] work on offset bug fix --- .../mode/experimental/ASTGenerator.java | 2 +- .../mode/experimental/ASTNodeWrapper.java | 36 ++++++++++++------- .../experimental/ErrorCheckerService.java | 10 ++++++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 67bca78..ebda1f9 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -240,7 +240,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = true; + public static final boolean SHOWAST = !true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 542d0d8..3acb311 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -196,7 +196,7 @@ public int[] getJavaCodeOffsets(ErrorCheckerService ecs) { int pdeoffsets[] = getPDECodeOffsets(ecs); String pdeCode = ecs.getPDECodeAtLine(pdeoffsets[0],pdeoffsets[1] - 1).trim(); - int vals[] = createOffsetMapping(pdeCode,nodeOffset - altStartPos,nodeLength); + int vals[] = createOffsetMapping(ecs, pdeCode,nodeOffset - altStartPos,nodeLength); if (vals != null) return new int[] { lineNumber, nodeOffset + vals[0] - altStartPos, vals[1] }; @@ -315,9 +315,9 @@ private int getJavadocOffset(TypeDeclaration td){ * @param nodeLen * @return int[0] - difference in start offset, int[1] - node length */ - private int[] createOffsetMapping(String source, int inpOffset, int nodeLen) { + private int[] createOffsetMapping(ErrorCheckerService ecs, String source, int inpOffset, int nodeLen) { - int ret[][] = getOffsetMapping(source); + int ret[][] = getOffsetMapping(ecs, source); if(ret == null){ // no offset mapping needed return null; @@ -358,7 +358,7 @@ private int[] createOffsetMapping(String source, int inpOffset, int nodeLen) { * @param source * @return int[0] - java code offsets, int[1] = pde code offsets */ - public int[][] getOffsetMapping(String source){ + public int[][] getOffsetMapping(ErrorCheckerService ecs, String source){ /* * This is some tricky shiz. So detailed explanation follows: @@ -392,8 +392,13 @@ public int[][] getOffsetMapping(String source){ // Instead of converting pde into java, how can I simply extract the same source // from the java code? Think. TODO String sourceAlt = new String(source); + String sourceJava = ecs.astGenerator.getJavaSourceCodeline(lineNumber); TreeMap offsetmap = new TreeMap(); + if(sourceJava.trim().startsWith("public") && !source.startsWith("public")){ + offsetmap.put(0,6); + //TODO: This is a temp fix. You GOTTA rewrite offset matching + } // Find all #[web color] // Should be 6 digits only. final String webColorRegexp = "#{1}[A-F|a-f|0-9]{6}\\W"; @@ -435,7 +440,7 @@ public int[][] getOffsetMapping(String source){ + Character.toUpperCase(dataType.charAt(0)) + dataType.substring(1) + "("); - } + } if(offsetmap.isEmpty()){ log("No offset matching needed."); return null; @@ -452,8 +457,11 @@ public int[][] getOffsetMapping(String source){ colorMatcher = colorPattern.matcher(sourceAlt); sourceAlt = colorMatcher.replaceAll("int"); - + + log("From direct source: "); + sourceAlt = sourceJava; log(sourceAlt); + // Create code map. Beware! Dark magic ahead. int javaCodeMap[] = new int[source.length() * 2]; @@ -476,16 +484,20 @@ public int[][] getOffsetMapping(String source){ pi--; pj--; for (int i = 0; i < kval; i++, pi++, pj++) { - javaCodeMap[pi] = javaCodeMap[pi - 1]; - pdeCodeMap[pj] = pdeCodeMap[pj - 1] + 1; + if (pi > 1 && pj > 1) { + javaCodeMap[pi] = javaCodeMap[pi - 1]; + pdeCodeMap[pj] = pdeCodeMap[pj - 1] + 1; + } } } else { // repeat pde offsets pi--; pj--; for (int i = 0; i < -kval; i++, pi++, pj++) { - javaCodeMap[pi] = javaCodeMap[pi - 1] + 1; - pdeCodeMap[pj] = pdeCodeMap[pj - 1]; + if (pi > 1 && pj > 1) { + javaCodeMap[pi] = javaCodeMap[pi - 1] + 1; + pdeCodeMap[pj] = pdeCodeMap[pj - 1]; + } } } @@ -506,7 +518,7 @@ public int[][] getOffsetMapping(String source){ pj++; } - // deubg o/p + // debug o/p for (int i = 0; i < pdeCodeMap.length; i++) { if (pdeCodeMap[i] > 0 || javaCodeMap[i] > 0 || i == 0) { if (i < source.length()) @@ -609,7 +621,7 @@ public boolean highlightNode(ASTGenerator astGenerator){ public int[][] getOffsetMapping(ErrorCheckerService ecs){ int pdeoffsets[] = getPDECodeOffsets(ecs); String pdeCode = ecs.getPDECodeAtLine(pdeoffsets[0],pdeoffsets[1] - 1).trim(); - return getOffsetMapping(pdeCode); + return getOffsetMapping(ecs, pdeCode); } /** diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 19ac719..d390afb 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1163,6 +1163,16 @@ public int[] calculateTabIndexAndLineNumber(int javalineNumber) { return new int[] { codeIndex, x }; } + + public int getJavaLineNumFromPDElineNum(int tab, int pdeLineNum){ + int jLineNum = programImports.size() + 1; + for (int i = 0; i < tab; i++) { + SketchCode sc = editor.getSketch().getCode(i); + int len = Base.countLines(sc.getProgram()) + 1; + jLineNum += len; + } + return jLineNum; + } /** * Fetches code from the editor tabs and pre-processes it into parsable pure From 032af4d791929f03aa2cb66b2f1585d55180259b Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 5 May 2014 02:02:48 +0530 Subject: [PATCH 134/193] added Utils class, trying edit distance stuff for offset matching --- src/processing/mode/experimental/Utils.java | 145 ++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 src/processing/mode/experimental/Utils.java diff --git a/src/processing/mode/experimental/Utils.java b/src/processing/mode/experimental/Utils.java new file mode 100644 index 0000000..d471194 --- /dev/null +++ b/src/processing/mode/experimental/Utils.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2012-14 Manindra Moharana + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package processing.mode.experimental; + +/** + * A class containing multiple utility methods + * + * @author Manindra Moharana + * + */ + +public class Utils { + + public static int minDistance(String word1, String word2) { + int len1 = word1.length(); + int len2 = word2.length(); + + // len1+1, len2+1, because finally return dp[len1][len2] + int[][] dp = new int[len1 + 1][len2 + 1]; + + for (int i = 0; i <= len1; i++) { + dp[i][0] = i; + } + + for (int j = 0; j <= len2; j++) { + dp[0][j] = j; + } + + //iterate though, and check last char + for (int i = 0; i < len1; i++) { + char c1 = word1.charAt(i); + for (int j = 0; j < len2; j++) { + char c2 = word2.charAt(j); + //System.out.print(c1 + "<->" + c2); + //if last two chars equal + if (c1 == c2) { + //update dp value for +1 length + dp[i + 1][j + 1] = dp[i][j]; + System.out.println(); + } else { + int replace = dp[i][j] + 1; + int insert = dp[i][j + 1] + 1; + int delete = dp[i + 1][j] + 1; +// if (replace < delete) { +// System.out.println(" --- D"); +// } else +// System.out.println(" --- R"); + int min = replace > insert ? insert : replace; + min = delete > min ? min : delete; + dp[i + 1][j + 1] = min; + } + } + } +// for (int i = 0; i < dp.length; i++) { +// for (int j = 0; j < dp[0].length; j++) { +// System.out.print(dp[i][j] + " "); +// } +// System.out.println(); +// } + + System.out.println("Edit distance1: " + dp[len1][len2]); + minDistInGrid(dp, 0, 0, len1, len2, word1.toCharArray(), + word2.toCharArray()); + return dp[len1][len2]; + } + + public static int distance(String a, String b) { +// a = a.toLowerCase(); +// b = b.toLowerCase(); + + // i == 0 + int[] costs = new int[b.length() + 1]; + for (int j = 0; j < costs.length; j++) + costs[j] = j; + for (int i = 1; i <= a.length(); i++) { + // j == 0; nw = lev(i - 1, j) + costs[0] = i; + int nw = i - 1; + for (int j = 1; j <= b.length(); j++) { + int cj = Math.min(1 + Math.min(costs[j], costs[j - 1]), + a.charAt(i - 1) == b.charAt(j - 1) ? nw : nw + 1); + nw = costs[j]; + costs[j] = cj; + } + } + System.out.println("Edit distance2: " + costs[b.length()]); + return costs[b.length()]; + } + + public static void minDistInGrid(int g[][], int i, int j, int fi, int fj, + char s1[], char s2[]) { +// if(i < s1.length)System.out.print(s1[i] + " <->"); +// if(j < s2.length)System.out.print(s2[j]); + if (i < s1.length && j < s2.length) { + System.out.print(s1[i] + " <-> " + s2[j]); + if (s1[i] != s2[j]) + System.out.println("--"); + } + System.out.println(); + if (i == fi && j == fj) { + System.out.println("Reached end."); + } else { + int a = Integer.MAX_VALUE, b = a, c = a; + if (i < fi) + a = g[i + 1][j]; + if (i < fi && j < fj) + b = g[i][j + 1]; + if (i < fi && j < fj) + c = g[i + 1][j + 1]; + int mini = Math.min(a, Math.min(b, c)); + if (mini == a) { + //System.out.println(s1[i + 1] + " " + s2[j]); + minDistInGrid(g, i + 1, j, fi, fj, s1, s2); + } else if (mini == b) { + //System.out.println(s1[i] + " " + s2[j + 1]); + minDistInGrid(g, i, j + 1, fi, fj, s1, s2); + } else if (mini == c) { + //System.out.println(s1[i + 1] + " " + s2[j + 1]); + minDistInGrid(g, i + 1, j + 1, fi, fj, s1, s2); + } + } + } + + public static void main(String[] args) { + minDistance("c = #qwerty;", "c = 0xffqwerty;"); + //minDistance("c = #bb00aa;", "c = 0xffbb00aa;"); +// distance("c = #bb00aa;", "c = 0xffbb00aa;"); + } +} From d0e09b7e57e71520cd51c8e266ad0e275833661c Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 7 May 2014 11:42:47 +0530 Subject: [PATCH 135/193] now that's some real progress ;) --- src/processing/mode/experimental/Utils.java | 50 ++++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/processing/mode/experimental/Utils.java b/src/processing/mode/experimental/Utils.java index d471194..68db300 100644 --- a/src/processing/mode/experimental/Utils.java +++ b/src/processing/mode/experimental/Utils.java @@ -27,10 +27,23 @@ public class Utils { + public static String reverse(String s){ + char w[] = s.toCharArray(); + for (int i = 0; i < w.length/2; i++) { + char t = w[i]; + w[i] = w[w.length - 1 - i]; + w[w.length - 1 - i] = t; + } + return new String(w); + } + public static int minDistance(String word1, String word2) { +// word1 = reverse(word1); +// word2 = reverse(word2); int len1 = word1.length(); int len2 = word2.length(); - + System.out.println(word1 + " len: " + len1); + System.out.println(word2 + " len: " + len2); // len1+1, len2+1, because finally return dp[len1][len2] int[][] dp = new int[len1 + 1][len2 + 1]; @@ -52,7 +65,7 @@ public static int minDistance(String word1, String word2) { if (c1 == c2) { //update dp value for +1 length dp[i + 1][j + 1] = dp[i][j]; - System.out.println(); +// System.out.println(); } else { int replace = dp[i][j] + 1; int insert = dp[i][j + 1] + 1; @@ -67,6 +80,7 @@ public static int minDistance(String word1, String word2) { } } } + // for (int i = 0; i < dp.length; i++) { // for (int j = 0; j < dp[0].length; j++) { // System.out.print(dp[i][j] + " "); @@ -75,7 +89,7 @@ public static int minDistance(String word1, String word2) { // } System.out.println("Edit distance1: " + dp[len1][len2]); - minDistInGrid(dp, 0, 0, len1, len2, word1.toCharArray(), + minDistInGrid(dp,len1, len2, 0, 0 , word1.toCharArray(), word2.toCharArray()); return dp[len1][len2]; } @@ -108,38 +122,40 @@ public static void minDistInGrid(int g[][], int i, int j, int fi, int fj, // if(i < s1.length)System.out.print(s1[i] + " <->"); // if(j < s2.length)System.out.print(s2[j]); if (i < s1.length && j < s2.length) { - System.out.print(s1[i] + " <-> " + s2[j]); - if (s1[i] != s2[j]) - System.out.println("--"); + System.out.print(s1[i] + " "+ i +" <-> " + j + " " + s2[j]); +// if (s1[i] != s2[j]) +// System.out.println("--"); } System.out.println(); if (i == fi && j == fj) { System.out.println("Reached end."); } else { int a = Integer.MAX_VALUE, b = a, c = a; - if (i < fi) - a = g[i + 1][j]; - if (i < fi && j < fj) - b = g[i][j + 1]; - if (i < fi && j < fj) - c = g[i + 1][j + 1]; + if (i > 0) + a = g[i - 1][j]; + if (j > 0) + b = g[i][j - 1]; + if (i > 0 && j > 0) + c = g[i - 1][j - 1]; int mini = Math.min(a, Math.min(b, c)); if (mini == a) { //System.out.println(s1[i + 1] + " " + s2[j]); - minDistInGrid(g, i + 1, j, fi, fj, s1, s2); + minDistInGrid(g, i - 1, j, fi, fj, s1, s2); } else if (mini == b) { //System.out.println(s1[i] + " " + s2[j + 1]); - minDistInGrid(g, i, j + 1, fi, fj, s1, s2); + minDistInGrid(g, i, j - 1, fi, fj, s1, s2); } else if (mini == c) { //System.out.println(s1[i + 1] + " " + s2[j + 1]); - minDistInGrid(g, i + 1, j + 1, fi, fj, s1, s2); + minDistInGrid(g, i - 1, j - 1, fi, fj, s1, s2); } } } public static void main(String[] args) { - minDistance("c = #qwerty;", "c = 0xffqwerty;"); - //minDistance("c = #bb00aa;", "c = 0xffbb00aa;"); +// minDistance("c = #qwerty;", "c = 0xffqwerty;"); +// minDistance("int a = int(4.5);", "int a = PApplet.parseInt(4.5f);"); + minDistance("static void main(){;", "public static void main(){;"); +// minDistance("#bb00aa", "0xffbb00aa"); // distance("c = #bb00aa;", "c = 0xffbb00aa;"); } } From ee1be6a659e1af3cedda1e10740d93f268cf380f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 7 May 2014 13:10:08 +0530 Subject: [PATCH 136/193] fixed size arrays don't cut it. --- src/processing/mode/experimental/Utils.java | 46 ++++++++++++++------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/processing/mode/experimental/Utils.java b/src/processing/mode/experimental/Utils.java index 68db300..bed7839 100644 --- a/src/processing/mode/experimental/Utils.java +++ b/src/processing/mode/experimental/Utils.java @@ -18,25 +18,27 @@ package processing.mode.experimental; +import java.util.HashMap; + /** * A class containing multiple utility methods * * @author Manindra Moharana - * + * */ public class Utils { - - public static String reverse(String s){ + + public static String reverse(String s) { char w[] = s.toCharArray(); - for (int i = 0; i < w.length/2; i++) { + for (int i = 0; i < w.length / 2; i++) { char t = w[i]; w[i] = w[w.length - 1 - i]; w[w.length - 1 - i] = t; } return new String(w); } - + public static int minDistance(String word1, String word2) { // word1 = reverse(word1); // word2 = reverse(word2); @@ -80,17 +82,24 @@ public static int minDistance(String word1, String word2) { } } } - + // for (int i = 0; i < dp.length; i++) { // for (int j = 0; j < dp[0].length; j++) { // System.out.print(dp[i][j] + " "); // } // System.out.println(); // } - + int maxLen = Math.max(len1, len2); + int pdeCodeMap[] = new int[maxLen], javaCodeMap[] = new int[maxLen]; System.out.println("Edit distance1: " + dp[len1][len2]); - minDistInGrid(dp,len1, len2, 0, 0 , word1.toCharArray(), - word2.toCharArray()); + minDistInGrid(dp, len1, len2, 0, 0, word1.toCharArray(), + word2.toCharArray(), pdeCodeMap, javaCodeMap, maxLen); + System.out.println("PDE-to-Java"); + for (int i = 0; i < maxLen; i++) { + System.out.print(pdeCodeMap[i] + " <-> " + javaCodeMap[i]); + System.out.println(", " + word1.charAt(pdeCodeMap[i]) + " <-> " + + word2.charAt(javaCodeMap[i])); + } return dp[len1][len2]; } @@ -118,11 +127,14 @@ public static int distance(String a, String b) { } public static void minDistInGrid(int g[][], int i, int j, int fi, int fj, - char s1[], char s2[]) { + char s1[], char s2[], int pdeCodeMap[], + int javaCodeMap[], int k) { // if(i < s1.length)System.out.print(s1[i] + " <->"); // if(j < s2.length)System.out.print(s2[j]); if (i < s1.length && j < s2.length) { - System.out.print(s1[i] + " "+ i +" <-> " + j + " " + s2[j]); + pdeCodeMap[k] = i; + javaCodeMap[k] = j; + System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j] + " k = " + k); // if (s1[i] != s2[j]) // System.out.println("--"); } @@ -140,21 +152,25 @@ public static void minDistInGrid(int g[][], int i, int j, int fi, int fj, int mini = Math.min(a, Math.min(b, c)); if (mini == a) { //System.out.println(s1[i + 1] + " " + s2[j]); - minDistInGrid(g, i - 1, j, fi, fj, s1, s2); + minDistInGrid(g, i - 1, j, fi, fj, s1, s2, pdeCodeMap, javaCodeMap, + k - 1); } else if (mini == b) { //System.out.println(s1[i] + " " + s2[j + 1]); - minDistInGrid(g, i, j - 1, fi, fj, s1, s2); + minDistInGrid(g, i, j - 1, fi, fj, s1, s2, pdeCodeMap, javaCodeMap, + k - 1); } else if (mini == c) { //System.out.println(s1[i + 1] + " " + s2[j + 1]); - minDistInGrid(g, i - 1, j - 1, fi, fj, s1, s2); + minDistInGrid(g, i - 1, j - 1, fi, fj, s1, s2, pdeCodeMap, javaCodeMap, + k - 1); } } } public static void main(String[] args) { // minDistance("c = #qwerty;", "c = 0xffqwerty;"); + minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); // minDistance("int a = int(4.5);", "int a = PApplet.parseInt(4.5f);"); - minDistance("static void main(){;", "public static void main(){;"); +// minDistance("static void main(){;", "public static void main(){;"); // minDistance("#bb00aa", "0xffbb00aa"); // distance("c = #bb00aa;", "c = 0xffbb00aa;"); } From e698f2f6e442ba4d9360d93eb08f14213c80d15d Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 7 May 2014 14:24:40 +0530 Subject: [PATCH 137/193] too much trouble this --- src/processing/mode/experimental/Utils.java | 57 +++++++++++++-------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/processing/mode/experimental/Utils.java b/src/processing/mode/experimental/Utils.java index bed7839..09007ab 100644 --- a/src/processing/mode/experimental/Utils.java +++ b/src/processing/mode/experimental/Utils.java @@ -18,6 +18,7 @@ package processing.mode.experimental; +import java.util.ArrayList; import java.util.HashMap; /** @@ -39,7 +40,7 @@ public static String reverse(String s) { return new String(w); } - public static int minDistance(String word1, String word2) { + public int minDistance(String word1, String word2) { // word1 = reverse(word1); // word2 = reverse(word2); int len1 = word1.length(); @@ -89,17 +90,24 @@ public static int minDistance(String word1, String word2) { // } // System.out.println(); // } - int maxLen = Math.max(len1, len2); - int pdeCodeMap[] = new int[maxLen], javaCodeMap[] = new int[maxLen]; - System.out.println("Edit distance1: " + dp[len1][len2]); +// int maxLen = Math.max(len1, len2)+2; +// int pdeCodeMap[] = new int[maxLen], javaCodeMap[] = new int[maxLen]; +// System.out.println("Edit distance1: " + dp[len1][len2]); + ArrayList alist = new ArrayList(); minDistInGrid(dp, len1, len2, 0, 0, word1.toCharArray(), - word2.toCharArray(), pdeCodeMap, javaCodeMap, maxLen); + word2.toCharArray(), alist); System.out.println("PDE-to-Java"); - for (int i = 0; i < maxLen; i++) { - System.out.print(pdeCodeMap[i] + " <-> " + javaCodeMap[i]); - System.out.println(", " + word1.charAt(pdeCodeMap[i]) + " <-> " - + word2.charAt(javaCodeMap[i])); +// for (int i = 0; i < maxLen; i++) { +// System.out.print(pdeCodeMap[i] + " <-> " + javaCodeMap[i]); +// System.out.println(", " + word1.charAt(pdeCodeMap[i]) + " <-> " +// + word2.charAt(javaCodeMap[i])); +// } + for (int i = 0; i < alist.size(); i++) { + System.out.print(alist.get(i).pdeOffset + " <-> " + alist.get(i).javaOffset); + System.out.println(", " + word1.charAt(alist.get(i).pdeOffset) + " <-> " + + word2.charAt(alist.get(i).javaOffset)); } + System.out.println("Length " + alist.size()); return dp[len1][len2]; } @@ -126,15 +134,15 @@ public static int distance(String a, String b) { return costs[b.length()]; } - public static void minDistInGrid(int g[][], int i, int j, int fi, int fj, - char s1[], char s2[], int pdeCodeMap[], - int javaCodeMap[], int k) { + public void minDistInGrid(int g[][], int i, int j, int fi, int fj, + char s1[], char s2[], ArrayList set) { // if(i < s1.length)System.out.print(s1[i] + " <->"); // if(j < s2.length)System.out.print(s2[j]); if (i < s1.length && j < s2.length) { - pdeCodeMap[k] = i; - javaCodeMap[k] = j; - System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j] + " k = " + k); +// pdeCodeMap[k] = i; +// javaCodeMap[k] = j; + System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j]); + set.add(new OfsSet(i, j)); // if (s1[i] != s2[j]) // System.out.println("--"); } @@ -152,23 +160,28 @@ public static void minDistInGrid(int g[][], int i, int j, int fi, int fj, int mini = Math.min(a, Math.min(b, c)); if (mini == a) { //System.out.println(s1[i + 1] + " " + s2[j]); - minDistInGrid(g, i - 1, j, fi, fj, s1, s2, pdeCodeMap, javaCodeMap, - k - 1); + minDistInGrid(g, i - 1, j, fi, fj, s1, s2,set); } else if (mini == b) { //System.out.println(s1[i] + " " + s2[j + 1]); - minDistInGrid(g, i, j - 1, fi, fj, s1, s2, pdeCodeMap, javaCodeMap, - k - 1); + minDistInGrid(g, i, j - 1, fi, fj, s1, s2, set); } else if (mini == c) { //System.out.println(s1[i + 1] + " " + s2[j + 1]); - minDistInGrid(g, i - 1, j - 1, fi, fj, s1, s2, pdeCodeMap, javaCodeMap, - k - 1); + minDistInGrid(g, i - 1, j - 1, fi, fj, s1, s2, set); } } } + + public class OfsSet { + public final int pdeOffset, javaOffset; + public OfsSet(int pde, int java){ + pdeOffset = pde; + javaOffset = java; + } + } public static void main(String[] args) { // minDistance("c = #qwerty;", "c = 0xffqwerty;"); - minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); + new Utils().minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); // minDistance("int a = int(4.5);", "int a = PApplet.parseInt(4.5f);"); // minDistance("static void main(){;", "public static void main(){;"); // minDistance("#bb00aa", "0xffbb00aa"); From 3039e458b7fedb3da1ab5ca7c4c35cb1db4ede4f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 9 May 2014 22:06:54 +0530 Subject: [PATCH 138/193] release notes for 1.0.4 --- pdeX.txt | 4 ++-- revisions.txt | 24 ++++++++++++++++++- .../mode/experimental/ASTNodeWrapper.java | 4 ++-- .../experimental/ErrorCheckerService.java | 9 +++++++ 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/pdeX.txt b/pdeX.txt index 2cc551f..7c2a3aa 100644 --- a/pdeX.txt +++ b/pdeX.txt @@ -3,5 +3,5 @@ authorList=[The Processing Foundation](http://processing.org) url=https://github.com/processing/processing-experimental sentence=The next generation of PDE paragraph=Intelligent Code Completion, Live Error Checker, Debugger, Auto Refactor, etc. -version=6 -prettyVersion=1.0.3b +version=7 +prettyVersion=1.0.4b diff --git a/revisions.txt b/revisions.txt index 5a2a1fd..647859a 100644 --- a/revisions.txt +++ b/revisions.txt @@ -1,11 +1,33 @@ -PDE X v1.0.4b - February , 2014 +PDE X v1.0.4b - May 9, 2014 + +Requires Processing 2.1.2 or above. Bug fixes ++ Disabled auto-save. My sincere apologies to those who lost data due +to this bug. It was wrong of me to release an untested feature without +adding an option to enable/disable it. I've learnt a lesson and I shall +ensure this sort of thing doesn't happen again in the future. + + Autocompletion bug, column is sometimes off by 1 https://github.com/processing/processing-experimental/issues/38 ++ Persistent completion dialog on OS X +https://github.com/processing/processing-experimental/issues/32 + ++ Status bar update bug +https://github.com/processing/processing-experimental/issues/29 + ++ Export application broken +https://github.com/processing/processing-experimental/issues/45 + ++ Status Bar - New Tab prompt bug +https://github.com/processing/processing-experimental/issues/53 + ++ Show usage fails for methods which have javadoc comment +https://github.com/processing/processing-experimental/issues/51 + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PDE X v1.0.3b - January 21, 2014 diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 3acb311..2823cc9 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -459,7 +459,7 @@ public int[][] getOffsetMapping(ErrorCheckerService ecs, String source){ sourceAlt = colorMatcher.replaceAll("int"); log("From direct source: "); - sourceAlt = sourceJava; +// sourceAlt = sourceJava; log(sourceAlt); @@ -582,7 +582,7 @@ public boolean highlightNode(ASTGenerator astGenerator){ int lsto = lineElement.getStartOffset(); while(matcher.find()){ count++; - System.out.println(matcher.start() + lsto); + //log(matcher.start() + lsto); if(lsto + matcher.start() == nodeName.getStartPosition()) break; } diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index d390afb..c026a56 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -213,6 +213,7 @@ public class ErrorCheckerService implements Runnable{ protected ErrorMessageSimplifier errorMsgSimplifier; public ErrorCheckerService(DebugEditor debugEditor) { + ensureMinP5Version(); this.editor = debugEditor; stopThread = new AtomicBoolean(false); pauseThread = new AtomicBoolean(false); @@ -283,6 +284,14 @@ public void run() { } }); } + + public void ensureMinP5Version(){ + // Processing 2.1.2 - Revision 0225 + if(Base.getRevision() < 225){ +// System.err.println("ERROR: PDE X requires Processing 2.1.2 or higher."); + Base.showWarning("Error", "ERROR: PDE X requires Processing 2.1.2 or higher.", null); + } + } public void run() { stopThread.set(false); From 787af5d2b9ffd6c5137e03e1f0c25588f63d166c Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 1 Jun 2014 17:02:05 +0530 Subject: [PATCH 139/193] Fixes #66 --- .../mode/experimental/CompletionPanel.java | 63 +++++++++++-------- .../mode/experimental/DebugEditor.java | 2 +- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/processing/mode/experimental/CompletionPanel.java b/src/processing/mode/experimental/CompletionPanel.java index cadc007..00ee4e1 100644 --- a/src/processing/mode/experimental/CompletionPanel.java +++ b/src/processing/mode/experimental/CompletionPanel.java @@ -22,16 +22,12 @@ import static processing.mode.experimental.ExperimentalMode.logE; import java.awt.BorderLayout; -import java.awt.Color; import java.awt.Component; import java.awt.FontMetrics; import java.awt.Point; -import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.Iterator; -import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JLabel; import javax.swing.JList; @@ -210,17 +206,29 @@ public void run() { public boolean insertSelection() { if (completionList.getSelectedValue() != null) { try { + // If user types 'abc.', subword becomes '.' and null is returned String currentSubword = fetchCurrentSubword(); + int currentSubwordLen = currentSubword == null ? 0 : currentSubword + .length(); + //logE(currentSubword + " <= subword,len => " + currentSubword.length()); String selectedSuggestion = ((CompletionCandidate) completionList - .getSelectedValue()).getCompletionString().substring(currentSubword - .length()); - logE(subWord + " <= subword,Inserting suggestion=> " + .getSelectedValue()).getCompletionString(); + + if (currentSubword != null) { + selectedSuggestion = selectedSuggestion.substring(currentSubwordLen); + } else { + currentSubword = ""; + } + + logE(subWord + " <= subword, Inserting suggestion=> " + selectedSuggestion + " Current sub: " + currentSubword); - textarea.getDocument().remove(insertionPosition - - currentSubword.length(), - currentSubword.length()); + if (currentSubword.length() > 0) { + textarea.getDocument().remove(insertionPosition - currentSubwordLen, + currentSubwordLen); + } + textarea.getDocument() - .insertString(insertionPosition - currentSubword.length(), + .insertString(insertionPosition - currentSubwordLen, ((CompletionCandidate) completionList .getSelectedValue()).getCompletionString(), null); if (selectedSuggestion.endsWith(")")) { @@ -240,12 +248,16 @@ public boolean insertSelection() { } catch (BadLocationException e1) { e1.printStackTrace(); } + catch (Exception e) { + e.printStackTrace(); + } hide(); } return false; } private String fetchCurrentSubword() { + //log("Entering fetchCurrentSubword"); TextArea ta = editor.ta; int off = ta.getCaretPosition(); //log2("off " + off); @@ -256,35 +268,32 @@ private String fetchCurrentSubword() { return null; String s = ta.getLineText(line); //log2("lin " + line); - /* - * if (s == null) return null; else if (s.length() == 0) return null; - */ -// else { //log2(s + " len " + s.length()); - int x = ta.getCaretPosition() - ta.getLineStartOffset(line) - 1, x2 = x + 1, x1 = x - 1; + int x = ta.getCaretPosition() - ta.getLineStartOffset(line) - 1, x1 = x - 1; if(x >= s.length() || x < 0) return null; //TODO: Does this check cause problems? Verify. - //log2(" x char: " + s.charAt(x)); + log2(" x char: " + s.charAt(x)); //int xLS = off - getLineStartNonWhiteSpaceOffset(line); String word = (x < s.length() ? s.charAt(x) : "") + ""; if (s.trim().length() == 1) { -// word = "" -// + (keyChar == KeyEvent.CHAR_UNDEFINED ? s.charAt(x - 1) : keyChar); - //word = (x < s.length()?s.charAt(x):"") + ""; + // word = "" + // + (keyChar == KeyEvent.CHAR_UNDEFINED ? s.charAt(x - 1) : keyChar); + //word = (x < s.length()?s.charAt(x):"") + ""; word = word.trim(); if (word.endsWith(".")) word = word.substring(0, word.length() - 1); return word; } -// if (keyChar == KeyEvent.VK_BACK_SPACE || keyChar == KeyEvent.VK_DELETE) -// ; // accepted these keys -// else if (!(Character.isLetterOrDigit(keyChar) || keyChar == '_' || keyChar == '$')) -// return null; + //log("fetchCurrentSubword 1 " + word); + if(word.equals(".")) return null; // If user types 'abc.', subword becomes '.' + // if (keyChar == KeyEvent.VK_BACK_SPACE || keyChar == KeyEvent.VK_DELETE) + // ; // accepted these keys + // else if (!(Character.isLetterOrDigit(keyChar) || keyChar == '_' || keyChar == '$')) + // return null; int i = 0; - int closeB = 0; while (true) { i++; @@ -307,13 +316,13 @@ private String fetchCurrentSubword() { } } // if (keyChar != KeyEvent.CHAR_UNDEFINED) - + //log("fetchCurrentSubword 2 " + word); if (Character.isDigit(word.charAt(0))) return null; word = word.trim(); if (word.endsWith(".")) word = word.substring(0, word.length() - 1); - + //log("fetchCurrentSubword 3 " + word); //showSuggestionLater(); return word; //} diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 3e4041e..8813d5a 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -921,7 +921,7 @@ public boolean handleSaveAs() { vi.setTitle(getSketch().getName()); } // if file location has changed, update autosaver - autosaver.reloadAutosaveDir(); +// autosaver.reloadAutosaveDir(); return saved; } From c9db4e9447cc8ba6b56ce0c8e18db4e320534517 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 2 Jun 2014 01:12:42 +0530 Subject: [PATCH 140/193] more progress with offset matching --- src/processing/mode/experimental/Utils.java | 52 ++++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/processing/mode/experimental/Utils.java b/src/processing/mode/experimental/Utils.java index 09007ab..f160dcc 100644 --- a/src/processing/mode/experimental/Utils.java +++ b/src/processing/mode/experimental/Utils.java @@ -30,6 +30,8 @@ public class Utils { + public ArrayList offsetMatch; + String word1, word2; public static String reverse(String s) { char w[] = s.toCharArray(); for (int i = 0; i < w.length / 2; i++) { @@ -39,8 +41,19 @@ public static String reverse(String s) { } return new String(w); } + + public void getJavaOffForPdeOff(int start, int length){ + for (int i = 0; i < offsetMatch.size(); i++) { + System.out.print(offsetMatch.get(i).pdeOffset + " <-> " + offsetMatch.get(i).javaOffset); + System.out.println(", " + word1.charAt(offsetMatch.get(i).pdeOffset) + " <-> " + + word2.charAt(offsetMatch.get(i).javaOffset)); + } + System.out.println("Length " + offsetMatch.size()); + } public int minDistance(String word1, String word2) { + this.word1 = word1; + this.word2 = word2; // word1 = reverse(word1); // word2 = reverse(word2); int len1 = word1.length(); @@ -94,20 +107,21 @@ public int minDistance(String word1, String word2) { // int pdeCodeMap[] = new int[maxLen], javaCodeMap[] = new int[maxLen]; // System.out.println("Edit distance1: " + dp[len1][len2]); ArrayList alist = new ArrayList(); + offsetMatch = alist; minDistInGrid(dp, len1, len2, 0, 0, word1.toCharArray(), word2.toCharArray(), alist); - System.out.println("PDE-to-Java"); +// System.out.println("PDE-to-Java"); // for (int i = 0; i < maxLen; i++) { // System.out.print(pdeCodeMap[i] + " <-> " + javaCodeMap[i]); // System.out.println(", " + word1.charAt(pdeCodeMap[i]) + " <-> " // + word2.charAt(javaCodeMap[i])); // } - for (int i = 0; i < alist.size(); i++) { - System.out.print(alist.get(i).pdeOffset + " <-> " + alist.get(i).javaOffset); - System.out.println(", " + word1.charAt(alist.get(i).pdeOffset) + " <-> " - + word2.charAt(alist.get(i).javaOffset)); - } - System.out.println("Length " + alist.size()); +// for (int i = 0; i < alist.size(); i++) { +// System.out.print(alist.get(i).pdeOffset + " <-> " + alist.get(i).javaOffset); +// System.out.println(", " + word1.charAt(alist.get(i).pdeOffset) + " <-> " +// + word2.charAt(alist.get(i).javaOffset)); +// } +// System.out.println("Length " + alist.size()); return dp[len1][len2]; } @@ -141,14 +155,14 @@ public void minDistInGrid(int g[][], int i, int j, int fi, int fj, if (i < s1.length && j < s2.length) { // pdeCodeMap[k] = i; // javaCodeMap[k] = j; - System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j]); + //System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j]); set.add(new OfsSet(i, j)); // if (s1[i] != s2[j]) // System.out.println("--"); } - System.out.println(); + //System.out.println(); if (i == fi && j == fj) { - System.out.println("Reached end."); + //System.out.println("Reached end."); } else { int a = Integer.MAX_VALUE, b = a, c = a; if (i > 0) @@ -178,13 +192,27 @@ public OfsSet(int pde, int java){ javaOffset = java; } } + +// public class OffsetMatch{ +// public final ArrayList pdeOffset, javaOffset; +// +// public OffsetMatch(){ +// pdeOffset = new ArrayList(); +// javaOffset = new ArrayList(); +// } +// } public static void main(String[] args) { // minDistance("c = #qwerty;", "c = 0xffqwerty;"); - new Utils().minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); -// minDistance("int a = int(4.5);", "int a = PApplet.parseInt(4.5f);"); + Utils a = new Utils(); + + a.minDistance("int a = int(can); int ball;", "int a = PApplet.parseInt(can); int ball;"); + a.getJavaOffForPdeOff(10, 20); // minDistance("static void main(){;", "public static void main(){;"); // minDistance("#bb00aa", "0xffbb00aa"); + //a.minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); + a.minDistance("color abc = #qwerty;", "int abc = 0xffqwerty;"); + a.getJavaOffForPdeOff(10, 20); // distance("c = #bb00aa;", "c = 0xffbb00aa;"); } } From 875fca41d06dc68c339b23c784f3ca9583ac3f0f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 2 Jun 2014 02:31:17 +0530 Subject: [PATCH 141/193] things looking promising with offset matching --- src/processing/mode/experimental/Utils.java | 58 +++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/src/processing/mode/experimental/Utils.java b/src/processing/mode/experimental/Utils.java index f160dcc..4081bae 100644 --- a/src/processing/mode/experimental/Utils.java +++ b/src/processing/mode/experimental/Utils.java @@ -42,13 +42,64 @@ public static String reverse(String s) { return new String(w); } - public void getJavaOffForPdeOff(int start, int length){ + public void getPdeOffForJavaOff(int start, int length){ + System.out.println("PDE <-> Java" ); for (int i = 0; i < offsetMatch.size(); i++) { System.out.print(offsetMatch.get(i).pdeOffset + " <-> " + offsetMatch.get(i).javaOffset); System.out.println(", " + word1.charAt(offsetMatch.get(i).pdeOffset) + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); } System.out.println("Length " + offsetMatch.size()); + System.out.println(start + " java start off, pde start off " + + getPdeOffForJavaOff(start)); + System.out.println((start + length - 1) + " java end off, pde end off " + + getPdeOffForJavaOff(start + length - 1)); + } + + public int getPdeOffForJavaOff(int javaOff){ + for (int i = offsetMatch.size() - 1; i >= 0;i--) { + if(offsetMatch.get(i).javaOffset < javaOff){ + continue; + } + else + if(offsetMatch.get(i).javaOffset == javaOff){ +// int j = i; + while(offsetMatch.get(--i).javaOffset == javaOff){ + System.out.println("MP " + offsetMatch.get(i).javaOffset + " " + + offsetMatch.get(i).pdeOffset); + } + int pdeOff = offsetMatch.get(++i).pdeOffset; + while(offsetMatch.get(--i).pdeOffset == pdeOff); + int j = i + 1; + if (j > -1 && j < offsetMatch.size()) + return offsetMatch.get(j).pdeOffset; + } + + } + return -1; + } + + public int getJavaOffForPdeOff(int pdeOff){ + for (int i = offsetMatch.size() - 1; i >= 0;i--) { + if(offsetMatch.get(i).pdeOffset < pdeOff){ + continue; + } + else + if(offsetMatch.get(i).pdeOffset == pdeOff){ +// int j = i; + while(offsetMatch.get(--i).pdeOffset == pdeOff){ +// System.out.println("MP " + offsetMatch.get(i).javaOffset + " " +// + offsetMatch.get(i).pdeOffset); + } + int javaOff = offsetMatch.get(++i).javaOffset; + while(offsetMatch.get(--i).javaOffset == javaOff); + int j = i + 1; + if (j > -1 && j < offsetMatch.size()) + return offsetMatch.get(j).javaOffset; + } + + } + return -1; } public int minDistance(String word1, String word2) { @@ -207,12 +258,13 @@ public static void main(String[] args) { Utils a = new Utils(); a.minDistance("int a = int(can); int ball;", "int a = PApplet.parseInt(can); int ball;"); - a.getJavaOffForPdeOff(10, 20); + a.getPdeOffForJavaOff(25, 3); // minDistance("static void main(){;", "public static void main(){;"); // minDistance("#bb00aa", "0xffbb00aa"); //a.minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); + System.out.println("--"); a.minDistance("color abc = #qwerty;", "int abc = 0xffqwerty;"); - a.getJavaOffForPdeOff(10, 20); + a.getPdeOffForJavaOff(4, 3); // distance("c = #bb00aa;", "c = 0xffbb00aa;"); } } From e980682bdaac22fb06f55927bbf838c4a63a0048 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 2 Jun 2014 02:50:41 +0530 Subject: [PATCH 142/193] Added OffsetMatcher. Time for a trial run --- .../mode/experimental/OffsetMatcher.java | 253 ++++++++++++++++++ src/processing/mode/experimental/Utils.java | 27 +- 2 files changed, 274 insertions(+), 6 deletions(-) create mode 100644 src/processing/mode/experimental/OffsetMatcher.java diff --git a/src/processing/mode/experimental/OffsetMatcher.java b/src/processing/mode/experimental/OffsetMatcher.java new file mode 100644 index 0000000..1fe0b62 --- /dev/null +++ b/src/processing/mode/experimental/OffsetMatcher.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2012-14 Manindra Moharana + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package processing.mode.experimental; + +import java.util.ArrayList; +import static processing.mode.experimental.ExperimentalMode.log; + +/** + * Performs offset matching between PDE and Java code (one line of code only) + * + * @author Manindra Moharana + * + */ + +public class OffsetMatcher { + + public ArrayList offsetMatch; + + String word1, word2; + + public OffsetMatcher(String pdeCode, String javaCode) { + this.word1 = pdeCode; + this.word2 = javaCode; + minDistance(); + log("PDE <-> Java"); + for (int i = 0; i < offsetMatch.size(); i++) { + log(offsetMatch.get(i).pdeOffset + " <-> " + + offsetMatch.get(i).javaOffset + + ", " + word1.charAt(offsetMatch.get(i).pdeOffset) + + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); + } + log("Length " + offsetMatch.size()); + } + + public void getPdeOffForJavaOff(int start, int length) { + + log(start + " java start off, pde start off " + + getPdeOffForJavaOff(start)); + log((start + length - 1) + " java end off, pde end off " + + getPdeOffForJavaOff(start + length - 1)); + } + + public void getJavaOffForPdeOff(int start, int length) { +// System.out.println("PDE <-> Java" ); +// for (int i = 0; i < offsetMatch.size(); i++) { +// System.out.print(offsetMatch.get(i).pdeOffset + " <-> " + offsetMatch.get(i).javaOffset); +// System.out.println(", " + word1.charAt(offsetMatch.get(i).pdeOffset) + " <-> " +// + word2.charAt(offsetMatch.get(i).javaOffset)); +// } +// System.out.println("Length " + offsetMatch.size()); + log(start + " pde start off, java start off " + + getJavaOffForPdeOff(start)); + log((start + length - 1) + " pde end off, java end off " + + getJavaOffForPdeOff(start + length - 1)); + } + + public int getPdeOffForJavaOff(int javaOff) { + for (int i = offsetMatch.size() - 1; i >= 0; i--) { + if (offsetMatch.get(i).javaOffset < javaOff) { + continue; + } else if (offsetMatch.get(i).javaOffset == javaOff) { +// int j = i; + while (offsetMatch.get(--i).javaOffset == javaOff) { + log("MP " + offsetMatch.get(i).javaOffset + " " + + offsetMatch.get(i).pdeOffset); + } + int pdeOff = offsetMatch.get(++i).pdeOffset; + while (offsetMatch.get(--i).pdeOffset == pdeOff) + ; + int j = i + 1; + if (j > -1 && j < offsetMatch.size()) + return offsetMatch.get(j).pdeOffset; + } + + } + return -1; + } + + public int getJavaOffForPdeOff(int pdeOff) { + for (int i = offsetMatch.size() - 1; i >= 0; i--) { + if (offsetMatch.get(i).pdeOffset < pdeOff) { + continue; + } else if (offsetMatch.get(i).pdeOffset == pdeOff) { +// int j = i; + while (offsetMatch.get(--i).pdeOffset == pdeOff) { +// log("MP " + offsetMatch.get(i).javaOffset + " " +// + offsetMatch.get(i).pdeOffset); + } + int javaOff = offsetMatch.get(++i).javaOffset; + while (offsetMatch.get(--i).javaOffset == javaOff) + ; + int j = i + 1; + if (j > -1 && j < offsetMatch.size()) + return offsetMatch.get(j).javaOffset; + } + + } + return -1; + } + + private int minDistance() { + +// word1 = reverse(word1); +// word2 = reverse(word2); + int len1 = word1.length(); + int len2 = word2.length(); + log(word1 + " len: " + len1); + log(word2 + " len: " + len2); + // len1+1, len2+1, because finally return dp[len1][len2] + int[][] dp = new int[len1 + 1][len2 + 1]; + + for (int i = 0; i <= len1; i++) { + dp[i][0] = i; + } + + for (int j = 0; j <= len2; j++) { + dp[0][j] = j; + } + + //iterate though, and check last char + for (int i = 0; i < len1; i++) { + char c1 = word1.charAt(i); + for (int j = 0; j < len2; j++) { + char c2 = word2.charAt(j); + //System.out.print(c1 + "<->" + c2); + //if last two chars equal + if (c1 == c2) { + //update dp value for +1 length + dp[i + 1][j + 1] = dp[i][j]; +// log(); + } else { + int replace = dp[i][j] + 1; + int insert = dp[i][j + 1] + 1; + int delete = dp[i + 1][j] + 1; +// if (replace < delete) { +// log(" --- D"); +// } else +// log(" --- R"); + int min = replace > insert ? insert : replace; + min = delete > min ? min : delete; + dp[i + 1][j + 1] = min; + } + } + } + +// for (int i = 0; i < dp.length; i++) { +// for (int j = 0; j < dp[0].length; j++) { +// System.out.print(dp[i][j] + " "); +// } +// System.out.println(); +// } +// int maxLen = Math.max(len1, len2)+2; +// int pdeCodeMap[] = new int[maxLen], javaCodeMap[] = new int[maxLen]; +// System.out.println("Edit distance1: " + dp[len1][len2]); + ArrayList alist = new ArrayList(); + offsetMatch = alist; + minDistInGrid(dp, len1, len2, 0, 0, word1.toCharArray(), + word2.toCharArray(), alist); +// System.out.println("PDE-to-Java"); +// for (int i = 0; i < maxLen; i++) { +// System.out.print(pdeCodeMap[i] + " <-> " + javaCodeMap[i]); +// System.out.println(", " + word1.charAt(pdeCodeMap[i]) + " <-> " +// + word2.charAt(javaCodeMap[i])); +// } +// for (int i = 0; i < alist.size(); i++) { +// System.out.print(alist.get(i).pdeOffset + " <-> " + alist.get(i).javaOffset); +// System.out.println(", " + word1.charAt(alist.get(i).pdeOffset) + " <-> " +// + word2.charAt(alist.get(i).javaOffset)); +// } +// System.out.println("Length " + alist.size()); + return dp[len1][len2]; + } + + private void minDistInGrid(int g[][], int i, int j, int fi, int fj, + char s1[], char s2[], ArrayList set) { +// if(i < s1.length)System.out.print(s1[i] + " <->"); +// if(j < s2.length)System.out.print(s2[j]); + if (i < s1.length && j < s2.length) { +// pdeCodeMap[k] = i; +// javaCodeMap[k] = j; + //System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j]); + set.add(new OffsetPair(i, j)); +// if (s1[i] != s2[j]) +// System.out.println("--"); + } + //System.out.println(); + if (i == fi && j == fj) { + //System.out.println("Reached end."); + } else { + int a = Integer.MAX_VALUE, b = a, c = a; + if (i > 0) + a = g[i - 1][j]; + if (j > 0) + b = g[i][j - 1]; + if (i > 0 && j > 0) + c = g[i - 1][j - 1]; + int mini = Math.min(a, Math.min(b, c)); + if (mini == a) { + //System.out.println(s1[i + 1] + " " + s2[j]); + minDistInGrid(g, i - 1, j, fi, fj, s1, s2, set); + } else if (mini == b) { + //System.out.println(s1[i] + " " + s2[j + 1]); + minDistInGrid(g, i, j - 1, fi, fj, s1, s2, set); + } else if (mini == c) { + //System.out.println(s1[i + 1] + " " + s2[j + 1]); + minDistInGrid(g, i - 1, j - 1, fi, fj, s1, s2, set); + } + } + } + + private class OffsetPair { + public final int pdeOffset, javaOffset; + + public OffsetPair(int pde, int java) { + pdeOffset = pde; + javaOffset = java; + } + } + + public static void main(String[] args) { +// minDistance("c = #qwerty;", "c = 0xffqwerty;"); + OffsetMatcher a; + + a = new OffsetMatcher("int a = int(can); int ball;", + "int a = PApplet.parseInt(can); int ball;"); + a.getPdeOffForJavaOff(25, 3); + a.getJavaOffForPdeOff(12, 3); +// minDistance("static void main(){;", "public static void main(){;"); +// minDistance("#bb00aa", "0xffbb00aa"); + //a.minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); + log("--"); + a = new OffsetMatcher("color abc = #qwerty;", "int abc = 0xffqwerty;"); + a.getPdeOffForJavaOff(4, 3); + a.getJavaOffForPdeOff(6, 3); +// distance("c = #bb00aa;", "c = 0xffbb00aa;"); + } +} diff --git a/src/processing/mode/experimental/Utils.java b/src/processing/mode/experimental/Utils.java index 4081bae..7992676 100644 --- a/src/processing/mode/experimental/Utils.java +++ b/src/processing/mode/experimental/Utils.java @@ -19,7 +19,6 @@ package processing.mode.experimental; import java.util.ArrayList; -import java.util.HashMap; /** * A class containing multiple utility methods @@ -30,7 +29,7 @@ public class Utils { - public ArrayList offsetMatch; + public ArrayList offsetMatch; String word1, word2; public static String reverse(String s) { char w[] = s.toCharArray(); @@ -56,6 +55,20 @@ public void getPdeOffForJavaOff(int start, int length){ + getPdeOffForJavaOff(start + length - 1)); } + public void getJavaOffForPdeOff(int start, int length){ +// System.out.println("PDE <-> Java" ); +// for (int i = 0; i < offsetMatch.size(); i++) { +// System.out.print(offsetMatch.get(i).pdeOffset + " <-> " + offsetMatch.get(i).javaOffset); +// System.out.println(", " + word1.charAt(offsetMatch.get(i).pdeOffset) + " <-> " +// + word2.charAt(offsetMatch.get(i).javaOffset)); +// } +// System.out.println("Length " + offsetMatch.size()); + System.out.println(start + " pde start off, java start off " + + getJavaOffForPdeOff(start)); + System.out.println((start + length - 1) + " pde end off, java end off " + + getJavaOffForPdeOff(start + length - 1)); + } + public int getPdeOffForJavaOff(int javaOff){ for (int i = offsetMatch.size() - 1; i >= 0;i--) { if(offsetMatch.get(i).javaOffset < javaOff){ @@ -157,7 +170,7 @@ public int minDistance(String word1, String word2) { // int maxLen = Math.max(len1, len2)+2; // int pdeCodeMap[] = new int[maxLen], javaCodeMap[] = new int[maxLen]; // System.out.println("Edit distance1: " + dp[len1][len2]); - ArrayList alist = new ArrayList(); + ArrayList alist = new ArrayList(); offsetMatch = alist; minDistInGrid(dp, len1, len2, 0, 0, word1.toCharArray(), word2.toCharArray(), alist); @@ -207,7 +220,7 @@ public void minDistInGrid(int g[][], int i, int j, int fi, int fj, // pdeCodeMap[k] = i; // javaCodeMap[k] = j; //System.out.print(s1[i] + " " + i + " <-> " + j + " " + s2[j]); - set.add(new OfsSet(i, j)); + set.add(new OfsSetTemp(i, j)); // if (s1[i] != s2[j]) // System.out.println("--"); } @@ -236,9 +249,9 @@ public void minDistInGrid(int g[][], int i, int j, int fi, int fj, } } - public class OfsSet { + public class OfsSetTemp { public final int pdeOffset, javaOffset; - public OfsSet(int pde, int java){ + public OfsSetTemp(int pde, int java){ pdeOffset = pde; javaOffset = java; } @@ -259,12 +272,14 @@ public static void main(String[] args) { a.minDistance("int a = int(can); int ball;", "int a = PApplet.parseInt(can); int ball;"); a.getPdeOffForJavaOff(25, 3); + a.getJavaOffForPdeOff(12,3); // minDistance("static void main(){;", "public static void main(){;"); // minDistance("#bb00aa", "0xffbb00aa"); //a.minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); System.out.println("--"); a.minDistance("color abc = #qwerty;", "int abc = 0xffqwerty;"); a.getPdeOffForJavaOff(4, 3); + a.getJavaOffForPdeOff(6,3); // distance("c = #bb00aa;", "c = 0xffbb00aa;"); } } From c99d4ee472af77b19fca1fbe7d0bf5480efdf525 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 2 Jun 2014 16:27:55 +0530 Subject: [PATCH 143/193] First phase of tests, no major casualties --- .../mode/experimental/ASTNodeWrapper.java | 15 ++++ .../mode/experimental/OffsetMatcher.java | 80 +++++++++---------- 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 2823cc9..734da04 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -575,6 +575,20 @@ public boolean highlightNode(ASTGenerator astGenerator){ return false; } + OffsetMatcher ofm = new OffsetMatcher(pdeLine, javaLine); + int highlightStart = ofm.getPdeOffForJavaOff(nodeName.getStartPosition() + - lineElement.getStartOffset(), + nodeName.getLength()); + if (highlightStart == -1) { + logE("Logical error in highLightNode() during offset matching. " + + "Please file a bug report."); + return false; + } + int lso = astGenerator.editor.ta.getLineStartOffset(pdeOffs[1]); + highlightStart += lso; + astGenerator.editor.setSelection(highlightStart, highlightStart + + nodeName.getLength()); + /* // First find the name in the java line, and marks its index Pattern toFind = Pattern.compile("\\b" + nodeName.toString() + "\\b"); Matcher matcher = toFind.matcher(javaLine); @@ -603,6 +617,7 @@ public boolean highlightNode(ASTGenerator astGenerator){ int lso = astGenerator.editor.ta.getLineStartOffset(pdeOffs[1]); astGenerator.editor.setSelection(lso + index - lookingFor.length(), lso + index); + */ return true; } catch (BadLocationException e) { logE("BLE in highLightNode() for " + nodeName); diff --git a/src/processing/mode/experimental/OffsetMatcher.java b/src/processing/mode/experimental/OffsetMatcher.java index 1fe0b62..d5aff52 100644 --- a/src/processing/mode/experimental/OffsetMatcher.java +++ b/src/processing/mode/experimental/OffsetMatcher.java @@ -33,44 +33,57 @@ public class OffsetMatcher { public ArrayList offsetMatch; String word1, word2; + + boolean matchingNeeded = false; public OffsetMatcher(String pdeCode, String javaCode) { this.word1 = pdeCode; this.word2 = javaCode; - minDistance(); - log("PDE <-> Java"); + if(word1.trim().equals(word2.trim())){ //TODO: trim() needed here? + matchingNeeded = false; + offsetMatch = new ArrayList(); + log("Offset Matching not needed"); + } + else + { + matchingNeeded = true; + minDistance(); + } + +// log("PDE <-> Java"); for (int i = 0; i < offsetMatch.size(); i++) { - log(offsetMatch.get(i).pdeOffset + " <-> " - + offsetMatch.get(i).javaOffset + - ", " + word1.charAt(offsetMatch.get(i).pdeOffset) - + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); +// log(offsetMatch.get(i).pdeOffset + " <-> " +// + offsetMatch.get(i).javaOffset + +// ", " + word1.charAt(offsetMatch.get(i).pdeOffset) +// + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); } - log("Length " + offsetMatch.size()); +// log("Length " + offsetMatch.size()); } - public void getPdeOffForJavaOff(int start, int length) { - + public int getPdeOffForJavaOff(int start, int length) { + if(!matchingNeeded) return start; + int ans = getPdeOffForJavaOff(start), end = getPdeOffForJavaOff(start + length - 1); log(start + " java start off, pde start off " - + getPdeOffForJavaOff(start)); + + ans); log((start + length - 1) + " java end off, pde end off " - + getPdeOffForJavaOff(start + length - 1)); + + end); + log("J: " + word2.substring(start, start + length) + "\nP: " + + word1.substring(ans, end + 1)); + return ans; } - public void getJavaOffForPdeOff(int start, int length) { -// System.out.println("PDE <-> Java" ); -// for (int i = 0; i < offsetMatch.size(); i++) { -// System.out.print(offsetMatch.get(i).pdeOffset + " <-> " + offsetMatch.get(i).javaOffset); -// System.out.println(", " + word1.charAt(offsetMatch.get(i).pdeOffset) + " <-> " -// + word2.charAt(offsetMatch.get(i).javaOffset)); -// } -// System.out.println("Length " + offsetMatch.size()); + public int getJavaOffForPdeOff(int start, int length) { + if(!matchingNeeded) return start; + int ans = getJavaOffForPdeOff(start); log(start + " pde start off, java start off " + getJavaOffForPdeOff(start)); log((start + length - 1) + " pde end off, java end off " + getJavaOffForPdeOff(start + length - 1)); + return ans; } public int getPdeOffForJavaOff(int javaOff) { + if(!matchingNeeded) return javaOff; for (int i = offsetMatch.size() - 1; i >= 0; i--) { if (offsetMatch.get(i).javaOffset < javaOff) { continue; @@ -93,6 +106,7 @@ public int getPdeOffForJavaOff(int javaOff) { } public int getJavaOffForPdeOff(int pdeOff) { + if(!matchingNeeded) return pdeOff; for (int i = offsetMatch.size() - 1; i >= 0; i--) { if (offsetMatch.get(i).pdeOffset < pdeOff) { continue; @@ -114,6 +128,13 @@ public int getJavaOffForPdeOff(int pdeOff) { return -1; } + /** + * Finds 'distance' between two Strings. + * See Edit Distance Problem + * https://secweb.cs.odu.edu/~zeil/cs361/web/website/Lectures/styles/pages/editdistance.html + * http://www.stanford.edu/class/cs124/lec/med.pdf + * + */ private int minDistance() { // word1 = reverse(word1); @@ -159,31 +180,10 @@ private int minDistance() { } } -// for (int i = 0; i < dp.length; i++) { -// for (int j = 0; j < dp[0].length; j++) { -// System.out.print(dp[i][j] + " "); -// } -// System.out.println(); -// } -// int maxLen = Math.max(len1, len2)+2; -// int pdeCodeMap[] = new int[maxLen], javaCodeMap[] = new int[maxLen]; -// System.out.println("Edit distance1: " + dp[len1][len2]); ArrayList alist = new ArrayList(); offsetMatch = alist; minDistInGrid(dp, len1, len2, 0, 0, word1.toCharArray(), word2.toCharArray(), alist); -// System.out.println("PDE-to-Java"); -// for (int i = 0; i < maxLen; i++) { -// System.out.print(pdeCodeMap[i] + " <-> " + javaCodeMap[i]); -// System.out.println(", " + word1.charAt(pdeCodeMap[i]) + " <-> " -// + word2.charAt(javaCodeMap[i])); -// } -// for (int i = 0; i < alist.size(); i++) { -// System.out.print(alist.get(i).pdeOffset + " <-> " + alist.get(i).javaOffset); -// System.out.println(", " + word1.charAt(alist.get(i).pdeOffset) + " <-> " -// + word2.charAt(alist.get(i).javaOffset)); -// } -// System.out.println("Length " + alist.size()); return dp[len1][len2]; } From 9f62f6de2569d430dabfd466558c8c45655ff04e Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 2 Jun 2014 17:05:30 +0530 Subject: [PATCH 144/193] Testing the new markdown --- Todo, GSoC 2013.txt | 172 ++++++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/Todo, GSoC 2013.txt b/Todo, GSoC 2013.txt index d2e5777..c7020fc 100644 --- a/Todo, GSoC 2013.txt +++ b/Todo, GSoC 2013.txt @@ -4,7 +4,7 @@ This would also be a break down of my thought process and ideas as I tackle vari Manindra Moharana (me@mkmoharana.com) -* : Todo, x : Done, ? : Undecided Todo, ! : Critical, + : Minor Todo +[ ]: Todo, [x] : Done, ? : Undecided Todo, ! : Critical, + : Minor Todo Code Completion =============== @@ -16,122 +16,122 @@ The big stuff: - Many of the cases seem to have been covered, and I'm achieving more and more code unification as I'm working through the problem step by step - Looks almost complete now, nearly all cases covered(July 13th) x After popup appears, the popup location is fixed for the current line. So if editor window is moved while staying in the same line, popup appears at the prev location. Need to ensure editor is still at last know location. Fixed. -* Keyboard Shortcut for completion popup - Ctrl + Space -* Scope handling? Static/non static scope? -* Disable completions on comment line -* Trie implementation would be lower priority, "premature optimisation is pure evil". Get all features of CC working good enough and then plan this. +[ ]Keyboard Shortcut for completion popup - Ctrl + Space +[ ]Scope handling? Static/non static scope? +[ ]Disable completions on comment line +[ ]Trie implementation would be lower priority, "premature optimisation is pure evil". Get all features of CC working good enough and then plan this. -x Ensure that a compilation unit is created at startup! +[x]Ensure that a compilation unit is created at startup! x! Code competition for local code is working with recursive look up. -x Completion doesn't seem to show up for fields of a type defined locally. But works for methods with return type defined locally. Take ideas. Some case missing most probably. Fixed -x Discovered another major issue due to offset differences -> While looking for predictions, if the parsed string contains pde enhancements, predictions FAIL! Zomg. +[x]Completion doesn't seem to show up for fields of a type defined locally. But works for methods with return type defined locally. Take ideas. Some case missing most probably. Fixed +[x]Discovered another major issue due to offset differences -> While looking for predictions, if the parsed string contains pde enhancements, predictions FAIL! Zomg. Ex - "s.substring(int(13.4))." fails. Thinking to just do the substitutions before sending it to updatePredictions(), coz offsets aren't really a concern here, right? Yup, fixed it! x! Code completion with library code, non-nested seems to be broken, fix it. Fixed. -x Completion for external classes - ArrayList, HashMap, etc. +[x]Completion for external classes - ArrayList, HashMap, etc. x! Recursive lookup for compiled(library) code! x! Library CC for nested would be tricky. Need to jump from local->compiled code while searching recursively. Recursive find's current implementation is based on ASTNode return type. Afaik, no way to instantiate orphaned ASTNode objects(or did I miss it?). ASTNode objects have to be created only from the main ast instance. But I need to find a way to switch to compiled instances from local class instance. x! Should I implement wrapper for ASTNode? - possibly needed for code completion with compiled and non-compiled code. Done. -x Differentiating between multiple statements on the same line. How to? Done with offset handling. -x - Cache predictions if current 'word' is increasing in length. If already showing predictions beginning with 's', for 'sa', remove extra completions, rather than recalculating predictions. Performance increase. -x Parameterized type support is broken. -x Array types, all all other types support broken. :\ -x Completion for array access, strings[0]. +[x]Differentiating between multiple statements on the same line. How to? Done with offset handling. +[x]- Cache predictions if current 'word' is increasing in length. If already showing predictions beginning with 's', for 'sa', remove extra completions, rather than recalculating predictions. Performance increase. +[x]Parameterized type support is broken. +[x]Array types, all all other types support broken. :\ +[x]Completion for array access, strings[0]. Finer details -* findDeclarations should support 3rd party classes too. It's about time. ;) -* printStuff(int,float,String) - completion endings have to be appropriate. Right now it's just printStuff(,,). Cursor positioning also needs to be taken care of(done). Argument list as tooltip if possible? +[ ]findDeclarations should support 3rd party classes too. It's about time. ;) +[ ]printStuff(int,float,String) - completion endings have to be appropriate. Right now it's just printStuff(,,). Cursor positioning also needs to be taken care of(done). Argument list as tooltip if possible? *! p5 enhanced stuff in java, how does it fit in with everything else, and edge cases. Possibly add support for them. Offset handling improvements should help here. -* Diamond operator isn't supported for now. Bummer. +[ ]Diamond operator isn't supported for now. Bummer. -x Completion popup height is now dynamic, decreases to fit. -* Completion width can be dynamic, if really needed.. -x Icons for completions? Or overkill right now? -x 'Show Usage' menu item added -x Show declaring class for completions +[x]Completion popup height is now dynamic, decreases to fit. +[ ]Completion width can be dynamic, if really needed.. +[x]Icons for completions? Or overkill right now? +[x]'Show Usage' menu item added +[x]Show declaring class for completions x! Ignore String case while finding completion candidates -x Multiple 3rd party classes found in various packages. Not a chance no more. -x Obj a1; a1.-> completion doesn't work before it is instantiated. Look into that. Began working again by itself. Yay! -x Cursor positioning should be after the first ( if arguments present, else after () -x Display the type of Completion(method return type, variable type) in the popup. +[x]Multiple 3rd party classes found in various packages. Not a chance no more. +[x]Obj a1; a1.-> completion doesn't work before it is instantiated. Look into that. Began working again by itself. Yay! +[x]Cursor positioning should be after the first ( if arguments present, else after () +[x]Display the type of Completion(method return type, variable type) in the popup. - facing some issues for local types. Fixed. -x Sorted list of completion candidates - fields, then methods. It's unsorted presently. -x Reflection API - getMethods vs getDeclaredMethods. declared. -x Need to add offset correction to ASTGenerator and its lookup methods. Or leave it for later? All set to implement -x Completion List should get hidden on hitting esc key +[x]Sorted list of completion candidates - fields, then methods. It's unsorted presently. +[x]Reflection API - getMethods vs getDeclaredMethods. declared. +[x]Need to add offset correction to ASTGenerator and its lookup methods. Or leave it for later? All set to implement +[x]Completion List should get hidden on hitting esc key Offset Mapping ============== First major hurdle is offset mapping *! pde<->java code offset : precise conversion needed -* W.r.t PDE specific enhancements, things are almost working. There are some offset issues when multiple pde statements are in the same line, but I guess it's good enough for now to proceed ahead. Will keep a close watch for potential bugs. -x for the above, I've decide to first implement a sketch outline like feature, which would highlight an AST element precisely in the pde code. This would ensure I've got the mapping working properly. And may lead to a future feature. -x This is precise upto a certain line. Once on a line, pde stuff have to be taken into consideration. -x Edge case - multiple statements in a single line -x PDE specific enhancements will also have to be tackled like int(), # literals. The length of the node returned needs to be modified to make up for extra chars added like PApplet.parseFloat, etc. Also the 2nd or futher pde enhancements in the same line means even the beginning offset would need adjustment. Meh. +[ ]W.r.t PDE specific enhancements, things are almost working. There are some offset issues when multiple pde statements are in the same line, but I guess it's good enough for now to proceed ahead. Will keep a close watch for potential bugs. +[x]for the above, I've decide to first implement a sketch outline like feature, which would highlight an AST element precisely in the pde code. This would ensure I've got the mapping working properly. And may lead to a future feature. +[x]This is precise upto a certain line. Once on a line, pde stuff have to be taken into consideration. +[x]Edge case - multiple statements in a single line +[x]PDE specific enhancements will also have to be tackled like int(), # literals. The length of the node returned needs to be modified to make up for extra chars added like PApplet.parseFloat, etc. Also the 2nd or futher pde enhancements in the same line means even the beginning offset would need adjustment. Meh. Refactoring =========== -* Undo misbehaves here, handle carefully. -* Fails to rename the first defined global variable, if a javadoc comment precedes it. But owrds for single/multiline comments. Wth! -x New Name is validated. -x Ordered list in 'Show Usage' window -x Add support for word select on right click and rename, mouse co-ordinates need to obtained carefully +[ ]Undo misbehaves here, handle carefully. +[ ]Fails to rename the first defined global variable, if a javadoc comment precedes it. But owrds for single/multiline comments. Wth! +[x]New Name is validated. +[x]Ordered list in 'Show Usage' window +[x]Add support for word select on right click and rename, mouse co-ordinates need to obtained carefully Refactoring would work only when code is compiler error free. I plan to do a find replace type op on the compile ready code. 1. First identify the declaration of the variable in the AST. We'll then make a list of all its occurrences. 2. DFS through the AST, for each (SimpleName)instance of the word in code, find if the matched word is the same one whose declaration we found. -x Edge Case: For renaming a TypeDeclaration, the declaration of SimpleName instance of the TD and it's constructor(s) aren't added to the list generated by DFS. So for renaming TD, will have to manually add the TD SimpleName and it's constructors' SimpleNames to the a list of declaration nodes that can be positively matched against. -x Renaming any constructor is equivalent to renaming the TD +[x]Edge Case: For renaming a TypeDeclaration, the declaration of SimpleName instance of the TD and it's constructor(s) aren't added to the list generated by DFS. So for renaming TD, will have to manually add the TD SimpleName and it's constructors' SimpleNames to the a list of declaration nodes that can be positively matched against. +[x]Renaming any constructor is equivalent to renaming the TD 3. Find corresponding PDE offsets of the SimpleNames, rename in each line. -x Edge Case: Need to take displaced offsets on a line, due to pde enhancements, into consideration. +[x]Edge Case: Need to take displaced offsets on a line, due to pde enhancements, into consideration. 4. All the changes in code would be made in a separate copy of the code(?). After all the renaming is done, allow it only if the new code compiles. Basically an undo should be possible in case of conflicts. -x Refactoring ui -x For now, user needs to highlight the name of the var, and then right-click -> Rename.. -x Handle saving. If sketch closed after renaming w/o saving find bugs. Done, marking the sketch as modified after renaming. +[x]Refactoring ui +[x]For now, user needs to highlight the name of the var, and then right-click -> Rename.. +[x]Handle saving. If sketch closed after renaming w/o saving find bugs. Done, marking the sketch as modified after renaming. Quick Navigation ================ *+ A silly bug where the name of the first field declaration isn't highlighted correctly. Seems to be happening if there's a javadoc or multiline comment near about the top. -x On OS X, Ctrl + Click is right mouse click, so implement Cmd + Click instead. isMetaDown()? -x Ctrl + Click on an element to scroll to its definition in code -x Local Vars -x Local Methods -x Local Classes -x Recursive lookup, a.b().c() -x Now highlihgting the declaration name, rather than the whole declaration. +[x]On OS X, Ctrl + Click is right mouse click, so implement Cmd + Click instead. isMetaDown()? +[x]Ctrl + Click on an element to scroll to its definition in code +[x]Local Vars +[x]Local Methods +[x]Local Classes +[x]Recursive lookup, a.b().c() +[x]Now highlihgting the declaration name, rather than the whole declaration. Sketch Outline ============== -x Show Sketch Outline Tree -x Filter stuff in text field -x Add icons - custom cell renderer +[x]Show Sketch Outline Tree +[x]Filter stuff in text field +[x]Add icons - custom cell renderer Suggestion for missing imports ============================== -* Find a more subtle way to suggest for imports. The current method is too troublesome. Randomly pops up offering suggestions. May intimidate beginners. +[ ]Find a more subtle way to suggest for imports. The current method is too troublesome. Randomly pops up offering suggestions. May intimidate beginners. 1. In compileCheck() in ECS, check if error message is of the type "__" cannot be resolved to a type. 2. Find the class name via astGen, and suggest import as a popup. -x Barebones functionality done. -x Add imports only to beginning of first tab. -x Search within contributed libraries folder -x Hide suggestion list before showing import suggestions -x Search within code folder of sketch +[x]Barebones functionality done. +[x]Add imports only to beginning of first tab. +[x]Search within contributed libraries folder +[x]Hide suggestion list before showing import suggestions +[x]Search within code folder of sketch Labels for Java elements ======================== -x Working for local code -* Need to modify getASTNodeAt to also fetch the type for predefined classes. -* Labels for predefined class objects -* Chaining support for labels +[x]Working for local code +[ ]Need to modify getASTNodeAt to also fetch the type for predefined classes. +[ ]Labels for predefined class objects +[ ]Chaining support for labels Synchronization =============== @@ -140,31 +140,31 @@ Gotta do it carefully between main thread, ECS Thread, and SwingWorker threads Fields that are concurrently accessed: ECS members: -x ArrayList problems - updated in ECS, accessed by ErrorBar.update() -x ArrayList classpathJars - updated in ECS, accessed by ASTGenerator.loadJars() -x hasErrors, syntaxErrors - Atomic Boolean -x boolean warningsEnabled - made it volatile -* CompilationUnit cu - updated in ECS, accessed a zillion times in ASTGenerator :'( +[x]ArrayList problems - updated in ECS, accessed by ErrorBar.update() +[x]ArrayList classpathJars - updated in ECS, accessed by ASTGenerator.loadJars() +[x]hasErrors, syntaxErrors - Atomic Boolean +[x]boolean warningsEnabled - made it volatile +[ ]CompilationUnit cu - updated in ECS, accessed a zillion times in ASTGenerator :'( General Stuff ============= -* [Critical] PermGen out of memory bug. Manually triggering GC after making the classloader null ensures permgen memory is reclaimed on editor exit. Max open window still limited by max permgen size. Also, added a classloadcounter in ECS to trigger GC periodically. +[ ][Critical] PermGen out of memory bug. Manually triggering GC after making the classloader null ensures permgen memory is reclaimed on editor exit. Max open window still limited by max permgen size. Also, added a classloadcounter in ECS to trigger GC periodically. https://github.com/processing/processing-experimental/issues/1 See: http://stackoverflow.com/questions/2095974/how-to-unload-a-already-loaded-class-in-java I'm making the classLoader null, but what about the classes loaded by ASTGen? Investigate. -x Disabling Error Checking disables predictions as well! Fixed. -x Added doc listener for text area updates -x Consult Ben on where to save preferences - main preferences.txt or custom one. - Main prefs file -x Save preferences to main preference.txt -x Hide breakpoint markers when Debugger isn't active -x Ensure gutter mouse handler is taken care of when hiding Debugger breakpoint bar. -x Ensure all editor windows are closed when editor is closed. -x Add a red marker near Errors label in console toggle, to indicate errors present in sketch. -x Add option for toggling debug output -x On Run/Debug Console is visible(ProblemsList hidden) -* Update wiki for Ctrl + H instead of Ctrl + J shortcuts -x update build.xml to produce dists -x Make this a contributed mode - mode.txt, github releases feature, version numbering, git tags, etc -x Add GitHub link to PDE X Menu +[x]Disabling Error Checking disables predictions as well! Fixed. +[x]Added doc listener for text area updates +[x]Consult Ben on where to save preferences - main preferences.txt or custom one. - Main prefs file +[x]Save preferences to main preference.txt +[x]Hide breakpoint markers when Debugger isn't active +[x]Ensure gutter mouse handler is taken care of when hiding Debugger breakpoint bar. +[x]Ensure all editor windows are closed when editor is closed. +[x]Add a red marker near Errors label in console toggle, to indicate errors present in sketch. +[x]Add option for toggling debug output +[x]On Run/Debug Console is visible(ProblemsList hidden) +[ ]Update wiki for Ctrl + H instead of Ctrl + J shortcuts +[x]update build.xml to produce dists +[x]Make this a contributed mode - mode.txt, github releases feature, version numbering, git tags, etc +[x]Add GitHub link to PDE X Menu From d1d11a24c190ea09e8d2615db7e9eb75a08a9d8d Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 2 Jun 2014 21:41:59 +0530 Subject: [PATCH 145/193] Added a new todo.txt --- todo.txt | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 todo.txt diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..acc6cc5 --- /dev/null +++ b/todo.txt @@ -0,0 +1,38 @@ +TODO List for PDE X +=================== + +This would also be a break down of my thought process and ideas as I tackle +various tasks. Previously, a different todo file was used for GSoC 2013. + +Manindra Moharana (me@mkmoharana.com) + +[ ]: Todo, [x] : Done, ? : Undecided Todo, ! : Critical, + : Minor Todo + + +Critical Bugs +------------- + +[ ] Better memory management. #1 + +[ ] Breakpoints in classes. #47 + + +Normal Bugs +----------- +[ ] Sketch NOC 6_09: steer PVector, doesn't show completion. +Classname in Template, doesn't scroll to decl. This is happening due certain +post processing offsets not being accounted for. "public void" + +Enhancements/New Features +------------------------- + +[ ] When viewing Outline View, instead of showing the beginning of the list, +it should select the current node element within which the cursor is presently positioned. + +[ ] Begin work on code snippets. + +[ ] JUnit Testing? + +[ ] Preferences panel + +[ ] Line Numbers From 973816e46768c26b6cf9bb872d40141577364d93 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Mon, 2 Jun 2014 23:49:55 +0530 Subject: [PATCH 146/193] Basic fnctionality of autosave before running TODO: Add preferences Improve UI --- .../mode/experimental/DebugEditor.java | 80 ++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 3e4041e..7ab11b6 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -48,6 +48,7 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.border.EtchedBorder; import javax.swing.table.TableModel; import javax.swing.text.Document; @@ -921,7 +922,7 @@ public boolean handleSaveAs() { vi.setTitle(getSketch().getName()); } // if file location has changed, update autosaver - autosaver.reloadAutosaveDir(); +// autosaver.reloadAutosaveDir(); return saved; } @@ -1071,6 +1072,83 @@ public TextArea textArea() { return ta; } + /** + * Grab current contents of the sketch window, advance the console, stop any + * other running sketches, auto-save the user's code... not in that order. + */ + @Override + public void prepareRun() { + super.prepareRun(); + try { + if (sketch.isUntitled()) { + if (handleSave(true)) + statusTimedNotice("Saved. Running...", 5); + else + statusTimedNotice("Save Canceled. Running anyway...", 5); + } + else if (sketch.isModified())// TODO: Fix ugly UI + // TODO: Add to preferences + { + Object[] options = { "Save", "Continue Without Saving" }; + int op = JOptionPane + .showOptionDialog( + new Frame(), + "There are unsaved changes in your sketch. Save before proceeding?", + this.getSketch().getName(), JOptionPane.YES_NO_OPTION, + JOptionPane.PLAIN_MESSAGE, null, options, options[0]); + if (op == JOptionPane.YES_OPTION) { + if (handleSave(true)) + statusTimedNotice("Saved. Running...", 5); + } + else + if (op == JOptionPane.NO_OPTION) + statusTimedNotice("Not saved. Running...", 5); + } + } catch (Exception e) { + // show the error as a message in the window + statusError(e); + } + } + + /** + * Shows a notice message in the editor status bar for a certain duration of + * time. + * + * @param msg + * @param secs + */ + public void statusTimedNotice(final String msg, final int secs) { +// EventQueue.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// statusNotice(msg); +// try { +// Thread.sleep(secs * 1000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// statusEmpty(); +// +// } +// }); + SwingWorker s = new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + statusNotice(msg); + try { + Thread.sleep(secs * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + statusEmpty(); + return null; + } + }; + s.execute(); + } + /** * Access variable inspector window. * From be0378ce54343fab28420c92b75c77e6998abc32 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Wed, 4 Jun 2014 20:19:42 +0530 Subject: [PATCH 147/193] Added untitledAutoSave, autoSave to preferences --- .../mode/experimental/DebugEditor.java | 19 ++++--------------- .../mode/experimental/ExperimentalMode.java | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 7ab11b6..51e7341 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -1079,8 +1079,11 @@ public TextArea textArea() { @Override public void prepareRun() { super.prepareRun(); + if (!ExperimentalMode.autoSaveEnabled) + return; + try { - if (sketch.isUntitled()) { + if (sketch.isUntitled() && ExperimentalMode.untitledAutoSaveEnabled) { if (handleSave(true)) statusTimedNotice("Saved. Running...", 5); else @@ -1118,20 +1121,6 @@ else if (sketch.isModified())// TODO: Fix ugly UI * @param secs */ public void statusTimedNotice(final String msg, final int secs) { -// EventQueue.invokeLater(new Runnable() { -// -// @Override -// public void run() { -// statusNotice(msg); -// try { -// Thread.sleep(secs * 1000); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// } -// statusEmpty(); -// -// } -// }); SwingWorker s = new SwingWorker() { @Override diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 5b04896..b90b5a5 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -127,13 +127,15 @@ public File getContentFile(String path) { } volatile public static boolean errorCheckEnabled = true, warningsEnabled = true, - codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false; + codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false, + untitledAutoSaveEnabled = false, autoSaveEnabled = true; public static int autoSaveInterval = 3; //in minutes public static final String prefErrorCheck = "pdex.errorCheckEnabled", prefWarnings = "pdex.warningsEnabled", prefCodeCompletionEnabled = "pdex.ccEnabled", - prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs", prefAutoSaveInterval = "pdex.autoSaveInterval"; + prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs", prefAutoSaveInterval = "pdex.autoSaveInterval", + prefUntitledAutoSave = "pdex.autoSave.untitledAutoSaveEnabled", prefAutoSave = "pdex.autoSaveEnabled"; public void loadPreferences(){ log("Load PDEX prefs"); @@ -144,6 +146,8 @@ public void loadPreferences(){ DEBUG = Preferences.getBoolean(prefDebugOP); errorLogsEnabled = Preferences.getBoolean(prefErrorLogs); autoSaveInterval = Preferences.getInteger(prefAutoSaveInterval); + untitledAutoSaveEnabled = Preferences.getBoolean(prefUntitledAutoSave); + autoSaveEnabled = Preferences.getBoolean(prefAutoSave); } public void savePreferences(){ @@ -154,6 +158,8 @@ public void savePreferences(){ Preferences.setBoolean(prefDebugOP, DEBUG); Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); Preferences.setInteger(prefAutoSaveInterval,autoSaveInterval); + Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled); + Preferences.setBoolean(prefAutoSave,autoSaveEnabled); } public void ensurePrefsExist(){ @@ -169,6 +175,10 @@ public void ensurePrefsExist(){ Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); if(Preferences.get(prefAutoSaveInterval) == null) Preferences.setInteger(prefAutoSaveInterval,autoSaveInterval); + if(Preferences.get(prefUntitledAutoSave) == null) + Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled); + if(Preferences.get(prefAutoSave) == null) + Preferences.setBoolean(prefAutoSave,autoSaveEnabled); } From ce3ee9f79734fd94589f409aa7a5b3a1f228b9f8 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 4 Jun 2014 21:25:12 +0530 Subject: [PATCH 148/193] minor todo update --- todo.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/todo.txt b/todo.txt index acc6cc5..a56bb9b 100644 --- a/todo.txt +++ b/todo.txt @@ -19,9 +19,10 @@ Critical Bugs Normal Bugs ----------- -[ ] Sketch NOC 6_09: steer PVector, doesn't show completion. -Classname in Template, doesn't scroll to decl. This is happening due certain -post processing offsets not being accounted for. "public void" +[ ] Sketch NOC 6_09: steer PVector, doesn't show completion. #68 + +[x] Sketch NOC 6_09: Classname in Template, doesn't scroll to decl. This is +happening due certain post processing offsets not being accounted for - "public void" Enhancements/New Features ------------------------- From 628f3c230b90c8e0f0bcb54d43c7a0c31d117f15 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Wed, 4 Jun 2014 22:10:40 +0530 Subject: [PATCH 149/193] Commenting out untitledAutoSave --- src/processing/mode/experimental/DebugEditor.java | 15 ++++++++------- .../mode/experimental/ExperimentalMode.java | 12 ++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 51e7341..5ac4a98 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -1083,13 +1083,14 @@ public void prepareRun() { return; try { - if (sketch.isUntitled() && ExperimentalMode.untitledAutoSaveEnabled) { - if (handleSave(true)) - statusTimedNotice("Saved. Running...", 5); - else - statusTimedNotice("Save Canceled. Running anyway...", 5); - } - else if (sketch.isModified())// TODO: Fix ugly UI +// if (sketch.isUntitled() && ExperimentalMode.untitledAutoSaveEnabled) { +// if (handleSave(true)) +// statusTimedNotice("Saved. Running...", 5); +// else +// statusTimedNotice("Save Canceled. Running anyway...", 5); +// } +// else + if (sketch.isModified() && !sketch.isUntitled())// TODO: Fix ugly UI // TODO: Add to preferences { Object[] options = { "Save", "Continue Without Saving" }; diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index b90b5a5..29941ad 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -128,14 +128,14 @@ public File getContentFile(String path) { volatile public static boolean errorCheckEnabled = true, warningsEnabled = true, codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false, - untitledAutoSaveEnabled = false, autoSaveEnabled = true; + autoSaveEnabled = true; //,untitledAutoSaveEnabled; public static int autoSaveInterval = 3; //in minutes public static final String prefErrorCheck = "pdex.errorCheckEnabled", prefWarnings = "pdex.warningsEnabled", prefCodeCompletionEnabled = "pdex.ccEnabled", prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs", prefAutoSaveInterval = "pdex.autoSaveInterval", - prefUntitledAutoSave = "pdex.autoSave.untitledAutoSaveEnabled", prefAutoSave = "pdex.autoSaveEnabled"; + prefAutoSave = "pdex.autoSaveEnabled"; //prefUntitledAutoSave = "pdex.autoSave.untitledAutoSaveEnabled" public void loadPreferences(){ log("Load PDEX prefs"); @@ -146,7 +146,7 @@ public void loadPreferences(){ DEBUG = Preferences.getBoolean(prefDebugOP); errorLogsEnabled = Preferences.getBoolean(prefErrorLogs); autoSaveInterval = Preferences.getInteger(prefAutoSaveInterval); - untitledAutoSaveEnabled = Preferences.getBoolean(prefUntitledAutoSave); +// untitledAutoSaveEnabled = Preferences.getBoolean(prefUntitledAutoSave); autoSaveEnabled = Preferences.getBoolean(prefAutoSave); } @@ -158,7 +158,7 @@ public void savePreferences(){ Preferences.setBoolean(prefDebugOP, DEBUG); Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); Preferences.setInteger(prefAutoSaveInterval,autoSaveInterval); - Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled); +// Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled); Preferences.setBoolean(prefAutoSave,autoSaveEnabled); } @@ -175,8 +175,8 @@ public void ensurePrefsExist(){ Preferences.setBoolean(prefErrorLogs,errorLogsEnabled); if(Preferences.get(prefAutoSaveInterval) == null) Preferences.setInteger(prefAutoSaveInterval,autoSaveInterval); - if(Preferences.get(prefUntitledAutoSave) == null) - Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled); +// if(Preferences.get(prefUntitledAutoSave) == null) +// Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled); if(Preferences.get(prefAutoSave) == null) Preferences.setBoolean(prefAutoSave,autoSaveEnabled); } From 6ec10b8d0be5719a63bedd4ce581f8b503239a32 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Thu, 5 Jun 2014 02:27:33 +0530 Subject: [PATCH 150/193] some tidying up, tinkering around --- .../mode/experimental/ASTGenerator.java | 16 +++++++++++++--- .../mode/experimental/ErrorCheckerService.java | 11 +++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index ebda1f9..141c388 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -240,7 +240,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = !true; + public static final boolean SHOWAST = true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { @@ -794,6 +794,13 @@ protected void trimCandidates(String newWord){ private AtomicBoolean predictionOngoing; + /** + * The main function that calculates possible code completion candidates + * + * @param word + * @param line + * @param lineStartNonWSOffset + */ public void preparePredictions(final String word, final int line, final int lineStartNonWSOffset) { if(predictionOngoing.get()) return; @@ -890,11 +897,14 @@ public void preparePredictions(final String word, final int line, final int line MethodInvocation mi = (MethodInvocation)testnode; System.out.println(mi.getName() + "," + mi.getExpression() + "," + mi.typeArguments().size()); } + + // find nearest ASTNode nearestNode = findClosestNode(lineNumber, (ASTNode) compilationUnit.types() .get(0)); - if (nearestNode == null) - //Make sure nearestNode is not NULL if couldn't find a closeset node + if (nearestNode == null) { + // Make sure nearestNode is not NULL if couldn't find a closeset node nearestNode = (ASTNode) compilationUnit.types().get(0); + } logE(lineNumber + " Nearest ASTNode to PRED " + getNodeAsString(nearestNode)); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index c026a56..ead109c 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -36,11 +36,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.swing.JCheckBoxMenuItem; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.table.DefaultTableModel; -import javax.swing.text.AbstractDocument; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.IProblem; @@ -137,7 +135,7 @@ public class ErrorCheckerService implements Runnable{ /** * Compilation Unit for current sketch */ - protected CompilationUnit cu; + protected CompilationUnit cu, lastCorrectCu; /** * If true, compilation checker will be reloaded with updated classpath @@ -537,7 +535,10 @@ protected void syntaxCheck() { if (problems.length == 0) { syntaxErrors.set(false); containsErrors.set(false); + lastCorrectCu = cu; } else { + CompilationUnit cuTemp = null; + lastCorrectCu = cuTemp; syntaxErrors.set(true); containsErrors.set(true); } @@ -548,7 +549,8 @@ protected void syntaxCheck() { protected void compileCheck() { - // CU needs to be updated coz before compileCheck xqpreprocessor is run on the source code which makes some further changes + // CU needs to be updated coz before compileCheck xqpreprocessor is run on + // the source code which makes some further changes //TODO Check if this breaks things parser.setSource(sourceCode.toCharArray()); @@ -565,6 +567,7 @@ protected void compileCheck() { cu = (CompilationUnit) parser.createAST(null); else { synchronized (cu) { + if (!hasSyntaxErrors()) cu = (CompilationUnit) parser.createAST(null); } } From 4d6781774bbab6e2aabafc062e2575b2c5e06b95 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Thu, 5 Jun 2014 21:38:46 +0530 Subject: [PATCH 151/193] reverting changes before branching --- src/processing/mode/experimental/ErrorCheckerService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index ead109c..af6702a 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -135,7 +135,7 @@ public class ErrorCheckerService implements Runnable{ /** * Compilation Unit for current sketch */ - protected CompilationUnit cu, lastCorrectCu; + protected CompilationUnit cu; /** * If true, compilation checker will be reloaded with updated classpath @@ -535,10 +535,10 @@ protected void syntaxCheck() { if (problems.length == 0) { syntaxErrors.set(false); containsErrors.set(false); - lastCorrectCu = cu; + //lastCorrectCu = cu; } else { CompilationUnit cuTemp = null; - lastCorrectCu = cuTemp; + //lastCorrectCu = cuTemp; syntaxErrors.set(true); containsErrors.set(true); } @@ -567,7 +567,7 @@ protected void compileCheck() { cu = (CompilationUnit) parser.createAST(null); else { synchronized (cu) { - if (!hasSyntaxErrors()) + //if (!hasSyntaxErrors()) cu = (CompilationUnit) parser.createAST(null); } } From e258b916841082b099ea93c4f32106fd86aedfa5 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Thu, 5 Jun 2014 21:39:47 +0530 Subject: [PATCH 152/193] Added a 2nd CU --- .../mode/experimental/ErrorCheckerService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index af6702a..f75e744 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -135,7 +135,7 @@ public class ErrorCheckerService implements Runnable{ /** * Compilation Unit for current sketch */ - protected CompilationUnit cu; + protected CompilationUnit cu, lastCorrectCu; /** * If true, compilation checker will be reloaded with updated classpath @@ -535,10 +535,10 @@ protected void syntaxCheck() { if (problems.length == 0) { syntaxErrors.set(false); containsErrors.set(false); - //lastCorrectCu = cu; + lastCorrectCu = cu; } else { CompilationUnit cuTemp = null; - //lastCorrectCu = cuTemp; + lastCorrectCu = cuTemp; syntaxErrors.set(true); containsErrors.set(true); } @@ -567,8 +567,8 @@ protected void compileCheck() { cu = (CompilationUnit) parser.createAST(null); else { synchronized (cu) { - //if (!hasSyntaxErrors()) - cu = (CompilationUnit) parser.createAST(null); + if (!hasSyntaxErrors()) + cu = (CompilationUnit) parser.createAST(null); } } compilationUnitState = 2; From 41977f7876b26400570732924dd19798e92279df Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 6 Jun 2014 01:30:29 +0530 Subject: [PATCH 153/193] A possible solution to #68 --- .../mode/experimental/ASTGenerator.java | 4 +- .../experimental/ErrorCheckerService.java | 43 +++++++++++++++---- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 141c388..6415787 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -899,11 +899,11 @@ public void preparePredictions(final String word, final int line, final int line } // find nearest ASTNode - nearestNode = findClosestNode(lineNumber, (ASTNode) compilationUnit.types() + nearestNode = findClosestNode(lineNumber, (ASTNode) errorCheckerService.getLastCorrectCU().types() .get(0)); if (nearestNode == null) { // Make sure nearestNode is not NULL if couldn't find a closeset node - nearestNode = (ASTNode) compilationUnit.types().get(0); + nearestNode = (ASTNode) errorCheckerService.getLastCorrectCU().types().get(0); } logE(lineNumber + " Nearest ASTNode to PRED " + getNodeAsString(nearestNode)); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index f75e744..1a507fb 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -135,7 +135,17 @@ public class ErrorCheckerService implements Runnable{ /** * Compilation Unit for current sketch */ - protected CompilationUnit cu, lastCorrectCu; + protected CompilationUnit cu; + + /** + * The Compilation Unit generated during compile check + */ + protected CompilationUnit compileCheckCU; + + /** + * This Compilation Unit points to the last error free CU + */ + protected CompilationUnit lastCorrectCU; /** * If true, compilation checker will be reloaded with updated classpath @@ -431,6 +441,9 @@ protected boolean checkCode() { // No syntax errors, proceed for compilation check, Stage 2. //if(hasSyntaxErrors()) astGenerator.buildAST(null); + if (!hasSyntaxErrors()) { + + } if (problems.length == 0 && editor.compilationCheckEnabled) { //mainClassOffset++; // just a hack. @@ -535,10 +548,11 @@ protected void syntaxCheck() { if (problems.length == 0) { syntaxErrors.set(false); containsErrors.set(false); - lastCorrectCu = cu; + parser.setSource(sourceCode.toCharArray()); + parser.setKind(ASTParser.K_COMPILATION_UNIT); + parser.setCompilerOptions(options); + lastCorrectCU = (CompilationUnit) parser.createAST(null); } else { - CompilationUnit cuTemp = null; - lastCorrectCu = cuTemp; syntaxErrors.set(true); containsErrors.set(true); } @@ -563,14 +577,17 @@ protected void compileCheck() { options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); parser.setCompilerOptions(options); - if (cu == null) - cu = (CompilationUnit) parser.createAST(null); + if (compileCheckCU == null) + compileCheckCU = (CompilationUnit) parser.createAST(null); else { - synchronized (cu) { - if (!hasSyntaxErrors()) - cu = (CompilationUnit) parser.createAST(null); + synchronized (compileCheckCU) { + compileCheckCU = (CompilationUnit) parser.createAST(null); } } + if(!hasSyntaxErrors()) + lastCorrectCU = compileCheckCU; + cu = compileCheckCU; + compilationUnitState = 2; // Currently (Sept, 2012) I'm using Java's reflection api to load the // CompilationChecker class(from CompilationChecker.jar) that houses the @@ -722,6 +739,14 @@ public boolean accept(File file) { // log("Compilecheck, Done."); } + public CompilationUnit getLastCorrectCU(){ + return lastCorrectCU; + } + + public CompilationUnit getLatestCU(){ + return compileCheckCU; + } + private int loadClassCounter = 0; public URLClassLoader getSketchClassLoader() { loadClassCounter++; From 3b5deb07cfa032f3551455668d986514e95f9da8 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 6 Jun 2014 14:19:51 +0530 Subject: [PATCH 154/193] Dealing with better status messages --- .../mode/experimental/ASTGenerator.java | 23 +++++-- .../mode/experimental/DebugEditor.java | 60 +++++++++++++++++++ .../experimental/ErrorCheckerService.java | 9 +-- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 6415787..00758a0 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1681,8 +1681,13 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, logE("DECLA: " + decl.getClass().getName()); nodeLabel = getLabelIfType(new ASTNodeWrapper(decl), (SimpleName) simpName); //retLabelString = getNodeAsString(decl); - } else + } else { logE("null"); + if(scrollOnly) { + editor.statusMessage("Can't find definition of " + simpName, + DebugEditor.STATUS_ERR); + } + } log(getNodeAsString(decl)); @@ -2027,19 +2032,22 @@ protected void refactorIt(){ public void handleShowUsage(){ log("Last clicked word:" + lastClickedWord); if(lastClickedWord == null && editor.ta.getSelectedText() == null){ - editor.statusError("Highlight the class/function/variable name first"); + editor.statusMessage("Highlight the class/function/variable name first" + , DebugEditor.STATUS_INFO); return; } if(errorCheckerService.hasSyntaxErrors()){ - editor.statusError("Can't perform action until syntax errors are fixed :("); + editor.statusMessage("Can't perform action until syntax errors are " + + "fixed :(", DebugEditor.STATUS_WARNING); return; } DefaultMutableTreeNode defCU = findAllOccurrences(); String selText = lastClickedWord == null ? editor.ta.getSelectedText() : lastClickedWord; if(defCU == null){ - editor.statusError("Can't locate definition of " + selText); + editor.statusMessage("Can't locate definition of " + selText, + DebugEditor.STATUS_ERR); return; } if(defCU.getChildCount() == 0) @@ -2291,12 +2299,15 @@ protected boolean isInstanceOfType(ASTNode node,ASTNode decl, String name){ public void handleRefactor(){ log("Last clicked word:" + lastClickedWord); if(lastClickedWord == null && editor.ta.getSelectedText() == null){ - editor.statusError("Highlight the class/function/variable name first"); + editor.statusMessage("Highlight the class/function/variable name first", + DebugEditor.STATUS_INFO); return; } if(errorCheckerService.hasSyntaxErrors()){ - editor.statusError("Can't perform action until syntax errors are fixed :("); + editor + .statusMessage("Can't perform action until syntax errors are fixed :(", + DebugEditor.STATUS_WARNING); return; } if (!frmRename.isVisible()){ diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 8813d5a..cd7ce4c 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -36,6 +36,8 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; +import java.util.Timer; +import java.util.TimerTask; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; @@ -48,6 +50,7 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.border.EtchedBorder; import javax.swing.table.TableModel; import javax.swing.text.Document; @@ -1377,6 +1380,63 @@ public void statusHalted() { statusNotice("Debugger halted."); } + public static final int STATUS_EMPTY = 100, STATUS_COMPILER_ERR = 200, + STATUS_WARNING = 300, STATUS_INFO = 400, STATUS_ERR = 500; + public int statusMessageType = STATUS_EMPTY; + public String statusMessage; + public void statusMessage(final String what, int type){ + // Don't re-display the old message again + if(what.equals(statusMessage) && type == statusMessageType) { + return; + } + statusMessage = what; + statusMessageType = type; + switch (type) { + case STATUS_COMPILER_ERR: + case STATUS_ERR: + super.statusError(what); + break; + case STATUS_INFO: + case STATUS_WARNING: + statusNotice(what); + break; + } +// log("SW 0"); +// final Timer t = new Timer(); +// t.schedule(new TimerTask() { +// @Override +// public void run() { +// log("SW 1"); +// statusEmpty(); +// log("SW 2"); +// t.cancel(); +// } +// }, 2000); + SwingWorker s = new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + + try { + log("SW 1"); + Thread.sleep(2 * 1000); + log("SW 2"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + statusEmpty(); + return null; + } + }; + s.execute(); + } + + public void statusEmpty(){ + statusMessage = null; + statusMessageType = STATUS_EMPTY; + super.statusEmpty(); + } + ErrorCheckerService errorCheckerService; /** diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 1a507fb..0c7fbf5 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1005,12 +1005,14 @@ public void updateEditorStatus() { if (emarker.getProblem().getLineNumber() == editor.getTextArea() .getCaretLine() + 1) { if (emarker.getType() == ErrorMarker.Warning) { - editor.statusNotice(emarker.getProblem().getMessage()); + editor.statusMessage(emarker.getProblem().getMessage(), + DebugEditor.STATUS_INFO); //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); //TODO: this is temporary } else { - editor.statusError(emarker.getProblem().getMessage()); + editor.statusMessage(emarker.getProblem().getMessage(), + DebugEditor.STATUS_COMPILER_ERR); //+ " : " + errorMsgSimplifier.getIDName(emarker.problem.getIProblem().getID())); } return; @@ -1019,8 +1021,7 @@ public void updateEditorStatus() { } // This line isn't an error line anymore, so probably just clear it - if (editor.getStatusMode() == EditorStatus.ERR - || editor.getStatusMode() == EditorStatus.NOTICE) { + if (editor.statusMessageType == DebugEditor.STATUS_COMPILER_ERR) { editor.statusEmpty(); return; } From f2b9efac8bfe343940f5946180be70a38b03f02a Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 6 Jun 2014 14:27:32 +0530 Subject: [PATCH 155/193] A possible solution to #65 --- .../mode/experimental/ASTGenerator.java | 2 +- .../mode/experimental/DebugEditor.java | 27 +++++++------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 00758a0..d4fdbff 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -240,7 +240,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = true; + public static final boolean SHOWAST = !true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index cd7ce4c..19eaa3e 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -1386,10 +1386,12 @@ public void statusHalted() { public String statusMessage; public void statusMessage(final String what, int type){ // Don't re-display the old message again - if(what.equals(statusMessage) && type == statusMessageType) { - return; + if(type != STATUS_EMPTY) { + if(what.equals(statusMessage) && type == statusMessageType) { + return; + } } - statusMessage = what; + statusMessage = new String(what); statusMessageType = type; switch (type) { case STATUS_COMPILER_ERR: @@ -1401,26 +1403,15 @@ public void statusMessage(final String what, int type){ statusNotice(what); break; } -// log("SW 0"); -// final Timer t = new Timer(); -// t.schedule(new TimerTask() { -// @Override -// public void run() { -// log("SW 1"); -// statusEmpty(); -// log("SW 2"); -// t.cancel(); -// } -// }, 2000); + // Don't need to clear compiler error messages + if(type == STATUS_COMPILER_ERR) return; + + // Clear the message after a delay SwingWorker s = new SwingWorker() { - @Override protected Void doInBackground() throws Exception { - try { - log("SW 1"); Thread.sleep(2 * 1000); - log("SW 2"); } catch (InterruptedException e) { e.printStackTrace(); } From 8e872eb9c3ccdd3e347e3a54b67104e54c9a0d56 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 6 Jun 2014 14:38:43 +0530 Subject: [PATCH 156/193] Fixes #69 --- src/processing/mode/experimental/ASTGenerator.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index d4fdbff..3e9d608 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1684,7 +1684,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } else { logE("null"); if(scrollOnly) { - editor.statusMessage("Can't find definition of " + simpName, + editor.statusMessage(simpName + " is not defined in this sketch", DebugEditor.STATUS_ERR); } } @@ -2310,6 +2310,15 @@ public void handleRefactor(){ DebugEditor.STATUS_WARNING); return; } + + DefaultMutableTreeNode defCU = findAllOccurrences(); + String selText = lastClickedWord == null ? editor.ta.getSelectedText() + : lastClickedWord; + if(defCU == null){ + editor.statusMessage(selText + " isn't defined in this sketch, so it can't" + + " be renamed", DebugEditor.STATUS_ERR); + return; + } if (!frmRename.isVisible()){ frmRename.setLocation(editor.getX() + (editor.getWidth() - frmRename.getWidth()) / 2, From 86411f04ac93bc9444598f8bab7a86aa3a155f77 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 6 Jun 2014 17:06:41 +0530 Subject: [PATCH 157/193] todo formatting --- todo.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/todo.txt b/todo.txt index a56bb9b..af2cc8d 100644 --- a/todo.txt +++ b/todo.txt @@ -12,28 +12,29 @@ Manindra Moharana (me@mkmoharana.com) Critical Bugs ------------- -[ ] Better memory management. #1 +-[ ] Better memory management. #1 -[ ] Breakpoints in classes. #47 +-[ ] Breakpoints in classes. #47 Normal Bugs ----------- -[ ] Sketch NOC 6_09: steer PVector, doesn't show completion. #68 +-[x] Sketch NOC 6_09: steer PVector, doesn't show completion. #68 -[x] Sketch NOC 6_09: Classname in Template, doesn't scroll to decl. This is +-[ ] Sketch NOC 6_09: Classname in Template, doesn't scroll to decl. This is happening due certain post processing offsets not being accounted for - "public void" Enhancements/New Features ------------------------- -[ ] When viewing Outline View, instead of showing the beginning of the list, -it should select the current node element within which the cursor is presently positioned. +-[ ] When viewing Outline View, instead of showing the beginning of the list, +it should select the current node element within which the cursor is presently +positioned. -[ ] Begin work on code snippets. +-[ ] Begin work on code snippets. -[ ] JUnit Testing? +-[ ] JUnit Testing? -[ ] Preferences panel +-[ ] Preferences panel -[ ] Line Numbers +-[ ] Line Numbers From f2a0ed27061a3cd5b06d2ab86b495f10fe2c9dbc Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Fri, 6 Jun 2014 18:47:59 +0530 Subject: [PATCH 158/193] hey look, sweeping changes --- .../mode/experimental/ASTGenerator.java | 133 ++++++++++-------- .../mode/experimental/OffsetMatcher.java | 26 ++-- .../mode/experimental/TextAreaPainter.java | 5 +- 3 files changed, 90 insertions(+), 74 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 3e9d608..97f9566 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1574,7 +1574,7 @@ public void scrollToDeclaration(int lineNumber, String name, int offset) { */ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, boolean scrollOnly) { - + int originalLN = lineNumber - errorCheckerService.mainClassOffset; log("----getASTNodeAt---- CU State: " + errorCheckerService.compilationUnitState); if (errorCheckerService != null) { editor = errorCheckerService.getEditor(); @@ -1596,67 +1596,80 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, String nodeLabel = null; String nameOfNode = null; // The node name which is to be scrolled to if (lineNode != null) { + // Being test + + //ASTNodeWrapper lineNodeWrap = new ASTNodeWrapper(lineNode); + String pdeCodeLine = errorCheckerService.getPDECodeAtLine(editor + .getSketch().getCurrentCodeIndex(), originalLN); + String javaCodeLine = getJavaSourceCodeline(lineNumber); - // Some delicate offset handling follows. - ASTNodeWrapper lineNodeWrap = new ASTNodeWrapper(lineNode); - int altOff = offset; - int ret[][] = lineNodeWrap.getOffsetMapping(errorCheckerService); - if(ret != null){ - altOff = 0; - int javaCodeMap[] = ret[0], pdeCodeMap[] = ret[1]; - - for (; altOff < javaCodeMap.length; altOff++) { - if (javaCodeMap[altOff] == pdeCodeMap[offset]) { - break; - } - } - } - log("FLON2: " + lineNumber + " LN start pos " - + lineNode.getStartPosition() + " off " + offset + " alt off" + altOff); - /* - * Now I need to see if multiple statements exist with this same line number - * If that's the case, I need to ensure the offset is right. - */ - ASTNode parLineNode = lineNode.getParent(); - - Iterator it = parLineNode - .structuralPropertiesForType().iterator(); - boolean flag = true; - int offAdjust = 0; - while (it.hasNext() && flag) { - StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it - .next(); - if (prop.isChildListProperty()) { - List nodelist = (List) parLineNode - .getStructuralProperty(prop); - for (ASTNode cnode : nodelist) { - if (getLineNumber(cnode) == lineNumber) { - if (cnode.getStartPosition() <= lineNode.getStartPosition() - + altOff - && cnode.getStartPosition() + cnode.getLength() > lineNode - .getStartPosition() + altOff) { - log(cnode); - offAdjust = cnode.getStartPosition() - lineNode.getStartPosition(); - lineNode = cnode; - altOff -= offAdjust; - flag = false; - break; - } - - } - } - } - } - log("FLON3 new alt off: " + altOff); - ASTNode simpName = pinpointOnLine(lineNode, altOff, - lineNode.getStartPosition(), name); + log(originalLN + " PDE :" + pdeCodeLine); + log("JAVA:" + javaCodeLine); + log("Clicked on: " + name + " start offset: " + offset); + OffsetMatcher ofm = new OffsetMatcher(pdeCodeLine, javaCodeLine); + int javaOffset = ofm.getJavaOffForPdeOff(offset, name.length()); - if(simpName == null){ //Added while fixing #51 - log("pinpointOnLine 1+++> " + simpName); - simpName = pinpointOnLine(lineNode.getParent(), altOff, - lineNode.getStartPosition(), name); - } - log("pinpointOnLine 2+++> " + simpName); + ASTNode simpName = null; + if(simpName == null) return null; + // End test +// int altOff = offset; +// int ret[][] = lineNodeWrap.getOffsetMapping(errorCheckerService); +// if(ret != null){ +// altOff = 0; +// int javaCodeMap[] = ret[0], pdeCodeMap[] = ret[1]; +// +// for (; altOff < javaCodeMap.length; altOff++) { +// if (javaCodeMap[altOff] == pdeCodeMap[offset]) { +// break; +// } +// } +// } +// log("FLON2: " + lineNumber + " LN start pos " +// + lineNode.getStartPosition() + " off " + offset + " alt off" + altOff); +// /* +// * Now I need to see if multiple statements exist with this same line number +// * If that's the case, I need to ensure the offset is right. +// */ +// ASTNode parLineNode = lineNode.getParent(); +// +// Iterator it = parLineNode +// .structuralPropertiesForType().iterator(); +// boolean flag = true; +// int offAdjust = 0; +// while (it.hasNext() && flag) { +// StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it +// .next(); +// if (prop.isChildListProperty()) { +// List nodelist = (List) parLineNode +// .getStructuralProperty(prop); +// for (ASTNode cnode : nodelist) { +// if (getLineNumber(cnode) == lineNumber) { +// if (cnode.getStartPosition() <= lineNode.getStartPosition() +// + altOff +// && cnode.getStartPosition() + cnode.getLength() > lineNode +// .getStartPosition() + altOff) { +// log(cnode); +// offAdjust = cnode.getStartPosition() - lineNode.getStartPosition(); +// lineNode = cnode; +// altOff -= offAdjust; +// flag = false; +// break; +// } +// +// } +// } +// } +// } +// log("FLON3 new alt off: " + altOff); +// ASTNode simpName = pinpointOnLine(lineNode, altOff, +// lineNode.getStartPosition(), name); +// +// if(simpName == null){ //Added while fixing #51 +// log("pinpointOnLine 1+++> " + simpName); +// simpName = pinpointOnLine(lineNode.getParent(), altOff, +// lineNode.getStartPosition(), name); +// } +// log("pinpointOnLine 2+++> " + simpName); if(simpName == null && lineNode instanceof SimpleName){ switch (lineNode.getParent().getNodeType()) { case ASTNode.TYPE_DECLARATION: diff --git a/src/processing/mode/experimental/OffsetMatcher.java b/src/processing/mode/experimental/OffsetMatcher.java index d5aff52..d0707a9 100644 --- a/src/processing/mode/experimental/OffsetMatcher.java +++ b/src/processing/mode/experimental/OffsetMatcher.java @@ -52,10 +52,10 @@ public OffsetMatcher(String pdeCode, String javaCode) { // log("PDE <-> Java"); for (int i = 0; i < offsetMatch.size(); i++) { -// log(offsetMatch.get(i).pdeOffset + " <-> " -// + offsetMatch.get(i).javaOffset + -// ", " + word1.charAt(offsetMatch.get(i).pdeOffset) -// + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); + log(offsetMatch.get(i).pdeOffset + " <-> " + + offsetMatch.get(i).javaOffset + + ", " + word1.charAt(offsetMatch.get(i).pdeOffset) + + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); } // log("Length " + offsetMatch.size()); } @@ -237,17 +237,19 @@ public static void main(String[] args) { // minDistance("c = #qwerty;", "c = 0xffqwerty;"); OffsetMatcher a; - a = new OffsetMatcher("int a = int(can); int ball;", - "int a = PApplet.parseInt(can); int ball;"); - a.getPdeOffForJavaOff(25, 3); - a.getJavaOffForPdeOff(12, 3); +// a = new OffsetMatcher("int a = int(can); int ball;", +// "int a = PApplet.parseInt(can); int ball;"); +// a.getPdeOffForJavaOff(25, 3); +// a.getJavaOffForPdeOff(12, 3); // minDistance("static void main(){;", "public static void main(){;"); // minDistance("#bb00aa", "0xffbb00aa"); - //a.minDistance("color g = #qwerty;", "int g = 0xffqwerty;"); + a = new OffsetMatcher("void test(ArrayList boids){", + "public void test(ArrayList boids){"); + a.getJavaOffForPdeOff(20,4); log("--"); - a = new OffsetMatcher("color abc = #qwerty;", "int abc = 0xffqwerty;"); - a.getPdeOffForJavaOff(4, 3); - a.getJavaOffForPdeOff(6, 3); +// a = new OffsetMatcher("color abc = #qwerty;", "int abc = 0xffqwerty;"); +// a.getPdeOffForJavaOff(4, 3); +// a.getJavaOffForPdeOff(6, 3); // distance("c = #bb00aa;", "c = 0xffbb00aa;"); } } diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 4e8b888..30f031b 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -101,7 +101,7 @@ else if (s.length() == 0) else { int x = ta.xToOffset(line, evt.getX()), x2 = x + 1, x1 = x - 1; log("x="+x); - int xLS = off - ta.getLineStartNonWhiteSpaceOffset(line); + int xLS = off - ta.getLineStartOffset(line); if (x < 0 || x >= s.length()) return; String word = s.charAt(x) + ""; @@ -116,6 +116,7 @@ else if (s.length() == 0) if (x1 >= 0 && x1 < s.length()) { if (Character.isLetter(s.charAt(x1)) || s.charAt(x1) == '_') { word = s.charAt(x1--) + word; + xLS--; } else x1 = -1; } else @@ -140,7 +141,7 @@ else if (s.length() == 0) } if (Character.isDigit(word.charAt(0))) return; - + log(errorCheckerService.mainClassOffset + line + "|" + line + "| offset " + xLS + word + " <= \n"); errorCheckerService.getASTGenerator().scrollToDeclaration(line From 875cad0f26e3a3e9e3c5d7126321bf3a965d44a9 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sun, 8 Jun 2014 12:31:10 +0530 Subject: [PATCH 159/193] Done with adding autoSave to PDE X --- .../mode/experimental/DebugEditor.java | 140 +++++++++++++----- .../mode/experimental/ExperimentalMode.java | 14 +- 2 files changed, 117 insertions(+), 37 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 5ac4a98..6405894 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -22,7 +22,10 @@ import java.awt.CardLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Container; import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Font; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -40,8 +43,14 @@ import java.util.logging.Level; import java.util.logging.Logger; +import javax.swing.BorderFactory; import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JCheckBoxMenuItem; +import javax.swing.JDialog; +import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; @@ -49,6 +58,7 @@ import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import javax.swing.border.Border; import javax.swing.border.EtchedBorder; import javax.swing.table.TableModel; import javax.swing.text.Document; @@ -59,6 +69,7 @@ import processing.app.EditorState; import processing.app.EditorToolbar; import processing.app.Mode; +import processing.app.Preferences; import processing.app.Sketch; import processing.app.SketchCode; import processing.app.Toolkit; @@ -922,7 +933,7 @@ public boolean handleSaveAs() { vi.setTitle(getSketch().getName()); } // if file location has changed, update autosaver -// autosaver.reloadAutosaveDir(); + autosaver.reloadAutosaveDir(); return saved; } @@ -1080,36 +1091,95 @@ public TextArea textArea() { public void prepareRun() { super.prepareRun(); if (!ExperimentalMode.autoSaveEnabled) - return; - + return; + try { -// if (sketch.isUntitled() && ExperimentalMode.untitledAutoSaveEnabled) { -// if (handleSave(true)) -// statusTimedNotice("Saved. Running...", 5); -// else -// statusTimedNotice("Save Canceled. Running anyway...", 5); -// } -// else - if (sketch.isModified() && !sketch.isUntitled())// TODO: Fix ugly UI - // TODO: Add to preferences - { - Object[] options = { "Save", "Continue Without Saving" }; - int op = JOptionPane - .showOptionDialog( - new Frame(), - "There are unsaved changes in your sketch. Save before proceeding?", - this.getSketch().getName(), JOptionPane.YES_NO_OPTION, - JOptionPane.PLAIN_MESSAGE, null, options, options[0]); - if (op == JOptionPane.YES_OPTION) { - if (handleSave(true)) - statusTimedNotice("Saved. Running...", 5); - } - else - if (op == JOptionPane.NO_OPTION) - statusTimedNotice("Not saved. Running...", 5); + // if (sketch.isUntitled() && + // ExperimentalMode.untitledAutoSaveEnabled) { + // if (handleSave(true)) + // statusTimedNotice("Saved. Running...", 5); + // else + // statusTimedNotice("Save Canceled. Running anyway...", 5); + // } + // else + if (sketch.isModified() && !sketch.isUntitled()) { + if (ExperimentalMode.autoSavePromptEnabled) { + final JDialog autoSaveDialog = new JDialog( + base.getActiveEditor(), this.getSketch().getName(), + true); + Container container = autoSaveDialog.getContentPane(); + + JPanel panel = new JPanel(); + panel.setBorder(BorderFactory.createEmptyBorder(4, 0, 2, 2)); + panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); + + JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); + JLabel label = new JLabel( + " There are unsaved" + + " changes in your sketch.
" + + "    Do you want to save it before" + + " running? "); + label.setFont(new Font(label.getFont().getName(), + Font.PLAIN, label.getFont().getSize() + 1)); + panel1.add(label); + panel.add(panel1); + final JCheckBox dontRedisplay = new JCheckBox( + "Remember this decision"); + + panel1 = new JPanel(new FlowLayout( + FlowLayout.CENTER, 8, 2)); + JButton button = new JButton("Save and Run"); + button.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (handleSave(true)) + statusTimedNotice("Saved. Running...", 5); + if (dontRedisplay.isSelected()) { + ExperimentalMode.autoSavePromptEnabled = !dontRedisplay + .isSelected(); + ExperimentalMode.defaultAutoSaveEnabled = true; + dmode.savePreferences(); + } + autoSaveDialog.dispose(); + } + }); + panel1.add(button); + button = new JButton("Run, Don't Save"); + button.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + statusTimedNotice("Not saved. Running...", 5); + if (dontRedisplay.isSelected()) { + ExperimentalMode.autoSavePromptEnabled = !dontRedisplay + .isSelected(); + ExperimentalMode.defaultAutoSaveEnabled = false; + dmode.savePreferences(); + } + autoSaveDialog.dispose(); + } + }); + panel1.add(button); + panel.add(panel1); + + panel1 = new JPanel(); + panel1.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); + panel1.add(dontRedisplay); + panel.add(panel1); + + container.add(panel); + + autoSaveDialog.setResizable(false); + autoSaveDialog.pack(); + autoSaveDialog + .setLocationRelativeTo(base.getActiveEditor()); + autoSaveDialog.setVisible(true); + + } else if (ExperimentalMode.defaultAutoSaveEnabled) + handleSave(true); } } catch (Exception e) { - // show the error as a message in the window statusError(e); } } @@ -1126,13 +1196,13 @@ public void statusTimedNotice(final String msg, final int secs) { @Override protected Void doInBackground() throws Exception { - statusNotice(msg); - try { - Thread.sleep(secs * 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - statusEmpty(); + statusNotice(msg); + try { + Thread.sleep(secs * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + statusEmpty(); return null; } }; diff --git a/src/processing/mode/experimental/ExperimentalMode.java b/src/processing/mode/experimental/ExperimentalMode.java index 29941ad..26cb99f 100755 --- a/src/processing/mode/experimental/ExperimentalMode.java +++ b/src/processing/mode/experimental/ExperimentalMode.java @@ -128,14 +128,16 @@ public File getContentFile(String path) { volatile public static boolean errorCheckEnabled = true, warningsEnabled = true, codeCompletionsEnabled = true, debugOutputEnabled = false, errorLogsEnabled = false, - autoSaveEnabled = true; //,untitledAutoSaveEnabled; + autoSaveEnabled = true, autoSavePromptEnabled = true, + defaultAutoSaveEnabled = true; // ,untitledAutoSaveEnabled; public static int autoSaveInterval = 3; //in minutes public static final String prefErrorCheck = "pdex.errorCheckEnabled", prefWarnings = "pdex.warningsEnabled", prefCodeCompletionEnabled = "pdex.ccEnabled", prefDebugOP = "pdex.dbgOutput", prefErrorLogs = "pdex.writeErrorLogs", prefAutoSaveInterval = "pdex.autoSaveInterval", - prefAutoSave = "pdex.autoSaveEnabled"; //prefUntitledAutoSave = "pdex.autoSave.untitledAutoSaveEnabled" + prefAutoSave = "pdex.autoSave.autoSaveEnabled", // prefUntitledAutoSave = "pdex.autoSave.untitledAutoSaveEnabled", + prefAutoSavePrompt = "pdex.autoSave.promptDisplay", prefDefaultAutoSave = "pdex.autoSave.autoSaveByDefault"; public void loadPreferences(){ log("Load PDEX prefs"); @@ -148,6 +150,8 @@ public void loadPreferences(){ autoSaveInterval = Preferences.getInteger(prefAutoSaveInterval); // untitledAutoSaveEnabled = Preferences.getBoolean(prefUntitledAutoSave); autoSaveEnabled = Preferences.getBoolean(prefAutoSave); + autoSavePromptEnabled = Preferences.getBoolean(prefAutoSavePrompt); + defaultAutoSaveEnabled = Preferences.getBoolean(prefDefaultAutoSave); } public void savePreferences(){ @@ -160,6 +164,8 @@ public void savePreferences(){ Preferences.setInteger(prefAutoSaveInterval,autoSaveInterval); // Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled); Preferences.setBoolean(prefAutoSave,autoSaveEnabled); + Preferences.setBoolean(prefAutoSavePrompt, autoSavePromptEnabled); + Preferences.setBoolean(prefDefaultAutoSave, defaultAutoSaveEnabled); } public void ensurePrefsExist(){ @@ -179,6 +185,10 @@ public void ensurePrefsExist(){ // Preferences.setBoolean(prefUntitledAutoSave,untitledAutoSaveEnabled); if(Preferences.get(prefAutoSave) == null) Preferences.setBoolean(prefAutoSave,autoSaveEnabled); + if(Preferences.get(prefAutoSavePrompt) == null) + Preferences.setBoolean(prefAutoSavePrompt,autoSavePromptEnabled); + if(Preferences.get(prefDefaultAutoSave) == null) + Preferences.setBoolean(prefDefaultAutoSave,defaultAutoSaveEnabled); } From f2c9a25bf7248e9173d9f109082543366686f92f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 20:38:01 +0530 Subject: [PATCH 160/193] Initial dfs name search impl --- .../mode/experimental/ASTGenerator.java | 62 +++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 97f9566..a0f2f98 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -240,7 +240,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = !true; + public static final boolean SHOWAST = true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { @@ -1607,8 +1607,11 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, log("JAVA:" + javaCodeLine); log("Clicked on: " + name + " start offset: " + offset); OffsetMatcher ofm = new OffsetMatcher(pdeCodeLine, javaCodeLine); - int javaOffset = ofm.getJavaOffForPdeOff(offset, name.length()); - + int javaOffset = ofm.getJavaOffForPdeOff(offset, name.length()) + + lineNode.getStartPosition(); + log("JAVA ast offset: " + (javaOffset)); + dfsLookForASTNode(errorCheckerService.getLatestCU(), name, + javaOffset, javaOffset + name.length() - 1); ASTNode simpName = null; if(simpName == null) return null; // End test @@ -2224,7 +2227,8 @@ public void dfsNameOnly(DefaultMutableTreeNode tnode,ASTNode decl, String name) ASTNodeWrapper awnode = (ASTNodeWrapper) cnode.getUserObject(); // log("Visiting: " + getNodeAsString(awnode.getNode())); if(isInstanceOfType(awnode.getNode(), decl, name)){ - int val[] = errorCheckerService.JavaToPdeOffsets(awnode.getLineNumber(), 0); + int val[] = errorCheckerService + .JavaToPdeOffsets(awnode.getLineNumber(), 0); tnode.add(new DefaultMutableTreeNode(new ASTNodeWrapper(awnode .getNode(), "Line " + (val[1] + 1) + " | Tab: " + editor.getSketch().getCode(val[0]).getPrettyName()))); @@ -2233,6 +2237,56 @@ public void dfsNameOnly(DefaultMutableTreeNode tnode,ASTNode decl, String name) } } + public ASTNode dfsLookForASTNode(ASTNode root, String name, int startOffset, + int endOffset) { + log("dfsLookForASTNode() lookin for " + name + " Offsets: " + startOffset + + "," + endOffset); + Stack stack = new Stack(); + stack.push(root); + + while (!stack.isEmpty()) { + ASTNode node = (ASTNode) stack.pop(); + log("Popped from stack: " + getNodeAsString(node)); + Iterator it = node + .structuralPropertiesForType().iterator(); + while (it.hasNext()) { + StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it + .next(); + + if (prop.isChildProperty() || prop.isSimpleProperty()) { + if (node.getStructuralProperty(prop) instanceof ASTNode) { + ASTNode temp = (ASTNode) node.getStructuralProperty(prop); + if (temp.getStartPosition() <= startOffset + && (temp.getStartPosition() + temp.getLength()) >= endOffset) { + if(temp instanceof SimpleName){ + if(name.equals(temp.toString())){ + log("Found simplename: " + getNodeAsString(temp)); + return temp; + } + } + else + stack.push(temp); + log("Pushed onto stack: " + getNodeAsString(temp)); + } + } + } + else if (prop.isChildListProperty()) { + List nodelist = (List) node + .getStructuralProperty(prop); + for (ASTNode temp : nodelist) { + if (temp.getStartPosition() <= startOffset + && (temp.getStartPosition() + temp.getLength()) >= endOffset) { + stack.push(temp); + log("Pushed onto stack: " + getNodeAsString(temp)); + } + } + } + } + } + log("dfsLookForASTNode() not found " + name); + return null; + } + protected SketchOutline sketchOutline; protected void showSketchOutline(){ sketchOutline = new SketchOutline(codeTree, errorCheckerService); From c9f7f3e4e4d49d30b2219c1dd71b6de90e70760f Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 21:02:04 +0530 Subject: [PATCH 161/193] non white space offset it is --- src/processing/mode/experimental/ASTGenerator.java | 6 ++++-- src/processing/mode/experimental/TextAreaPainter.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index a0f2f98..536cf6f 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1603,7 +1603,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, .getSketch().getCurrentCodeIndex(), originalLN); String javaCodeLine = getJavaSourceCodeline(lineNumber); - log(originalLN + " PDE :" + pdeCodeLine); + log(originalLN + " Original Line num.\nPDE :" + pdeCodeLine); log("JAVA:" + javaCodeLine); log("Clicked on: " + name + " start offset: " + offset); OffsetMatcher ofm = new OffsetMatcher(pdeCodeLine, javaCodeLine); @@ -1611,7 +1611,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, + lineNode.getStartPosition(); log("JAVA ast offset: " + (javaOffset)); dfsLookForASTNode(errorCheckerService.getLatestCU(), name, - javaOffset, javaOffset + name.length() - 1); + javaOffset, javaOffset + name.length()); ASTNode simpName = null; if(simpName == null) return null; // End test @@ -2259,10 +2259,12 @@ public ASTNode dfsLookForASTNode(ASTNode root, String name, int startOffset, if (temp.getStartPosition() <= startOffset && (temp.getStartPosition() + temp.getLength()) >= endOffset) { if(temp instanceof SimpleName){ + log("Found possible simplename: " + getNodeAsString(temp)); if(name.equals(temp.toString())){ log("Found simplename: " + getNodeAsString(temp)); return temp; } + log("Bummer, didn't match"); } else stack.push(temp); diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 30f031b..d7571fb 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -101,7 +101,7 @@ else if (s.length() == 0) else { int x = ta.xToOffset(line, evt.getX()), x2 = x + 1, x1 = x - 1; log("x="+x); - int xLS = off - ta.getLineStartOffset(line); + int xLS = off - ta.getLineStartNonWhiteSpaceOffset(line); if (x < 0 || x >= s.length()) return; String word = s.charAt(x) + ""; From 6de00b391173eb0d49c67c6d8536127f7b4ba1b7 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 21:04:38 +0530 Subject: [PATCH 162/193] things look good, real good --- .../mode/experimental/ASTGenerator.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 536cf6f..51d2303 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -2246,7 +2246,7 @@ public ASTNode dfsLookForASTNode(ASTNode root, String name, int startOffset, while (!stack.isEmpty()) { ASTNode node = (ASTNode) stack.pop(); - log("Popped from stack: " + getNodeAsString(node)); + //log("Popped from stack: " + getNodeAsString(node)); Iterator it = node .structuralPropertiesForType().iterator(); while (it.hasNext()) { @@ -2259,7 +2259,6 @@ public ASTNode dfsLookForASTNode(ASTNode root, String name, int startOffset, if (temp.getStartPosition() <= startOffset && (temp.getStartPosition() + temp.getLength()) >= endOffset) { if(temp instanceof SimpleName){ - log("Found possible simplename: " + getNodeAsString(temp)); if(name.equals(temp.toString())){ log("Found simplename: " + getNodeAsString(temp)); return temp; @@ -2268,7 +2267,7 @@ public ASTNode dfsLookForASTNode(ASTNode root, String name, int startOffset, } else stack.push(temp); - log("Pushed onto stack: " + getNodeAsString(temp)); + //log("Pushed onto stack: " + getNodeAsString(temp)); } } } @@ -2280,6 +2279,16 @@ else if (prop.isChildListProperty()) { && (temp.getStartPosition() + temp.getLength()) >= endOffset) { stack.push(temp); log("Pushed onto stack: " + getNodeAsString(temp)); + if(temp instanceof SimpleName){ + if(name.equals(temp.toString())){ + log("Found simplename: " + getNodeAsString(temp)); + return temp; + } + log("Bummer, didn't match"); + } + else + stack.push(temp); + //log("Pushed onto stack: " + getNodeAsString(temp)); } } } From 0a33d949e32a05a76152ac05ad933a1aa45aa5df Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 21:32:53 +0530 Subject: [PATCH 163/193] code cleanup --- .../mode/experimental/ASTGenerator.java | 71 ++----------------- .../mode/experimental/OffsetMatcher.java | 8 +-- 2 files changed, 10 insertions(+), 69 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 51d2303..7d8c38b 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1565,7 +1565,7 @@ public void scrollToDeclaration(int lineNumber, String name, int offset) { /** - * + * Given a word(identifier) in pde code, finds its location in the ASTNode * @param lineNumber * @param name * @param offset - line start nonwhitespace offset @@ -1588,7 +1588,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } } - log("FLON: Node line number " + lineNumber); + log("getASTNodeAt: Node line number " + lineNumber); ASTNode lineNode = findLineOfNode(compilationUnit, lineNumber, offset, name); log("Node text +> " + lineNode); @@ -1610,69 +1610,10 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, int javaOffset = ofm.getJavaOffForPdeOff(offset, name.length()) + lineNode.getStartPosition(); log("JAVA ast offset: " + (javaOffset)); - dfsLookForASTNode(errorCheckerService.getLatestCU(), name, - javaOffset, javaOffset + name.length()); - ASTNode simpName = null; - if(simpName == null) return null; - // End test -// int altOff = offset; -// int ret[][] = lineNodeWrap.getOffsetMapping(errorCheckerService); -// if(ret != null){ -// altOff = 0; -// int javaCodeMap[] = ret[0], pdeCodeMap[] = ret[1]; -// -// for (; altOff < javaCodeMap.length; altOff++) { -// if (javaCodeMap[altOff] == pdeCodeMap[offset]) { -// break; -// } -// } -// } -// log("FLON2: " + lineNumber + " LN start pos " -// + lineNode.getStartPosition() + " off " + offset + " alt off" + altOff); -// /* -// * Now I need to see if multiple statements exist with this same line number -// * If that's the case, I need to ensure the offset is right. -// */ -// ASTNode parLineNode = lineNode.getParent(); -// -// Iterator it = parLineNode -// .structuralPropertiesForType().iterator(); -// boolean flag = true; -// int offAdjust = 0; -// while (it.hasNext() && flag) { -// StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it -// .next(); -// if (prop.isChildListProperty()) { -// List nodelist = (List) parLineNode -// .getStructuralProperty(prop); -// for (ASTNode cnode : nodelist) { -// if (getLineNumber(cnode) == lineNumber) { -// if (cnode.getStartPosition() <= lineNode.getStartPosition() -// + altOff -// && cnode.getStartPosition() + cnode.getLength() > lineNode -// .getStartPosition() + altOff) { -// log(cnode); -// offAdjust = cnode.getStartPosition() - lineNode.getStartPosition(); -// lineNode = cnode; -// altOff -= offAdjust; -// flag = false; -// break; -// } -// -// } -// } -// } -// } -// log("FLON3 new alt off: " + altOff); -// ASTNode simpName = pinpointOnLine(lineNode, altOff, -// lineNode.getStartPosition(), name); -// -// if(simpName == null){ //Added while fixing #51 -// log("pinpointOnLine 1+++> " + simpName); -// simpName = pinpointOnLine(lineNode.getParent(), altOff, -// lineNode.getStartPosition(), name); -// } -// log("pinpointOnLine 2+++> " + simpName); + ASTNode simpName = dfsLookForASTNode(errorCheckerService.getLatestCU(), + name, javaOffset, + javaOffset + name.length()); + if(simpName == null && lineNode instanceof SimpleName){ switch (lineNode.getParent().getNodeType()) { case ASTNode.TYPE_DECLARATION: diff --git a/src/processing/mode/experimental/OffsetMatcher.java b/src/processing/mode/experimental/OffsetMatcher.java index d0707a9..9c2f00f 100644 --- a/src/processing/mode/experimental/OffsetMatcher.java +++ b/src/processing/mode/experimental/OffsetMatcher.java @@ -52,10 +52,10 @@ public OffsetMatcher(String pdeCode, String javaCode) { // log("PDE <-> Java"); for (int i = 0; i < offsetMatch.size(); i++) { - log(offsetMatch.get(i).pdeOffset + " <-> " - + offsetMatch.get(i).javaOffset + - ", " + word1.charAt(offsetMatch.get(i).pdeOffset) - + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); +// log(offsetMatch.get(i).pdeOffset + " <-> " +// + offsetMatch.get(i).javaOffset + +// ", " + word1.charAt(offsetMatch.get(i).pdeOffset) +// + " <-> " + word2.charAt(offsetMatch.get(i).javaOffset)); } // log("Length " + offsetMatch.size()); } From d8cd711c499bd8b27f4b86857ef02380d9205f91 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 21:41:53 +0530 Subject: [PATCH 164/193] refactoring --- .../mode/experimental/ASTGenerator.java | 23 +++++++++++-------- .../mode/experimental/TextAreaPainter.java | 4 ++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 7d8c38b..fc20917 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1574,7 +1574,8 @@ public void scrollToDeclaration(int lineNumber, String name, int offset) { */ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, boolean scrollOnly) { - int originalLN = lineNumber - errorCheckerService.mainClassOffset; + int originalLN = lineNumber; + lineNumber += errorCheckerService.mainClassOffset; log("----getASTNodeAt---- CU State: " + errorCheckerService.compilationUnitState); if (errorCheckerService != null) { editor = errorCheckerService.getEditor(); @@ -1588,6 +1589,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } } + lineNumber = pdeLineNumToJavaLineNum(lineNumber); log("getASTNodeAt: Node line number " + lineNumber); ASTNode lineNode = findLineOfNode(compilationUnit, lineNumber, offset, name); @@ -1595,10 +1597,8 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, ASTNode decl = null; String nodeLabel = null; String nameOfNode = null; // The node name which is to be scrolled to + if (lineNode != null) { - // Being test - - //ASTNodeWrapper lineNodeWrap = new ASTNodeWrapper(lineNode); String pdeCodeLine = errorCheckerService.getPDECodeAtLine(editor .getSketch().getCurrentCodeIndex(), originalLN); String javaCodeLine = getJavaSourceCodeline(lineNumber); @@ -2247,7 +2247,7 @@ protected void showSketchOutline(){ public int javaCodeOffsetToLineStartOffset(int line, int jOffset){ // Find the first node with this line number, return its offset - jOffset - line = PdeToJavaLineNumber(line); + line = pdeLineNumToJavaLineNum(line); log("Looking for line: " + line + ", jOff " + jOffset); Stack temp = new Stack(); temp.push(codeTree); @@ -2271,17 +2271,22 @@ public int javaCodeOffsetToLineStartOffset(int line, int jOffset){ return -1; } - protected int PdeToJavaLineNumber(int lineNum){ - int lineNumber = lineNum + errorCheckerService.getPdeImportsCount(); + /** + * Converts pde line number to java line number + * @param pdeLineNum - pde line number + * @return + */ + protected int pdeLineNumToJavaLineNum(int pdeLineNum){ + int javaLineNumber = pdeLineNum + errorCheckerService.getPdeImportsCount(); // Adjust line number for tabbed sketches int codeIndex = editor.getSketch().getCodeIndex(editor.getCurrentTab()); if (codeIndex > 0) for (int i = 0; i < codeIndex; i++) { SketchCode sc = editor.getSketch().getCode(i); int len = Base.countLines(sc.getProgram()) + 1; - lineNumber += len; + javaLineNumber += len; } - return lineNumber; + return javaLineNumber; } protected boolean isInstanceOfType(ASTNode node,ASTNode decl, String name){ diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index d7571fb..bf0a9a2 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -144,8 +144,8 @@ else if (s.length() == 0) log(errorCheckerService.mainClassOffset + line + "|" + line + "| offset " + xLS + word + " <= \n"); - errorCheckerService.getASTGenerator().scrollToDeclaration(line - + errorCheckerService.mainClassOffset, word, xLS); + errorCheckerService.getASTGenerator() + .scrollToDeclaration(line, word, xLS); } } From 262f0bd484aad8a9bf3c1bf0e4170b937718c4b2 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 21:49:02 +0530 Subject: [PATCH 165/193] code cleanup --- .../mode/experimental/ASTGenerator.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index fc20917..e785ac6 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1574,8 +1574,8 @@ public void scrollToDeclaration(int lineNumber, String name, int offset) { */ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, boolean scrollOnly) { - int originalLN = lineNumber; - lineNumber += errorCheckerService.mainClassOffset; + //int originalLN = lineNumber; + int pdeLineNumber = lineNumber + errorCheckerService.mainClassOffset; log("----getASTNodeAt---- CU State: " + errorCheckerService.compilationUnitState); if (errorCheckerService != null) { editor = errorCheckerService.getEditor(); @@ -1584,14 +1584,14 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, for (int i = 0; i < codeIndex; i++) { SketchCode sc = editor.getSketch().getCode(i); int len = Base.countLines(sc.getProgram()) + 1; - lineNumber += len; + pdeLineNumber += len; } } } - lineNumber = pdeLineNumToJavaLineNum(lineNumber); - log("getASTNodeAt: Node line number " + lineNumber); - ASTNode lineNode = findLineOfNode(compilationUnit, lineNumber, offset, name); + + log("getASTNodeAt: Node line number " + pdeLineNumber); + ASTNode lineNode = findLineOfNode(compilationUnit, pdeLineNumber, offset, name); log("Node text +> " + lineNode); ASTNode decl = null; @@ -1600,10 +1600,10 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, if (lineNode != null) { String pdeCodeLine = errorCheckerService.getPDECodeAtLine(editor - .getSketch().getCurrentCodeIndex(), originalLN); - String javaCodeLine = getJavaSourceCodeline(lineNumber); + .getSketch().getCurrentCodeIndex(), lineNumber); + String javaCodeLine = getJavaSourceCodeline(pdeLineNumber); - log(originalLN + " Original Line num.\nPDE :" + pdeCodeLine); + log(lineNumber + " Original Line num.\nPDE :" + pdeCodeLine); log("JAVA:" + javaCodeLine); log("Clicked on: " + name + " start offset: " + offset); OffsetMatcher ofm = new OffsetMatcher(pdeCodeLine, javaCodeLine); From 1debe4857fd15a50e5e58d8d042bcba4f10fab5c Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 22:18:32 +0530 Subject: [PATCH 166/193] code cleanup. --- .../mode/experimental/ASTGenerator.java | 64 ++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index e785ac6..296fecf 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1576,7 +1576,8 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, boolean scrollOnly) { //int originalLN = lineNumber; int pdeLineNumber = lineNumber + errorCheckerService.mainClassOffset; - log("----getASTNodeAt---- CU State: " + errorCheckerService.compilationUnitState); + log("----getASTNodeAt---- CU State: " + + errorCheckerService.compilationUnitState); if (errorCheckerService != null) { editor = errorCheckerService.getEditor(); int codeIndex = editor.getSketch().getCodeIndex(editor.getCurrentTab()); @@ -1591,18 +1592,19 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } log("getASTNodeAt: Node line number " + pdeLineNumber); - ASTNode lineNode = findLineOfNode(compilationUnit, pdeLineNumber, offset, name); - + ASTNode lineNode = findLineOfNode(compilationUnit, pdeLineNumber, offset, + name); + log("Node text +> " + lineNode); ASTNode decl = null; String nodeLabel = null; String nameOfNode = null; // The node name which is to be scrolled to - + if (lineNode != null) { String pdeCodeLine = errorCheckerService.getPDECodeAtLine(editor .getSketch().getCurrentCodeIndex(), lineNumber); String javaCodeLine = getJavaSourceCodeline(pdeLineNumber); - + log(lineNumber + " Original Line num.\nPDE :" + pdeCodeLine); log("JAVA:" + javaCodeLine); log("Clicked on: " + name + " start offset: " + offset); @@ -1613,76 +1615,78 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, ASTNode simpName = dfsLookForASTNode(errorCheckerService.getLatestCU(), name, javaOffset, javaOffset + name.length()); - - if(simpName == null && lineNode instanceof SimpleName){ + + if (simpName == null && lineNode instanceof SimpleName) { switch (lineNode.getParent().getNodeType()) { case ASTNode.TYPE_DECLARATION: - + case ASTNode.METHOD_DECLARATION: case ASTNode.FIELD_DECLARATION: case ASTNode.VARIABLE_DECLARATION_FRAGMENT: decl = lineNode.getParent(); - return new ASTNodeWrapper(decl,""); + return new ASTNodeWrapper(decl, ""); default: break; } } - + if (simpName instanceof SimpleName) { nameOfNode = simpName.toString(); log(getNodeAsString(simpName)); decl = findDeclaration((SimpleName) simpName); if (decl != null) { logE("DECLA: " + decl.getClass().getName()); - nodeLabel = getLabelIfType(new ASTNodeWrapper(decl), (SimpleName) simpName); + nodeLabel = getLabelIfType(new ASTNodeWrapper(decl), + (SimpleName) simpName); //retLabelString = getNodeAsString(decl); } else { logE("null"); - if(scrollOnly) { + if (scrollOnly) { editor.statusMessage(simpName + " is not defined in this sketch", DebugEditor.STATUS_ERR); } } log(getNodeAsString(decl)); - + // - findDecl3 testing - - ASTNode nearestNode = findClosestNode(lineNumber, (ASTNode) compilationUnit.types() - .get(0)); + + ASTNode nearestNode = findClosestNode(lineNumber, + (ASTNode) compilationUnit.types() + .get(0)); ClassMember cmem = resolveExpression3rdParty(nearestNode, - (SimpleName) simpName, false); - if(cmem != null){ - log("CMEM-> "+cmem); - } - else + (SimpleName) simpName, + false); + if (cmem != null) { + log("CMEM-> " + cmem); + } else log("CMEM-> null"); } } if (decl != null && scrollOnly) { /* - * For scrolling, we highlight just the name of the node, - * i.e., a SimpleName instance. But the declared node always - * points to the declared node itself, like TypeDecl, MethodDecl, etc. - * This is important since it contains all the properties. + * For scrolling, we highlight just the name of the node, i.e., a + * SimpleName instance. But the declared node always points to the + * declared node itself, like TypeDecl, MethodDecl, etc. This is important + * since it contains all the properties. */ - ASTNode simpName2 = getNodeName(decl,nameOfNode); + ASTNode simpName2 = getNodeName(decl, nameOfNode); logE("FINAL String decl: " + getNodeAsString(decl)); logE("FINAL String label: " + getNodeAsString(simpName2)); //errorCheckerService.highlightNode(simpName2); - ASTNodeWrapper declWrap = new ASTNodeWrapper(simpName2,nodeLabel); + ASTNodeWrapper declWrap = new ASTNodeWrapper(simpName2, nodeLabel); //errorCheckerService.highlightNode(declWrap); if (!declWrap.highlightNode(this)) { logE("Highlighting failed."); } - } + } - return new ASTNodeWrapper(decl,nodeLabel); + return new ASTNodeWrapper(decl, nodeLabel); } - + /** * Given a declaration type astnode, returns the SimpleName peroperty * of that node. From 43c55aea7e43f371ce0704552fbe341885a16bdd Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 22:36:38 +0530 Subject: [PATCH 167/193] Removed unnecessary stuff --- src/processing/mode/experimental/ASTGenerator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 296fecf..40f4729 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1651,6 +1651,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, log(getNodeAsString(decl)); + /* // - findDecl3 testing ASTNode nearestNode = findClosestNode(lineNumber, @@ -1663,6 +1664,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, log("CMEM-> " + cmem); } else log("CMEM-> null"); + */ } } From 2a0d44951a6035ff990a59f3aa28bc6c6a1799fc Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 22:42:28 +0530 Subject: [PATCH 168/193] code comments, coz I am not a mean person --- src/processing/mode/experimental/ASTGenerator.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 40f4729..b6f32a8 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1574,7 +1574,8 @@ public void scrollToDeclaration(int lineNumber, String name, int offset) { */ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, boolean scrollOnly) { - //int originalLN = lineNumber; + + // Convert tab based pde line number to actual line number int pdeLineNumber = lineNumber + errorCheckerService.mainClassOffset; log("----getASTNodeAt---- CU State: " + errorCheckerService.compilationUnitState); @@ -1591,6 +1592,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } + // Find closest ASTNode to the linenumber log("getASTNodeAt: Node line number " + pdeLineNumber); ASTNode lineNode = findLineOfNode(compilationUnit, pdeLineNumber, offset, name); @@ -1600,6 +1602,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, String nodeLabel = null; String nameOfNode = null; // The node name which is to be scrolled to + // Obtain correspondin java code at that line, match offsets if (lineNode != null) { String pdeCodeLine = errorCheckerService.getPDECodeAtLine(editor .getSketch().getCurrentCodeIndex(), lineNumber); @@ -1608,14 +1611,18 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, log(lineNumber + " Original Line num.\nPDE :" + pdeCodeLine); log("JAVA:" + javaCodeLine); log("Clicked on: " + name + " start offset: " + offset); + // Calculate expected java offset based on the pde line OffsetMatcher ofm = new OffsetMatcher(pdeCodeLine, javaCodeLine); int javaOffset = ofm.getJavaOffForPdeOff(offset, name.length()) + lineNode.getStartPosition(); log("JAVA ast offset: " + (javaOffset)); + + // Find the corresponding node in the AST ASTNode simpName = dfsLookForASTNode(errorCheckerService.getLatestCU(), name, javaOffset, javaOffset + name.length()); + // If node wasn't found in the AST, lineNode may contain something if (simpName == null && lineNode instanceof SimpleName) { switch (lineNode.getParent().getNodeType()) { case ASTNode.TYPE_DECLARATION: @@ -1632,6 +1639,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } } + // SimpleName instance found, now find its declaration in code if (simpName instanceof SimpleName) { nameOfNode = simpName.toString(); log(getNodeAsString(simpName)); @@ -1686,6 +1694,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, } } + // Return the declaration wrapped as ASTNodeWrapper return new ASTNodeWrapper(decl, nodeLabel); } From 6e2805b0f3e785f6edb79a78537cd69989a6d891 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Mon, 9 Jun 2014 23:23:15 +0530 Subject: [PATCH 169/193] managing collateral damage from offset algo change --- src/processing/mode/experimental/ASTGenerator.java | 4 +++- src/processing/mode/experimental/TextArea.java | 4 ++-- src/processing/mode/experimental/TextAreaPainter.java | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index b6f32a8..8ce8b71 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1798,6 +1798,7 @@ public static void traversal2() { } } + final ASTGenerator thisASTGenerator = this; protected void addListeners(){ jtree.addTreeSelectionListener(new TreeSelectionListener() { @@ -1918,7 +1919,8 @@ protected void done() { if (tnode.getUserObject() instanceof ASTNodeWrapper) { ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject(); - errorCheckerService.highlightNode(awrap); + //errorCheckerService.highlightNode(awrap); + awrap.highlightNode(thisASTGenerator); } } }; diff --git a/src/processing/mode/experimental/TextArea.java b/src/processing/mode/experimental/TextArea.java index 6657353..b0971b3 100644 --- a/src/processing/mode/experimental/TextArea.java +++ b/src/processing/mode/experimental/TextArea.java @@ -256,6 +256,7 @@ else if (s.length() == 0) if (x1 >= 0 && x1 < s.length()) { if (Character.isLetter(s.charAt(x1)) || s.charAt(x1) == '_') { word = s.charAt(x1--) + word; + xLS--; } else x1 = -1; } else @@ -280,8 +281,7 @@ else if (s.length() == 0) if (Character.isDigit(word.charAt(0))) return null; log("Mouse click, word: " + word.trim()); - errorCheckerService.getASTGenerator().setLastClickedWord(line - + errorCheckerService.mainClassOffset, word, xLS); + errorCheckerService.getASTGenerator().setLastClickedWord(line, word, xLS); return word.trim(); } } diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index bf0a9a2..8b7f5e9 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -458,6 +458,7 @@ else if (s.length() == 0) if (x1 >= 0 && x1 < s.length()) { if (Character.isLetter(s.charAt(x1)) || s.charAt(x1) == '_') { word = s.charAt(x1--) + word; + xLS--; } else x1 = -1; } else @@ -483,8 +484,7 @@ else if (s.length() == 0) if (Character.isDigit(word.charAt(0))) return null; String tooltipText = errorCheckerService.getASTGenerator() - .getLabelForASTNode(line + errorCheckerService.mainClassOffset, word, - xLS); + .getLabelForASTNode(line, word, xLS); log(errorCheckerService.mainClassOffset + " MCO " + "|" + line + "| offset " + xLS + word + " <= offf: "+off+ "\n"); From e95ccfb032d666698298cfbcd57ef131e3224f17 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 01:42:14 +0530 Subject: [PATCH 170/193] some utility methods --- .../mode/experimental/ASTGenerator.java | 123 +++++++++++++++++- 1 file changed, 117 insertions(+), 6 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 8ce8b71..fd0e047 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1189,22 +1189,54 @@ public ArrayList getMembersForType(ClassMember tehClass, return candidates; } - public String getJavaSourceCodeline(int jLineNumber){ + /** + * Returns the java source code line at the given line number + * @param javaLineNumber + * @return + */ + public String getJavaSourceCodeline(int javaLineNumber) { try { PlainDocument javaSource = new PlainDocument(); javaSource.insertString(0, errorCheckerService.sourceCode, null); Element lineElement = javaSource.getDefaultRootElement() - .getElement(jLineNumber-1); - if(lineElement == null) { - log("Couldn't fetch jlinenum " + jLineNumber); + .getElement(javaLineNumber - 1); + if (lineElement == null) { + log("Couldn't fetch jlinenum " + javaLineNumber); return null; - } + } String javaLine = javaSource.getText(lineElement.getStartOffset(), lineElement.getEndOffset() - lineElement.getStartOffset()); return javaLine; } catch (BadLocationException e) { - logE(e + " in getJavaSourceCodeline() for jinenum: " + jLineNumber); + logE(e + " in getJavaSourceCodeline() for jinenum: " + javaLineNumber); + } + return null; + } + + /** + * Returns the java source code line Element at the given line number. + * The Element object stores the offset data, but not the actual line + * of code. + * @param javaLineNumber + * @return + */ + public Element getJavaSourceCodeElement(int javaLineNumber) { + try { + PlainDocument javaSource = new PlainDocument(); + javaSource.insertString(0, errorCheckerService.sourceCode, null); + Element lineElement = javaSource.getDefaultRootElement() + .getElement(javaLineNumber - 1); + if (lineElement == null) { + log("Couldn't fetch jlinenum " + javaLineNumber); + return null; + } +// String javaLine = javaSource.getText(lineElement.getStartOffset(), +// lineElement.getEndOffset() +// - lineElement.getStartOffset()); + return lineElement; + } catch (BadLocationException e) { + logE(e + " in getJavaSourceCodeline() for jinenum: " + javaLineNumber); } return null; } @@ -1929,6 +1961,7 @@ protected void done() { }); } + /* protected void refactorIt(){ String newName = txtRenameField.getText().trim(); String selText = lastClickedWord == null ? editor.ta.getSelectedText() @@ -1994,6 +2027,84 @@ protected void refactorIt(){ // for (Integer lineNum : lineOffsetDisplacement.keySet()) { // log(lineNum + "line, disp" // + lineOffsetDisplacement.get(lineNum)); +// } + editor.getSketch().setModified(true); + errorCheckerService.runManualErrorCheck(); + frmOccurenceList.setVisible(false); + frmRename.setVisible(false); + lastClickedWord = null; + lastClickedWordNode = null; + } + */ + + protected void refactorIt(){ + String newName = txtRenameField.getText().trim(); + String selText = lastClickedWord == null ? editor.ta.getSelectedText() + : lastClickedWord; + // Find all occurrences of last clicked word + DefaultMutableTreeNode defCU = findAllOccurrences(); //TODO: Repetition here + if(defCU == null){ + editor.statusMessage("Can't locate definition of " + selText, + DebugEditor.STATUS_ERR); + return; + } + + // Verify if the new name is a valid java identifier + if(!newName.matches("([a-zA-Z][a-zA-Z0-9_]*)|([_][a-zA-Z0-9_]+)")) + { + JOptionPane.showConfirmDialog(new JFrame(), newName + + " isn't a valid name.", "Uh oh..", JOptionPane.PLAIN_MESSAGE); + return; + } + //else log("New name looks K."); + + errorCheckerService.pauseThread(); + if(treeRename.isVisible()){ + treeRename.setModel(new DefaultTreeModel(defCU)); + ((DefaultTreeModel) treeRename.getModel()).reload(); + } + frmOccurenceList.setTitle("Usage of " + selText); + frmOccurenceList.setLocation(editor.getX() + editor.getWidth(),editor.getY()); + frmOccurenceList.setVisible(true); + int lineOffsetDisplacementConst = newName.length() + - selText.length(); + HashMap lineOffsetDisplacement = new HashMap(); + + // I need to store the pde and java offsets beforehand because once + // the replace starts, all offsets returned are affected + int offsetsMap[][][] = new int[defCU.getChildCount()][2][]; + for (int i = 0; i < defCU.getChildCount(); i++) { + ASTNodeWrapper awrap = (ASTNodeWrapper) ((DefaultMutableTreeNode) (defCU + .getChildAt(i))).getUserObject(); + offsetsMap[i][0] = awrap.getPDECodeOffsets(errorCheckerService); + offsetsMap[i][1] = awrap.getJavaCodeOffsets(errorCheckerService); + } + + for (int i = 0; i < defCU.getChildCount(); i++) { + int pdeoffsets[] = offsetsMap[i][0]; + int javaoffsets[] = offsetsMap[i][1]; + // correction for pde enhancements related displacement on a line + int off = 0; + if (lineOffsetDisplacement.get(javaoffsets[0]) != null) { + off = lineOffsetDisplacement.get(javaoffsets[0]); + + lineOffsetDisplacement.put(javaoffsets[0], + lineOffsetDisplacementConst + off); + } else { + lineOffsetDisplacement.put(javaoffsets[0], + lineOffsetDisplacementConst); + } + ErrorCheckerService.scrollToErrorLine(editor, pdeoffsets[0], + pdeoffsets[1], + javaoffsets[1] + off, + javaoffsets[2]); + //int k = JOptionPane.showConfirmDialog(new JFrame(), "Rename?","", JOptionPane.INFORMATION_MESSAGE)); + editor.ta.setSelectedText(newName); + } + errorCheckerService.resumeThread(); +// for (Integer lineNum : lineOffsetDisplacement.keySet()) { +// log(lineNum + "line, disp" +// + lineOffsetDisplacement.get(lineNum)); // } editor.getSketch().setModified(true); errorCheckerService.runManualErrorCheck(); From 5313f9c18a02ce689f1a1d2b7e7fe3b205a61828 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 02:12:07 +0530 Subject: [PATCH 171/193] moar utility methods --- .../mode/experimental/ASTGenerator.java | 13 +++++++++++-- .../mode/experimental/ASTNodeWrapper.java | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index fd0e047..f970575 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1189,12 +1189,21 @@ public ArrayList getMembersForType(ClassMember tehClass, return candidates; } + public String getPDESourceCodeLine(int javaLineNumber) { + int res[] = errorCheckerService + .calculateTabIndexAndLineNumber(javaLineNumber); + if (res != null) { + return errorCheckerService.getPDECodeAtLine(res[0], res[1]); + } + return null; + } + /** * Returns the java source code line at the given line number * @param javaLineNumber * @return */ - public String getJavaSourceCodeline(int javaLineNumber) { + public String getJavaSourceCodeLine(int javaLineNumber) { try { PlainDocument javaSource = new PlainDocument(); javaSource.insertString(0, errorCheckerService.sourceCode, null); @@ -1638,7 +1647,7 @@ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset, if (lineNode != null) { String pdeCodeLine = errorCheckerService.getPDECodeAtLine(editor .getSketch().getCurrentCodeIndex(), lineNumber); - String javaCodeLine = getJavaSourceCodeline(pdeLineNumber); + String javaCodeLine = getJavaSourceCodeLine(pdeLineNumber); log(lineNumber + " Original Line num.\nPDE :" + pdeCodeLine); log("JAVA:" + javaCodeLine); diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 734da04..450dfb6 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -392,7 +392,7 @@ public int[][] getOffsetMapping(ErrorCheckerService ecs, String source){ // Instead of converting pde into java, how can I simply extract the same source // from the java code? Think. TODO String sourceAlt = new String(source); - String sourceJava = ecs.astGenerator.getJavaSourceCodeline(lineNumber); + String sourceJava = ecs.astGenerator.getJavaSourceCodeLine(lineNumber); TreeMap offsetmap = new TreeMap(); if(sourceJava.trim().startsWith("public") && !source.startsWith("public")){ @@ -650,6 +650,23 @@ public int[][] getOffsetMapping(ErrorCheckerService ecs){ public int[] getPDECodeOffsets(ErrorCheckerService ecs) { return ecs.JavaToPdeOffsets(lineNumber + 1, Node.getStartPosition()); } + + public int getPDECodeOffsetForSN(ASTGenerator astGen){ + if (Node instanceof SimpleName) { + Element lineElement = astGen.getJavaSourceCodeElement(lineNumber); + + OffsetMatcher ofm = new OffsetMatcher( + astGen + .getPDESourceCodeLine(lineNumber), + astGen + .getJavaSourceCodeLine(lineNumber)); + //log(""); + int pdeOffset = ofm.getPdeOffForJavaOff(Node.getStartPosition() + - lineElement.getStartOffset(), Node.toString().length()); + return pdeOffset; + } + return -1; + } public String toString() { return label; From 240d32d613f489b657c7e8a2bbd613f4bc5e28f1 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 02:18:48 +0530 Subject: [PATCH 172/193] further work --- src/processing/mode/experimental/ASTGenerator.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index f970575..f8d2771 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -2087,8 +2087,10 @@ protected void refactorIt(){ .getChildAt(i))).getUserObject(); offsetsMap[i][0] = awrap.getPDECodeOffsets(errorCheckerService); offsetsMap[i][1] = awrap.getJavaCodeOffsets(errorCheckerService); + log(getNodeAsString(awrap.getNode()) + ", " + + awrap.getPDECodeOffsetForSN(this)); } - + /* for (int i = 0; i < defCU.getChildCount(); i++) { int pdeoffsets[] = offsetsMap[i][0]; int javaoffsets[] = offsetsMap[i][1]; @@ -2109,7 +2111,7 @@ protected void refactorIt(){ javaoffsets[2]); //int k = JOptionPane.showConfirmDialog(new JFrame(), "Rename?","", JOptionPane.INFORMATION_MESSAGE)); editor.ta.setSelectedText(newName); - } + }*/ errorCheckerService.resumeThread(); // for (Integer lineNum : lineOffsetDisplacement.keySet()) { // log(lineNum + "line, disp" From 92f21776a13b25283f6a6369efe13e6459bc8a77 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 02:19:35 +0530 Subject: [PATCH 173/193] refactoring.. --- .../mode/experimental/OffsetMatcher.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/processing/mode/experimental/OffsetMatcher.java b/src/processing/mode/experimental/OffsetMatcher.java index 9c2f00f..5161808 100644 --- a/src/processing/mode/experimental/OffsetMatcher.java +++ b/src/processing/mode/experimental/OffsetMatcher.java @@ -32,14 +32,14 @@ public class OffsetMatcher { public ArrayList offsetMatch; - String word1, word2; + String pdeCodeLine, javaCodeLine; boolean matchingNeeded = false; public OffsetMatcher(String pdeCode, String javaCode) { - this.word1 = pdeCode; - this.word2 = javaCode; - if(word1.trim().equals(word2.trim())){ //TODO: trim() needed here? + this.pdeCodeLine = pdeCode; + this.javaCodeLine = javaCode; + if(pdeCodeLine.trim().equals(javaCodeLine.trim())){ //TODO: trim() needed here? matchingNeeded = false; offsetMatch = new ArrayList(); log("Offset Matching not needed"); @@ -67,8 +67,8 @@ public int getPdeOffForJavaOff(int start, int length) { + ans); log((start + length - 1) + " java end off, pde end off " + end); - log("J: " + word2.substring(start, start + length) + "\nP: " - + word1.substring(ans, end + 1)); + log("J: " + javaCodeLine.substring(start, start + length) + "\nP: " + + pdeCodeLine.substring(ans, end + 1)); return ans; } @@ -139,10 +139,10 @@ private int minDistance() { // word1 = reverse(word1); // word2 = reverse(word2); - int len1 = word1.length(); - int len2 = word2.length(); - log(word1 + " len: " + len1); - log(word2 + " len: " + len2); + int len1 = pdeCodeLine.length(); + int len2 = javaCodeLine.length(); + log(pdeCodeLine + " len: " + len1); + log(javaCodeLine + " len: " + len2); // len1+1, len2+1, because finally return dp[len1][len2] int[][] dp = new int[len1 + 1][len2 + 1]; @@ -156,9 +156,9 @@ private int minDistance() { //iterate though, and check last char for (int i = 0; i < len1; i++) { - char c1 = word1.charAt(i); + char c1 = pdeCodeLine.charAt(i); for (int j = 0; j < len2; j++) { - char c2 = word2.charAt(j); + char c2 = javaCodeLine.charAt(j); //System.out.print(c1 + "<->" + c2); //if last two chars equal if (c1 == c2) { @@ -182,8 +182,8 @@ private int minDistance() { ArrayList alist = new ArrayList(); offsetMatch = alist; - minDistInGrid(dp, len1, len2, 0, 0, word1.toCharArray(), - word2.toCharArray(), alist); + minDistInGrid(dp, len1, len2, 0, 0, pdeCodeLine.toCharArray(), + javaCodeLine.toCharArray(), alist); return dp[len1][len2]; } From 99c6d6af30b86e917b3be82f54d87bfdbab47764 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 02:57:12 +0530 Subject: [PATCH 174/193] Refactoring rewritten. Hail Daft Punk --- .../mode/experimental/ASTGenerator.java | 63 +++++++++++++------ .../mode/experimental/ASTNodeWrapper.java | 2 +- .../mode/experimental/OffsetMatcher.java | 1 + 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index f8d2771..7f8753b 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -2081,37 +2081,49 @@ protected void refactorIt(){ // I need to store the pde and java offsets beforehand because once // the replace starts, all offsets returned are affected - int offsetsMap[][][] = new int[defCU.getChildCount()][2][]; + //int offsetsMap[][][] = new int[defCU.getChildCount()][2][]; + int pdeOffsets[][] = new int[defCU.getChildCount()][3]; for (int i = 0; i < defCU.getChildCount(); i++) { ASTNodeWrapper awrap = (ASTNodeWrapper) ((DefaultMutableTreeNode) (defCU .getChildAt(i))).getUserObject(); - offsetsMap[i][0] = awrap.getPDECodeOffsets(errorCheckerService); - offsetsMap[i][1] = awrap.getJavaCodeOffsets(errorCheckerService); - log(getNodeAsString(awrap.getNode()) + ", " - + awrap.getPDECodeOffsetForSN(this)); +// offsetsMap[i][0] = awrap.getPDECodeOffsets(errorCheckerService); +// offsetsMap[i][1] = awrap.getJavaCodeOffsets(errorCheckerService); + int ans[] = errorCheckerService.calculateTabIndexAndLineNumber(awrap + .getLineNumber()); + pdeOffsets[i][0] = ans[0]; + pdeOffsets[i][1] = ans[1]; + pdeOffsets[i][2] = awrap.getPDECodeOffsetForSN(this); +// logE(getNodeAsString(awrap.getNode()) + ", " +// + pdeOffsets[i][2]); } - /* + for (int i = 0; i < defCU.getChildCount(); i++) { - int pdeoffsets[] = offsetsMap[i][0]; - int javaoffsets[] = offsetsMap[i][1]; + ASTNodeWrapper awrap = (ASTNodeWrapper) ((DefaultMutableTreeNode) (defCU + .getChildAt(i))).getUserObject(); // correction for pde enhancements related displacement on a line int off = 0; - if (lineOffsetDisplacement.get(javaoffsets[0]) != null) { - off = lineOffsetDisplacement.get(javaoffsets[0]); + if (lineOffsetDisplacement.get(awrap.getLineNumber()) != null) { + off = lineOffsetDisplacement.get(awrap.getLineNumber()); - lineOffsetDisplacement.put(javaoffsets[0], + lineOffsetDisplacement.put(awrap.getLineNumber(), lineOffsetDisplacementConst + off); } else { - lineOffsetDisplacement.put(javaoffsets[0], + lineOffsetDisplacement.put(awrap.getLineNumber(), lineOffsetDisplacementConst); } - ErrorCheckerService.scrollToErrorLine(editor, pdeoffsets[0], - pdeoffsets[1], - javaoffsets[1] + off, - javaoffsets[2]); - //int k = JOptionPane.showConfirmDialog(new JFrame(), "Rename?","", JOptionPane.INFORMATION_MESSAGE)); + logE(getNodeAsString(awrap.getNode()) + ", T:" + pdeOffsets[i][0] + + ", L:" + pdeOffsets[i][1] + ", O:" + pdeOffsets[i][2]); +// ErrorCheckerService.scrollToErrorLine(editor, pdeOffsets[i][0], +// pdeOffsets[i][1] - 1, pdeOffsets[i][2] +// + off, awrap.getNode() +// .toString().length()); + highlightPDECode(pdeOffsets[i][0], + pdeOffsets[i][1], pdeOffsets[i][2] + + off, awrap.getNode() + .toString().length()); + //int k = JOptionPane.showConfirmDialog(new JFrame(), "Rename?","", JOptionPane.INFORMATION_MESSAGE); editor.ta.setSelectedText(newName); - }*/ + } errorCheckerService.resumeThread(); // for (Integer lineNum : lineOffsetDisplacement.keySet()) { // log(lineNum + "line, disp" @@ -2125,6 +2137,21 @@ protected void refactorIt(){ lastClickedWordNode = null; } + /** + * 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) { + editor.toFront(); + editor.getSketch().setCurrentCode(tab); + lineStartWSOffset += editor.ta.getLineStartOffset(lineNumber); + editor.ta.select(lineStartWSOffset, lineStartWSOffset + length); + } + public void handleShowUsage(){ log("Last clicked word:" + lastClickedWord); if(lastClickedWord == null && editor.ta.getSelectedText() == null){ diff --git a/src/processing/mode/experimental/ASTNodeWrapper.java b/src/processing/mode/experimental/ASTNodeWrapper.java index 450dfb6..9798f3e 100644 --- a/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/src/processing/mode/experimental/ASTNodeWrapper.java @@ -654,7 +654,7 @@ public int[] getPDECodeOffsets(ErrorCheckerService ecs) { public int getPDECodeOffsetForSN(ASTGenerator astGen){ if (Node instanceof SimpleName) { Element lineElement = astGen.getJavaSourceCodeElement(lineNumber); - + log("Line element off " + lineElement.getStartOffset()); OffsetMatcher ofm = new OffsetMatcher( astGen .getPDESourceCodeLine(lineNumber), diff --git a/src/processing/mode/experimental/OffsetMatcher.java b/src/processing/mode/experimental/OffsetMatcher.java index 5161808..af48dfe 100644 --- a/src/processing/mode/experimental/OffsetMatcher.java +++ b/src/processing/mode/experimental/OffsetMatcher.java @@ -61,6 +61,7 @@ public OffsetMatcher(String pdeCode, String javaCode) { } public int getPdeOffForJavaOff(int start, int length) { + log("PDE :" + pdeCodeLine + "\nJAVA:" + javaCodeLine); if(!matchingNeeded) return start; int ans = getPdeOffForJavaOff(start), end = getPdeOffForJavaOff(start + length - 1); log(start + " java start off, pde start off " From 03f7732a86efa16b9874407cce4d01000bfff87a Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 02:58:26 +0530 Subject: [PATCH 175/193] Dunno how I wrote such bad code earlier. Lol --- .../mode/experimental/ASTGenerator.java | 92 +------------------ 1 file changed, 2 insertions(+), 90 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 7f8753b..017874f 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1970,82 +1970,6 @@ protected void done() { }); } - /* - protected void refactorIt(){ - String newName = txtRenameField.getText().trim(); - String selText = lastClickedWord == null ? editor.ta.getSelectedText() - : lastClickedWord; - DefaultMutableTreeNode defCU = findAllOccurrences(); - if(defCU == null){ - editor.statusError("Can't locate definition of " + selText); - return; - } - - if(!newName.matches("([a-zA-Z][a-zA-Z0-9_]*)|([_][a-zA-Z0-9_]+)")) - { - JOptionPane.showConfirmDialog(new JFrame(), newName - + " isn't a valid name.", "Uh oh..", JOptionPane.PLAIN_MESSAGE); - return; - } - //else log("New name looks K."); - - errorCheckerService.pauseThread(); - if(treeRename.isVisible()){ - treeRename.setModel(new DefaultTreeModel(defCU)); - ((DefaultTreeModel) treeRename.getModel()).reload(); - } - frmOccurenceList.setTitle("Usage of " + selText); - frmOccurenceList.setLocation(editor.getX() + editor.getWidth(),editor.getY()); - frmOccurenceList.setVisible(true); - int lineOffsetDisplacementConst = newName.length() - - selText.length(); - HashMap lineOffsetDisplacement = new HashMap(); - - // I need to store the pde and java offsets beforehand because once - // the replace starts, all offsets returned are affected - int offsetsMap[][][] = new int[defCU.getChildCount()][2][]; - for (int i = 0; i < defCU.getChildCount(); i++) { - ASTNodeWrapper awrap = (ASTNodeWrapper) ((DefaultMutableTreeNode) (defCU - .getChildAt(i))).getUserObject(); - offsetsMap[i][0] = awrap.getPDECodeOffsets(errorCheckerService); - offsetsMap[i][1] = awrap.getJavaCodeOffsets(errorCheckerService); - } - - for (int i = 0; i < defCU.getChildCount(); i++) { - int pdeoffsets[] = offsetsMap[i][0]; - int javaoffsets[] = offsetsMap[i][1]; - // correction for pde enhancements related displacement on a line - int off = 0; - if (lineOffsetDisplacement.get(javaoffsets[0]) != null) { - off = lineOffsetDisplacement.get(javaoffsets[0]); - - lineOffsetDisplacement.put(javaoffsets[0], - lineOffsetDisplacementConst + off); - } else { - lineOffsetDisplacement.put(javaoffsets[0], - lineOffsetDisplacementConst); - } - ErrorCheckerService.scrollToErrorLine(editor, pdeoffsets[0], - pdeoffsets[1], - javaoffsets[1] + off, - javaoffsets[2]); - //int k = JOptionPane.showConfirmDialog(new JFrame(), "Rename?","", JOptionPane.INFORMATION_MESSAGE)); - editor.ta.setSelectedText(newName); - } - errorCheckerService.resumeThread(); -// for (Integer lineNum : lineOffsetDisplacement.keySet()) { -// log(lineNum + "line, disp" -// + lineOffsetDisplacement.get(lineNum)); -// } - editor.getSketch().setModified(true); - errorCheckerService.runManualErrorCheck(); - frmOccurenceList.setVisible(false); - frmRename.setVisible(false); - lastClickedWord = null; - lastClickedWordNode = null; - } - */ - protected void refactorIt(){ String newName = txtRenameField.getText().trim(); String selText = lastClickedWord == null ? editor.ta.getSelectedText() @@ -2086,15 +2010,11 @@ protected void refactorIt(){ for (int i = 0; i < defCU.getChildCount(); i++) { ASTNodeWrapper awrap = (ASTNodeWrapper) ((DefaultMutableTreeNode) (defCU .getChildAt(i))).getUserObject(); -// offsetsMap[i][0] = awrap.getPDECodeOffsets(errorCheckerService); -// offsetsMap[i][1] = awrap.getJavaCodeOffsets(errorCheckerService); int ans[] = errorCheckerService.calculateTabIndexAndLineNumber(awrap .getLineNumber()); pdeOffsets[i][0] = ans[0]; pdeOffsets[i][1] = ans[1]; pdeOffsets[i][2] = awrap.getPDECodeOffsetForSN(this); -// logE(getNodeAsString(awrap.getNode()) + ", " -// + pdeOffsets[i][2]); } for (int i = 0; i < defCU.getChildCount(); i++) { @@ -2111,12 +2031,8 @@ protected void refactorIt(){ lineOffsetDisplacement.put(awrap.getLineNumber(), lineOffsetDisplacementConst); } - logE(getNodeAsString(awrap.getNode()) + ", T:" + pdeOffsets[i][0] - + ", L:" + pdeOffsets[i][1] + ", O:" + pdeOffsets[i][2]); -// ErrorCheckerService.scrollToErrorLine(editor, pdeOffsets[i][0], -// pdeOffsets[i][1] - 1, pdeOffsets[i][2] -// + off, awrap.getNode() -// .toString().length()); +// logE(getNodeAsString(awrap.getNode()) + ", T:" + pdeOffsets[i][0] +// + ", L:" + pdeOffsets[i][1] + ", O:" + pdeOffsets[i][2]); highlightPDECode(pdeOffsets[i][0], pdeOffsets[i][1], pdeOffsets[i][2] + off, awrap.getNode() @@ -2125,10 +2041,6 @@ protected void refactorIt(){ editor.ta.setSelectedText(newName); } errorCheckerService.resumeThread(); -// for (Integer lineNum : lineOffsetDisplacement.keySet()) { -// log(lineNum + "line, disp" -// + lineOffsetDisplacement.get(lineNum)); -// } editor.getSketch().setModified(true); errorCheckerService.runManualErrorCheck(); frmOccurenceList.setVisible(false); From bf6ec9b8e3f06feb52a79e62e7b76f6808582054 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 03:04:01 +0530 Subject: [PATCH 176/193] Minor modifications to show usage window. --- src/processing/mode/experimental/ASTGenerator.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 017874f..97970ce 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -1996,9 +1996,10 @@ protected void refactorIt(){ treeRename.setModel(new DefaultTreeModel(defCU)); ((DefaultTreeModel) treeRename.getModel()).reload(); } - frmOccurenceList.setTitle("Usage of " + selText); - frmOccurenceList.setLocation(editor.getX() + editor.getWidth(),editor.getY()); - frmOccurenceList.setVisible(true); +// frmOccurenceList.setTitle("Usage of \"" + selText + "\" : " +// + defCU.getChildCount() + " time(s)"); +// frmOccurenceList.setLocation(editor.getX() + editor.getWidth(),editor.getY()); +// frmOccurenceList.setVisible(true); int lineOffsetDisplacementConst = newName.length() - selText.length(); HashMap lineOffsetDisplacement = new HashMap(); @@ -2043,7 +2044,7 @@ protected void refactorIt(){ errorCheckerService.resumeThread(); editor.getSketch().setModified(true); errorCheckerService.runManualErrorCheck(); - frmOccurenceList.setVisible(false); +// frmOccurenceList.setVisible(false); frmRename.setVisible(false); lastClickedWord = null; lastClickedWordNode = null; @@ -2090,7 +2091,8 @@ public void handleShowUsage(){ treeRename.setModel(new DefaultTreeModel(defCU)); ((DefaultTreeModel) treeRename.getModel()).reload(); treeRename.setRootVisible(false); - frmOccurenceList.setTitle("Usage of \"" + selText+ "\""); + frmOccurenceList.setTitle("Usage of \"" + selText + "\" : " + + defCU.getChildCount() + " time(s)"); frmOccurenceList.setLocation(editor.getX() + editor.getWidth(),editor.getY()); frmOccurenceList.setVisible(true); lastClickedWord = null; From 5dbe1a58e5e35ebe2562134e81ab240ea224efdb Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 15:16:33 +0530 Subject: [PATCH 177/193] updated todo --- src/processing/mode/experimental/ASTGenerator.java | 2 +- todo.txt | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 97970ce..83a659c 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -240,7 +240,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = true; + public static final boolean SHOWAST = !true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { diff --git a/todo.txt b/todo.txt index af2cc8d..d7a2337 100644 --- a/todo.txt +++ b/todo.txt @@ -21,9 +21,13 @@ Normal Bugs ----------- -[x] Sketch NOC 6_09: steer PVector, doesn't show completion. #68 --[ ] Sketch NOC 6_09: Classname in Template, doesn't scroll to decl. This is +-[x] Sketch NOC 6_09: Classname in Template, doesn't scroll to decl. This is happening due certain post processing offsets not being accounted for - "public void" +-[x] New offset matching now used by Show Usage + +-[x] New offset matching now used by Refactoring + Enhancements/New Features ------------------------- From 71a5a1dcafaf0c382dec50ec73064d7fee691354 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 18:36:34 +0530 Subject: [PATCH 178/193] Removed ErrorWindow, wasn't getting used much --- .../mode/experimental/DebugEditor.java | 4 +-- .../experimental/ErrorCheckerService.java | 30 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 19eaa3e..28feed5 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -567,7 +567,7 @@ public void actionPerformed(ActionEvent e) { }); debugMenu.add(item); - problemWindowMenuCB = new JCheckBoxMenuItem("Show Problem Window"); + /*problemWindowMenuCB = new JCheckBoxMenuItem("Show Problem Window"); // problemWindowMenuCB.setSelected(true); problemWindowMenuCB.addActionListener(new ActionListener() { @@ -583,7 +583,7 @@ public void actionPerformed(ActionEvent e) { showProblemListView(XQConsoleToggle.CONSOLE); } }); - debugMenu.add(problemWindowMenuCB); + debugMenu.add(problemWindowMenuCB);*/ showWarnings = new JCheckBoxMenuItem("Warnings Enabled"); showWarnings.setSelected(ExperimentalMode.warningsEnabled); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 0c7fbf5..e2dafdd 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -87,7 +87,7 @@ public class ErrorCheckerService implements Runnable{ */ protected AtomicBoolean pauseThread; - protected ErrorWindow errorWindow; + //protected ErrorWindow errorWindow; /** * IProblem[] returned by parser stored in here @@ -230,7 +230,7 @@ public ErrorCheckerService(DebugEditor debugEditor) { classpathJars = new ArrayList(); initParser(); - initializeErrorWindow(); + //initializeErrorWindow(); xqpreproc = new XQPreprocessor(); PdePreprocessor pdePrepoc = new PdePreprocessor(null); defaultImportsOffset = pdePrepoc.getCoreImports().length + @@ -266,7 +266,7 @@ protected void initParser() { /** * Initialiazes the Error Window */ - public void initializeErrorWindow() { + /*public void initializeErrorWindow() { if (editor == null) { return; @@ -291,7 +291,7 @@ public void run() { } } }); - } + }*/ public void ensureMinP5Version(){ // Processing 2.1.2 - Revision 0225 @@ -927,26 +927,28 @@ public void updateErrorTable() { String[][] errorData = new String[problemsList.size()][3]; for (int i = 0; i < problemsList.size(); i++) { errorData[i][0] = problemsList.get(i).getMessage(); ////TODO: this is temporary - //+ " : " + errorMsgSimplifier.getIDName(problemsList.get(i).getIProblem().getID()); + //+ " : " + errorMsgSimplifier.getIDName(problemsList.get(i).getIProblem().getID()); errorData[i][1] = editor.getSketch() .getCode(problemsList.get(i).getTabIndex()).getPrettyName(); errorData[i][2] = problemsList.get(i).getLineNumber() + ""; - + //TODO: This is temporary - if(tempErrorLog.size() < 200) - tempErrorLog.put(problemsList.get(i).getMessage(),problemsList.get(i).getIProblem()); + if (tempErrorLog.size() < 200) + tempErrorLog.put(problemsList.get(i).getMessage(), problemsList + .get(i).getIProblem()); } + + DefaultTableModel tm = new DefaultTableModel(errorData, + XQErrorTable.columnNames); + // Update error table in the editor + editor.updateTable(tm); + /* if (errorWindow != null) { - DefaultTableModel tm = new DefaultTableModel(errorData, - XQErrorTable.columnNames); if (errorWindow.isVisible()) { errorWindow.updateTable(tm); } - // Update error table in the editor - editor.updateTable(tm); - // A rotating slash animation on the title bar to show // that error checker thread is running @@ -961,7 +963,7 @@ public void updateErrorTable() { errorWindow.setTitle("Problems - " + editor.getSketch().getName() + " " + info); } - } + }*/ } catch (Exception e) { log("Exception at updateErrorTable() " + e); From ea25389befccc98e1e819d7c5afe01e3e347d921 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 21:36:20 +0530 Subject: [PATCH 179/193] Precise error highlighting :D --- .../mode/experimental/ASTGenerator.java | 4 +- .../experimental/ErrorCheckerService.java | 41 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/processing/mode/experimental/ASTGenerator.java b/src/processing/mode/experimental/ASTGenerator.java index 83a659c..d254db7 100644 --- a/src/processing/mode/experimental/ASTGenerator.java +++ b/src/processing/mode/experimental/ASTGenerator.java @@ -240,7 +240,7 @@ protected void setupGUI(){ /** * Toggle AST View window */ - public static final boolean SHOWAST = !true; + public static final boolean SHOWAST = true; protected DefaultMutableTreeNode buildAST(String source, CompilationUnit cu) { if (cu == null) { @@ -2059,6 +2059,8 @@ protected void refactorIt(){ */ public void highlightPDECode(int tab, int lineNumber, int lineStartWSOffset, int length) { + log("ASTGen.highlightPDECode: T " + tab + ",L: " + lineNumber + ",LSO: " + + lineStartWSOffset + ",Len: " + length); editor.toFront(); editor.getSketch().setCurrentCode(tab); lineStartWSOffset += editor.ta.getLineStartOffset(lineNumber); diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index e2dafdd..ac43898 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -39,6 +39,7 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.table.DefaultTableModel; +import javax.swing.text.Element; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.IProblem; @@ -1404,7 +1405,7 @@ public void scrollToErrorLine(int errorIndex) { } } - public void scrollToErrorLine(Problem p) { + /*public void scrollToErrorLine(Problem p) { if (editor == null) { return; } @@ -1429,6 +1430,44 @@ public void scrollToErrorLine(Problem p) { e.printStackTrace(); } // log("---"); + }*/ + + public void scrollToErrorLine(Problem p) { + if (editor == null) { + return; + } + if (p == null) + return; + try { + int pkgNameOffset = ("package " + className + ";\n").length(); + int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset, prbEnd = p + .getIProblem().getSourceEnd() - pkgNameOffset; + log("Scrolling to problem: " + p.toString()); + log("P start: " + prbStart + " to " + + prbEnd + " pkgOffset " + pkgNameOffset); + int lineNumber = p + .getIProblem().getSourceLineNumber(); + Element lineElement = astGenerator.getJavaSourceCodeElement(lineNumber); + log("Line element off " + lineElement.getStartOffset()); + OffsetMatcher ofm = new OffsetMatcher( + astGenerator + .getPDESourceCodeLine(lineNumber), + astGenerator + .getJavaSourceCodeLine(lineNumber)); + //log(""); + int pdeOffset = ofm.getPdeOffForJavaOff(prbStart + - lineElement.getStartOffset(), (prbEnd - p + .getIProblem().getSourceStart())); + astGenerator.highlightPDECode(p.getTabIndex(), p.getLineNumber(), + pdeOffset, (prbEnd - prbStart + 1)); + editor.getTextArea().scrollTo(p.getLineNumber() - 1, 0); + editor.repaint(); + } catch (Exception e) { + System.err.println(e + + " : Error while selecting text in scrollToErrorLine()"); + e.printStackTrace(); + } + // log("---"); } /** From 2aeb6117b408ef008df1cf2d804355ab5821deef Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Tue, 10 Jun 2014 21:59:15 +0530 Subject: [PATCH 180/193] err underline, nearly there.. --- .../experimental/ErrorCheckerService.java | 40 +++++++++++++++++++ src/processing/mode/experimental/Problem.java | 9 +++++ 2 files changed, 49 insertions(+) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index ac43898..8c62a0c 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -39,7 +39,9 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.table.DefaultTableModel; +import javax.swing.text.BadLocationException; import javax.swing.text.Element; +import javax.swing.text.PlainDocument; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.IProblem; @@ -740,6 +742,44 @@ public boolean accept(File file) { // log("Compilecheck, Done."); } + private void calcPDEOffsetsForProbList() { + PlainDocument javaSource = new PlainDocument(); + try { + javaSource.insertString(0, sourceCode, null); + int pkgNameOffset = ("package " + className + ";\n").length(); + for (Problem p : problemsList) { + int javaLineNumber = p.getIProblem().getSourceLineNumber(); + Element lineElement = javaSource.getDefaultRootElement() + .getElement(javaLineNumber - 1); + if (lineElement == null) { + log("calcPDEOffsetsForProbList(): Couldn't fetch javalinenum " + + javaLineNumber); + continue; + } + String javaLine = javaSource + .getText(lineElement.getStartOffset(), lineElement.getEndOffset() + - lineElement.getStartOffset()); + int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset, prbEnd = p + .getIProblem().getSourceEnd() - pkgNameOffset; + + OffsetMatcher ofm = new OffsetMatcher( + astGenerator + .getPDESourceCodeLine(javaLineNumber), + javaLine); + //log(""); + int pdeOffset = ofm.getPdeOffForJavaOff(prbStart + - lineElement.getStartOffset(), (prbEnd - p + .getIProblem().getSourceStart())); +// astGenerator.highlightPDECode(p.getTabIndex(), p.getLineNumber(), +// pdeOffset, (prbEnd - prbStart + 1)); + p.setPDEOffsets(pdeOffset, prbEnd - prbStart); + } + } catch (BadLocationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public CompilationUnit getLastCorrectCU(){ return lastCorrectCU; } diff --git a/src/processing/mode/experimental/Problem.java b/src/processing/mode/experimental/Problem.java index aaa8cca..1225238 100644 --- a/src/processing/mode/experimental/Problem.java +++ b/src/processing/mode/experimental/Problem.java @@ -49,6 +49,10 @@ public class Problem { * Line number(pde code) of the error */ private int lineNumber; + + private int lineStartOffset; + + private int lineStopOffset; /** * Error Message. Processed form of IProblem.getMessage() @@ -80,6 +84,11 @@ else if(iProblem.isWarning()) { this.lineNumber = lineNumber; this.message = process(iProblem); } + + public void setPDEOffsets(int startOffset, int stopOffset){ + lineStartOffset = startOffset; + lineStopOffset = stopOffset; + } public String toString() { return new String("TAB " + tabIndex + ",LN " + lineNumber + ",PROB: " From fb432de3abe38ef8fca34b24ef212dd8f0918210 Mon Sep 17 00:00:00 2001 From: Joel Moniz Date: Tue, 10 Jun 2014 23:44:10 +0530 Subject: [PATCH 181/193] Polishing up autosave implementation --- .../mode/experimental/DebugEditor.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 62c6db7..05bd025 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -1085,13 +1085,24 @@ public TextArea textArea() { return ta; } + private boolean wasSaved; + /** * Grab current contents of the sketch window, advance the console, stop any * other running sketches, auto-save the user's code... not in that order. */ @Override public void prepareRun() { + wasSaved = false; + autoSave(); super.prepareRun(); + if (wasSaved) + statusTimedNotice("Saved. Running...", 5); + else + statusTimedNotice("Not saved. Running...", 5); + } + + protected void autoSave() { if (!ExperimentalMode.autoSaveEnabled) return; @@ -1128,15 +1139,14 @@ public void prepareRun() { final JCheckBox dontRedisplay = new JCheckBox( "Remember this decision"); - panel1 = new JPanel(new FlowLayout( - FlowLayout.CENTER, 8, 2)); + panel1 = new JPanel(new FlowLayout(FlowLayout.CENTER, 8, 2)); JButton button = new JButton("Save and Run"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (handleSave(true)) - statusTimedNotice("Saved. Running...", 5); + wasSaved = true; if (dontRedisplay.isSelected()) { ExperimentalMode.autoSavePromptEnabled = !dontRedisplay .isSelected(); @@ -1152,7 +1162,6 @@ public void actionPerformed(ActionEvent e) { @Override public void actionPerformed(ActionEvent e) { - statusTimedNotice("Not saved. Running...", 5); if (dontRedisplay.isSelected()) { ExperimentalMode.autoSavePromptEnabled = !dontRedisplay .isSelected(); @@ -1179,11 +1188,13 @@ public void actionPerformed(ActionEvent e) { autoSaveDialog.setVisible(true); } else if (ExperimentalMode.defaultAutoSaveEnabled) - handleSave(true); + if (handleSave(true)) + wasSaved = true; } } catch (Exception e) { statusError(e); } + } /** From 45035f81f383a0280bcd6237dbe94bd8093bd298 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 00:06:46 +0530 Subject: [PATCH 182/193] meh. broke something again --- .../experimental/ErrorCheckerService.java | 45 ++++++++++++++++--- src/processing/mode/experimental/Problem.java | 13 +++++- .../mode/experimental/TextAreaPainter.java | 15 ++++--- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 8c62a0c..50e912c 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -715,6 +715,7 @@ public boolean accept(File file) { } problemsList.add(p); } + calcPDEOffsetsForProbList(); } } catch (ClassNotFoundException e) { System.err.println("Compiltation Checker files couldn't be found! " @@ -742,15 +743,37 @@ public boolean accept(File file) { // log("Compilecheck, Done."); } + /** + * Calculates PDE Offsets from Java Offsets for Problems + */ private void calcPDEOffsetsForProbList() { PlainDocument javaSource = new PlainDocument(); - try { + // Code in pde tabs stored as PlainDocument + PlainDocument pdeTabs[] = new PlainDocument[editor.getSketch() + .getCodeCount()]; + + try { javaSource.insertString(0, sourceCode, null); + for (int i = 0; i < pdeTabs.length; i++) { + SketchCode sc = editor.getSketch().getCode(i); + pdeTabs[i] = new PlainDocument(); + if (editor.getSketch().getCurrentCode().equals(sc)) { + pdeTabs[i].insertString(0, + sc.getDocument().getText(0, + sc.getDocument() + .getLength()), + null); + } else { + pdeTabs[i].insertString(0, + sc.getProgram(), + null); + } + } int pkgNameOffset = ("package " + className + ";\n").length(); for (Problem p : problemsList) { int javaLineNumber = p.getIProblem().getSourceLineNumber(); Element lineElement = javaSource.getDefaultRootElement() - .getElement(javaLineNumber - 1); + .getElement(javaLineNumber - 2); if (lineElement == null) { log("calcPDEOffsetsForProbList(): Couldn't fetch javalinenum " + javaLineNumber); @@ -761,11 +784,19 @@ private void calcPDEOffsetsForProbList() { - lineElement.getStartOffset()); int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset, prbEnd = p .getIProblem().getSourceEnd() - pkgNameOffset; - - OffsetMatcher ofm = new OffsetMatcher( - astGenerator - .getPDESourceCodeLine(javaLineNumber), - javaLine); + Element pdeLineElement = pdeTabs[p.getTabIndex()] + .getDefaultRootElement().getElement(p.getLineNumber()-1); + if (pdeLineElement == null) { + log("calcPDEOffsetsForProbList(): Couldn't fetch pdelinenum " + + javaLineNumber); + continue; + } + String pdeLine = pdeTabs[p.getTabIndex()] + .getText(pdeLineElement.getStartOffset(), pdeLineElement.getEndOffset() + - pdeLineElement.getStartOffset()); + log("calcPDEOffsetsForProbList(): P " + pdeLine); + log("calcPDEOffsetsForProbList(): J " + javaLine); + OffsetMatcher ofm = new OffsetMatcher(pdeLine, javaLine); //log(""); int pdeOffset = ofm.getPdeOffForJavaOff(prbStart - lineElement.getStartOffset(), (prbEnd - p diff --git a/src/processing/mode/experimental/Problem.java b/src/processing/mode/experimental/Problem.java index 1225238..4f7e9c4 100644 --- a/src/processing/mode/experimental/Problem.java +++ b/src/processing/mode/experimental/Problem.java @@ -89,10 +89,19 @@ public void setPDEOffsets(int startOffset, int stopOffset){ lineStartOffset = startOffset; lineStopOffset = stopOffset; } + + public int getPDELineStartOffset(){ + return lineStartOffset; + } + + public int getPDELineStopOffset(){ + return lineStopOffset; + } public String toString() { - return new String("TAB " + tabIndex + ",LN " + lineNumber + ",PROB: " - + message); + return new String("TAB " + tabIndex + ",LN " + lineNumber + "LN START OFF: " + + lineStartOffset + ",LN STOP OFF: " + lineStopOffset + ",PROB: " + + message); } public boolean isError(){ diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 8b7f5e9..4a5c628 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -314,7 +314,8 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { boolean notFound = true; boolean isWarning = false; - + Problem problem = null; + // Check if current line contains an error. If it does, find if it's an // error or warning for (ErrorMarker emarker : errorCheckerService.getEditor().errorBar.errorPoints) { @@ -323,6 +324,8 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { if (emarker.getType() == ErrorMarker.Warning) { isWarning = true; } + problem = emarker.getProblem(); + log(problem.toString()); break; } } @@ -337,15 +340,15 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { int y = ta.lineToY(line); y += fm.getLeading() + fm.getMaxDescent(); int height = fm.getHeight(); - int start = ta.getLineStartOffset(line); - + int start = ta.getLineStartOffset(line) + problem.getPDELineStartOffset(); + int pLength = problem.getPDELineStopOffset() + 1 + - problem.getPDELineStartOffset(); try { String linetext = null; try { - linetext = ta.getDocument().getText(start, - ta.getLineStopOffset(line) - start - - 1); + linetext = ta.getDocument().getText(start, pLength); + log("paintErrorLine() LineText: " + linetext); } catch (BadLocationException bl) { // Error in the import statements or end of code. // System.out.print("BL caught. " + ta.getLineCount() + " ," From e8bfb33ad6db1a52c4f959bb2ed6bf59dfbb5c83 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 00:43:32 +0530 Subject: [PATCH 183/193] precisise highlighting working only for specific compiler errors, needs more work --- .../experimental/ErrorCheckerService.java | 4 ++-- .../mode/experimental/TextAreaPainter.java | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 50e912c..89ca039 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -751,7 +751,7 @@ private void calcPDEOffsetsForProbList() { // Code in pde tabs stored as PlainDocument PlainDocument pdeTabs[] = new PlainDocument[editor.getSketch() .getCodeCount()]; - + log("calcPDEOffsetsForProbList() mco: " + mainClassOffset); try { javaSource.insertString(0, sourceCode, null); for (int i = 0; i < pdeTabs.length; i++) { @@ -803,7 +803,7 @@ private void calcPDEOffsetsForProbList() { .getIProblem().getSourceStart())); // astGenerator.highlightPDECode(p.getTabIndex(), p.getLineNumber(), // pdeOffset, (prbEnd - prbStart + 1)); - p.setPDEOffsets(pdeOffset, prbEnd - prbStart); + p.setPDEOffsets(pdeOffset, pdeOffset + prbEnd - prbStart); } } catch (BadLocationException e) { // TODO Auto-generated catch block diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 4a5c628..04714dd 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -325,7 +325,7 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { isWarning = true; } problem = emarker.getProblem(); - log(problem.toString()); + //log(problem.toString()); break; } } @@ -343,12 +343,16 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { int start = ta.getLineStartOffset(line) + problem.getPDELineStartOffset(); int pLength = problem.getPDELineStopOffset() + 1 - problem.getPDELineStartOffset(); + try { - String linetext = null; - + String badCode = null; + String goodCode = null; try { - linetext = ta.getDocument().getText(start, pLength); - log("paintErrorLine() LineText: " + linetext); + badCode = ta.getDocument().getText(start, pLength); + goodCode = ta.getDocument().getText(ta.getLineStartOffset(line), + problem.getPDELineStartOffset()); + //log("paintErrorLine() LineText GC: " + goodCode); + //log("paintErrorLine() LineText BC: " + badCode); } catch (BadLocationException bl) { // Error in the import statements or end of code. // System.out.print("BL caught. " + ta.getLineCount() + " ," @@ -358,11 +362,12 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { } // Take care of offsets - int aw = fm.stringWidth(trimRight(linetext)) + ta.getHorizontalOffset(); // apparent width. Whitespaces + int aw = fm.stringWidth(trimRight(badCode)) + ta.getHorizontalOffset(); // apparent width. Whitespaces // to the left of line + text // width - int rw = fm.stringWidth(linetext.trim()); // real width - int x1 = 0 + (aw - rw), y1 = y + fm.getHeight() - 2, x2 = x1 + rw; + int rw = fm.stringWidth(badCode.trim()); // real width + int x1 = fm.stringWidth(goodCode) + (aw - rw), y1 = y + fm.getHeight() + - 2, x2 = x1 + rw; // Adding offsets for the gutter x1 += ta.getGutterWidth(); x2 += ta.getGutterWidth(); From ecf071d617d521a8694ce26515aa8ac724a75255 Mon Sep 17 00:00:00 2001 From: Joel Moniz Date: Wed, 11 Jun 2014 00:59:18 +0530 Subject: [PATCH 184/193] More changes to auto-save Removing status notices --- .../mode/experimental/DebugEditor.java | 88 +++++++------------ 1 file changed, 32 insertions(+), 56 deletions(-) diff --git a/src/processing/mode/experimental/DebugEditor.java b/src/processing/mode/experimental/DebugEditor.java index 05bd025..7fa9713 100755 --- a/src/processing/mode/experimental/DebugEditor.java +++ b/src/processing/mode/experimental/DebugEditor.java @@ -1085,23 +1085,21 @@ public TextArea textArea() { return ta; } - private boolean wasSaved; - + /** * Grab current contents of the sketch window, advance the console, stop any * other running sketches, auto-save the user's code... not in that order. */ @Override public void prepareRun() { - wasSaved = false; autoSave(); super.prepareRun(); - if (wasSaved) - statusTimedNotice("Saved. Running...", 5); - else - statusTimedNotice("Not saved. Running...", 5); } + /** + * Displays a JDialog prompting the user to save when the user hits + * run/present/etc. + */ protected void autoSave() { if (!ExperimentalMode.autoSaveEnabled) return; @@ -1122,11 +1120,14 @@ protected void autoSave() { true); Container container = autoSaveDialog.getContentPane(); - JPanel panel = new JPanel(); - panel.setBorder(BorderFactory.createEmptyBorder(4, 0, 2, 2)); - panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); + JPanel panelMain = new JPanel(); + panelMain.setBorder(BorderFactory.createEmptyBorder(4, 0, + 2, 2)); + panelMain.setLayout(new BoxLayout(panelMain, + BoxLayout.PAGE_AXIS)); - JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); + JPanel panelLabel = new JPanel(new FlowLayout( + FlowLayout.LEFT)); JLabel label = new JLabel( " There are unsaved" + " changes in your sketch.
" @@ -1134,19 +1135,19 @@ protected void autoSave() { + " running? "); label.setFont(new Font(label.getFont().getName(), Font.PLAIN, label.getFont().getSize() + 1)); - panel1.add(label); - panel.add(panel1); + panelLabel.add(label); + panelMain.add(panelLabel); final JCheckBox dontRedisplay = new JCheckBox( "Remember this decision"); - panel1 = new JPanel(new FlowLayout(FlowLayout.CENTER, 8, 2)); - JButton button = new JButton("Save and Run"); - button.addActionListener(new ActionListener() { + JPanel panelButtons = new JPanel(new FlowLayout( + FlowLayout.CENTER, 8, 2)); + JButton btnRunSave = new JButton("Save and Run"); + btnRunSave.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (handleSave(true)) - wasSaved = true; + handleSave(true); if (dontRedisplay.isSelected()) { ExperimentalMode.autoSavePromptEnabled = !dontRedisplay .isSelected(); @@ -1156,9 +1157,9 @@ public void actionPerformed(ActionEvent e) { autoSaveDialog.dispose(); } }); - panel1.add(button); - button = new JButton("Run, Don't Save"); - button.addActionListener(new ActionListener() { + panelButtons.add(btnRunSave); + JButton btnRunNoSave = new JButton("Run, Don't Save"); + btnRunNoSave.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -1171,15 +1172,16 @@ public void actionPerformed(ActionEvent e) { autoSaveDialog.dispose(); } }); - panel1.add(button); - panel.add(panel1); + panelButtons.add(btnRunNoSave); + panelMain.add(panelButtons); - panel1 = new JPanel(); - panel1.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); - panel1.add(dontRedisplay); - panel.add(panel1); + JPanel panelCheck = new JPanel(); + panelCheck + .setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); + panelCheck.add(dontRedisplay); + panelMain.add(panelCheck); - container.add(panel); + container.add(panelMain); autoSaveDialog.setResizable(false); autoSaveDialog.pack(); @@ -1188,39 +1190,13 @@ public void actionPerformed(ActionEvent e) { autoSaveDialog.setVisible(true); } else if (ExperimentalMode.defaultAutoSaveEnabled) - if (handleSave(true)) - wasSaved = true; + handleSave(true); } } catch (Exception e) { statusError(e); } - } - - /** - * Shows a notice message in the editor status bar for a certain duration of - * time. - * - * @param msg - * @param secs - */ - public void statusTimedNotice(final String msg, final int secs) { - SwingWorker s = new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - statusNotice(msg); - try { - Thread.sleep(secs * 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - statusEmpty(); - return null; - } - }; - s.execute(); - } + } /** * Access variable inspector window. From 2eaf4acf751aa0bcf2dc3732224cb02ea18c1048 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 02:49:34 +0530 Subject: [PATCH 185/193] one simply doesn't have enough scrolling routines --- .../experimental/ErrorCheckerService.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 89ca039..3590c08 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1503,7 +1503,7 @@ public void scrollToErrorLine(int errorIndex) { // log("---"); }*/ - public void scrollToErrorLine(Problem p) { + /*public void scrollToErrorLine(Problem p) { if (editor == null) { return; } @@ -1517,7 +1517,7 @@ public void scrollToErrorLine(Problem p) { log("P start: " + prbStart + " to " + prbEnd + " pkgOffset " + pkgNameOffset); int lineNumber = p - .getIProblem().getSourceLineNumber(); + .getIProblem().getSourceLineNumber()-1; Element lineElement = astGenerator.getJavaSourceCodeElement(lineNumber); log("Line element off " + lineElement.getStartOffset()); OffsetMatcher ofm = new OffsetMatcher( @@ -1529,7 +1529,7 @@ public void scrollToErrorLine(Problem p) { int pdeOffset = ofm.getPdeOffForJavaOff(prbStart - lineElement.getStartOffset(), (prbEnd - p .getIProblem().getSourceStart())); - astGenerator.highlightPDECode(p.getTabIndex(), p.getLineNumber(), + astGenerator.highlightPDECode(p.getTabIndex(), p.getLineNumber()-1, pdeOffset, (prbEnd - prbStart + 1)); editor.getTextArea().scrollTo(p.getLineNumber() - 1, 0); editor.repaint(); @@ -1539,6 +1539,28 @@ public void scrollToErrorLine(Problem p) { e.printStackTrace(); } // log("---"); + }*/ + + public void scrollToErrorLine(Problem p) { + if (editor == null) { + return; + } + if (p == null) + return; + try { + astGenerator.highlightPDECode(p.getTabIndex(), + p.getLineNumber() - 1, + p.getPDELineStartOffset(), + (p.getPDELineStopOffset() + - p.getPDELineStartOffset() + 1)); + editor.getTextArea().scrollTo(p.getLineNumber() - 1, 0); + editor.repaint(); + } catch (Exception e) { + System.err.println(e + + " : Error while selecting text in scrollToErrorLine()"); + e.printStackTrace(); + } + // log("---"); } /** From f3330884c85211f24601d03a869f5d4ad157c8cc Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 03:06:38 +0530 Subject: [PATCH 186/193] declicate +1 -1 changes --- .../experimental/ErrorCheckerService.java | 42 +++++++++++-------- .../mode/experimental/TextAreaPainter.java | 2 +- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 3590c08..abcb5a1 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -463,8 +463,10 @@ protected boolean checkCode() { log(editor.getSketch().getName() + "2 MCO " + mainClassOffset); } + astGenerator.buildAST(cu); if(ExperimentalMode.errorCheckEnabled){ + calcPDEOffsetsForProbList(); updateErrorTable(); editor.updateErrorBar(problemsList); updateEditorStatus(); @@ -686,7 +688,10 @@ public boolean accept(File file) { ((Integer) errorList[i][4]).intValue(), ((Integer) errorList[i][5]).intValue(), ((Integer) errorList[i][6]).intValue(), - ((Integer) errorList[i][7]).intValue(), 0); + ((Integer) errorList[i][7]).intValue() - 1, 0); + // added a -1 to line number because in compile check code + // an extra package statement is added, so all line numbers + // are increased by 1 // System.out // .println("ECS: " + problems[i].getMessage() + "," @@ -715,7 +720,6 @@ public boolean accept(File file) { } problemsList.add(p); } - calcPDEOffsetsForProbList(); } } catch (ClassNotFoundException e) { System.err.println("Compiltation Checker files couldn't be found! " @@ -747,12 +751,14 @@ public boolean accept(File file) { * Calculates PDE Offsets from Java Offsets for Problems */ private void calcPDEOffsetsForProbList() { - PlainDocument javaSource = new PlainDocument(); - // Code in pde tabs stored as PlainDocument - PlainDocument pdeTabs[] = new PlainDocument[editor.getSketch() - .getCodeCount()]; - log("calcPDEOffsetsForProbList() mco: " + mainClassOffset); - try { + try { + PlainDocument javaSource = new PlainDocument(); + // Code in pde tabs stored as PlainDocument + PlainDocument pdeTabs[] = new PlainDocument[editor.getSketch() + .getCodeCount()]; + log("calcPDEOffsetsForProbList() mco: " + mainClassOffset + " CU state: " + + compilationUnitState); + javaSource.insertString(0, sourceCode, null); for (int i = 0; i < pdeTabs.length; i++) { SketchCode sc = editor.getSketch().getCode(i); @@ -771,9 +777,10 @@ private void calcPDEOffsetsForProbList() { } int pkgNameOffset = ("package " + className + ";\n").length(); for (Problem p : problemsList) { - int javaLineNumber = p.getIProblem().getSourceLineNumber(); + log(p.toString()); + int javaLineNumber = p.getIProblem().getSourceLineNumber() - 1; Element lineElement = javaSource.getDefaultRootElement() - .getElement(javaLineNumber - 2); + .getElement(javaLineNumber); if (lineElement == null) { log("calcPDEOffsetsForProbList(): Couldn't fetch javalinenum " + javaLineNumber); @@ -785,7 +792,7 @@ private void calcPDEOffsetsForProbList() { int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset, prbEnd = p .getIProblem().getSourceEnd() - pkgNameOffset; Element pdeLineElement = pdeTabs[p.getTabIndex()] - .getDefaultRootElement().getElement(p.getLineNumber()-1); + .getDefaultRootElement().getElement(p.getLineNumber()); if (pdeLineElement == null) { log("calcPDEOffsetsForProbList(): Couldn't fetch pdelinenum " + javaLineNumber); @@ -794,8 +801,8 @@ private void calcPDEOffsetsForProbList() { String pdeLine = pdeTabs[p.getTabIndex()] .getText(pdeLineElement.getStartOffset(), pdeLineElement.getEndOffset() - pdeLineElement.getStartOffset()); - log("calcPDEOffsetsForProbList(): P " + pdeLine); - log("calcPDEOffsetsForProbList(): J " + javaLine); + //log("calcPDEOffsetsForProbList(): P " + pdeLine); + //log("calcPDEOffsetsForProbList(): J " + javaLine); OffsetMatcher ofm = new OffsetMatcher(pdeLine, javaLine); //log(""); int pdeOffset = ofm.getPdeOffForJavaOff(prbStart @@ -805,8 +812,9 @@ private void calcPDEOffsetsForProbList() { // pdeOffset, (prbEnd - prbStart + 1)); p.setPDEOffsets(pdeOffset, pdeOffset + prbEnd - prbStart); } - } catch (BadLocationException e) { - // TODO Auto-generated catch block + } catch (BadLocationException ble) { + ble.printStackTrace(); + } catch (Exception e) { e.printStackTrace(); } } @@ -1549,11 +1557,11 @@ public void scrollToErrorLine(Problem p) { return; try { astGenerator.highlightPDECode(p.getTabIndex(), - p.getLineNumber() - 1, + p.getLineNumber(), p.getPDELineStartOffset(), (p.getPDELineStopOffset() - p.getPDELineStartOffset() + 1)); - editor.getTextArea().scrollTo(p.getLineNumber() - 1, 0); + editor.getTextArea().scrollTo(p.getLineNumber(), 0); editor.repaint(); } catch (Exception e) { System.err.println(e diff --git a/src/processing/mode/experimental/TextAreaPainter.java b/src/processing/mode/experimental/TextAreaPainter.java index 04714dd..4961510 100644 --- a/src/processing/mode/experimental/TextAreaPainter.java +++ b/src/processing/mode/experimental/TextAreaPainter.java @@ -319,7 +319,7 @@ protected void paintErrorLine(Graphics gfx, int line, int x) { // Check if current line contains an error. If it does, find if it's an // error or warning for (ErrorMarker emarker : errorCheckerService.getEditor().errorBar.errorPoints) { - if (emarker.getProblem().getLineNumber() == line + 1) { + if (emarker.getProblem().getLineNumber() == line) { notFound = false; if (emarker.getType() == ErrorMarker.Warning) { isWarning = true; From 0528fb3613408c6cf4ebabf85754c6ed90795d28 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 03:13:39 +0530 Subject: [PATCH 187/193] no more cheeky stuff --- .../mode/experimental/ErrorCheckerService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index abcb5a1..a6e936d 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -540,8 +540,7 @@ protected void syntaxCheck() { problemsList = new ArrayList(); for (int i = 0; i < problems.length; i++) { int a[] = calculateTabIndexAndLineNumber(problems[i].getSourceLineNumber()); - Problem p = new Problem(problems[i], a[0], a[1] + 1); - //TODO: ^Why do cheeky stuff? + Problem p = new Problem(problems[i], a[0], a[1]); problemsList.add(p); // log(problems[i].getMessage()); // for (String j : problems[i].getArguments()) { @@ -777,7 +776,10 @@ private void calcPDEOffsetsForProbList() { } int pkgNameOffset = ("package " + className + ";\n").length(); for (Problem p : problemsList) { + int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset, prbEnd = p + .getIProblem().getSourceEnd() - pkgNameOffset; log(p.toString()); + log("IProblem Start " + prbStart + ", End " + prbEnd); int javaLineNumber = p.getIProblem().getSourceLineNumber() - 1; Element lineElement = javaSource.getDefaultRootElement() .getElement(javaLineNumber); @@ -789,8 +791,7 @@ private void calcPDEOffsetsForProbList() { String javaLine = javaSource .getText(lineElement.getStartOffset(), lineElement.getEndOffset() - lineElement.getStartOffset()); - int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset, prbEnd = p - .getIProblem().getSourceEnd() - pkgNameOffset; + Element pdeLineElement = pdeTabs[p.getTabIndex()] .getDefaultRootElement().getElement(p.getLineNumber()); if (pdeLineElement == null) { @@ -806,8 +807,7 @@ private void calcPDEOffsetsForProbList() { OffsetMatcher ofm = new OffsetMatcher(pdeLine, javaLine); //log(""); int pdeOffset = ofm.getPdeOffForJavaOff(prbStart - - lineElement.getStartOffset(), (prbEnd - p - .getIProblem().getSourceStart())); + - lineElement.getStartOffset(), (prbEnd - prbStart + 1)); // astGenerator.highlightPDECode(p.getTabIndex(), p.getLineNumber(), // pdeOffset, (prbEnd - prbStart + 1)); p.setPDEOffsets(pdeOffset, pdeOffset + prbEnd - prbStart); From 8115c9873136293b3f07a8e43fa5c41fff4f1af5 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 03:17:53 +0530 Subject: [PATCH 188/193] should've done it like this --- src/processing/mode/experimental/ErrorCheckerService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index a6e936d..7e4280d 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1010,7 +1010,8 @@ public void updateErrorTable() { //+ " : " + errorMsgSimplifier.getIDName(problemsList.get(i).getIProblem().getID()); errorData[i][1] = editor.getSketch() .getCode(problemsList.get(i).getTabIndex()).getPrettyName(); - errorData[i][2] = problemsList.get(i).getLineNumber() + ""; + errorData[i][2] = (problemsList.get(i).getLineNumber() + 1) + ""; + // Added +1 because lineNumbers internally are 0-indexed //TODO: This is temporary if (tempErrorLog.size() < 200) From ddceda2e07aa37e077d276aa6d03e6845bbf4994 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 03:29:57 +0530 Subject: [PATCH 189/193] precise error highlighting. Nailed it \m/ --- src/processing/mode/experimental/ErrorCheckerService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index 7e4280d..a8ba5e9 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -775,6 +775,9 @@ private void calcPDEOffsetsForProbList() { } } int pkgNameOffset = ("package " + className + ";\n").length(); + // package name is added only during compile check + if(compilationUnitState != 2) pkgNameOffset = 0; + for (Problem p : problemsList) { int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset, prbEnd = p .getIProblem().getSourceEnd() - pkgNameOffset; @@ -1086,7 +1089,7 @@ public void updateEditorStatus() { synchronized (editor.errorBar.errorPoints) { for (ErrorMarker emarker : editor.errorBar.errorPoints) { if (emarker.getProblem().getLineNumber() == editor.getTextArea() - .getCaretLine() + 1) { + .getCaretLine()) { if (emarker.getType() == ErrorMarker.Warning) { editor.statusMessage(emarker.getProblem().getMessage(), DebugEditor.STATUS_INFO); From 437244ea95119bba3963a45049b407f3ea981c43 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 03:34:49 +0530 Subject: [PATCH 190/193] updated todo --- todo.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/todo.txt b/todo.txt index d7a2337..c177853 100644 --- a/todo.txt +++ b/todo.txt @@ -31,6 +31,10 @@ happening due certain post processing offsets not being accounted for - "public Enhancements/New Features ------------------------- +-[x] Precise error highlighting(PEH). Now working for one error per line. Hell yeah! + +-[ ] Gotta fix PEH for multiple errors per line. Will be slightly meticulous. + -[ ] When viewing Outline View, instead of showing the beginning of the list, it should select the current node element within which the cursor is presently positioned. @@ -42,3 +46,5 @@ positioned. -[ ] Preferences panel -[ ] Line Numbers + + From ffe9159d0a70ef673b664f68ab13e5e2192dc42b Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Wed, 11 Jun 2014 03:35:27 +0530 Subject: [PATCH 191/193] sweet joys of trimming code --- .../experimental/ErrorCheckerService.java | 65 ------------------- 1 file changed, 65 deletions(-) diff --git a/src/processing/mode/experimental/ErrorCheckerService.java b/src/processing/mode/experimental/ErrorCheckerService.java index a8ba5e9..61cc974 100644 --- a/src/processing/mode/experimental/ErrorCheckerService.java +++ b/src/processing/mode/experimental/ErrorCheckerService.java @@ -1488,71 +1488,6 @@ public void scrollToErrorLine(int errorIndex) { } } - /*public void scrollToErrorLine(Problem p) { - if (editor == null) { - return; - } - if (p == null) - return; - try { - editor.toFront(); - editor.getSketch().setCurrentCode(p.getTabIndex()); - - editor - .setSelection(editor.getTextArea() - .getLineStartNonWhiteSpaceOffset(p.getLineNumber() - 1) - + editor.getTextArea() - .getLineText(p.getLineNumber() - 1).trim().length(), - editor.getTextArea() - .getLineStartNonWhiteSpaceOffset(p.getLineNumber() - 1)); - editor.getTextArea().scrollTo(p.getLineNumber() - 1, 0); - editor.repaint(); - } catch (Exception e) { - System.err.println(e - + " : Error while selecting text in scrollToErrorLine()"); - e.printStackTrace(); - } - // log("---"); - }*/ - - /*public void scrollToErrorLine(Problem p) { - if (editor == null) { - return; - } - if (p == null) - return; - try { - int pkgNameOffset = ("package " + className + ";\n").length(); - int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset, prbEnd = p - .getIProblem().getSourceEnd() - pkgNameOffset; - log("Scrolling to problem: " + p.toString()); - log("P start: " + prbStart + " to " - + prbEnd + " pkgOffset " + pkgNameOffset); - int lineNumber = p - .getIProblem().getSourceLineNumber()-1; - Element lineElement = astGenerator.getJavaSourceCodeElement(lineNumber); - log("Line element off " + lineElement.getStartOffset()); - OffsetMatcher ofm = new OffsetMatcher( - astGenerator - .getPDESourceCodeLine(lineNumber), - astGenerator - .getJavaSourceCodeLine(lineNumber)); - //log(""); - int pdeOffset = ofm.getPdeOffForJavaOff(prbStart - - lineElement.getStartOffset(), (prbEnd - p - .getIProblem().getSourceStart())); - astGenerator.highlightPDECode(p.getTabIndex(), p.getLineNumber()-1, - pdeOffset, (prbEnd - prbStart + 1)); - editor.getTextArea().scrollTo(p.getLineNumber() - 1, 0); - editor.repaint(); - } catch (Exception e) { - System.err.println(e - + " : Error while selecting text in scrollToErrorLine()"); - e.printStackTrace(); - } - // log("---"); - }*/ - public void scrollToErrorLine(Problem p) { if (editor == null) { return; From 786f26f263eb062e9d327fbc300ae970064b1784 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Thu, 12 Jun 2014 19:24:14 +0530 Subject: [PATCH 192/193] tracking build props file again --- build.properties | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build.properties b/build.properties index 4dfc002..ed26d76 100644 --- a/build.properties +++ b/build.properties @@ -1,10 +1,10 @@ -sketchbook.location= -classpath.local.location= -core.library.location= -app.library.location= -java.target.version=1.6 +sketchbook.location=${user.home}/Documents/Processing +classpath.local.location=${user.home}/Documents/workspace/libs +core.library.location=/home/quarkninja/Workspaces/processing-workspace/processing/app/core/library +app.library.location=/home/quarkninja/Workspaces/processing-workspace/processing/app/ +java.target.version=1.7 lib.name=ExperimentalMode prettyName=PDE X dist=dist -release=3 -prettyVersion=1.0.0b +release=7 +prettyVersion=1.0.4b From 2efe9b256724e1b13baf0f6e1b1074305d79ec47 Mon Sep 17 00:00:00 2001 From: Manindra Moharana Date: Sun, 21 Sep 2014 10:00:14 -0700 Subject: [PATCH 193/193] updated readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b536249..a49be85 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**Update**: This repo is no longer active. PDE X codebase was merged into the [main processing repo](https://github.com/processing/processing/) starting with the 3.0 alpha releases (July 2014), further development continues in the main repo. So please report any issues in the main Processing repo. + PDE X =====