diff --git a/pdex/Todo, GSoC 2013.txt b/pdex/Todo, GSoC 2013.txt index 03b0cdbdd..8ee9a09e6 100644 --- a/pdex/Todo, GSoC 2013.txt +++ b/pdex/Todo, GSoC 2013.txt @@ -11,11 +11,14 @@ Code Completion The big stuff: 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. +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. *! Recursive lookup for compiled(library) code! *! 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. -*! May be I should just implement recursive find for compiled code first, see how it goes and hopefully it would give me some ideas about how to integrating the two. +*! May be I should just implement recursive find for compiled code first, see how it goes and hopefully it would give me some ideas about how to integrating the two. + - Making very good progress here. The elegance of recurion - Hats off! x! Should I implement wrapper for ASTNode? - possibly needed for code completion with compiled and non-compiled code. Done. * Trie implementation would be lower priority, "premature optimisation is pure evil". Get all features of CC working good enough and then plan this. x Differentiating between multiple statements on the same line. How to? Done with offset handling. diff --git a/pdex/src/processing/mode/experimental/ASTGenerator.java b/pdex/src/processing/mode/experimental/ASTGenerator.java index cd970418f..be1e636ad 100644 --- a/pdex/src/processing/mode/experimental/ASTGenerator.java +++ b/pdex/src/processing/mode/experimental/ASTGenerator.java @@ -669,11 +669,29 @@ public class ASTGenerator { return ((FieldAccess) expression).getName(); } else if (expression instanceof QualifiedName) { return ((QualifiedName) expression).getName(); + }else if (expression instanceof MethodInvocation) { + return ((MethodInvocation) expression).getName(); } System.out.println(" resolveChildExpression returning NULL for " + getNodeAsString(expression)); return null; } + + public static ASTNode resolveParentExpression(ASTNode expression) { +// ASTNode anode = null; + if (expression instanceof SimpleName) { + return expression; + } else if (expression instanceof FieldAccess) { + return ((FieldAccess) expression).getExpression(); + } else if (expression instanceof QualifiedName) { + return ((QualifiedName) expression).getQualifier(); + } else if (expression instanceof MethodInvocation) { + return ((MethodInvocation) expression).getExpression(); + } + System.out.println("resolveParentExpression returning NULL for " + + getNodeAsString(expression)); + return null; +} public static TypeDeclaration getDefiningNode(ASTNode node) { ASTNode parent = node.getParent(); @@ -685,7 +703,7 @@ public class ASTGenerator { return (TypeDeclaration) parent; } - public void updatePredictions(final String word, final int line) { + public void updatePredictions(final String word, final int line, final int lineStartNonWSOffset) { SwingWorker worker = new SwingWorker() { @Override @@ -695,16 +713,16 @@ public class ASTGenerator { protected void done() { - String word2 = word; + String word2 = ASTNodeWrapper.getJavaCode(word); //After typing 'arg.' all members of arg type are to be listed. This one is a flag for it boolean noCompare = false; if (word2.endsWith(".")) { // return all matches - word2 = word2.substring(0, word.length() - 1); + word2 = word2.substring(0, word2.length() - 1); noCompare = true; } - + int lineNumber = line; // Adjust line number for tabbed sketches if (errorCheckerService != null) { @@ -726,7 +744,7 @@ public class ASTGenerator { parser.setKind(ASTParser.K_EXPRESSION); parser.setSource(word2.toCharArray()); ASTNode testnode = parser.createAST(null); - + //System.err.println("PREDICTION PARSER PROBLEMS: " + parser); // Find closest ASTNode of the document to this word System.err.print("Typed: " + word2 + "|"); nearestNode = findClosestNode(lineNumber, (ASTNode) compilationUnit.types() @@ -912,10 +930,17 @@ public class ASTGenerator { } if(candidates.size() == 0){ System.out.println("candidates empty"); - ClassMember expr = resolveExpression3rdParty(nearestNode, testnode, true); + String childExpr = resolveChildExpression(testnode) + .toString(); + System.out.println("Child expression : " + childExpr); + if(!noCompare){ + System.out.println("Original testnode " + getNodeAsString(testnode)); + testnode = resolveParentExpression(testnode); + System.out.println("Corrected testnode " + getNodeAsString(testnode)); + } + ClassMember expr = resolveExpression3rdParty(nearestNode, testnode, noCompare); candidates = getMembersForType(expr, - resolveChildExpression(testnode) - .toString(), true, false); + childExpr, noCompare, false); } } @@ -1201,7 +1226,7 @@ public class ASTGenerator { private static ASTNode findClosestParentNode(int lineNumber, ASTNode node) { Iterator it = node .structuralPropertiesForType().iterator(); - //System.err.println("Props of " + node.getClass().getName()); + System.err.println("Props of " + node.getClass().getName()); while (it.hasNext()) { StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it .next(); @@ -1212,7 +1237,7 @@ public class ASTGenerator { // .println(node.getStructuralProperty(prop) + " -> " + (prop)); if (node.getStructuralProperty(prop) instanceof ASTNode) { ASTNode cnode = (ASTNode) node.getStructuralProperty(prop); -// System.out.println("Looking at " + getNodeAsString(cnode)); +// System.out.println("Looking at " + getNodeAsString(cnode)+ " for line num " + lineNumber); int cLineNum = ((CompilationUnit) cnode.getRoot()) .getLineNumber(cnode.getStartPosition() + cnode.getLength()); if (getLineNumber(cnode) <= lineNumber && lineNumber <= cLineNum) { @@ -1228,7 +1253,7 @@ public class ASTGenerator { for (ASTNode cnode : nodelist) { int cLineNum = ((CompilationUnit) cnode.getRoot()) .getLineNumber(cnode.getStartPosition() + cnode.getLength()); -// System.out.println("Looking at " + getNodeAsString(cnode)); +// System.out.println("Looking at " + getNodeAsString(cnode)+ " for line num " + lineNumber); if (getLineNumber(cnode) <= lineNumber && lineNumber <= cLineNum) { return findClosestParentNode(lineNumber, cnode); } @@ -1272,81 +1297,6 @@ public class ASTGenerator { return null; } -// static DefaultMutableTreeNode findNodeBS(DefaultMutableTreeNode tree, -// int lineNumber, String name, -// int elementOffset) { -// if (tree.getUserObject() == null) -// return null; -// -// ASTNodeWrapper node = ((ASTNodeWrapper) tree.getUserObject()); -// -// if (node.getLineNumber() == lineNumber) { -// System.out.println("Located line " + lineNumber + " , " + tree); -// if (name == null) -// return tree; -// else -// return findOnLine(tree, lineNumber, name, elementOffset, node.getNode() -// .getStartPosition()); -// } -// -// int low = 0, high = tree.getChildCount() - 1, mid = (high + low) / 2; -// DefaultMutableTreeNode tnode = null; -// while (low <= high) { -// mid = (high + low) / 2; -// tnode = (DefaultMutableTreeNode) tree.getChildAt(mid); -// node = ((ASTNodeWrapper) tnode.getUserObject()); -// if (node.getLineNumber() == lineNumber) { -// System.out.println("Located line " + lineNumber + " , " + tnode); -// if (name == null) -// return tnode; -// else -// return findOnLine(tnode, lineNumber, name, elementOffset, node -// .getNode().getStartPosition()); -// } else if (lineNumber < node.getLineNumber()) { -// high = mid - 1; -// } else { -// if (high - mid <= 1) { -// if (lineNumber > ((ASTNodeWrapper) ((DefaultMutableTreeNode) tree -// .getChildAt(high)).getUserObject()).getLineNumber()) //high l no. -// low = mid + 1; -// else -// -// high = mid - 1; -// } -// low = mid + 1; -// } -// -// } -// -// if (!tnode.isLeaf()) -// return findNodeBS(tnode, lineNumber, name, elementOffset); -// else -// return tnode; -// -// //System.out.println("visiting: " + getNodeAsString(node.getNode()) + " on line "+node.getLineNumber()); -// if (node.getLineNumber() == lineNumber) { -// System.err.println("Located line: " + node.toString()); -// if (name == null) // name ==null, finds any node equal to line -// // number -// { -// System.out.println("Closest node at line: " + lineNumber); -// return tree; -// } else -// return findOnLine(tree, lineNumber, name, elementOffset, node.getNode() -// .getStartPosition()); -// -// } else if (!tree.isLeaf()) { -// for (int i = 0; i < tree.getChildCount(); i++) { -// .getChildAt(i), -// lineNumber, name, elementOffset); -// if (node2 != null) -// return node2; -// } -// } -// -// return null; -// } - public DefaultMutableTreeNode getAST() { return codeTree; } diff --git a/pdex/src/processing/mode/experimental/ASTNodeWrapper.java b/pdex/src/processing/mode/experimental/ASTNodeWrapper.java index 359d3d4e2..31c902171 100644 --- a/pdex/src/processing/mode/experimental/ASTNodeWrapper.java +++ b/pdex/src/processing/mode/experimental/ASTNodeWrapper.java @@ -373,6 +373,72 @@ public class ASTNodeWrapper { public int getLineNumber() { return lineNumber; } + + /** + * Applies pde enhancements to code. + * TODO: Code reuse happening here. :\ + * @param source + * @return + */ + public static String getJavaCode(String source){ + System.out.println("Src:" + source); + String sourceAlt = new String(source); + + // Find all #[web color] + // Should be 6 digits only. + final String webColorRegexp = "#{1}[A-F|a-f|0-9]{6}\\W"; + Pattern webPattern = Pattern.compile(webColorRegexp); + Matcher webMatcher = webPattern.matcher(sourceAlt); + while (webMatcher.find()) { + // System.out.println("Found at: " + webMatcher.start()); + // System.out.println("-> " + found); + } + + // Find all color data types + final String colorTypeRegex = "color(?![a-zA-Z0-9_])(?=\\[*)(?!(\\s*\\())"; + Pattern colorPattern = Pattern.compile(colorTypeRegex); + Matcher colorMatcher = colorPattern.matcher(sourceAlt); + while (colorMatcher.find()) { +// System.out.print("Start index: " + colorMatcher.start()); +// System.out.println(" End index: " + colorMatcher.end() + " "); +// System.out.println("-->" + colorMatcher.group() + "<--"); + } + + // Find all int(), char() + String dataTypeFunc[] = { "int", "char", "float", "boolean", "byte" }; + + for (String dataType : dataTypeFunc) { + String dataTypeRegexp = "\\b" + dataType + "\\s*\\("; + Pattern pattern = Pattern.compile(dataTypeRegexp); + Matcher matcher = pattern.matcher(sourceAlt); + + while (matcher.find()) { +// System.out.print("Start index: " + matcher.start()); +// System.out.println(" End index: " + matcher.end() + " "); +// System.out.println("-->" + matcher.group() + "<--"); + } + matcher.reset(); + sourceAlt = matcher.replaceAll("PApplet.parse" + + Character.toUpperCase(dataType.charAt(0)) + dataType.substring(1) + + "("); + + } + // replace with 0xff[webcolor] and others + webMatcher = webPattern.matcher(sourceAlt); + while (webMatcher.find()) { + // System.out.println("Found at: " + webMatcher.start()); + String found = sourceAlt.substring(webMatcher.start(), webMatcher.end()); + // System.out.println("-> " + found); + sourceAlt = webMatcher.replaceFirst("0xff" + found.substring(1)); + webMatcher = webPattern.matcher(sourceAlt); + } + + colorMatcher = colorPattern.matcher(sourceAlt); + sourceAlt = colorMatcher.replaceAll("int"); + + System.out.println("Converted:"+sourceAlt); + return sourceAlt; + } private static int getLineNumber(ASTNode node) { return ((CompilationUnit) node.getRoot()).getLineNumber(node diff --git a/pdex/src/processing/mode/experimental/TextArea.java b/pdex/src/processing/mode/experimental/TextArea.java index ef027771c..2da36972f 100644 --- a/pdex/src/processing/mode/experimental/TextArea.java +++ b/pdex/src/processing/mode/experimental/TextArea.java @@ -290,7 +290,7 @@ public class TextArea extends JEditTextArea { if (word.endsWith(".")) word = word.substring(0, word.length() - 1); errorCheckerService.astGenerator.updatePredictions(word, line - + errorCheckerService.mainClassOffset); + + errorCheckerService.mainClassOffset,0); return word; } // if (keyChar == KeyEvent.VK_BACK_SPACE || keyChar == KeyEvent.VK_DELETE) @@ -353,8 +353,9 @@ public class TextArea extends JEditTextArea { word = word.trim(); // if (word.endsWith(".")) // word = word.substring(0, word.length() - 1); + int lineStartNonWSOffset = 0; errorCheckerService.astGenerator.updatePredictions(word, line - + errorCheckerService.mainClassOffset); + + errorCheckerService.mainClassOffset,lineStartNonWSOffset); //showSuggestionLater(); return word;