diff --git a/pdex/.project b/pdex/.project
index 1be6ebc0c..dd2d29121 100644
--- a/pdex/.project
+++ b/pdex/.project
@@ -10,6 +10,16 @@
+
+ org.eclipse.ui.externaltools.ExternalToolBuilder
+ full,incremental,
+
+
+ LaunchConfigHandle
+ <project>/.externalToolBuilders/processing-experimental build.xml [Builder] (1).launch
+
+
+
org.eclipse.jdt.core.javanature
diff --git a/pdex/build.xml b/pdex/build.xml
index 2e0f18baa..489c3f93d 100644
--- a/pdex/build.xml
+++ b/pdex/build.xml
@@ -56,4 +56,10 @@
+
+
+
+
+
+
diff --git a/pdex/src/processing/mode/experimental/ASTGenerator.java b/pdex/src/processing/mode/experimental/ASTGenerator.java
new file mode 100644
index 000000000..03841481e
--- /dev/null
+++ b/pdex/src/processing/mode/experimental/ASTGenerator.java
@@ -0,0 +1,1509 @@
+package processing.mode.experimental;
+
+import java.awt.Rectangle;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTree;
+import javax.swing.SwingWorker;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.ArrayAccess;
+import org.eclipse.jdt.core.dom.ArrayCreation;
+import org.eclipse.jdt.core.dom.ArrayInitializer;
+import org.eclipse.jdt.core.dom.ArrayType;
+import org.eclipse.jdt.core.dom.Assignment;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.BodyDeclaration;
+import org.eclipse.jdt.core.dom.BooleanLiteral;
+import org.eclipse.jdt.core.dom.BreakStatement;
+import org.eclipse.jdt.core.dom.CastExpression;
+import org.eclipse.jdt.core.dom.CatchClause;
+import org.eclipse.jdt.core.dom.CharacterLiteral;
+import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.ConditionalExpression;
+import org.eclipse.jdt.core.dom.ConstructorInvocation;
+import org.eclipse.jdt.core.dom.ContinueStatement;
+import org.eclipse.jdt.core.dom.DoStatement;
+import org.eclipse.jdt.core.dom.EnhancedForStatement;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.ExpressionStatement;
+import org.eclipse.jdt.core.dom.FieldAccess;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.ForStatement;
+import org.eclipse.jdt.core.dom.IfStatement;
+import org.eclipse.jdt.core.dom.InfixExpression;
+import org.eclipse.jdt.core.dom.Initializer;
+import org.eclipse.jdt.core.dom.InstanceofExpression;
+import org.eclipse.jdt.core.dom.Javadoc;
+import org.eclipse.jdt.core.dom.LineComment;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.MethodInvocation;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.NodeFinder;
+import org.eclipse.jdt.core.dom.NumberLiteral;
+import org.eclipse.jdt.core.dom.ParameterizedType;
+import org.eclipse.jdt.core.dom.ParenthesizedExpression;
+import org.eclipse.jdt.core.dom.PostfixExpression;
+import org.eclipse.jdt.core.dom.PrefixExpression;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.QualifiedName;
+import org.eclipse.jdt.core.dom.ReturnStatement;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.dom.SimpleType;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.Statement;
+import org.eclipse.jdt.core.dom.StringLiteral;
+import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
+import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
+import org.eclipse.jdt.core.dom.SuperFieldAccess;
+import org.eclipse.jdt.core.dom.SuperMethodInvocation;
+import org.eclipse.jdt.core.dom.SwitchCase;
+import org.eclipse.jdt.core.dom.SwitchStatement;
+import org.eclipse.jdt.core.dom.SynchronizedStatement;
+import org.eclipse.jdt.core.dom.ThrowStatement;
+import org.eclipse.jdt.core.dom.TryStatement;
+import org.eclipse.jdt.core.dom.Type;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
+import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
+import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
+import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
+import org.eclipse.jdt.core.dom.WhileStatement;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
+
+
+import processing.app.Base;
+import processing.app.SketchCode;
+import processing.app.syntax.InputHandler.clipboard_copy;
+
+public class ASTGenerator {
+
+ protected ErrorCheckerService errorCheckerService;
+
+ protected DebugEditor editor;
+
+ public DefaultMutableTreeNode codeTree = new DefaultMutableTreeNode();
+
+ private DefaultMutableTreeNode currentParent = null;
+
+ private JFrame frame2, frameAutoComp;
+
+ private JTree jtree;
+
+ private CompilationUnit compilationUnit;
+
+ private JTable tableAuto;
+
+ public ASTGenerator(ErrorCheckerService ecs) {
+ this.errorCheckerService = ecs;
+ this.editor = ecs.getEditor();
+ frame2 = new JFrame();
+
+ jtree = new JTree();
+ frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ frame2.setBounds(new Rectangle(100, 100, 460, 620));
+ JScrollPane sp = new JScrollPane();
+ sp.setViewportView(jtree);
+ frame2.add(sp);
+
+ frameAutoComp = new JFrame();
+ frameAutoComp.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ frameAutoComp.setBounds(new Rectangle(1280, 100, 460, 620));
+ tableAuto = new JTable();
+ JScrollPane sp2 = new JScrollPane();
+ sp2.setViewportView(tableAuto);
+ frameAutoComp.add(sp2);
+
+ }
+
+ public class ASTNodeWrapper {
+ private ASTNode node;
+
+ private String label;
+
+ private int lineNumber;
+
+ private int apiLevel;
+
+ public ASTNodeWrapper(ASTNode node) {
+ if (node == null)
+ return;
+ this.node = node;
+ label = getNodeAsString(node);
+ if (label == null)
+ label = node.toString();
+ lineNumber = compilationUnit.getLineNumber(node.getStartPosition());
+ label += " | Line " + lineNumber;
+ apiLevel = 0;
+ }
+
+ public String toString() {
+ return label;
+ }
+
+ public ASTNode getNode() {
+ return node;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public int getNodeType() {
+ return node.getNodeType();
+ }
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
+ }
+
+ private DefaultMutableTreeNode buildAST2(String source) {
+ ASTParser parser = ASTParser.newParser(AST.JLS4);
+ parser.setSource(source.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);
+ parser.setCompilerOptions(options);
+ compilationUnit = (CompilationUnit) parser.createAST(null);
+// OutlineVisitor visitor = new OutlineVisitor();
+// compilationUnit.accept(visitor);
+ codeTree = new DefaultMutableTreeNode(
+ getNodeAsString((ASTNode) compilationUnit
+ .types().get(0)));
+ visitRecur((ASTNode) compilationUnit.types().get(0), codeTree);
+ SwingWorker worker = new SwingWorker() {
+
+ @Override
+ protected Object doInBackground() throws Exception {
+ return null;
+ }
+
+ 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 (!frameAutoComp.isVisible())
+ frameAutoComp.setVisible(true);
+ jtree.validate();
+ }
+ }
+ };
+ worker.execute();
+
+ return codeTree;
+ }
+
+ public DefaultMutableTreeNode buildAST() {
+ return buildAST2(errorCheckerService.sourceCode);
+ }
+
+ public String[] checkForTypes2(ASTNode node) {
+
+ List vdfs = null;
+ switch (node.getNodeType()) {
+ case ASTNode.TYPE_DECLARATION:
+ return new String[] { ((TypeDeclaration) node).getName().toString() };
+
+ case ASTNode.METHOD_DECLARATION:
+ String[] ret1 = new String[] { ((MethodDeclaration) node).getName()
+ .toString() };
+ return ret1;
+
+ case ASTNode.SINGLE_VARIABLE_DECLARATION:
+ return new String[] { ((SingleVariableDeclaration) node).getName()
+ .toString() };
+
+ case ASTNode.FIELD_DECLARATION:
+ vdfs = ((FieldDeclaration) node).fragments();
+ break;
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+ vdfs = ((VariableDeclarationStatement) node).fragments();
+ break;
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
+ vdfs = ((VariableDeclarationExpression) node).fragments();
+ break;
+ default:
+ break;
+ }
+
+ if (vdfs != null) {
+ String ret[] = new String[vdfs.size()];
+ int i = 0;
+ for (VariableDeclarationFragment vdf : vdfs) {
+ ret[i++] = vdf.getName().toString();
+ }
+ return ret;
+ }
+
+ return null;
+ }
+
+ public static String[] checkForTypes(ASTNode node) {
+
+ List vdfs = null;
+ switch (node.getNodeType()) {
+ case ASTNode.TYPE_DECLARATION:
+ return new String[] { getNodeAsString(node) };
+
+ case ASTNode.METHOD_DECLARATION:
+ String[] ret1 = new String[] { getNodeAsString(node) };
+ return ret1;
+
+ case ASTNode.SINGLE_VARIABLE_DECLARATION:
+ return new String[] { getNodeAsString(node) };
+
+ case ASTNode.FIELD_DECLARATION:
+ vdfs = ((FieldDeclaration) node).fragments();
+ break;
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+ vdfs = ((VariableDeclarationStatement) node).fragments();
+ break;
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
+ vdfs = ((VariableDeclarationExpression) node).fragments();
+ break;
+ default:
+ break;
+ }
+
+ if (vdfs != null) {
+ String ret[] = new String[vdfs.size()];
+ int i = 0;
+ for (VariableDeclarationFragment vdf : vdfs) {
+ ret[i++] = getNodeAsString(vdf);
+ }
+ return ret;
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ArrayList getNameIfType(ASTNode astnode) {
+
+ ArrayList names = new ArrayList();
+ List sprops = astnode
+ .structuralPropertiesForType();
+ for (StructuralPropertyDescriptor sprop : sprops) {
+ ASTNode cnode = null;
+ if (!sprop.isChildListProperty()) {
+ if (astnode.getStructuralProperty(sprop) instanceof ASTNode) {
+ cnode = (ASTNode) astnode.getStructuralProperty(sprop);
+ //if(cnode)
+ }
+ } else {
+ // Childlist prop
+ List nodelist = (List) astnode
+ .getStructuralProperty(sprop);
+ for (ASTNode clnode : nodelist) {
+
+ }
+ }
+ }
+
+ return names;
+ }
+
+ public static ASTNode resolveExpression(ASTNode nearestNode,
+ ASTNode expression) {
+// ASTNode anode = null;
+ if (expression instanceof SimpleName) {
+ return findDeclaration2(((SimpleName) expression), nearestNode);
+ } else if (expression instanceof MethodInvocation) {
+ return findDeclaration2(((MethodInvocation) expression).getName(),
+ nearestNode);
+ } else if (expression instanceof FieldAccess) {
+ return findDeclaration2(((FieldAccess) expression).getName(), nearestNode);
+ } else if (expression instanceof QualifiedName) {
+ return findDeclaration2(((QualifiedName) expression).getName(),
+ nearestNode);
+ }
+
+// if (anode != null) {
+// System.out.println("Expression: " + anode);
+// anode = resolveExpression(nearestNode, anode);
+// }
+// String word = anode.toString();
+// // Here expression should be a SN type hopefully.
+// System.out.println("Final Expression: " + word);
+//// anode = expression.getParent();
+//
+// anode = nearestNode.getParent();
+// ASTNode matchinNode = null;
+// while (anode != null) {
+//
+// List sprops = anode
+// .structuralPropertiesForType();
+// for (StructuralPropertyDescriptor sprop : sprops) {
+// ASTNode cnode = null;
+// if (!sprop.isChildListProperty()) {
+// if (anode.getStructuralProperty(sprop) instanceof ASTNode) {
+// cnode = (ASTNode) anode.getStructuralProperty(sprop);
+// String[] types = checkForTypes(cnode);
+// if (types != null) {
+// for (int i = 0; i < types.length; i++) {
+// if (types[i].startsWith(word))
+// {
+// System.out.println("match: "+types[i]);
+// }
+// }
+// }
+// }
+// } else {
+// // Childlist prop
+// List nodelist = (List) anode
+// .getStructuralProperty(sprop);
+// for (ASTNode clnode : nodelist) {
+// String[] types = checkForTypes(clnode);
+// if (types != null) {
+// for (int i = 0; i < types.length; i++) {
+// if (types[i].startsWith(word))
+// System.out.println("match: "+types[i]);;
+// }
+// }
+// }
+// }
+// }
+// anode = anode.getParent();
+// }
+
+ return null;
+ }
+
+ public static TypeDeclaration getDefiningNode(ASTNode node) {
+ ASTNode parent = node.getParent();
+ while (!(parent instanceof TypeDeclaration)) {
+ parent = parent.getParent();
+ if (parent instanceof CompilationUnit)
+ return null;
+ }
+ return (TypeDeclaration) parent;
+ }
+
+ public void updatePredictions(final String word, final int line) {
+ SwingWorker worker = new SwingWorker() {
+
+ @Override
+ protected Object doInBackground() throws Exception {
+ return null;
+ }
+
+ protected void done() {
+// ArrayList candidates = new ArrayList();
+
+ //ASTNodeWrapper[][] candi = new ASTNodeWrapper[80][1];
+ int lineNumber = line;
+ // Adjust line number for tabbed sketches
+ if (errorCheckerService != null) {
+ editor = errorCheckerService.getEditor();
+ 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;
+ }
+
+ }
+
+ ASTNode anode = null;
+ ASTParser parser = ASTParser.newParser(AST.JLS4);
+ parser.setKind(ASTParser.K_EXPRESSION);
+ parser.setSource(word.toCharArray());
+ ASTNode testnode = parser.createAST(null);
+ System.out.print("Typed: " + word + "|");
+ anode = findClosestNode(lineNumber, (ASTNode) compilationUnit.types()
+ .get(0));
+ System.out.println(lineNumber + " Nearest ASTNode to PRED "
+ + getNodeAsString(anode));
+
+ ArrayList candidates = new ArrayList();
+
+ if (testnode instanceof SimpleName) {
+ anode = anode.getParent();
+ while (anode != null) {
+
+ List sprops = anode
+ .structuralPropertiesForType();
+ for (StructuralPropertyDescriptor sprop : sprops) {
+ ASTNode cnode = null;
+ if (!sprop.isChildListProperty()) {
+ if (anode.getStructuralProperty(sprop) instanceof ASTNode) {
+ cnode = (ASTNode) anode.getStructuralProperty(sprop);
+ String[] types = checkForTypes(cnode);
+ if (types != null) {
+ for (int i = 0; i < types.length; i++) {
+ if (types[i].startsWith(word))
+ candidates.add(types[i]);
+ }
+ }
+ }
+ } else {
+ // Childlist prop
+ List nodelist = (List) anode
+ .getStructuralProperty(sprop);
+ for (ASTNode clnode : nodelist) {
+ String[] types = checkForTypes(clnode);
+ if (types != null) {
+ for (int i = 0; i < types.length; i++) {
+ if (types[i].startsWith(word))
+ candidates.add(types[i]);
+ }
+ }
+ }
+ }
+ }
+ anode = anode.getParent();
+ }
+ } else {
+
+ // Complicated completion
+ System.out.println("Not a SN " + getNodeAsString(testnode));
+ ASTNode det = resolveExpression(anode, testnode);
+ if (det != null) {
+ TypeDeclaration td = null;
+ if (det instanceof MethodDeclaration) {
+ if (((MethodDeclaration) det).getReturnType2() instanceof SimpleType) {
+ SimpleType stp = (SimpleType) (((MethodDeclaration) det)
+ .getReturnType2());
+ td = (TypeDeclaration) findDeclaration(stp.getName());
+ }
+ } else if (det instanceof FieldDeclaration) {
+ if (((FieldDeclaration) det).getType() instanceof SimpleType) {
+ SimpleType stp = (SimpleType) (((FieldDeclaration) det)
+ .getType());
+ td = (TypeDeclaration) findDeclaration(stp.getName());
+ }
+ }
+
+ System.out.println(getNodeAsString(det) + " defined in "
+ + getNodeAsString(td));
+ if (td != null) {
+ for (int i = 0; i < td.getFields().length; i++) {
+ candidates.add(getNodeAsString(td.getFields()[i]));
+ }
+ for (int i = 0; i < td.getMethods().length; i++) {
+ candidates.add(getNodeAsString(td.getMethods()[i]));
+ }
+ }
+
+ }
+
+ }
+
+ String[][] candi = new String[candidates.size()][1];
+ for (int i = 0; i < candi.length; i++) {
+ candi[i][0] = candidates.get(i);
+ }
+ System.out.println("K = " + candidates.size());
+ DefaultTableModel tm = new DefaultTableModel(
+ candi,
+ new String[] { "Suggestions" });
+ tableAuto.setModel(tm);
+ tableAuto.validate();
+ tableAuto.repaint();
+ }
+ };
+
+ worker.execute();
+
+ }
+
+ @SuppressWarnings("unchecked")
+ private static ASTNode findClosestParentNode(int lineNumber, ASTNode node) {
+ Iterator it = node
+ .structuralPropertiesForType().iterator();
+ //System.err.println("Props of " + node.getClass().getName());
+ while (it.hasNext()) {
+ StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it
+ .next();
+
+ if (prop.isChildProperty() || prop.isSimpleProperty()) {
+ if (node.getStructuralProperty(prop) != null) {
+// System.out
+// .println(node.getStructuralProperty(prop) + " -> " + (prop));
+ if (node.getStructuralProperty(prop) instanceof ASTNode) {
+ ASTNode cnode = (ASTNode) node.getStructuralProperty(prop);
+ System.out.println("Looking at " + getNodeAsString(cnode));
+ int cLineNum = ((CompilationUnit) cnode.getRoot())
+ .getLineNumber(cnode.getStartPosition() + cnode.getLength());
+ if (getLineNumber(cnode) <= lineNumber && lineNumber <= cLineNum) {
+ return findClosestParentNode(lineNumber, cnode);
+ }
+ }
+ }
+ }
+
+ else if (prop.isChildListProperty()) {
+ List nodelist = (List) node
+ .getStructuralProperty(prop);
+ for (ASTNode cnode : nodelist) {
+ int cLineNum = ((CompilationUnit) cnode.getRoot())
+ .getLineNumber(cnode.getStartPosition() + cnode.getLength());
+ System.out.println("Looking at " + getNodeAsString(cnode));
+ if (getLineNumber(cnode) <= lineNumber && lineNumber <= cLineNum) {
+ return findClosestParentNode(lineNumber, cnode);
+ }
+ }
+ }
+ }
+ return node;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static ASTNode findClosestNode(int lineNumber, ASTNode node) {
+ ASTNode parent = findClosestParentNode(lineNumber, node);
+ if (parent == null)
+ return null;
+ if (getLineNumber(parent) == lineNumber)
+ return parent;
+ List nodes = null;
+ if (parent instanceof TypeDeclaration) {
+ nodes = (List) ((TypeDeclaration) parent)
+ .getStructuralProperty(TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
+ } else if (parent instanceof Block) {
+ nodes = (List) ((Block) parent)
+ .getStructuralProperty(Block.STATEMENTS_PROPERTY);
+ } else {
+ System.err.println("THIS CONDITION SHOULD NOT OCCUR - findClosestNode "
+ + getNodeAsString(parent));
+ return null;
+ }
+
+ ASTNode retNode = nodes.get(0);
+ for (ASTNode cNode : nodes) {
+ if (getLineNumber(cNode) <= lineNumber)
+ retNode = cNode;
+ else
+ break;
+ }
+
+ return retNode;
+ }
+
+// 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;
+ }
+
+ public String getLabelForASTNode(int lineNumber, String name, int offset) {
+ retLabelString = "";
+ getASTNodeAt(lineNumber, name, offset, false);
+ return retLabelString;
+ }
+
+ public void scrollToDeclaration(int lineNumber, String name, int offset) {
+ getASTNodeAt(lineNumber, name, offset, true);
+ }
+
+ String retLabelString;
+
+ public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset,
+ boolean scrollOnly) {
+ System.out.println("--------");
+ if (errorCheckerService != null) {
+ editor = errorCheckerService.getEditor();
+ 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;
+ }
+ }
+
+ }
+ System.out.println("FLON: " + lineNumber);
+ ASTNode lineNode = findLineOfNode(compilationUnit, lineNumber, offset, name);
+ System.out.println("+> " + lineNode);
+ ASTNode decl = null;
+ if (lineNode != null) {
+ System.out.println("FLON2: " + lineNumber + " LN O "
+ + lineNode.getStartPosition());
+ ASTNode simpName = pinpointOnLine(lineNode, offset,
+ lineNode.getStartPosition(), name);
+ System.out.println("+++> " + simpName);
+ if (simpName instanceof SimpleName) {
+ System.out.println(getNodeAsString(simpName));
+ decl = findDeclaration((SimpleName) simpName);
+ if (decl != null) {
+ System.err.println("DECLA: " + decl.getClass().getName());
+ retLabelString = getNodeAsString(decl);
+ } else
+ System.err.println("null");
+
+ System.out.println(getNodeAsString(decl));
+ }
+ }
+
+//
+// retStr = "";
+ if (decl != null && scrollOnly) {
+ System.err.println("FINAL String label: " + getNodeAsString(decl));
+
+ DefaultProblem dpr = new DefaultProblem(null, null, -1, null, -1,
+ decl.getStartPosition(),
+ decl.getStartPosition(),
+ getLineNumber(decl) + 1, 0);
+ int[] position = errorCheckerService.calculateTabIndexAndLineNumber(dpr);
+ System.out.println("Tab " + position[0] + ", Line: " + (position[1]));
+ Problem p = new Problem(dpr, position[0], position[1]);
+ //errorCheckerService.scrollToErrorLine(p);
+ } // uncomment this one, it works
+
+ return null;
+ }
+
+ private static int getLineNumber(ASTNode node) {
+ return ((CompilationUnit) node.getRoot()).getLineNumber(node
+ .getStartPosition());
+ }
+
+ public static void main(String[] args) {
+ traversal2();
+// ASTParserd
+ }
+
+ public static void traversal2() {
+ ASTParser parser = ASTParser.newParser(AST.JLS4);
+ String source = readFile("/media/quarkninja/Work/TestStuff/low.java");
+// String source = "package decl; \npublic class ABC{\n int ret(){\n}\n}";
+ parser.setSource(source.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);
+ parser.setCompilerOptions(options);
+
+ CompilationUnit cu = (CompilationUnit) parser.createAST(null);
+ System.out.println(CompilationUnit.propertyDescriptors(AST.JLS4).size());
+
+ DefaultMutableTreeNode astTree = new DefaultMutableTreeNode(
+ "CompilationUnit");
+ System.err.println("Errors: " + cu.getProblems().length);
+ visitRecur(cu, astTree);
+ System.out.println(astTree.getChildCount());
+
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ JFrame frame2 = new JFrame();
+ JTree jtree = new JTree(astTree);
+ frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame2.setBounds(new Rectangle(100, 100, 460, 620));
+ JScrollPane sp = new JScrollPane();
+ sp.setViewportView(jtree);
+ frame2.add(sp);
+ frame2.setVisible(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ ASTNode found = NodeFinder.perform(cu, 468, 5);
+ if (found != null) {
+ System.out.println(found);
+ }
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ public static void visitRecur(ASTNode node, DefaultMutableTreeNode tnode) {
+ Iterator it = node
+ .structuralPropertiesForType().iterator();
+ //System.err.println("Props of " + node.getClass().getName());
+ DefaultMutableTreeNode ctnode = null;
+ while (it.hasNext()) {
+ StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it
+ .next();
+
+ if (prop.isChildProperty() || prop.isSimpleProperty()) {
+ if (node.getStructuralProperty(prop) != null) {
+// System.out
+// .println(node.getStructuralProperty(prop) + " -> " + (prop));
+ if (node.getStructuralProperty(prop) instanceof ASTNode) {
+ ASTNode cnode = (ASTNode) node.getStructuralProperty(prop);
+ if (isAddableASTNode(cnode)) {
+ ctnode = new DefaultMutableTreeNode(
+ getNodeAsString((ASTNode) node
+ .getStructuralProperty(prop)));
+ tnode.add(ctnode);
+ visitRecur(cnode, ctnode);
+ }
+ } else {
+ tnode.add(new DefaultMutableTreeNode(node
+ .getStructuralProperty(prop)));
+ }
+ }
+ }
+
+ else if (prop.isChildListProperty()) {
+ List nodelist = (List) node
+ .getStructuralProperty(prop);
+ for (ASTNode cnode : nodelist) {
+ if (isAddableASTNode(cnode)) {
+ ctnode = new DefaultMutableTreeNode(getNodeAsString(cnode));
+ tnode.add(ctnode);
+ visitRecur(cnode, ctnode);
+ } else
+ visitRecur(cnode, tnode);
+ }
+ }
+ }
+ }
+
+ public static void printRecur(ASTNode node) {
+ Iterator it = node
+ .structuralPropertiesForType().iterator();
+ //System.err.println("Props of " + node.getClass().getName());
+ while (it.hasNext()) {
+ StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) it
+ .next();
+
+ if (prop.isChildProperty() || prop.isSimpleProperty()) {
+ if (node.getStructuralProperty(prop) != null) {
+// System.out
+// .println(node.getStructuralProperty(prop) + " -> " + (prop));
+ if (node.getStructuralProperty(prop) instanceof ASTNode) {
+ ASTNode cnode = (ASTNode) node.getStructuralProperty(prop);
+ System.out.println(getNodeAsString(cnode));
+ printRecur(cnode);
+ }
+ }
+ }
+
+ else if (prop.isChildListProperty()) {
+ List nodelist = (List) node
+ .getStructuralProperty(prop);
+ for (ASTNode cnode : nodelist) {
+ System.out.println(getNodeAsString(cnode));
+ printRecur(cnode);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static ASTNode findLineOfNode(ASTNode node, int lineNumber,
+ int offset, String name) {
+
+ CompilationUnit root = (CompilationUnit) node.getRoot();
+// System.out.println("Inside "+getNodeAsString(node) + " | " + root.getLineNumber(node.getStartPosition()));
+ if (root.getLineNumber(node.getStartPosition()) == lineNumber) {
+ System.err
+ .println(3 + getNodeAsString(node) + " len " + node.getLength());
+
+ if (offset < node.getLength())
+ return node;
+ else {
+ System.err.println(-11);
+ return null;
+ }
+ }
+ for (Object oprop : node.structuralPropertiesForType()) {
+ StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) oprop;
+ if (prop.isChildProperty() || prop.isSimpleProperty()) {
+ if (node.getStructuralProperty(prop) != null) {
+ if (node.getStructuralProperty(prop) instanceof ASTNode) {
+ ASTNode retNode = findLineOfNode((ASTNode) node
+ .getStructuralProperty(prop),
+ lineNumber, offset, name);
+ if (retNode != null) {
+// System.err.println(11 + getNodeAsString(retNode));
+ return retNode;
+ }
+ }
+ }
+ } else if (prop.isChildListProperty()) {
+ List nodelist = (List) node
+ .getStructuralProperty(prop);
+ for (ASTNode retNode : nodelist) {
+
+ ASTNode rr = findLineOfNode(retNode, lineNumber, offset, name);
+ if (rr != null) {
+// System.err.println(12 + getNodeAsString(rr));
+ return rr;
+ }
+ }
+ }
+ }
+// System.err.println("-1");
+ return null;
+ }
+
+ /**
+ *
+ * @param node
+ * @param offset
+ * - from textarea painter
+ * @param lineStartOffset
+ * - obtained from findLineOfNode
+ * @param name
+ * @param root
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static ASTNode pinpointOnLine(ASTNode node, int offset,
+ int lineStartOffset, String name) {
+
+ if (node instanceof SimpleName) {
+ SimpleName sn = (SimpleName) node;
+ if ((lineStartOffset + offset) >= sn.getStartPosition()
+ && (lineStartOffset + offset) <= sn.getStartPosition()
+ + sn.getLength()) {
+ if (sn.toString().equals(name))
+ return sn;
+ else
+ return null;
+ } else
+ return null;
+ }
+ for (Object oprop : node.structuralPropertiesForType()) {
+ StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) oprop;
+ if (prop.isChildProperty() || prop.isSimpleProperty()) {
+ if (node.getStructuralProperty(prop) != null) {
+ if (node.getStructuralProperty(prop) instanceof ASTNode) {
+ ASTNode retNode = pinpointOnLine((ASTNode) node
+ .getStructuralProperty(prop),
+ offset, lineStartOffset, name);
+ if (retNode != null) {
+// System.err.println(11 + getNodeAsString(retNode));
+ return retNode;
+ }
+ }
+ }
+ } else if (prop.isChildListProperty()) {
+ List nodelist = (List) node
+ .getStructuralProperty(prop);
+ for (ASTNode retNode : nodelist) {
+
+ ASTNode rr = pinpointOnLine(retNode, offset, lineStartOffset, name);
+ if (rr != null) {
+// System.err.println(12 + getNodeAsString(rr));
+ return rr;
+ }
+ }
+ }
+ }
+// System.err.println("-1");
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static ASTNode findDeclaration(Name findMe) {
+ ASTNode declaringClass = null;
+ ASTNode parent = findMe.getParent();
+ ASTNode ret = null;
+ ArrayList constrains = new ArrayList();
+ if (parent.getNodeType() == ASTNode.METHOD_INVOCATION) {
+ Expression exp = (Expression) ((MethodInvocation) parent)
+ .getStructuralProperty(MethodInvocation.EXPRESSION_PROPERTY);
+ //TODO: Note the imbalance of constrains.add(ASTNode.METHOD_DECLARATION);
+ // Possibly a bug here. Investigate later.
+ if (((MethodInvocation) parent).getName().toString()
+ .equals(findMe.toString())) {
+ constrains.add(ASTNode.METHOD_DECLARATION);
+
+ if (exp != null) {
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ System.out.println("MI EXP: " + exp.toString() + " of type "
+ + exp.getClass().getName() + " parent: " + exp.getParent());
+ if (exp instanceof MethodInvocation) {
+ SimpleType stp = extracTypeInfo(findDeclaration(((MethodInvocation) exp)
+ .getName()));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration(stp.getName());
+ return definedIn(declaringClass, ((MethodInvocation) parent)
+ .getName().toString(), constrains, declaringClass);
+ } else if (exp instanceof FieldAccess) {
+ SimpleType stp = extracTypeInfo(findDeclaration(((FieldAccess) exp)
+ .getName()));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration((stp.getName()));
+ return definedIn(declaringClass, ((MethodInvocation) parent)
+ .getName().toString(), constrains, declaringClass);
+ }
+ if (exp instanceof SimpleName) {
+ SimpleType stp = extracTypeInfo(findDeclaration(((SimpleName) exp)));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration(stp.getName());
+ System.out.println("MI.SN " + getNodeAsString(declaringClass));
+ constrains.add(ASTNode.METHOD_DECLARATION);
+ return definedIn(declaringClass, ((MethodInvocation) parent)
+ .getName().toString(), constrains, declaringClass);
+ }
+
+ }
+ } else {
+ parent = parent.getParent(); // Move one up the ast. V V IMP!!
+ }
+ } else if (parent.getNodeType() == ASTNode.FIELD_ACCESS) {
+ FieldAccess fa = (FieldAccess) parent;
+ Expression exp = fa.getExpression();
+ if (fa.getName().toString().equals(findMe.toString())) {
+ constrains.add(ASTNode.FIELD_DECLARATION);
+
+ if (exp != null) {
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ System.out.println("FA EXP: " + exp.toString() + " of type "
+ + exp.getClass().getName() + " parent: " + exp.getParent());
+ if (exp instanceof MethodInvocation) {
+ SimpleType stp = extracTypeInfo(findDeclaration(((MethodInvocation) exp)
+ .getName()));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration(stp.getName());
+ return definedIn(declaringClass, fa.getName().toString(),
+ constrains, declaringClass);
+ } else if (exp instanceof FieldAccess) {
+ SimpleType stp = extracTypeInfo(findDeclaration(((FieldAccess) exp)
+ .getName()));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration((stp.getName()));
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ return definedIn(declaringClass, fa.getName().toString(),
+ constrains, declaringClass);
+ }
+ if (exp instanceof SimpleName) {
+ SimpleType stp = extracTypeInfo(findDeclaration(((SimpleName) exp)));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration(stp.getName());
+ System.out.println("FA.SN " + getNodeAsString(declaringClass));
+ constrains.add(ASTNode.METHOD_DECLARATION);
+ return definedIn(declaringClass, fa.getName().toString(),
+ constrains, declaringClass);
+ }
+ }
+
+ } else {
+ parent = parent.getParent(); // Move one up the ast. V V IMP!!
+ }
+ } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME) {
+
+ QualifiedName qn = (QualifiedName) parent;
+ if (!findMe.toString().equals(qn.getQualifier().toString())) {
+
+ SimpleType stp = extracTypeInfo(findDeclaration((qn.getQualifier())));
+ declaringClass = findDeclaration(stp.getName());
+ System.out.println(qn.getQualifier() + "->" + qn.getName());
+ System.out.println("QN decl class: " + getNodeAsString(declaringClass));
+ constrains.clear();
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ constrains.add(ASTNode.FIELD_DECLARATION);
+ return definedIn(declaringClass, qn.getName().toString(), constrains,
+ null);
+ }
+ } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE) {
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ if (parent.getParent().getNodeType() == ASTNode.CLASS_INSTANCE_CREATION)
+ constrains.add(ASTNode.CLASS_INSTANCE_CREATION);
+ } else if (parent instanceof Expression) {
+// constrains.add(ASTNode.TYPE_DECLARATION);
+// constrains.add(ASTNode.METHOD_DECLARATION);
+// constrains.add(ASTNode.FIELD_DECLARATION);
+ }
+ while (parent != null) {
+ System.out.println("findDeclaration1 -> " + getNodeAsString(parent));
+ for (Object oprop : parent.structuralPropertiesForType()) {
+ StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) oprop;
+ if (prop.isChildProperty() || prop.isSimpleProperty()) {
+ if (parent.getStructuralProperty(prop) instanceof ASTNode) {
+ System.out.println(prop + " C/S Prop of -> "
+ + getNodeAsString(parent));
+ ret = definedIn((ASTNode) parent.getStructuralProperty(prop),
+ findMe.toString(), constrains, declaringClass);
+ if (ret != null)
+ return ret;
+ }
+ } else if (prop.isChildListProperty()) {
+ System.out.println((prop) + " ChildList props of "
+ + getNodeAsString(parent));
+ List nodelist = (List) parent
+ .getStructuralProperty(prop);
+ for (ASTNode retNode : nodelist) {
+ ret = definedIn(retNode, findMe.toString(), constrains,
+ declaringClass);
+ if (ret != null)
+ return ret;
+ }
+ }
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
+ private static ASTNode findDeclaration2(Name findMe, ASTNode alternateParent) {
+ ASTNode declaringClass = null;
+ ASTNode parent = findMe.getParent();
+ ASTNode ret = null;
+ ArrayList constrains = new ArrayList();
+ if (parent.getNodeType() == ASTNode.METHOD_INVOCATION) {
+ Expression exp = (Expression) ((MethodInvocation) parent)
+ .getStructuralProperty(MethodInvocation.EXPRESSION_PROPERTY);
+ //TODO: Note the imbalance of constrains.add(ASTNode.METHOD_DECLARATION);
+ // Possibly a bug here. Investigate later.
+ if (((MethodInvocation) parent).getName().toString()
+ .equals(findMe.toString())) {
+ constrains.add(ASTNode.METHOD_DECLARATION);
+
+ if (exp != null) {
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ System.out.println("MI EXP: " + exp.toString() + " of type "
+ + exp.getClass().getName() + " parent: " + exp.getParent());
+ if (exp instanceof MethodInvocation) {
+ SimpleType stp = extracTypeInfo(findDeclaration2(((MethodInvocation) exp)
+ .getName(),
+ alternateParent));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration2(stp.getName(), alternateParent);
+ return definedIn(declaringClass, ((MethodInvocation) parent)
+ .getName().toString(), constrains, declaringClass);
+ } else if (exp instanceof FieldAccess) {
+ SimpleType stp = extracTypeInfo(findDeclaration2(((FieldAccess) exp)
+ .getName(),
+ alternateParent));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration2((stp.getName()), alternateParent);
+ return definedIn(declaringClass, ((MethodInvocation) parent)
+ .getName().toString(), constrains, declaringClass);
+ }
+ if (exp instanceof SimpleName) {
+ SimpleType stp = extracTypeInfo(findDeclaration2(((SimpleName) exp),
+ alternateParent));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration2(stp.getName(), alternateParent);
+ System.out.println("MI.SN " + getNodeAsString(declaringClass));
+ constrains.add(ASTNode.METHOD_DECLARATION);
+ return definedIn(declaringClass, ((MethodInvocation) parent)
+ .getName().toString(), constrains, declaringClass);
+ }
+
+ }
+ } else {
+ parent = parent.getParent(); // Move one up the ast. V V IMP!!
+ alternateParent = alternateParent.getParent();
+ }
+ } else if (parent.getNodeType() == ASTNode.FIELD_ACCESS) {
+ FieldAccess fa = (FieldAccess) parent;
+ Expression exp = fa.getExpression();
+ if (fa.getName().toString().equals(findMe.toString())) {
+ constrains.add(ASTNode.FIELD_DECLARATION);
+
+ if (exp != null) {
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ System.out.println("FA EXP: " + exp.toString() + " of type "
+ + exp.getClass().getName() + " parent: " + exp.getParent());
+ if (exp instanceof MethodInvocation) {
+ SimpleType stp = extracTypeInfo(findDeclaration2(((MethodInvocation) exp)
+ .getName(),
+ alternateParent));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration2(stp.getName(), alternateParent);
+ return definedIn(declaringClass, fa.getName().toString(),
+ constrains, declaringClass);
+ } else if (exp instanceof FieldAccess) {
+ SimpleType stp = extracTypeInfo(findDeclaration2(((FieldAccess) exp)
+ .getName(),
+ alternateParent));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration2((stp.getName()), alternateParent);
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ return definedIn(declaringClass, fa.getName().toString(),
+ constrains, declaringClass);
+ }
+ if (exp instanceof SimpleName) {
+ SimpleType stp = extracTypeInfo(findDeclaration2(((SimpleName) exp),
+ alternateParent));
+ if (stp == null)
+ return null;
+ declaringClass = findDeclaration2(stp.getName(), alternateParent);
+ System.out.println("FA.SN " + getNodeAsString(declaringClass));
+ constrains.add(ASTNode.METHOD_DECLARATION);
+ return definedIn(declaringClass, fa.getName().toString(),
+ constrains, declaringClass);
+ }
+ }
+
+ } else {
+ parent = parent.getParent(); // Move one up the ast. V V IMP!!
+ alternateParent = alternateParent.getParent();
+ }
+ } else if (parent.getNodeType() == ASTNode.QUALIFIED_NAME) {
+
+ QualifiedName qn = (QualifiedName) parent;
+ if (!findMe.toString().equals(qn.getQualifier().toString())) {
+
+ SimpleType stp = extracTypeInfo(findDeclaration2((qn.getQualifier()),
+ alternateParent));
+ declaringClass = findDeclaration2(stp.getName(), alternateParent);
+ System.out.println(qn.getQualifier() + "->" + qn.getName());
+ System.out.println("QN decl class: " + getNodeAsString(declaringClass));
+ constrains.clear();
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ constrains.add(ASTNode.FIELD_DECLARATION);
+ return definedIn(declaringClass, qn.getName().toString(), constrains,
+ null);
+ }
+ } else if (parent.getNodeType() == ASTNode.SIMPLE_TYPE) {
+ constrains.add(ASTNode.TYPE_DECLARATION);
+ if (parent.getParent().getNodeType() == ASTNode.CLASS_INSTANCE_CREATION)
+ constrains.add(ASTNode.CLASS_INSTANCE_CREATION);
+ } else if (parent instanceof Expression) {
+// constrains.add(ASTNode.TYPE_DECLARATION);
+// constrains.add(ASTNode.METHOD_DECLARATION);
+// constrains.add(ASTNode.FIELD_DECLARATION);
+ }
+ System.out.println("Alternate parent: " + getNodeAsString(alternateParent));
+ while (alternateParent != null) {
+ System.out.println("findDeclaration2 -> "
+ + getNodeAsString(alternateParent));
+ for (Object oprop : alternateParent.structuralPropertiesForType()) {
+ StructuralPropertyDescriptor prop = (StructuralPropertyDescriptor) oprop;
+ if (prop.isChildProperty() || prop.isSimpleProperty()) {
+ if (alternateParent.getStructuralProperty(prop) instanceof ASTNode) {
+ System.out.println(prop + " C/S Prop of -> "
+ + getNodeAsString(alternateParent));
+ ret = definedIn((ASTNode) alternateParent
+ .getStructuralProperty(prop),
+ findMe.toString(), constrains, declaringClass);
+ if (ret != null)
+ return ret;
+ }
+ } else if (prop.isChildListProperty()) {
+ System.out.println((prop) + " ChildList props of "
+ + getNodeAsString(alternateParent));
+ List nodelist = (List) alternateParent
+ .getStructuralProperty(prop);
+ for (ASTNode retNode : nodelist) {
+ ret = definedIn(retNode, findMe.toString(), constrains,
+ declaringClass);
+ if (ret != null)
+ return ret;
+ }
+ }
+ }
+ alternateParent = alternateParent.getParent();
+ }
+ return null;
+ }
+
+ /**
+ * Find the SimpleType from FD, SVD, VDS, etc
+ *
+ * @param node
+ * @return
+ */
+ private static SimpleType extracTypeInfo(ASTNode node) {
+ if (node == null)
+ return null;
+ switch (node.getNodeType()) {
+ case ASTNode.METHOD_DECLARATION:
+ return (SimpleType) ((MethodDeclaration) node)
+ .getStructuralProperty(MethodDeclaration.RETURN_TYPE2_PROPERTY);
+ case ASTNode.FIELD_DECLARATION:
+ return (SimpleType) ((FieldDeclaration) node)
+ .getStructuralProperty(FieldDeclaration.TYPE_PROPERTY);
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
+ return (SimpleType) ((VariableDeclarationExpression) node)
+ .getStructuralProperty(VariableDeclarationExpression.TYPE_PROPERTY);
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+ return (SimpleType) ((VariableDeclarationStatement) node)
+ .getStructuralProperty(VariableDeclarationStatement.TYPE_PROPERTY);
+ case ASTNode.SINGLE_VARIABLE_DECLARATION:
+ return (SimpleType) ((SingleVariableDeclaration) node)
+ .getStructuralProperty(SingleVariableDeclaration.TYPE_PROPERTY);
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static ASTNode definedIn(ASTNode node, String name,
+ ArrayList constrains,
+ ASTNode declaringClass) {
+ if (node == null)
+ return null;
+ if (constrains != null) {
+ System.out.println("Looking at " + getNodeAsString(node) + " for " + name
+ + " in definedIn");
+ if (!constrains.contains(node.getNodeType()) && constrains.size() > 0) {
+ System.err.print("definedIn -1 " + " But constrain was ");
+ for (Integer integer : constrains) {
+ System.out.print(ASTNode.nodeClassForType(integer) + ",");
+ }
+ System.out.println();
+ return null;
+ }
+ }
+
+ List vdfList = null;
+ switch (node.getNodeType()) {
+
+ case ASTNode.TYPE_DECLARATION:
+ System.err.println(getNodeAsString(node));
+ TypeDeclaration td = (TypeDeclaration) node;
+ if (td.getName().toString().equals(name)) {
+ if (constrains.contains(ASTNode.CLASS_INSTANCE_CREATION)) {
+ // look for constructor;
+ MethodDeclaration[] methods = td.getMethods();
+ for (MethodDeclaration md : methods) {
+ if (md.getName().toString().equals(name)) {
+ return md;
+ }
+ }
+ } else {
+ // it's just the TD we're lookin for
+ return node;
+ }
+ } else {
+ if (constrains.contains(ASTNode.FIELD_DECLARATION)) {
+ // look for fields
+ FieldDeclaration[] fields = td.getFields();
+ for (FieldDeclaration fd : fields) {
+ List fragments = fd.fragments();
+ for (VariableDeclarationFragment vdf : fragments) {
+ if (vdf.getName().toString().equals(name))
+ return fd;
+ }
+ }
+ } else if (constrains.contains(ASTNode.METHOD_DECLARATION)) {
+ // look for methods
+ MethodDeclaration[] methods = td.getMethods();
+ for (MethodDeclaration md : methods) {
+ if (md.getName().toString().equals(name)) {
+ return md;
+ }
+ }
+ }
+ }
+ break;
+ case ASTNode.METHOD_DECLARATION:
+ System.err.println(getNodeAsString(node));
+ if (((MethodDeclaration) node).getName().toString().equals(name))
+ return node;
+ break;
+ case ASTNode.SINGLE_VARIABLE_DECLARATION:
+ System.err.println(getNodeAsString(node));
+ if (((SingleVariableDeclaration) node).getName().toString().equals(name))
+ return node;
+ break;
+ case ASTNode.FIELD_DECLARATION:
+ System.err.println("FD" + node);
+ vdfList = ((FieldDeclaration) node).fragments();
+ break;
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
+ System.err.println("VDE" + node);
+ vdfList = ((VariableDeclarationExpression) node).fragments();
+ break;
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+ System.err.println("VDS" + node);
+ vdfList = ((VariableDeclarationStatement) node).fragments();
+ break;
+
+ default:
+
+ }
+ if (vdfList != null) {
+ for (VariableDeclarationFragment vdf : vdfList) {
+ if (vdf.getName().toString().equals(name))
+ return node;
+ }
+ }
+ return null;
+ }
+
+ public static boolean isAddableASTNode(ASTNode node) {
+ return true;
+ }
+
+ static private String getNodeAsString(ASTNode node) {
+ if (node == null)
+ return "NULL";
+ String className = node.getClass().getName();
+ int index = className.lastIndexOf(".");
+ if (index > 0)
+ className = className.substring(index + 1);
+
+ // if(node instanceof BodyDeclaration)
+ // return className;
+
+ String value = className;
+
+ if (node instanceof TypeDeclaration)
+ value = ((TypeDeclaration) node).getName().toString() + " | " + className;
+ else if (node instanceof MethodDeclaration)
+ value = ((MethodDeclaration) node).getName().toString() + " | "
+ + className;
+ else if (node instanceof MethodInvocation)
+ value = ((MethodInvocation) node).getName().toString() + " | "
+ + className;
+ else if (node instanceof FieldDeclaration)
+ value = ((FieldDeclaration) node).toString() + " FldDecl| ";
+ else if (node instanceof SingleVariableDeclaration)
+ value = ((SingleVariableDeclaration) node).getName() + " - "
+ + ((SingleVariableDeclaration) node).getType() + " | SVD ";
+ else if (node instanceof ExpressionStatement)
+ value = node.toString() + className;
+ else if (node instanceof SimpleName)
+ value = ((SimpleName) node).getFullyQualifiedName() + " | " + className;
+ else if (className.startsWith("Variable"))
+ value = node.toString() + " | " + className;
+ else if (className.endsWith("Type"))
+ value = node.toString() + " |" + className;
+ value += " [" + node.getStartPosition() + ","
+ + (node.getStartPosition() + node.getLength()) + "]";
+ value += " Line: "
+ + ((CompilationUnit) node.getRoot()).getLineNumber(node
+ .getStartPosition());
+ return value;
+ }
+
+ public static String readFile(String path) {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(
+ new File(
+ path))));
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ try {
+ StringBuilder ret = new StringBuilder();
+ // ret.append("package " + className + ";\n");
+ String line;
+ while ((line = reader.readLine()) != null) {
+ ret.append(line);
+ ret.append("\n");
+ }
+ return ret.toString();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/pdex/src/processing/mode/experimental/DebugEditor.java b/pdex/src/processing/mode/experimental/DebugEditor.java
index 91bf862b9..b8f44a05b 100755
--- a/pdex/src/processing/mode/experimental/DebugEditor.java
+++ b/pdex/src/processing/mode/experimental/DebugEditor.java
@@ -179,7 +179,9 @@ public class DebugEditor extends JavaEditor implements ActionListener {
checkForJavaTabs();
initializeErrorChecker();
ta.setECSandThemeforTextArea(errorCheckerService, dmode);
- addXQModeUI();
+ addXQModeUI();
+ //TODO: Remove this later
+ setBounds(160, 400, getWidth(), getHeight());
}
private void addXQModeUI(){
diff --git a/pdex/src/processing/mode/experimental/ErrorBar.java b/pdex/src/processing/mode/experimental/ErrorBar.java
index b21aaac40..24d552ae5 100755
--- a/pdex/src/processing/mode/experimental/ErrorBar.java
+++ b/pdex/src/processing/mode/experimental/ErrorBar.java
@@ -187,11 +187,12 @@ public class ErrorBar extends JPanel {
// Each problem.getSourceLine() will have an extra line added
// because of
- // class declaration in the beginning
+ // 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 / ((float) totalLines);
+ 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,
diff --git a/pdex/src/processing/mode/experimental/ErrorCheckerService.java b/pdex/src/processing/mode/experimental/ErrorCheckerService.java
old mode 100755
new mode 100644
index 435d54903..e0ce2a646
--- a/pdex/src/processing/mode/experimental/ErrorCheckerService.java
+++ b/pdex/src/processing/mode/experimental/ErrorCheckerService.java
@@ -28,6 +28,7 @@ import processing.app.Base;
import processing.app.Library;
import processing.app.SketchCode;
import processing.core.PApplet;
+import processing.mode.java.preproc.PdePreprocessor;
public class ErrorCheckerService implements Runnable{
@@ -87,6 +88,11 @@ public class ErrorCheckerService implements Runnable{
*/
public int mainClassOffset;
+ /**
+ * Fixed p5 offsets for all sketches
+ */
+ public int defaultImportsOffset;
+
/**
* Is the sketch running in static mode or active mode?
*/
@@ -173,6 +179,9 @@ public class ErrorCheckerService implements Runnable{
initParser();
initializeErrorWindow();
xqpreproc = new XQPreprocessor();
+ PdePreprocessor pdePrepoc = new PdePreprocessor(null);
+ defaultImportsOffset = pdePrepoc.getCoreImports().length +
+ pdePrepoc.getDefaultImports().length + 1;
}
/**
@@ -222,11 +231,6 @@ public class ErrorCheckerService implements Runnable{
});
}
- /**
- * checkCode() only on text area update
- */
- protected AtomicInteger textModified = new AtomicInteger(0);
-
public void run() {
stopThread = false;
@@ -239,62 +243,62 @@ public class ErrorCheckerService implements Runnable{
System.out.println("Oops! [ErrorCheckerThreaded]: " + e);
// e.printStackTrace();
}
-
+
+ updatePaintedThingys();
+
if (pauseThread)
continue;
-
- updatePaintedThingy();
-
if(textModified.get() == 0)
continue;
-
// Check every x seconds
checkCode();
}
}
-
-
-
+ ASTGenerator astGenerator = new ASTGenerator(this);
+ AtomicInteger textModified = new AtomicInteger();
private boolean checkCode() {
-
+ System.out.println("checkCode() " + textModified.get() );
lastTimeStamp = System.currentTimeMillis();
try {
sourceCode = preprocessCode(editor.getSketch().getMainProgram());
syntaxCheck();
-
+ System.err.println(editor.getSketch().getName()+ " MCO " + mainClassOffset);
// No syntax errors, proceed for compilation check, Stage 2.
+
if (problems.length == 0 && editor.compilationCheckEnabled) {
+ astGenerator.buildAST();
sourceCode = xqpreproc.doYourThing(sourceCode, programImports);
prepareCompilerClasspath();
- mainClassOffset = xqpreproc.mainClassOffset; // tiny, but
- // significant
- if (staticMode) {
- mainClassOffset++; // Extra line for setup() decl.
- }
+// mainClassOffset = xqpreproc.mainClassOffset; // tiny, but
+// // significant
+// if (staticMode) {
+// mainClassOffset++; // Extra line for setup() decl.
+// }
// System.out.println(sourceCode);
// System.out.println("--------------------------");
compileCheck();
+
}
updateErrorTable();
editor.updateErrorBar(problemsList);
updateEditorStatus();
- // updatePaintedThingy();
+ updatePaintedThingys();
int x = textModified.get();
//System.out.println("TM " + x);
if(x>=3){
- textModified.set(3);
- x = 3;
+ textModified.set(3);
+ x = 3;
}
if(x>0)
- textModified.set(x - 1);
+ textModified.set(x - 1);
else
- textModified.set(0);
+ textModified.set(0);
return true;
} catch (Exception e) {
@@ -675,14 +679,15 @@ public class ErrorCheckerService implements Runnable{
/**
* Repaints the textarea if required
*/
- public void updatePaintedThingy() {
+ public void updatePaintedThingys() {
editor.getTextArea().repaint();
updateEditorStatus();
currentTab = editor.getSketch().getCodeIndex(
editor.getSketch().getCurrentCode());
+ //System.out.println("awesome! " + currentTab + " LT " + lastTab);
if (currentTab != lastTab) {
+ textModified.incrementAndGet();
lastTab = currentTab;
- editor.updateErrorBar(problemsList);
return;
}
@@ -725,7 +730,7 @@ public class ErrorCheckerService implements Runnable{
// String[] lines = {};// = PApplet.split(sourceString, '\n');
int codeIndex = 0;
- int x = problem.getSourceLineNumber() - mainClassOffset;
+ int x = problem.getSourceLineNumber() - mainClassOffset + 1;
if (x < 0) {
// System.out.println("Negative line number "
// + problem.getSourceLineNumber() + " , offset "
@@ -900,23 +905,31 @@ public class ErrorCheckerService implements Runnable{
className = (editor == null) ? "DefaultClass" : editor.getSketch()
.getName();
+
// Check whether the code is being written in STATIC mode(no function
// declarations) - append class declaration and void setup() declaration
Matcher matcher = FUNCTION_DECL.matcher(sourceAlt);
if (!matcher.find()) {
- sourceAlt = "public class " + className + " extends PApplet {\n"
+ sourceAlt = xqpreproc.prepareImports(programImports) + "public class " + className + " extends PApplet {\n"
+ "public void setup() {\n" + sourceAlt
+ "\nnoLoop();\n}\n" + "\n}\n";
- staticMode = true;
- mainClassOffset = 2;
+ staticMode = true;
} else {
- sourceAlt = "public class " + className + " extends PApplet {\n"
+ sourceAlt = xqpreproc.prepareImports(programImports) + "public class " + className + " extends PApplet {\n"
+ sourceAlt + "\n}";
- staticMode = false;
- mainClassOffset = 1;
+ staticMode = false;
}
-
+
+ int position = sourceAlt.indexOf("{") + 1;
+ mainClassOffset = 1;
+ for (int i = 0; i <= position; i++) {
+ if (sourceAlt.charAt(i) == '\n') {
+ mainClassOffset++;
+ }
+ }
+ if(staticMode) mainClassOffset++;
+ //mainClassOffset += 2;
// Handle unicode characters
sourceAlt = substituteUnicode(sourceAlt);
@@ -963,6 +976,36 @@ public class ErrorCheckerService implements Runnable{
}
}
+ public void scrollToErrorLine(Problem p) {
+ if (editor == null) {
+ return;
+ }
+ if(p==null)
+ return;
+ try {
+ editor.toFront();
+ editor.getSketch().setCurrentCode(p.tabIndex);
+
+ editor.setSelection(editor.getTextArea()
+ .getLineStartNonWhiteSpaceOffset(p.lineNumber - 1)
+ + editor.getTextArea().getLineText(p.lineNumber - 1)
+ .trim().length(), editor.getTextArea()
+ .getLineStartNonWhiteSpaceOffset(p.lineNumber - 1));
+ editor.getTextArea().scrollTo(p.lineNumber - 1, 0);
+ editor.repaint();
+ } catch (Exception e) {
+ System.err
+ .println(e
+ + " : Error while selecting text in scrollToErrorLine()");
+ e.printStackTrace();
+ }
+ // System.out.println("---");
+
+
+ }
+
+
+
/**
* Checks if import statements in the sketch have changed. If they have,
* compiler classpath needs to be updated.
@@ -1000,7 +1043,7 @@ public class ErrorCheckerService implements Runnable{
* @return String - Tab code with imports replaced with white spaces
*/
private String scrapImportStatements(String tabProgram, int tabNumber) {
-
+ //TODO: Commented out imports are still detected as main imports.
String tabSource = new String(tabProgram);
do {
// System.out.println("-->\n" + sourceAlt + "\n<--");
@@ -1025,7 +1068,7 @@ public class ErrorCheckerService implements Runnable{
programImports.add(new ImportStatement(piece, tabNumber, Base
.countLines(tabSource.substring(0, idx))));
// Remove the import from the main program
- // Substitue with white spaces
+ // Substitute with white spaces
String whiteSpace = "";
for (int j = 0; j < piece.length(); j++) {
whiteSpace += " ";
diff --git a/pdex/src/processing/mode/experimental/Problem.java b/pdex/src/processing/mode/experimental/Problem.java
old mode 100755
new mode 100644
index 6b5b95ff4..56cc0e833
--- a/pdex/src/processing/mode/experimental/Problem.java
+++ b/pdex/src/processing/mode/experimental/Problem.java
@@ -130,7 +130,7 @@ public class Problem {
public static String process(String message) {
// Remove all instances of token
// "Syntax error on token 'blah', delete this token"
-
+ if(message == null) return null;
pattern = Pattern.compile(tokenRegExp);
matcher = pattern.matcher(message);
message = matcher.replaceAll("");
diff --git a/pdex/src/processing/mode/experimental/TextArea.java b/pdex/src/processing/mode/experimental/TextArea.java
old mode 100755
new mode 100644
index 87722498a..a90d9c6b6
--- a/pdex/src/processing/mode/experimental/TextArea.java
+++ b/pdex/src/processing/mode/experimental/TextArea.java
@@ -33,318 +33,462 @@ import processing.app.syntax.TextAreaDefaults;
/**
* Customized text area. Adds support for line background colors.
- *
+ *
* @author Martin Leopold
*/
public class TextArea extends JEditTextArea {
- protected MouseListener[] mouseListeners; // cached mouselisteners, these are wrapped by MouseHandler
- protected DebugEditor editor; // the editor
- // line properties
- protected Map lineColors = new HashMap(); // contains line background colors
- // left-hand gutter properties
- protected int gutterPadding = 3; // [px] space added to the left and right of gutter chars
- protected Color gutterBgColor = new Color(252, 252, 252); // gutter background color
- protected Color gutterLineColor = new Color(233, 233, 233); // color of vertical separation line
- protected String breakpointMarker = "<>"; // the text marker for highlighting breakpoints in the gutter
- protected String currentLineMarker = "->"; // the text marker for highlighting the current line in the gutter
- protected Map gutterText = new HashMap(); // maps line index to gutter text
- protected Map gutterTextColors = new HashMap(); // maps line index to gutter text color
- protected TextAreaPainter customPainter;
- protected ErrorCheckerService errorCheckerService;
-
- public TextArea(TextAreaDefaults defaults, DebugEditor editor) {
- super(defaults);
- this.editor = editor;
+ protected MouseListener[] mouseListeners; // cached mouselisteners, these are wrapped by MouseHandler
- // replace the painter:
- // first save listeners, these are package-private in JEditTextArea, so not accessible
- ComponentListener[] componentListeners = painter.getComponentListeners();
- mouseListeners = painter.getMouseListeners();
- MouseMotionListener[] mouseMotionListeners = painter.getMouseMotionListeners();
+ protected DebugEditor editor; // the editor
- remove(painter);
+ // line properties
+ protected Map lineColors = new HashMap(); // contains line background colors
- // set new painter
- customPainter = new TextAreaPainter(this, defaults);
- painter = customPainter;
-
- // set listeners
- for (ComponentListener cl : componentListeners) {
- painter.addComponentListener(cl);
- }
+ // left-hand gutter properties
+ protected int gutterPadding = 3; // [px] space added to the left and right of gutter chars
- for (MouseMotionListener mml : mouseMotionListeners) {
- painter.addMouseMotionListener(mml);
- }
+ protected Color gutterBgColor = new Color(252, 252, 252); // gutter background color
- // use a custom mouse handler instead of directly using mouseListeners
- MouseHandler mouseHandler = new MouseHandler();
- painter.addMouseListener(mouseHandler);
- painter.addMouseMotionListener(mouseHandler);
+ protected Color gutterLineColor = new Color(233, 233, 233); // color of vertical separation line
- add(CENTER, painter);
+ protected String breakpointMarker = "<>"; // the text marker for highlighting breakpoints in the gutter
- // load settings from theme.txt
- ExperimentalMode theme = (ExperimentalMode) editor.getMode();
- gutterBgColor = theme.getThemeColor("gutter.bgcolor", gutterBgColor);
- gutterLineColor = theme.getThemeColor("gutter.linecolor", gutterLineColor);
- gutterPadding = theme.getInteger("gutter.padding");
- breakpointMarker = theme.loadThemeString("breakpoint.marker", breakpointMarker);
- currentLineMarker = theme.loadThemeString("currentline.marker", currentLineMarker);
+ protected String currentLineMarker = "->"; // the text marker for highlighting the current line in the gutter
+
+ protected Map gutterText = new HashMap(); // maps line index to gutter text
+
+ protected Map gutterTextColors = new HashMap(); // maps line index to gutter text color
+
+ protected TextAreaPainter customPainter;
+
+ protected ErrorCheckerService errorCheckerService;
+
+ public TextArea(TextAreaDefaults defaults, DebugEditor editor) {
+ super(defaults);
+ this.editor = editor;
+
+ // replace the painter:
+ // first save listeners, these are package-private in JEditTextArea, so not accessible
+ ComponentListener[] componentListeners = painter.getComponentListeners();
+ mouseListeners = painter.getMouseListeners();
+ MouseMotionListener[] mouseMotionListeners = painter
+ .getMouseMotionListeners();
+
+ remove(painter);
+
+ // set new painter
+ customPainter = new TextAreaPainter(this, defaults);
+ painter = customPainter;
+
+ // set listeners
+ for (ComponentListener cl : componentListeners) {
+ painter.addComponentListener(cl);
}
-
- /**
- * Sets ErrorCheckerService and loads theme for TextArea(XQMode)
- * @param ecs
- * @param mode
+
+ for (MouseMotionListener mml : mouseMotionListeners) {
+ painter.addMouseMotionListener(mml);
+ }
+
+ // use a custom mouse handler instead of directly using mouseListeners
+ MouseHandler mouseHandler = new MouseHandler();
+ painter.addMouseListener(mouseHandler);
+ painter.addMouseMotionListener(mouseHandler);
+
+ add(CENTER, painter);
+
+ // load settings from theme.txt
+ ExperimentalMode theme = (ExperimentalMode) editor.getMode();
+ gutterBgColor = theme.getThemeColor("gutter.bgcolor", gutterBgColor);
+ gutterLineColor = theme.getThemeColor("gutter.linecolor", gutterLineColor);
+ gutterPadding = theme.getInteger("gutter.padding");
+ breakpointMarker = theme.loadThemeString("breakpoint.marker",
+ breakpointMarker);
+ currentLineMarker = theme.loadThemeString("currentline.marker",
+ currentLineMarker);
+ }
+
+ /**
+ * Sets ErrorCheckerService and loads theme for TextArea(XQMode)
+ *
+ * @param ecs
+ * @param mode
+ */
+ public void setECSandThemeforTextArea(ErrorCheckerService ecs,
+ ExperimentalMode mode) {
+ errorCheckerService = ecs;
+ customPainter.setECSandTheme(ecs, mode);
+ }
+
+ public void processKeyEvent(KeyEvent evt) {
+ super.processKeyEvent(evt);
+ if (evt.getID() == KeyEvent.KEY_TYPED) {
+ errorCheckerService.textModified.incrementAndGet();
+ System.out.println(" Typing: " + fetchPhrase(evt) + " "
+ + (evt.getKeyChar() == KeyEvent.VK_BACK_SPACE));
+
+ }
+
+ }
+
+ private String fetchPhrase(KeyEvent evt) {
+ int off = getCaretPosition();
+ System.out.print("off " + off);
+ if (off < 0)
+ return null;
+ int line = getCaretLine();
+ if (line < 0)
+ return null;
+ String s = getLineText(line);
+ System.out.print("lin " + line);
+ /*
+ * if (s == null) return null; else if (s.length() == 0) return null;
*/
- public void setECSandThemeforTextArea(ErrorCheckerService ecs, ExperimentalMode mode)
- {
- errorCheckerService = ecs;
- customPainter.setECSandTheme(ecs, mode);
- }
-
- public void processKeyEvent(KeyEvent evt) {
- super.processKeyEvent(evt);
- if(evt.getID() == KeyEvent.KEY_TYPED){
- errorCheckerService.textModified.incrementAndGet();
- }
- }
+// else {
+ //System.out.print(s + " len " + s.length());
- /**
- * Retrieve the total width of the gutter area.
- *
- * @return gutter width in pixels
- */
- protected int getGutterWidth() {
- FontMetrics fm = painter.getFontMetrics();
+ int x = getCaretPosition() - getLineStartOffset(line) - 1, x2 = x + 1, x1 = x - 1;
+ System.out.print(" x char: " + s.charAt(x));
+ //int xLS = off - getLineStartNonWhiteSpaceOffset(line);
+ char keyChar = evt.getKeyChar();
+ if (keyChar == KeyEvent.VK_BACK_SPACE || keyChar == KeyEvent.VK_DELETE)
+ ; // accepted these keys
+ else if (keyChar == KeyEvent.CHAR_UNDEFINED)
+
+ return null;
+
+ 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);
+ errorCheckerService.astGenerator.updatePredictions(word, line
+ + errorCheckerService.mainClassOffset);
+ 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) == ')')
+ {
+
+ 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!
+ System.err.println("Whoopsy! :P");
+ 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);
+ errorCheckerService.astGenerator.updatePredictions(word, line
+ + errorCheckerService.mainClassOffset);
+ return word;
+
+ //}
+ }
+
+ /**
+ * Retrieve the total width of the gutter area.
+ *
+ * @return gutter width in pixels
+ */
+ protected int getGutterWidth() {
+ FontMetrics fm = painter.getFontMetrics();
// System.out.println("fm: " + (fm == null));
// System.out.println("editor: " + (editor == null));
- //System.out.println("BPBPBPBPB: " + (editor.breakpointMarker == null));
+ //System.out.println("BPBPBPBPB: " + (editor.breakpointMarker == null));
- int textWidth = Math.max(fm.stringWidth(breakpointMarker), fm.stringWidth(currentLineMarker));
- return textWidth + 2 * gutterPadding;
+ int textWidth = Math.max(fm.stringWidth(breakpointMarker),
+ fm.stringWidth(currentLineMarker));
+ return textWidth + 2 * gutterPadding;
+ }
+
+ /**
+ * Retrieve the width of margins applied to the left and right of the gutter
+ * text.
+ *
+ * @return margins in pixels
+ */
+ protected int getGutterMargins() {
+ return gutterPadding;
+ }
+
+ /**
+ * Set the gutter text of a specific line.
+ *
+ * @param lineIdx
+ * the line index (0-based)
+ * @param text
+ * the text
+ */
+ public void setGutterText(int lineIdx, String text) {
+ gutterText.put(lineIdx, text);
+ painter.invalidateLine(lineIdx);
+ }
+
+ /**
+ * Set the gutter text and color of a specific line.
+ *
+ * @param lineIdx
+ * the line index (0-based)
+ * @param text
+ * the text
+ * @param textColor
+ * the text color
+ */
+ public void setGutterText(int lineIdx, String text, Color textColor) {
+ gutterTextColors.put(lineIdx, textColor);
+ setGutterText(lineIdx, text);
+ }
+
+ /**
+ * Clear the gutter text of a specific line.
+ *
+ * @param lineIdx
+ * the line index (0-based)
+ */
+ public void clearGutterText(int lineIdx) {
+ gutterText.remove(lineIdx);
+ painter.invalidateLine(lineIdx);
+ }
+
+ /**
+ * Clear all gutter text.
+ */
+ public void clearGutterText() {
+ for (int lineIdx : gutterText.keySet()) {
+ painter.invalidateLine(lineIdx);
}
+ gutterText.clear();
+ }
- /**
- * Retrieve the width of margins applied to the left and right of the gutter
- * text.
- *
- * @return margins in pixels
- */
- protected int getGutterMargins() {
- return gutterPadding;
+ /**
+ * Retrieve the gutter text of a specific line.
+ *
+ * @param lineIdx
+ * the line index (0-based)
+ * @return the gutter text
+ */
+ public String getGutterText(int lineIdx) {
+ return gutterText.get(lineIdx);
+ }
+
+ /**
+ * Retrieve the gutter text color for a specific line.
+ *
+ * @param lineIdx
+ * the line index
+ * @return the gutter text color
+ */
+ public Color getGutterTextColor(int lineIdx) {
+ return gutterTextColors.get(lineIdx);
+ }
+
+ /**
+ * Set the background color of a line.
+ *
+ * @param lineIdx
+ * 0-based line number
+ * @param col
+ * the background color to set
+ */
+ public void setLineBgColor(int lineIdx, Color col) {
+ lineColors.put(lineIdx, col);
+ painter.invalidateLine(lineIdx);
+ }
+
+ /**
+ * Clear the background color of a line.
+ *
+ * @param lineIdx
+ * 0-based line number
+ */
+ public void clearLineBgColor(int lineIdx) {
+ lineColors.remove(lineIdx);
+ painter.invalidateLine(lineIdx);
+ }
+
+ /**
+ * Clear all line background colors.
+ */
+ public void clearLineBgColors() {
+ for (int lineIdx : lineColors.keySet()) {
+ painter.invalidateLine(lineIdx);
}
+ lineColors.clear();
+ }
- /**
- * Set the gutter text of a specific line.
- *
- * @param lineIdx the line index (0-based)
- * @param text the text
- */
- public void setGutterText(int lineIdx, String text) {
- gutterText.put(lineIdx, text);
- painter.invalidateLine(lineIdx);
- }
+ /**
+ * Get a lines background color.
+ *
+ * @param lineIdx
+ * 0-based line number
+ * @return the color or null if no color was set for the specified line
+ */
+ public Color getLineBgColor(int lineIdx) {
+ return lineColors.get(lineIdx);
+ }
- /**
- * Set the gutter text and color of a specific line.
- *
- * @param lineIdx the line index (0-based)
- * @param text the text
- * @param textColor the text color
- */
- public void setGutterText(int lineIdx, String text, Color textColor) {
- gutterTextColors.put(lineIdx, textColor);
- setGutterText(lineIdx, text);
- }
+ /**
+ * Convert a character offset to a horizontal pixel position inside the text
+ * area. Overridden to take gutter width into account.
+ *
+ * @param line
+ * the 0-based line number
+ * @param offset
+ * the character offset (0 is the first character on a line)
+ * @return the horizontal position
+ */
+ @Override
+ public int _offsetToX(int line, int offset) {
+ return super._offsetToX(line, offset) + getGutterWidth();
+ }
- /**
- * Clear the gutter text of a specific line.
- *
- * @param lineIdx the line index (0-based)
- */
- public void clearGutterText(int lineIdx) {
- gutterText.remove(lineIdx);
- painter.invalidateLine(lineIdx);
- }
+ /**
+ * Convert a horizontal pixel position to a character offset. Overridden to
+ * take gutter width into account.
+ *
+ * @param line
+ * the 0-based line number
+ * @param x
+ * the horizontal pixel position
+ * @return he character offset (0 is the first character on a line)
+ */
+ @Override
+ public int xToOffset(int line, int x) {
+ return super.xToOffset(line, x - getGutterWidth());
+ }
- /**
- * Clear all gutter text.
- */
- public void clearGutterText() {
- for (int lineIdx : gutterText.keySet()) {
- painter.invalidateLine(lineIdx);
- }
- gutterText.clear();
- }
+ /**
+ * Custom mouse handler. Implements double clicking in the gutter area to
+ * toggle breakpoints, sets default cursor (instead of text cursor) in the
+ * gutter area.
+ */
+ protected class MouseHandler implements MouseListener, MouseMotionListener {
- /**
- * Retrieve the gutter text of a specific line.
- *
- * @param lineIdx the line index (0-based)
- * @return the gutter text
- */
- public String getGutterText(int lineIdx) {
- return gutterText.get(lineIdx);
- }
+ protected int lastX; // previous horizontal positon of the mouse cursor
- /**
- * Retrieve the gutter text color for a specific line.
- *
- * @param lineIdx the line index
- * @return the gutter text color
- */
- public Color getGutterTextColor(int lineIdx) {
- return gutterTextColors.get(lineIdx);
- }
-
- /**
- * Set the background color of a line.
- *
- * @param lineIdx 0-based line number
- * @param col the background color to set
- */
- public void setLineBgColor(int lineIdx, Color col) {
- lineColors.put(lineIdx, col);
- painter.invalidateLine(lineIdx);
- }
-
- /**
- * Clear the background color of a line.
- *
- * @param lineIdx 0-based line number
- */
- public void clearLineBgColor(int lineIdx) {
- lineColors.remove(lineIdx);
- painter.invalidateLine(lineIdx);
- }
-
- /**
- * Clear all line background colors.
- */
- public void clearLineBgColors() {
- for (int lineIdx : lineColors.keySet()) {
- painter.invalidateLine(lineIdx);
- }
- lineColors.clear();
- }
-
- /**
- * Get a lines background color.
- *
- * @param lineIdx 0-based line number
- * @return the color or null if no color was set for the specified line
- */
- public Color getLineBgColor(int lineIdx) {
- return lineColors.get(lineIdx);
- }
-
- /**
- * Convert a character offset to a horizontal pixel position inside the text
- * area. Overridden to take gutter width into account.
- *
- * @param line the 0-based line number
- * @param offset the character offset (0 is the first character on a line)
- * @return the horizontal position
- */
@Override
- public int _offsetToX(int line, int offset) {
- return super._offsetToX(line, offset) + getGutterWidth();
+ public void mouseClicked(MouseEvent me) {
+ // forward to standard listeners
+ for (MouseListener ml : mouseListeners) {
+ ml.mouseClicked(me);
+ }
}
- /**
- * Convert a horizontal pixel position to a character offset. Overridden to
- * take gutter width into account.
- *
- * @param line the 0-based line number
- * @param x the horizontal pixel position
- * @return he character offset (0 is the first character on a line)
- */
@Override
- public int xToOffset(int line, int x) {
- return super.xToOffset(line, x - getGutterWidth());
+ public void mousePressed(MouseEvent me) {
+ // check if this happened in the gutter area
+ if (me.getX() < getGutterWidth()) {
+ if (me.getButton() == MouseEvent.BUTTON1 && me.getClickCount() == 2) {
+ int line = me.getY() / painter.getFontMetrics().getHeight()
+ + firstLine;
+ if (line >= 0 && line <= getLineCount() - 1) {
+ editor.gutterDblClicked(line);
+ }
+ }
+ } else {
+ // forward to standard listeners
+ for (MouseListener ml : mouseListeners) {
+ ml.mousePressed(me);
+ }
+ }
}
- /**
- * Custom mouse handler. Implements double clicking in the gutter area to
- * toggle breakpoints, sets default cursor (instead of text cursor) in the
- * gutter area.
- */
- protected class MouseHandler implements MouseListener, MouseMotionListener {
-
- protected int lastX; // previous horizontal positon of the mouse cursor
-
- @Override
- public void mouseClicked(MouseEvent me) {
- // forward to standard listeners
- for (MouseListener ml : mouseListeners) {
- ml.mouseClicked(me);
- }
- }
-
- @Override
- public void mousePressed(MouseEvent me) {
- // check if this happened in the gutter area
- if (me.getX() < getGutterWidth()) {
- if (me.getButton() == MouseEvent.BUTTON1 && me.getClickCount() == 2) {
- int line = me.getY() / painter.getFontMetrics().getHeight() + firstLine;
- if (line >= 0 && line <= getLineCount() - 1) {
- editor.gutterDblClicked(line);
- }
- }
- } else {
- // forward to standard listeners
- for (MouseListener ml : mouseListeners) {
- ml.mousePressed(me);
- }
- }
- }
-
- @Override
- public void mouseReleased(MouseEvent me) {
- // forward to standard listeners
- for (MouseListener ml : mouseListeners) {
- ml.mouseReleased(me);
- }
- }
-
- @Override
- public void mouseEntered(MouseEvent me) {
- // forward to standard listeners
- for (MouseListener ml : mouseListeners) {
- ml.mouseEntered(me);
- }
- }
-
- @Override
- public void mouseExited(MouseEvent me) {
- // forward to standard listeners
- for (MouseListener ml : mouseListeners) {
- ml.mouseExited(me);
- }
- }
-
- @Override
- public void mouseDragged(MouseEvent me) {
- // No need to forward since the standard MouseMotionListeners are called anyway
- // nop
- }
-
- @Override
- public void mouseMoved(MouseEvent me) {
- // No need to forward since the standard MouseMotionListeners are called anyway
- if (me.getX() < getGutterWidth()) {
- if (lastX >= getGutterWidth()) {
- painter.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
- }
- } else {
- if (lastX < getGutterWidth()) {
- painter.setCursor(new Cursor(Cursor.TEXT_CURSOR));
- }
- }
- lastX = me.getX();
- }
+ @Override
+ public void mouseReleased(MouseEvent me) {
+ // forward to standard listeners
+ for (MouseListener ml : mouseListeners) {
+ ml.mouseReleased(me);
+ }
}
+
+ @Override
+ public void mouseEntered(MouseEvent me) {
+ // forward to standard listeners
+ for (MouseListener ml : mouseListeners) {
+ ml.mouseEntered(me);
+ }
+ }
+
+ @Override
+ public void mouseExited(MouseEvent me) {
+ // forward to standard listeners
+ for (MouseListener ml : mouseListeners) {
+ ml.mouseExited(me);
+ }
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent me) {
+ // No need to forward since the standard MouseMotionListeners are called anyway
+ // nop
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent me) {
+ // No need to forward since the standard MouseMotionListeners are called anyway
+ if (me.getX() < getGutterWidth()) {
+ if (lastX >= getGutterWidth()) {
+ painter.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+ } else {
+ if (lastX < getGutterWidth()) {
+ painter.setCursor(new Cursor(Cursor.TEXT_CURSOR));
+ }
+ }
+ lastX = me.getX();
+ }
+ }
+
}
diff --git a/pdex/src/processing/mode/experimental/TextAreaPainter.java b/pdex/src/processing/mode/experimental/TextAreaPainter.java
old mode 100755
new mode 100644
index 8c93978f2..76dd2b3c6
--- a/pdex/src/processing/mode/experimental/TextAreaPainter.java
+++ b/pdex/src/processing/mode/experimental/TextAreaPainter.java
@@ -19,6 +19,13 @@ package processing.mode.experimental;
import java.awt.Color;
import java.awt.Graphics;
+import java.awt.Toolkit;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Segment;
@@ -26,293 +33,457 @@ import javax.swing.text.Utilities;
import processing.app.syntax.TextAreaDefaults;
import processing.app.syntax.TokenMarker;
+import processing.mode.experimental.ASTGenerator.ASTNodeWrapper;
/**
* Customized line painter. Adds support for background colors, left hand gutter
* area with background color and text.
- *
+ *
* @author Martin Leopold
*/
public class TextAreaPainter extends processing.app.syntax.TextAreaPainter {
- protected TextArea ta; // we need the subclassed textarea
- protected ErrorCheckerService errorCheckerService;
-
- /**
- * Error line underline color
- */
- public Color errorColor = new Color(0xED2630);
+ protected TextArea ta; // we need the subclassed textarea
- /**
- * Warning line underline color
- */
+ protected ErrorCheckerService errorCheckerService;
- public Color warningColor = new Color(0xFFC30E);
+ /**
+ * Error line underline color
+ */
+ public Color errorColor = new Color(0xED2630);
- /**
- * Color of Error Marker
- */
- public Color errorMarkerColor = new Color(0xED2630);
+ /**
+ * Warning line underline color
+ */
- /**
- * Color of Warning Marker
- */
- public Color warningMarkerColor = new Color(0xFFC30E);
-
- public TextAreaPainter(TextArea textArea, TextAreaDefaults defaults) {
- super(textArea, defaults);
- ta = textArea;
- }
-
- private void loadTheme(ExperimentalMode mode){
- errorColor = mode.getThemeColor("editor.errorcolor", errorColor);
- warningColor = mode.getThemeColor("editor.warningcolor",
- warningColor);
- errorMarkerColor = mode.getThemeColor("editor.errormarkercolor",
- errorMarkerColor);
- warningMarkerColor = mode.getThemeColor(
- "editor.warningmarkercolor", warningMarkerColor);
- }
+ public Color warningColor = new Color(0xFFC30E);
- /**
- * Paint a line. Paints the gutter (with background color and text) then the
- * line (background color and text).
- *
- * @param gfx the graphics context
- * @param tokenMarker
- * @param line 0-based line number
- * @param x horizontal position
- */
- @Override
- protected void paintLine(Graphics gfx, TokenMarker tokenMarker,
- int line, int x) {
+ /**
+ * Color of Error Marker
+ */
+ public Color errorMarkerColor = new Color(0xED2630);
- // paint gutter
- paintGutterBg(gfx, line, x);
+ /**
+ * Color of Warning Marker
+ */
+ public Color warningMarkerColor = new Color(0xFFC30E);
- paintLineBgColor(gfx, line, x + ta.getGutterWidth());
+ static int ctrlMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- paintGutterLine(gfx, line, x);
-
- // paint gutter symbol
- paintGutterText(gfx, line, x);
-
- paintErrorLine(gfx, line, x);
-
- super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth());
- }
-
- /**
- * Paint the gutter background (solid color).
- *
- * @param gfx the graphics context
- * @param line 0-based line number
- * @param x horizontal position
- */
- protected void paintGutterBg(Graphics gfx, int line, int x) {
- gfx.setColor(ta.gutterBgColor);
- int y = ta.lineToY(line) + fm.getLeading() + fm.getMaxDescent();
- gfx.fillRect(0, y, ta.getGutterWidth(), fm.getHeight());
- }
-
- /**
- * Paint the vertical gutter separator line.
- *
- * @param gfx the graphics context
- * @param line 0-based line number
- * @param x horizontal position
- */
- protected void paintGutterLine(Graphics gfx, int line, int x) {
- int y = ta.lineToY(line) + fm.getLeading() + fm.getMaxDescent();
- gfx.setColor(ta.gutterLineColor);
- gfx.drawLine(ta.getGutterWidth(), y, ta.getGutterWidth(), y + fm.getHeight());
- }
-
- /**
- * Paint the gutter text.
- *
- * @param gfx the graphics context
- * @param line 0-based line number
- * @param x horizontal position
- */
- protected void paintGutterText(Graphics gfx, int line, int x) {
- String text = ta.getGutterText(line);
- if (text == null) {
- return;
- }
-
- gfx.setFont(getFont());
- Color textColor = ta.getGutterTextColor(line);
- if (textColor == null) {
- gfx.setColor(getForeground());
- } else {
- gfx.setColor(textColor);
- }
- int y = ta.lineToY(line) + fm.getHeight();
-
- // draw 4 times to make it appear bold, displaced 1px to the right, to the bottom and bottom right.
- //int len = text.length() > ta.gutterChars ? ta.gutterChars : text.length();
- Utilities.drawTabbedText(new Segment(text.toCharArray(), 0, text.length()), ta.getGutterMargins(), y, gfx, this, 0);
- Utilities.drawTabbedText(new Segment(text.toCharArray(), 0, text.length()), ta.getGutterMargins() + 1, y, gfx, this, 0);
- Utilities.drawTabbedText(new Segment(text.toCharArray(), 0, text.length()), ta.getGutterMargins(), y + 1, gfx, this, 0);
- Utilities.drawTabbedText(new Segment(text.toCharArray(), 0, text.length()), ta.getGutterMargins() + 1, y + 1, gfx, this, 0);
- }
-
- /**
- * Paint the background color of a line.
- *
- * @param gfx the graphics context
- * @param line 0-based line number
- * @param x
- */
- protected void paintLineBgColor(Graphics gfx, int line, int x) {
- int y = ta.lineToY(line);
- y += fm.getLeading() + fm.getMaxDescent();
- int height = fm.getHeight();
-
- // get the color
- Color col = ta.getLineBgColor(line);
- //System.out.print("bg line " + line + ": ");
- // no need to paint anything
- if (col == null) {
- //System.out.println("none");
- return;
- }
- // paint line background
- gfx.setColor(col);
- gfx.fillRect(0, y, getWidth(), height);
- }
-
- /**
- * Paints the underline for an error/warning line
- *
- * @param gfx
- * the graphics context
- * @param tokenMarker
- * @param line
- * 0-based line number: NOTE
- * @param x
- */
- protected void paintErrorLine(Graphics gfx, int line, int x) {
-
- if (errorCheckerService == null) {
- return;
+ public TextAreaPainter(TextArea textArea, TextAreaDefaults defaults) {
+ super(textArea, defaults);
+ ta = textArea;
+ addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent evt) {
+// System.out.println( " Meta,Ctrl "+ (evt.getModifiers() & ctrlMask));
+ if (evt.isControlDown())
+ handleCtrlClick(evt);
}
-
- if (errorCheckerService.problemsList== null) {
- return;
- }
-
- boolean notFound = true;
- boolean isWarning = false;
+ });
- // 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) {
- notFound = false;
- if (emarker.type == ErrorMarker.Warning) {
- isWarning = true;
- }
+ }
+
+// public void processKeyEvent(KeyEvent evt) {
+// System.out.println(evt);
+// }
+
+ void handleCtrlClick(MouseEvent evt) {
+ System.out.println("--handleCtrlClick--");
+ int off = ta.xyToOffset(evt.getX(), evt.getY());
+ if (off < 0)
+ return;
+ int line = ta.getLineOfOffset(off);
+ if (line < 0)
+ return;
+ String s = ta.getLineText(line);
+ if (s == null)
+ return;
+ else if (s.length() == 0)
+ return;
+ else {
+ int x = ta.xToOffset(line, evt.getX()), x2 = x + 1, x1 = x - 1;
+ int xLS = off - ta.getLineStartNonWhiteSpaceOffset(line);
+ if (x < 0 || x >= s.length())
+ return;
+ String word = s.charAt(x) + "";
+ if (s.charAt(x) == ' ')
+ return;
+ if (!(Character.isLetterOrDigit(s.charAt(x)) || s.charAt(x) == '_' || s
+ .charAt(x) == '$'))
+ return;
+ int i = 0;
+ while (true) {
+ i++;
+ if (x1 >= 0 && x1 < s.length()) {
+ if (Character.isLetter(s.charAt(x1)) || s.charAt(x1) == '_') {
+ word = s.charAt(x1--) + word;
+ } else
+ x1 = -1;
+ } else
+ x1 = -1;
+
+ 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!
+ System.err.println("Whoopsy! :P");
break;
}
}
-
- if (notFound) {
+ if (Character.isDigit(word.charAt(0)))
return;
+
+ System.out.print(errorCheckerService.mainClassOffset + line);
+ System.out.print("|" + line + "| offset " + xLS + word + " <= \n");
+ errorCheckerService.astGenerator.scrollToDeclaration(line
+ + errorCheckerService.mainClassOffset, word, xLS);
+ }
+ }
+
+ private void loadTheme(ExperimentalMode mode) {
+ errorColor = mode.getThemeColor("editor.errorcolor", errorColor);
+ warningColor = mode.getThemeColor("editor.warningcolor", warningColor);
+ errorMarkerColor = mode.getThemeColor("editor.errormarkercolor",
+ errorMarkerColor);
+ warningMarkerColor = mode.getThemeColor("editor.warningmarkercolor",
+ warningMarkerColor);
+ }
+
+ /**
+ * Paint a line. Paints the gutter (with background color and text) then the
+ * line (background color and text).
+ *
+ * @param gfx
+ * the graphics context
+ * @param tokenMarker
+ * @param line
+ * 0-based line number
+ * @param x
+ * horizontal position
+ */
+ @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);
+
+ paintErrorLine(gfx, line, x);
+
+ super.paintLine(gfx, tokenMarker, line, x + ta.getGutterWidth());
+ }
+
+ /**
+ * Paint the gutter background (solid color).
+ *
+ * @param gfx
+ * the graphics context
+ * @param line
+ * 0-based line number
+ * @param x
+ * horizontal position
+ */
+ protected void paintGutterBg(Graphics gfx, int line, int x) {
+ gfx.setColor(ta.gutterBgColor);
+ int y = ta.lineToY(line) + fm.getLeading() + fm.getMaxDescent();
+ gfx.fillRect(0, y, ta.getGutterWidth(), fm.getHeight());
+ }
+
+ /**
+ * Paint the vertical gutter separator line.
+ *
+ * @param gfx
+ * the graphics context
+ * @param line
+ * 0-based line number
+ * @param x
+ * horizontal position
+ */
+ protected void paintGutterLine(Graphics gfx, int line, int x) {
+ int y = ta.lineToY(line) + fm.getLeading() + fm.getMaxDescent();
+ gfx.setColor(ta.gutterLineColor);
+ gfx.drawLine(ta.getGutterWidth(), y, ta.getGutterWidth(),
+ y + fm.getHeight());
+ }
+
+ /**
+ * Paint the gutter text.
+ *
+ * @param gfx
+ * the graphics context
+ * @param line
+ * 0-based line number
+ * @param x
+ * horizontal position
+ */
+ protected void paintGutterText(Graphics gfx, int line, int x) {
+ String text = ta.getGutterText(line);
+ if (text == null) {
+ return;
+ }
+
+ gfx.setFont(getFont());
+ Color textColor = ta.getGutterTextColor(line);
+ if (textColor == null) {
+ gfx.setColor(getForeground());
+ } else {
+ gfx.setColor(textColor);
+ }
+ int y = ta.lineToY(line) + fm.getHeight();
+
+ // draw 4 times to make it appear bold, displaced 1px to the right, to the bottom and bottom right.
+ //int len = text.length() > ta.gutterChars ? ta.gutterChars : text.length();
+ Utilities.drawTabbedText(new Segment(text.toCharArray(), 0, text.length()),
+ ta.getGutterMargins(), y, gfx, this, 0);
+ Utilities.drawTabbedText(new Segment(text.toCharArray(), 0, text.length()),
+ ta.getGutterMargins() + 1, y, gfx, this, 0);
+ Utilities.drawTabbedText(new Segment(text.toCharArray(), 0, text.length()),
+ ta.getGutterMargins(), y + 1, gfx, this, 0);
+ Utilities.drawTabbedText(new Segment(text.toCharArray(), 0, text.length()),
+ ta.getGutterMargins() + 1, y + 1, gfx, this, 0);
+ }
+
+ /**
+ * Paint the background color of a line.
+ *
+ * @param gfx
+ * the graphics context
+ * @param line
+ * 0-based line number
+ * @param x
+ */
+ protected void paintLineBgColor(Graphics gfx, int line, int x) {
+ int y = ta.lineToY(line);
+ y += fm.getLeading() + fm.getMaxDescent();
+ int height = fm.getHeight();
+
+ // get the color
+ Color col = ta.getLineBgColor(line);
+ //System.out.print("bg line " + line + ": ");
+ // no need to paint anything
+ if (col == null) {
+ //System.out.println("none");
+ return;
+ }
+ // paint line background
+ gfx.setColor(col);
+ gfx.fillRect(0, y, getWidth(), height);
+ }
+
+ /**
+ * Paints the underline for an error/warning line
+ *
+ * @param gfx
+ * the graphics context
+ * @param tokenMarker
+ * @param line
+ * 0-based line number: NOTE
+ * @param x
+ */
+ protected void paintErrorLine(Graphics gfx, int line, int x) {
+
+ if (errorCheckerService == null) {
+ return;
+ }
+
+ if (errorCheckerService.problemsList == null) {
+ return;
+ }
+
+ boolean notFound = true;
+ boolean isWarning = false;
+
+ // 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) {
+ notFound = false;
+ if (emarker.type == ErrorMarker.Warning) {
+ isWarning = true;
+ }
+ break;
}
-
- // Determine co-ordinates
- // System.out.println("Hoff " + ta.getHorizontalOffset() + ", " +
- // horizontalAdjustment);
- int y = ta.lineToY(line);
- y += fm.getLeading() + fm.getMaxDescent();
- int height = fm.getHeight();
- int start = ta.getLineStartOffset(line);
+ }
+
+ if (notFound) {
+ return;
+ }
+
+ // Determine co-ordinates
+ // System.out.println("Hoff " + ta.getHorizontalOffset() + ", " +
+ // horizontalAdjustment);
+ int y = ta.lineToY(line);
+ y += fm.getLeading() + fm.getMaxDescent();
+ int height = fm.getHeight();
+ int start = ta.getLineStartOffset(line);
+
+ try {
+ String linetext = null;
try {
- String linetext = null;
-
- try {
- linetext = ta.getDocument().getText(start,
- ta.getLineStopOffset(line) - start - 1);
- } catch (BadLocationException bl) {
- // Error in the import statements or end of code.
- // System.out.print("BL caught. " + ta.getLineCount() + " ,"
- // + line + " ,");
- // System.out.println((ta.getLineStopOffset(line) - start - 1));
- return;
- }
-
- // Take care of offsets
- int aw = fm.stringWidth(trimRight(linetext))
- + 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;
- // Adding offsets for the gutter
- x1 += 20;
- x2 += 20;
-
- // 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);
-
- gfx.setColor(errorColor);
- if (isWarning) {
- gfx.setColor(warningColor);
- }
- int xx = x1;
-
- // Draw the jagged lines
- while (xx < x2) {
- gfx.drawLine(xx, y1, xx + 2, y1 + 1);
- xx += 2;
- gfx.drawLine(xx, y1 + 1, xx + 2, y1);
- xx += 2;
- }
- } catch (Exception e) {
- System.out
- .println("Looks like I messed up! XQTextAreaPainter.paintLine() : "
- + e);
- //e.printStackTrace();
+ linetext = ta.getDocument().getText(start,
+ ta.getLineStopOffset(line) - start
+ - 1);
+ } catch (BadLocationException bl) {
+ // Error in the import statements or end of code.
+ // System.out.print("BL caught. " + ta.getLineCount() + " ,"
+ // + line + " ,");
+ // System.out.println((ta.getLineStopOffset(line) - start - 1));
+ return;
}
- // Won't highlight the line. Select the text instead.
- // gfx.setColor(Color.RED);
- // gfx.fillRect(2, y, 3, height);
+ // Take care of offsets
+ int aw = fm.stringWidth(trimRight(linetext)) + 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;
+ // Adding offsets for the gutter
+ x1 += 20;
+ x2 += 20;
+
+ // 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);
+
+ gfx.setColor(errorColor);
+ if (isWarning) {
+ gfx.setColor(warningColor);
+ }
+ int xx = x1;
+
+ // Draw the jagged lines
+ while (xx < x2) {
+ gfx.drawLine(xx, y1, xx + 2, y1 + 1);
+ xx += 2;
+ gfx.drawLine(xx, y1 + 1, xx + 2, y1);
+ xx += 2;
+ }
+ } catch (Exception e) {
+ System.out
+ .println("Looks like I messed up! XQTextAreaPainter.paintLine() : "
+ + e);
+ //e.printStackTrace();
}
-
- /**
- * Trims out trailing whitespaces (to the right)
- *
- * @param string
- * @return - String
- */
- private String trimRight(String string) {
- String newString = "";
- for (int i = 0; i < string.length(); i++) {
- if (string.charAt(i) != ' ') {
- newString = string.substring(0, i) + string.trim();
+
+ // Won't highlight the line. Select the text instead.
+ // gfx.setColor(Color.RED);
+ // gfx.fillRect(2, y, 3, height);
+ }
+
+ /**
+ * Trims out trailing whitespaces (to the right)
+ *
+ * @param string
+ * @return - String
+ */
+ private String trimRight(String string) {
+ String newString = "";
+ for (int i = 0; i < string.length(); i++) {
+ if (string.charAt(i) != ' ') {
+ newString = string.substring(0, i) + string.trim();
+ break;
+ }
+ }
+ return newString;
+ }
+
+ /**
+ * Sets ErrorCheckerService and loads theme for TextAreaPainter(XQMode)
+ *
+ * @param ecs
+ * @param mode
+ */
+ public void setECSandTheme(ErrorCheckerService ecs, ExperimentalMode mode) {
+ this.errorCheckerService = ecs;
+ loadTheme(mode);
+ }
+
+ public String getToolTipText(java.awt.event.MouseEvent evt) {System.err.println("GET");
+ int off = ta.xyToOffset(evt.getX(), evt.getY());
+ if (off < 0)
+ return null;
+ int line = ta.getLineOfOffset(off);
+ if (line < 0)
+ return null;
+ String s = ta.getLineText(line);
+ if (s == null)
+ return evt.toString();
+ else if (s.length() == 0)
+ return null;
+ else {
+ int x = ta.xToOffset(line, evt.getX()), x2 = x + 1, x1 = x - 1;
+ int xLS = off - ta.getLineStartNonWhiteSpaceOffset(line);
+ if (x < 0 || x >= s.length())
+ return null;
+ String word = s.charAt(x) + "";
+ if (s.charAt(x) == ' ')
+ return null;
+ if (!(Character.isLetterOrDigit(s.charAt(x)) || s.charAt(x) == '_' || s
+ .charAt(x) == '$'))
+ return null;
+ int i = 0;
+ while (true) {
+ i++;
+ if (x1 >= 0 && x1 < s.length()) {
+ if (Character.isLetter(s.charAt(x1)) || s.charAt(x1) == '_') {
+ word = s.charAt(x1--) + word;
+ } else
+ x1 = -1;
+ } else
+ x1 = -1;
+
+ 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!
+ System.err.println("Whoopsy! :P");
break;
}
}
- return newString;
- }
-
- /**
- * Sets ErrorCheckerService and loads theme for TextAreaPainter(XQMode)
- * @param ecs
- * @param mode
- */
- public void setECSandTheme(ErrorCheckerService ecs, ExperimentalMode mode){
- this.errorCheckerService = ecs;
- loadTheme(mode);
+ if (Character.isDigit(word.charAt(0)))
+ return null;
+ String tooltipText = errorCheckerService.astGenerator
+ .getLabelForASTNode(line + errorCheckerService.mainClassOffset, word,
+ xLS);
+
+ System.out.print(errorCheckerService.mainClassOffset + " MCO ");
+ System.out.print("|" + line + "| offset " + xLS + word + " <= offf: "+off+ "\n");
+ if (tooltipText != null)
+ return tooltipText;
+ return word;
}
+
+ }
+
}
diff --git a/pdex/src/processing/mode/experimental/XQPreprocessor.java b/pdex/src/processing/mode/experimental/XQPreprocessor.java
index cc263072f..34ee2a9a2 100755
--- a/pdex/src/processing/mode/experimental/XQPreprocessor.java
+++ b/pdex/src/processing/mode/experimental/XQPreprocessor.java
@@ -55,7 +55,6 @@ import processing.mode.java.preproc.PdePreprocessor;
public class XQPreprocessor {
private ASTRewrite rewrite = null;
- public int mainClassOffset = 0;
private ArrayList imports;
private ArrayList extraImports;
@@ -76,7 +75,7 @@ public class XQPreprocessor {
public String doYourThing(String source,
ArrayList programImports) {
this.extraImports = programImports;
- source = prepareImports() + source;
+ //source = prepareImports() + source;
Document doc = new Document(source);
ASTParser parser = ASTParser.newParser(AST.JLS4);
@@ -117,7 +116,6 @@ public class XQPreprocessor {
}
lines += 2;
// System.out.println("Lines: " + lines);
- mainClassOffset = lines;
return doc.get();
}
@@ -146,6 +144,11 @@ public class XQPreprocessor {
totalImports += "\n";
return totalImports;
}
+
+ public String prepareImports(ArrayList programImports) {
+ this.extraImports = programImports;
+ return prepareImports();
+ }
/**
* Visitor implementation that does all the substitution dirty work.