ECS: remove ASTNodeWrapper and old offset mapping

This commit is contained in:
Jakub Valtar
2016-04-11 03:12:28 +02:00
parent ec68e7cb71
commit 70b5e4824f
5 changed files with 154 additions and 1495 deletions

View File

@@ -436,6 +436,7 @@ public class ASTGenerator {
}
}
break;
case ASTNode.QUALIFIED_NAME:
QualifiedName qn = (QualifiedName) astNode;
ASTNode temp2 = findDeclaration2(qn.getName(), nearestNode);
@@ -752,7 +753,7 @@ public class ASTGenerator {
log("Looking in the classloader for " + className);
// TODO: get this from last code check result
List<ImportStatement> imports = Collections.emptyList(); //errorCheckerService.getProgramImports();
List<ImportStatement> imports = errorCheckerService.latestResult.programImports;
for (ImportStatement impS : imports) {
String temp = impS.getPackageName();
@@ -776,7 +777,7 @@ public class ASTGenerator {
}
// TODO: get this from last code check result
List<ImportStatement> codeFolderImports = Collections.emptyList();
List<ImportStatement> codeFolderImports = errorCheckerService.latestResult.codeFolderImports;
for (ImportStatement impS : codeFolderImports) {
String temp = impS.getPackageName();
if (impS.isStarredImport()) { // case of starred import: pkg.foo.*
@@ -798,26 +799,28 @@ public class ASTGenerator {
//log("Doesn't exist in (code folder) imp package: " + impS.getImportName());
}
// PdePreprocessor p = new PdePreprocessor(null);
PdePreprocessor p = editor.createPreprocessor(null);
for (String impS : p.getCoreImports()) {
tehClass = loadClass(impS.substring(0,impS.length()-1) + className);
// TODO: get this from last code check result
List<ImportStatement> coreAndDefaultImports =
errorCheckerService.latestResult.coreAndDefaultImports;
for (ImportStatement impS : coreAndDefaultImports) {
String temp = impS.getPackageName();
if (impS.isStarredImport()) { // case of starred import: pkg.foo.*
if (className.indexOf('.') == -1) {
temp = impS.getPackageName() + "." + className;
} else {
continue;
}
} else { // case of class import: pkg.foo.MyClass
if (!impS.getClassName().equals(className)) {
continue;
}
}
tehClass = loadClass(temp);
if (tehClass != null) {
log(tehClass.getName() + " located.");
return tehClass;
}
//log("Doesn't exist in package: " + impS);
}
for (String impS : p.getDefaultImports()) {
if(className.equals(impS) || impS.endsWith(className)){
tehClass = loadClass(impS);
if (tehClass != null) {
log(tehClass.getName() + " located.");
return tehClass;
}
// log("Doesn't exist in package: " + impS);
}
//log("Doesn't exist in (code folder) imp package: " + impS.getImportName());
}
// And finally, the daddy
@@ -837,9 +840,8 @@ public class ASTGenerator {
if (className != null) {
try {
// TODO: get the class loader from the last code check result
/*tehClass = Class.forName(className, false,
errorCheckerService.getSketchClassLoader());*/
tehClass = Class.forName(className);
tehClass = Class.forName(className, false,
errorCheckerService.latestResult.classLoader);
} catch (ClassNotFoundException e) {
//log("Doesn't exist in package: ");
}
@@ -982,17 +984,12 @@ public class ASTGenerator {
}
public String getLabelForASTNode(int lineNumber, String name, int offset) {
return getASTNodeAt(lineNumber, name, offset, false).getLabel();
//return "";
}
protected String getLabelIfType(ASTNodeWrapper node, SimpleName sn){
ASTNode current = node.getNode().getParent();
protected String getLabelIfType(ASTNode node){
ASTNode current = node.getParent();
String type = "";
StringBuilder fullName = new StringBuilder();
Stack<String> parents = new Stack<>();
String simpleName = (sn == null) ? node.getNode().toString() : sn.toString();
String simpleName = node.toString();
switch (node.getNodeType()) {
case ASTNode.TYPE_DECLARATION:
case ASTNode.METHOD_DECLARATION:
@@ -1007,8 +1004,8 @@ public class ASTGenerator {
fullName.append(parents.pop()).append(".");
}
fullName.append(simpleName);
if (node.getNode() instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) node.getNode();
if (node instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) node;
if (!md.isConstructor())
type = md.getReturnType2().toString();
fullName.append('(');
@@ -1025,22 +1022,22 @@ public class ASTGenerator {
fullName.deleteCharAt(fullName.length() - 1);
fullName.append(')');
}
else if(node.getNode() instanceof FieldDeclaration){
type = ((FieldDeclaration) node.getNode()).getType().toString();
else if(node instanceof FieldDeclaration){
type = ((FieldDeclaration) node).getType().toString();
}
int x = fullName.indexOf(".");
fullName.delete(0, x + 1);
return type + " " + fullName;
case ASTNode.SINGLE_VARIABLE_DECLARATION:
SingleVariableDeclaration svd = (SingleVariableDeclaration)node.getNode();
SingleVariableDeclaration svd = (SingleVariableDeclaration)node;
return svd.getType() + " " + svd.getName();
case ASTNode.VARIABLE_DECLARATION_STATEMENT:
return ((VariableDeclarationStatement) node.getNode()).getType() + " "
return ((VariableDeclarationStatement) node).getType() + " "
+ simpleName;
case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
return ((VariableDeclarationExpression) node.getNode()).getType() + " "
return ((VariableDeclarationExpression) node).getType() + " "
+ simpleName;
default:
break;
@@ -1059,7 +1056,8 @@ public class ASTGenerator {
* @param scrollOnly
* @return
*/
public ASTNodeWrapper getASTNodeAt(int lineNumber, String name, int offset,
// TODO: nuke this in favor of NodeFinder
public ASTNode getASTNodeAt(int lineNumber, String name, int offset,
boolean scrollOnly) {
// Convert tab based pde line number to actual line number
@@ -1087,8 +1085,9 @@ public class ASTGenerator {
// Obtain correspondin java code at that line, match offsets
if (lineNode != null) {
String pdeCodeLine = errorCheckerService.getPdeCodeAtLine(editor
.getSketch().getCurrentCodeIndex(), lineNumber);
// TODO
String pdeCodeLine = ""; //errorCheckerService.getPdeCodeAtLine(editor
// .getSketch().getCurrentCodeIndex(), lineNumber);
String javaCodeLine = getJavaSourceCodeLine(pdeLineNumber);
// log(lineNumber + " Original Line num.\nPDE :" + pdeCodeLine);
@@ -1115,8 +1114,7 @@ public class ASTGenerator {
case ASTNode.FIELD_DECLARATION:
case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
decl = lineNode.getParent();
return new ASTNodeWrapper(decl, "");
return lineNode.getParent();
default:
break;
}
@@ -1129,8 +1127,7 @@ public class ASTGenerator {
decl = findDeclaration((SimpleName) simpName);
if (decl != null) {
// Base.loge("DECLA: " + decl.getClass().getName());
nodeLabel = getLabelIfType(new ASTNodeWrapper(decl),
(SimpleName) simpName);
nodeLabel = getLabelIfType(decl);
//retLabelString = getNodeAsString(decl);
} else {
if (scrollOnly) {
@@ -1166,18 +1163,11 @@ public class ASTGenerator {
* since it contains all the properties.
*/
ASTNode simpName2 = getNodeName(decl, nameOfNode);
// Base.loge("FINAL String decl: " + getNodeAsString(decl));
// Base.loge("FINAL String label: " + getNodeAsString(simpName2));
//errorCheckerService.highlightNode(simpName2);
ASTNodeWrapper declWrap = new ASTNodeWrapper(simpName2, nodeLabel);
//errorCheckerService.highlightNode(declWrap);
if (!declWrap.highlightNode(editor)) {
Messages.loge("Highlighting failed.");
}
// TODO: highlight ASTNode (should not be here though)
}
// Return the declaration wrapped as ASTNodeWrapper
return new ASTNodeWrapper(decl, nodeLabel);
return decl;
}
/**
@@ -1234,52 +1224,7 @@ public class ASTGenerator {
return ((CompilationUnit) node.getRoot()).getLineNumber(pos);
}
// public static void main(String[] args) {
// traversal2();
// }
//
// 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<String, String> 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);
// log(CompilationUnit.propertyDescriptors(AST.JLS4).size());
//
// DefaultMutableTreeNode astTree = new DefaultMutableTreeNode("CompilationUnit");
// Base.loge("Errors: " + cu.getProblems().length);
// visitRecur(cu, astTree);
// Base.log("" + 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) {
// Base.log(found.toString());
// }
// }
// TODO: nuke and reimplement
protected void refactorIt(String newName){
String selText = lastClickedWord == null ? getSelectedText()
: lastClickedWord;
@@ -1316,22 +1261,22 @@ public class ASTGenerator {
//int offsetsMap[][][] = new int[defCU.getChildCount()][2][];
int pdeOffsets[][] = new int[defCU.getChildCount()][3];
for (int i = 0; i < defCU.getChildCount(); i++) {
ASTNodeWrapper awrap = (ASTNodeWrapper) ((DefaultMutableTreeNode) (defCU
ASTNode awrap = (ASTNode) ((DefaultMutableTreeNode) (defCU
.getChildAt(i))).getUserObject();
int ans[] = errorCheckerService.calculateTabIndexAndLineNumber(awrap
/*int ans[] = errorCheckerService.calculateTabIndexAndLineNumber(awrap
.getLineNumber());
pdeOffsets[i][0] = ans[0];
pdeOffsets[i][1] = ans[1];
pdeOffsets[i][2] = awrap.getPDECodeOffsetForSN(this);
pdeOffsets[i][2] = awrap.getPDECodeOffsetForSN(this);*/
}
editor.startCompoundEdit();
for (int i = 0; i < defCU.getChildCount(); i++) {
ASTNodeWrapper awrap = (ASTNodeWrapper) ((DefaultMutableTreeNode) (defCU
ASTNode awrap = (ASTNode) ((DefaultMutableTreeNode) (defCU
.getChildAt(i))).getUserObject();
// correction for pde enhancements related displacement on a line
int off = 0;
if (lineOffsetDisplacement.get(awrap.getLineNumber()) != null) {
/*if (lineOffsetDisplacement.get(awrap.getLineNumber()) != null) {
off = lineOffsetDisplacement.get(awrap.getLineNumber());
lineOffsetDisplacement.put(awrap.getLineNumber(),
@@ -1339,7 +1284,7 @@ public class ASTGenerator {
} else {
lineOffsetDisplacement.put(awrap.getLineNumber(),
lineOffsetDisplacementConst);
}
}*/
// Base.loge(getNodeAsString(awrap.getNode()) + ", T:" + pdeOffsets[i][0]
// + ", L:" + pdeOffsets[i][1] + ", O:" + pdeOffsets[i][2]);
// TODO: fix this line after fixing offsets in node wrapper
@@ -1393,7 +1338,7 @@ public class ASTGenerator {
}
protected String lastClickedWord = null;
protected ASTNodeWrapper lastClickedWordNode = null;
protected ASTNode lastClickedWordNode = null;
public String getLastClickedWord() {
return lastClickedWord;
@@ -1421,22 +1366,22 @@ public class ASTGenerator {
+ ", "
+ (ta.getSelectionStop() - ta.getLineStartOffset(line)));
int offwhitespace = ta.getLineStartNonWhiteSpaceOffset(line);
ASTNodeWrapper wnode;
if (lastClickedWord == null || lastClickedWordNode.getNode() == null) {
ASTNode wnode;
if (lastClickedWord == null || lastClickedWordNode == null) {
wnode = getASTNodeAt(line + errorCheckerService.mainClassOffset, selText,
ta.getSelectionStart() - offwhitespace, false);
}
else{
wnode = lastClickedWordNode;
}
if(wnode.getNode() == null){
if(wnode == null){
return null;
}
Messages.loge("Gonna find all occurrences of " + getNodeAsString(wnode.getNode()));
Messages.loge("Gonna find all occurrences of " + getNodeAsString(wnode));
//If wnode is a constructor, find the TD instead.
if (wnode.getNodeType() == ASTNode.METHOD_DECLARATION) {
MethodDeclaration md = (MethodDeclaration) wnode.getNode();
MethodDeclaration md = (MethodDeclaration) wnode;
ASTNode node = md.getParent();
while (node != null) {
if (node instanceof TypeDeclaration) {
@@ -1449,14 +1394,14 @@ public class ASTGenerator {
TypeDeclaration td = (TypeDeclaration) node;
if(td.getName().toString().equals(md.getName().toString())){
Messages.loge("Renaming constructor of " + getNodeAsString(td));
wnode = new ASTNodeWrapper(td);
wnode = td;
}
}
}
DefaultMutableTreeNode defCU =
new DefaultMutableTreeNode(new ASTNodeWrapper(wnode.getNode(), selText));
dfsNameOnly(defCU, wnode.getNode(), selText);
new DefaultMutableTreeNode(wnode);
dfsNameOnly(defCU, wnode, selText);
// Reverse the list obtained via dfs
Stack<Object> tempS = new Stack<>();
@@ -1493,9 +1438,7 @@ public class ASTGenerator {
if (node.getStructuralProperty(prop) instanceof ASTNode) {
ASTNode cnode = (ASTNode) node.getStructuralProperty(prop);
if (isAddableASTNode(cnode)) {
ctnode = new DefaultMutableTreeNode(
new ASTNodeWrapper((ASTNode) node
.getStructuralProperty(prop)));
ctnode = new DefaultMutableTreeNode(node.getStructuralProperty(prop));
tnode.add(ctnode);
visitRecur(cnode, ctnode);
}
@@ -1509,7 +1452,7 @@ public class ASTGenerator {
node.getStructuralProperty(prop);
for (ASTNode cnode : nodelist) {
if (isAddableASTNode(cnode)) {
ctnode = new DefaultMutableTreeNode(new ASTNodeWrapper(cnode));
ctnode = new DefaultMutableTreeNode(cnode);
tnode.add(ctnode);
visitRecur(cnode, ctnode);
} else {
@@ -1531,16 +1474,12 @@ public class ASTGenerator {
temp.push((DefaultMutableTreeNode) cnode.getChildAt(i));
}
if(!(cnode.getUserObject() instanceof ASTNodeWrapper))
if(!(cnode.getUserObject() instanceof ASTNode))
continue;
ASTNodeWrapper awnode = (ASTNodeWrapper) cnode.getUserObject();
ASTNode awnode = (ASTNode) cnode.getUserObject();
// log("Visiting: " + getNodeAsString(awnode.getNode()));
if(isInstanceOfType(awnode.getNode(), decl, name)){
int val[] = errorCheckerService
.JavaToPdeOffsets(awnode.getLineNumber(), 0);
tnode.add(new DefaultMutableTreeNode(new ASTNodeWrapper(awnode
.getNode(), "Line " + (val[1] + 1) + " | Tab: "
+ editor.getSketch().getCode(val[0]).getPrettyName())));
if(isInstanceOfType(awnode, decl, name)){
tnode.add(new DefaultMutableTreeNode(awnode));
}
}
@@ -1757,67 +1696,6 @@ public class ASTGenerator {
return null;
}
/**
*
* @param node
* @param offset
* - from textarea painter
* @param lineStartOffset
* - obtained from findLineOfNode
* @param name
* @param root
* @return
*/
public static ASTNode pinpointOnLine(ASTNode node, int offset,
int lineStartOffset, String name) {
//log("pinpointOnLine node class: " + node.getClass().getSimpleName());
if (node instanceof SimpleName) {
SimpleName sn = (SimpleName) node;
//log(offset+ "off,pol " + getNodeAsString(sn));
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) {
// Base.loge(11 + getNodeAsString(retNode));
return retNode;
}
}
}
} else if (prop.isChildListProperty()) {
List<ASTNode> nodelist = (List<ASTNode>) node
.getStructuralProperty(prop);
for (ASTNode retNode : nodelist) {
ASTNode rr = pinpointOnLine(retNode, offset, lineStartOffset, name);
if (rr != null) {
// Base.loge(12 + getNodeAsString(rr));
return rr;
}
}
}
}
// Base.loge("-1");
return null;
}
/**
* Give this thing a {@link Name} instance - a {@link SimpleName} from the
* ASTNode for ex, and it tries its level best to locate its declaration in
@@ -2487,45 +2365,6 @@ public class ASTGenerator {
}
/**
* For any line or expression, finds the line start offset(java code).
* @param node
* @return
*/
public int getASTNodeLineStartOffset(ASTNode node){
int nodeLineNo = getLineNumber(node);
while(node.getParent() != null){
if (getLineNumber(node.getParent()) == nodeLineNo) {
node = node.getParent();
} else {
break;
}
}
return node.getStartPosition();
}
/**
* For any node, finds various offsets (java code).
*
* @param node
* @return int[]{line number, line number start offset, node start offset,
* node length}
*/
public int[] getASTNodeAllOffsets(ASTNode node){
int nodeLineNo = getLineNumber(node), nodeOffset = node.getStartPosition(), nodeLength = node
.getLength();
while(node.getParent() != null){
if (getLineNumber(node.getParent()) == nodeLineNo) {
node = node.getParent();
} else {
break;
}
}
return new int[]{nodeLineNo, node.getStartPosition(), nodeOffset,nodeLength};
}
static protected String getNodeAsString(ASTNode node) {
if (node == null)
return "NULL";
@@ -2696,7 +2535,13 @@ public class ASTGenerator {
ASTNode astRootNode = (ASTNode) errorCheckerService.getLatestCU().types().get(0);
// If the parsed code contains pde enhancements, take 'em out.
String phrase = ASTNodeWrapper.getJavaCode(pdePhrase);
// TODO: test this
SourceMapping mapping = new SourceMapping();
mapping.addAll(SourceUtils.replaceTypeConstructors(pdePhrase));
mapping.addAll(SourceUtils.replaceHexLiterals(pdePhrase));
mapping.addAll(SourceUtils.replaceColorRegex(pdePhrase));
mapping.addAll(SourceUtils.fixFloatsRegex(pdePhrase));
String phrase = mapping.apply(pdePhrase);
//After typing 'arg.' all members of arg type are to be listed. This one is a flag for it
boolean noCompare = phrase.endsWith(".");
@@ -3056,8 +2901,7 @@ public class ASTGenerator {
}
ASTNode type0 = (ASTNode) cu.types().get(0);
ASTNodeWrapper w = new ASTNodeWrapper(type0);
DefaultMutableTreeNode codeTree = new DefaultMutableTreeNode(w);
DefaultMutableTreeNode codeTree = new DefaultMutableTreeNode(type0);
visitRecur(type0, codeTree);
return codeTree;
}
@@ -3107,67 +2951,6 @@ public class ASTGenerator {
}
private void hideSuggestion() {
((JavaTextArea) editor.getTextArea()).hideSuggestion();
}
public int javaCodeOffsetToLineStartOffset(int line, int jOffset){
// Find the first node with this line number, return its offset - jOffset
line = pdeLineNumToJavaLineNum(line);
log("Looking for line: " + line + ", jOff " + jOffset);
Stack<DefaultMutableTreeNode> temp = new Stack<>();
temp.push(codeTree);
while (!temp.isEmpty()) {
DefaultMutableTreeNode cnode = temp.pop();
for (int i = 0; i < cnode.getChildCount(); i++) {
temp.push((DefaultMutableTreeNode) cnode.getChildAt(i));
}
if (!(cnode.getUserObject() instanceof ASTNodeWrapper))
continue;
ASTNodeWrapper awnode = (ASTNodeWrapper) cnode.getUserObject();
// log("Visiting: " + getNodeAsString(awnode.getNode()));
if (awnode.getLineNumber() == line) {
log("First element with this line no is: " + awnode
+ "LSO: " + (jOffset - awnode.getNode().getStartPosition()));
return (jOffset - awnode.getNode().getStartPosition());
}
}
return -1;
}
/**
* Converts pde line number to java line number
* @param pdeLineNum - pde line number
* @return
*/
protected int pdeLineNumToJavaLineNum(int pdeLineNum){
int javaLineNumber = pdeLineNum + errorCheckerService.getPdeImportsCount();
// Adjust line number for tabbed sketches
int codeIndex = editor.getSketch().getCodeIndex(editor.getCurrentTab());
if (codeIndex > 0)
for (int i = 0; i < codeIndex; i++) {
SketchCode sc = editor.getSketch().getCode(i);
int len = Util.countLines(sc.getProgram()) + 1;
javaLineNumber += len;
}
return javaLineNumber;
}
public String getPDESourceCodeLine(int javaLineNumber) {
Messages.log("* getPDESourceCodeLine");
int res[] = errorCheckerService
.calculateTabIndexAndLineNumber(javaLineNumber);
if (res != null) {
return errorCheckerService.getPdeCodeAtLine(res[0], res[1]);
}
return null;
}
/**
* Returns the java source code line at the given line number
* @param javaLineNumber
@@ -3195,35 +2978,6 @@ public class ASTGenerator {
}
/**
* Returns the java source code line Element at the given line number.
* The Element object stores the offset data, but not the actual line
* of code.
* @param javaLineNumber
* @return
*/
public Element getJavaSourceCodeElement(int javaLineNumber) {
Messages.log("* getJavaSourceCodeElement");
try {
PlainDocument javaSource = new PlainDocument();
javaSource.insertString(0, errorCheckerService.latestResult.preprocessedCode, null);
Element lineElement = javaSource.getDefaultRootElement()
.getElement(javaLineNumber - 1);
if (lineElement == null) {
log("Couldn't fetch jlinenum " + javaLineNumber);
return null;
}
// String javaLine = javaSource.getText(lineElement.getStartOffset(),
// lineElement.getEndOffset()
// - lineElement.getStartOffset());
return lineElement;
} catch (BadLocationException e) {
Messages.loge(e + " in getJavaSourceCodeline() for jinenum: " + javaLineNumber);
}
return null;
}
/// GUI ----------------------------------------------------------------------
@@ -3357,10 +3111,8 @@ public class ASTGenerator {
DefaultMutableTreeNode tnode = (DefaultMutableTreeNode) showUsageTree
.getLastSelectedPathComponent();
if (tnode.getUserObject() instanceof ASTNodeWrapper) {
ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject();
//errorCheckerService.highlightNode(awrap);
awrap.highlightNode(editor);
if (tnode.getUserObject() instanceof ASTNode) {
// TODO: highlight ASTNode
}
}
});
@@ -3466,38 +3218,8 @@ public class ASTGenerator {
}
DefaultMutableTreeNode tnode =
(DefaultMutableTreeNode) debugTree.getLastSelectedPathComponent();
if (tnode.getUserObject() instanceof ASTNodeWrapper) {
ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject();
awrap.highlightNode(editor);
// errorCheckerService.highlightNode(awrap);
//--
try {
int javaLineNumber = getLineNumber(awrap.getNode());
int pdeOffs[] = editor.getErrorChecker()
.calculateTabIndexAndLineNumber(javaLineNumber);
PlainDocument javaSource = new PlainDocument();
javaSource.insertString(0, editor.getErrorChecker()
.latestResult.preprocessedCode, null);
Element lineElement = javaSource.getDefaultRootElement()
.getElement(javaLineNumber - 1);
if (lineElement == null) {
return;
}
String javaLine = javaSource.getText(lineElement.getStartOffset(),
lineElement.getEndOffset()
- lineElement.getStartOffset());
editor.getSketch().setCurrentCode(pdeOffs[0]);
String pdeLine = editor.getLineText(pdeOffs[1]);
//String lookingFor = nodeName.toString();
//log(lookingFor + ", " + nodeName.getStartPosition());
log("JL " + javaLine + " LSO " + lineElement.getStartOffset() + ","
+ lineElement.getEndOffset());
log("PL " + pdeLine);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
if (tnode.getUserObject() instanceof ASTNode) {
// TODO: highlight ASTNode, print some info maybe
}
}

View File

@@ -1,827 +0,0 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Processing project - http://processing.org
Copyright (c) 2012-15 The Processing Foundation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package processing.mode.java.pdex;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.PlainDocument;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import processing.app.Base;
import processing.app.Messages;
import processing.mode.java.JavaEditor;
/**
* Wrapper class for ASTNode objects
* @author Manindra Moharana <me@mkmoharana.com>
*
*/
public class ASTNodeWrapper {
private ASTNode node;
private String label;
private int lineNumber;
/*
* TODO: Every ASTNode object in ASTGenerator.codetree is stored as a
* ASTNodeWrapper instance. So how resource heavy would it be to store a
* pointer to ECS in every instance of ASTNodeWrapper? Currently I will rather
* pass an ECS pointer in the argument when I need to access a method which
* requires a method defined in ECS, i.e, only on demand.
* Bad design choice for ECS methods? IDK, yet.
*/
public ASTNodeWrapper(ASTNode node) {
if (node == null){
return;
}
this.node = node;
label = getNodeAsString(node);
if (label == null)
label = node.toString();
lineNumber = getLineNumber(node);
label += " | Line " + lineNumber;
//apiLevel = 0;
}
public ASTNodeWrapper(ASTNode node, String label){
if (node == null){
return;
}
this.node = node;
if(label != null)
this.label = label;
else{
label = getNodeAsString(node);
if (label == null)
label = node.toString();
label += " | Line " + lineNumber;
}
lineNumber = getLineNumber(node);
}
/**
* For this node, finds various offsets (java code).
* Note that line start offset for this node is int[2] - int[1]
* @return int[]{line number, line number start offset, node start offset,
* node length}
*/
public int[] getJavaCodeOffsets(ErrorCheckerService ecs) {
int nodeOffset = node.getStartPosition(), nodeLength = node
.getLength();
Messages.log("0.nodeOffset " + nodeOffset);
ASTNode thisNode = node;
while (thisNode.getParent() != null) {
if (getLineNumber(thisNode.getParent()) == lineNumber) {
thisNode = thisNode.getParent();
} else {
break;
}
}
/*
* There's an edge case here - multiple statements in a single line.
* After identifying the statement with the line number, I'll have to
* look at previous tree nodes in the same level for same line number.
* The correct line start offset would be the line start offset of
* the first node with this line number.
*
* Using linear search for now. P.S: Eclipse AST iterators are messy.
* TODO: binary search might improve speed by 0.001%?
*/
int altStartPos = thisNode.getStartPosition();
Messages.log("1.Altspos " + altStartPos);
thisNode = thisNode.getParent();
Javadoc jd = null;
/*
* There's another case that needs to be handled. If a TD, MD or FD
* contains javadoc comments(multi or single line) the starting position
* of the javadoc is treated as the beginning of the declaration by the AST parser.
* But that's clearly not what we need. The true decl begins after the javadoc ends.
* So this offset needs to be found carefully and stored in altStartPos
*
*/
if (thisNode instanceof TypeDeclaration) {
jd = ((TypeDeclaration) thisNode).getJavadoc();
altStartPos = getJavadocOffset((TypeDeclaration) thisNode);
Messages.log("Has t jdoc " + ((TypeDeclaration) thisNode).getJavadoc());
} else if (thisNode instanceof MethodDeclaration) {
altStartPos = getJavadocOffset((MethodDeclaration) thisNode);
jd = ((MethodDeclaration) thisNode).getJavadoc();
Messages.log("Has m jdoc " + jd);
} else if (thisNode instanceof FieldDeclaration) {
FieldDeclaration fd = ((FieldDeclaration) thisNode);
jd = fd.getJavadoc();
Messages.log("Has f jdoc " + fd.getJavadoc());
altStartPos = getJavadocOffset(fd);
//nodeOffset = ((VariableDeclarationFragment)(fd.fragments().get(0))).getName().getStartPosition();
}
if (jd == null) {
Messages.log("Visiting children of node " + getNodeAsString(thisNode));
@SuppressWarnings("unchecked")
Iterator<StructuralPropertyDescriptor> it =
thisNode.structuralPropertiesForType().iterator();
boolean flag = true;
while (it.hasNext()) {
StructuralPropertyDescriptor prop = it.next();
if (prop.isChildListProperty()) {
@SuppressWarnings("unchecked")
List<ASTNode> nodelist = (List<ASTNode>)
thisNode.getStructuralProperty(prop);
Messages.log("prop " + prop);
for (ASTNode cnode : nodelist) {
Messages.log("Visiting node " + getNodeAsString(cnode));
if (getLineNumber(cnode) == lineNumber) {
if (flag) {
altStartPos = cnode.getStartPosition();
// log("multi...");
flag = false;
} else {
if (cnode == node) {
// loop only till the current node.
break;
}
// We've located the first node in the line.
// Now normalize offsets till node
//altStartPos += normalizeOffsets(cnode);
}
}
}
}
}
Messages.log("Altspos " + altStartPos);
}
int pdeoffsets[] = getPDECodeOffsets(ecs);
String pdeCode = ecs.getPdeCodeAtLine(pdeoffsets[0],pdeoffsets[1] - 1).trim();
int vals[] = createOffsetMapping(ecs, pdeCode,nodeOffset - altStartPos,nodeLength);
if (vals != null)
return new int[] {
lineNumber, nodeOffset + vals[0] - altStartPos, vals[1] };
else {// no offset mapping needed
Messages.log("joff[1] = " + (nodeOffset - altStartPos));
return new int[] { lineNumber, nodeOffset - altStartPos, nodeLength };
}
}
/**
* When FD has javadoc attached, the beginning of FD is marked as the
* start of the javadoc. This kind of screws things when trying to locate
* the exact name of the FD. So, offset compensations...
*
* @param fd
* @return
*/
private int getJavadocOffset(FieldDeclaration fd){
@SuppressWarnings("unchecked")
List<ASTNode> list = fd.modifiers();
SimpleName sn = (SimpleName) getNode();
Type tp = fd.getType();
int lineNum = getLineNumber(sn);
Messages.log("SN "+sn + ", " + lineNum);
for (ASTNode astNode : list) {
if(getLineNumber(astNode) == lineNum) {
Messages.log("first node in that line " + astNode);
Messages.log("diff " + (sn.getStartPosition() - astNode.getStartPosition()));
return (astNode.getStartPosition());
}
}
if(getLineNumber(fd.getType()) == lineNum) {
Messages.log("first node in that line " + tp);
Messages.log("diff " + (sn.getStartPosition() - tp.getStartPosition()));
return (tp.getStartPosition());
}
return 0;
}
/**
* When MD has javadoc attached, the beginning of FD is marked as the
* start of the javadoc. This kind of screws things when trying to locate
* the exact name of the MD. So, offset compensations...
*
* @param md
* @return
*/
private int getJavadocOffset(MethodDeclaration md) {
@SuppressWarnings("unchecked")
List<ASTNode> list = md.modifiers();
SimpleName sn = (SimpleName) getNode();
int lineNum = getLineNumber(sn);
Messages.log("SN " + sn + ", " + lineNum);
for (ASTNode astNode : list) {
if (getLineNumber(astNode) == lineNum) {
Messages.log("first node in that line " + astNode);
Messages.log("diff " + (sn.getStartPosition() - astNode.getStartPosition()));
return (astNode.getStartPosition());
}
}
if (!md.isConstructor()) {
Type tp = md.getReturnType2();
if (getLineNumber(tp) == lineNum) {
Messages.log("first node in that line " + tp);
Messages.log("diff " + (sn.getStartPosition() - tp.getStartPosition()));
return (tp.getStartPosition());
}
}
return 0;
}
/**
* When TD has javadoc attached, the beginning of FD is marked as the
* start of the javadoc. This kind of screws things when trying to locate
* the exact name of the TD. So, offset compensations...
*
* @param td
* @return
*/
private int getJavadocOffset(TypeDeclaration td){
// TODO: This isn't perfect yet. Class \n \n \n className still breaks it.. :'(
@SuppressWarnings("unchecked")
List<ASTNode> list = td.modifiers();
SimpleName sn = (SimpleName) getNode();
int lineNum = getLineNumber(sn);
Messages.log("SN "+sn + ", " + lineNum);
for (ASTNode astNode : list) {
if (getLineNumber(astNode) == lineNum) {
Messages.log("first node in that line " + astNode);
Messages.log("diff " + (sn.getStartPosition() - astNode.getStartPosition()));
return (astNode.getStartPosition());
}
}
if (td.getJavadoc() != null){
Messages.log("diff "
+ (td.getJavadoc().getStartPosition() + td.getJavadoc().getLength() + 1));
return (td.getJavadoc().getStartPosition() + td.getJavadoc().getLength() + 1);
}
Messages.log("getJavadocOffset(TypeDeclaration td) "+sn + ", found nothing. Meh.");
return 0;
}
/**
* Finds the difference in pde and java code offsets
* @param source
* @param inpOffset
* @param nodeLen
* @return int[0] - difference in start offset, int[1] - node length
*/
private int[] createOffsetMapping(ErrorCheckerService ecs, String source, int inpOffset, int nodeLen) {
int ret[][] = getOffsetMapping(ecs, source);
if(ret == null){
// no offset mapping needed
return null;
}
int javaCodeMap[] = ret[0];
int pdeCodeMap[] = ret[1];
int pi = 1, pj = 1;
pj = 0;
pi = 0;
int count = 1;
// first find the java code index
pj = inpOffset;
int startIndex = javaCodeMap[pj];
// find beginning
while (pdeCodeMap[pi] != startIndex && pi < pdeCodeMap.length)
pi++;
int startoffDif = pi - pj;
int stopindex = javaCodeMap[pj + nodeLen - 1];
Messages.log(startIndex + "SI,St" + stopindex + "sod " + startoffDif);
// count till stopindex
while (pdeCodeMap[pi] < stopindex && pi < pdeCodeMap.length) {
pi++;
count++;
}
// log("PDE maps from " + pdeeCodeMap[pi]);
Messages.log("pde len " + count);
return new int[] { startoffDif, count };
}
/**
* Generates offset mapping between java and pde code
*
* @param source
* @return int[0] - java code offsets, int[1] = pde code offsets
*/
public int[][] getOffsetMapping(ErrorCheckerService ecs, String source) {
/*
* This is some tricky shiz. So detailed explanation follows:
*
* The main issue here is that pde enhancements like color vars, # literals
* and int() type casting deviate from standard java. But I need to exact
* index matching for pde and java versions of snippets.For ex:
* "color col = #ffaadd;" <-PDE version
* "int col = 0xffffaadd;" <-Converted to Java
*
* For exact index mapping, I need to know at which indices either is
* deviating from the other and by what amount. Turns out, it isn't quite
* easy.(1) First I take the pde version of the code as an argument(pde
* version fetched from the editor directly). I then find all instances
* which need to be converted to pure java, marking those indices and the
* index correction needed. (2) Now all java conversions are applied after
* marking the offsets. This ensures that the index order isn't disturbed by
* one at a time conversions as done in preprocessCode() in ECS. Took me
* sometime to figure out this was a bug. (3) Next I create a table(two
* separate arrays) which allows me to look it up for matching any index
* between pde or java version of the snippet. This also lets me find out
* any difference in length between both versions.
*
* Keep in mind though, dark magic was involved in creating the final lookup
* table.
*
* TODO: This is a work in progress. There may be more bugs here in hiding.
*/
Messages.log("Src:" + source);
// Instead of converting pde into java, how can I simply extract the same source
// from the java code? Think. TODO
String sourceAlt = new String(source);
String sourceJava;
synchronized (ecs.astGenerator) {
sourceJava = ecs.astGenerator.getJavaSourceCodeLine(lineNumber);
}
TreeMap<Integer, Integer> offsetmap = new TreeMap<Integer, Integer>();
if(sourceJava.trim().startsWith("public") && !source.startsWith("public")){
offsetmap.put(0,6);
//TODO: This is a temp fix. You GOTTA rewrite offset matching
}
// Find all #[web color]
// Should be 6 digits only.
final String webColorRegexp = "#{1}[A-F|a-f|0-9]{6}\\W";
Pattern webPattern = Pattern.compile(webColorRegexp);
Matcher webMatcher = webPattern.matcher(sourceAlt);
while (webMatcher.find()) {
// log("Found at: " + webMatcher.start());
// log("-> " + found);
offsetmap.put(webMatcher.end() - 1, 3);
}
// Find all color data types
final String colorTypeRegex = "color(?![a-zA-Z0-9_])(?=\\[*)(?!(\\s*\\())";
Pattern colorPattern = Pattern.compile(colorTypeRegex);
Matcher colorMatcher = colorPattern.matcher(sourceAlt);
while (colorMatcher.find()) {
// System.out.print("Start index: " + colorMatcher.start());
// log(" End index: " + colorMatcher.end() + " ");
// log("-->" + colorMatcher.group() + "<--");
offsetmap.put(colorMatcher.end() - 1, -2);
}
// Find all int(), char()
String dataTypeFunc[] = { "int", "char", "float", "boolean", "byte" };
for (String dataType : dataTypeFunc) {
String dataTypeRegexp = "\\b" + dataType + "\\s*\\(";
Pattern pattern = Pattern.compile(dataTypeRegexp);
Matcher matcher = pattern.matcher(sourceAlt);
while (matcher.find()) {
// System.out.print("Start index: " + matcher.start());
// log(" End index: " + matcher.end() + " ");
// log("-->" + matcher.group() + "<--");
offsetmap.put(matcher.end() - 1, ("PApplet.parse").length());
}
matcher.reset();
sourceAlt = matcher.replaceAll("PApplet.parse"
+ Character.toUpperCase(dataType.charAt(0)) + dataType.substring(1)
+ "(");
}
if(offsetmap.isEmpty()){
Messages.log("No offset matching needed.");
return null;
}
// replace with 0xff[webcolor] and others
webMatcher = webPattern.matcher(sourceAlt);
while (webMatcher.find()) {
// log("Found at: " + webMatcher.start());
String found = sourceAlt.substring(webMatcher.start(), webMatcher.end());
// log("-> " + found);
sourceAlt = webMatcher.replaceFirst("0xff" + found.substring(1));
webMatcher = webPattern.matcher(sourceAlt);
}
colorMatcher = colorPattern.matcher(sourceAlt);
sourceAlt = colorMatcher.replaceAll("int");
Messages.log("From direct source: ");
// sourceAlt = sourceJava;
Messages.log(sourceAlt);
// Create code map. Beware! Dark magic ahead.
int javaCodeMap[] = new int[source.length() * 2];
int pdeCodeMap[] = new int[source.length() * 2];
int pi = 1, pj = 1;
int keySum = 0;
for (Integer key : offsetmap.keySet()) {
for (; pi < key +keySum; pi++) {
javaCodeMap[pi] = javaCodeMap[pi - 1] + 1;
}
for (; pj < key; pj++) {
pdeCodeMap[pj] = pdeCodeMap[pj - 1] + 1;
}
Messages.log(key + ":" + offsetmap.get(key));
int kval = offsetmap.get(key);
if (kval > 0) {
// repeat java offsets
pi--;
pj--;
for (int i = 0; i < kval; i++, pi++, pj++) {
if (pi > 1 && pj > 1) {
javaCodeMap[pi] = javaCodeMap[pi - 1];
pdeCodeMap[pj] = pdeCodeMap[pj - 1] + 1;
}
}
} else {
// repeat pde offsets
pi--;
pj--;
for (int i = 0; i < -kval; i++, pi++, pj++) {
if (pi > 1 && pj > 1) {
javaCodeMap[pi] = javaCodeMap[pi - 1] + 1;
pdeCodeMap[pj] = pdeCodeMap[pj - 1];
}
}
}
// after each adjustment, the key values need to keep
// up with changed offset
keySum += kval;
}
javaCodeMap[pi] = javaCodeMap[pi - 1] + 1;
pdeCodeMap[pj] = pdeCodeMap[pj - 1] + 1;
while (pi < sourceAlt.length()) {
javaCodeMap[pi] = javaCodeMap[pi - 1] + 1;
pi++;
}
while (pj < source.length()) {
pdeCodeMap[pj] = pdeCodeMap[pj - 1] + 1;
pj++;
}
if (Base.DEBUG) {
// debug o/p
for (int i = 0; i < pdeCodeMap.length; i++) {
if (pdeCodeMap[i] > 0 || javaCodeMap[i] > 0 || i == 0) {
if (i < source.length())
System.out.print(source.charAt(i));
System.out.print(pdeCodeMap[i] + " - " + javaCodeMap[i]);
if (i < sourceAlt.length())
System.out.print(sourceAlt.charAt(i));
System.out.print(" <-[" + i + "]");
System.out.println();
}
}
System.out.println();
}
return new int[][] { javaCodeMap, pdeCodeMap };
}
/**
* Highlight the ASTNode in the editor, if it's of type
* SimpleName
* @param editor
* @return - true if highlighting was successful
*/
public boolean highlightNode(JavaEditor editor){
if (!(node instanceof SimpleName)) {
return false;
}
SimpleName nodeName = (SimpleName) node;
try {
//TODO: Redundant code. See ASTGenerator.getJavaSourceCodeline()
int javaLineNumber = getLineNumber(nodeName);
int pdeOffs[] = editor.getErrorChecker().calculateTabIndexAndLineNumber(javaLineNumber);
PlainDocument javaSource = new PlainDocument();
javaSource.insertString(0, editor.getErrorChecker().latestResult.preprocessedCode, null);
Element lineElement = javaSource.getDefaultRootElement()
.getElement(javaLineNumber-1);
if(lineElement == null) {
Messages.log(lineNumber + " line element null while highlighting " + nodeName);
return false;
}
String javaLine = javaSource.getText(lineElement.getStartOffset(),
lineElement.getEndOffset()
- lineElement.getStartOffset());
editor.getSketch().setCurrentCode(pdeOffs[0]);
String pdeLine = editor.getLineText(pdeOffs[1]);
String lookingFor = nodeName.toString();
Messages.log(lookingFor + ", " + nodeName.getStartPosition());
Messages.log(javaLineNumber +" JL " + javaLine + " LSO " + lineElement.getStartOffset() + ","
+ lineElement.getEndOffset());
Messages.log(pdeOffs[1] + " PL " + pdeLine);
if (!javaLine.contains(lookingFor) || !pdeLine.contains(lookingFor)) {
Messages.loge("Logical error in highLightNode(). Please file a bug report.");
return false;
}
OffsetMatcher ofm = new OffsetMatcher(pdeLine, javaLine);
int highlightStart = ofm.getPdeOffForJavaOff(nodeName.getStartPosition()
- lineElement.getStartOffset(),
nodeName.getLength());
if (highlightStart == -1) {
Messages.loge("Logical error in highLightNode() during offset matching. " +
"Please file a bug report.");
return false;
}
int lso = editor.getTextArea().getLineStartOffset(pdeOffs[1]);
highlightStart += lso;
editor.setSelection(highlightStart, highlightStart
+ nodeName.getLength());
/*
// First find the name in the java line, and marks its index
Pattern toFind = Pattern.compile("\\b" + nodeName.toString() + "\\b");
Matcher matcher = toFind.matcher(javaLine);
int count = 0, index = 0;
int lsto = lineElement.getStartOffset();
while(matcher.find()){
count++;
//log(matcher.start() + lsto);
if(lsto + matcher.start() == nodeName.getStartPosition())
break;
}
log("count=" + count);
index = 0;
// find the same name in the pde line by its index and get its offsets
matcher = toFind.matcher(pdeLine);
while(matcher.find()){
count--;
if(count == 0){
log("Found on pde line lso: " + matcher.start());
index = matcher.end();
break;
}
}
log("pde lso " + (index - lookingFor.length()));
int lso = astGenerator.editor.ta.getLineStartOffset(pdeOffs[1]);
astGenerator.editor.setSelection(lso + index - lookingFor.length(), lso
+ index);
*/
return true;
} catch (BadLocationException e) {
Messages.loge("BLE in highLightNode() for " + nodeName);
e.printStackTrace();
}
return false;
}
/**
* Gets offset mapping between java and pde code
* int[0][x] stores the java code offset and
* int[1][x] is the corresponding offset in pde code
* @param ecs
* @return int[0] - java code offset, int[1] - pde code offset
*/
public int[][] getOffsetMapping(ErrorCheckerService ecs){
int pdeoffsets[] = getPDECodeOffsets(ecs);
String pdeCode = ecs.getPdeCodeAtLine(pdeoffsets[0],pdeoffsets[1] - 1).trim();
return getOffsetMapping(ecs, pdeCode);
}
/**
*
* @param ecs
* - ErrorCheckerService instance
* @return int[0] - tab number, int[1] - line number in the int[0] tab, int[2]
* - line start offset, int[3] - offset from line start int[2] and
* int[3] are on TODO
*/
public int[] getPDECodeOffsets(ErrorCheckerService ecs) {
return ecs.JavaToPdeOffsets(lineNumber + 1, node.getStartPosition());
}
public int getPDECodeOffsetForSN(ASTGenerator astGen){
if (node instanceof SimpleName) {
Element lineElement = astGen.getJavaSourceCodeElement(lineNumber);
Messages.log("Line element off " + lineElement.getStartOffset());
OffsetMatcher ofm = new OffsetMatcher(astGen.getPDESourceCodeLine(lineNumber),
astGen.getJavaSourceCodeLine(lineNumber));
//log("");
int pdeOffset = ofm.getPdeOffForJavaOff(node.getStartPosition()
- lineElement.getStartOffset(), node.toString().length());
return pdeOffset;
}
return -1;
}
public String toString() {
return label;
}
public ASTNode getNode() {
return node;
}
public String getLabel() {
return label;
}
public int getNodeType() {
return node.getNodeType();
}
public int getLineNumber() {
return lineNumber;
}
/**
* Applies pde enhancements to code.
* TODO: Code reuse happening here. :\
* @param source
* @return
*/
public static String getJavaCode(String source){
Messages.log("Src:" + source);
String sourceAlt = new String(source);
// Find all #[web color]
// Should be 6 digits only.
final String webColorRegexp = "#{1}[A-F|a-f|0-9]{6}\\W";
Pattern webPattern = Pattern.compile(webColorRegexp);
Matcher webMatcher = webPattern.matcher(sourceAlt);
while (webMatcher.find()) {
// log("Found at: " + webMatcher.start());
// log("-> " + found);
}
// Find all color data types
final String colorTypeRegex = "color(?![a-zA-Z0-9_])(?=\\[*)(?!(\\s*\\())";
Pattern colorPattern = Pattern.compile(colorTypeRegex);
Matcher colorMatcher = colorPattern.matcher(sourceAlt);
while (colorMatcher.find()) {
// System.out.print("Start index: " + colorMatcher.start());
// log(" End index: " + colorMatcher.end() + " ");
// log("-->" + colorMatcher.group() + "<--");
}
// Find all int(), char()
String dataTypeFunc[] = { "int", "char", "float", "boolean", "byte" };
for (String dataType : dataTypeFunc) {
String dataTypeRegexp = "\\b" + dataType + "\\s*\\(";
Pattern pattern = Pattern.compile(dataTypeRegexp);
Matcher matcher = pattern.matcher(sourceAlt);
while (matcher.find()) {
// System.out.print("Start index: " + matcher.start());
// log(" End index: " + matcher.end() + " ");
// log("-->" + matcher.group() + "<--");
}
matcher.reset();
sourceAlt = matcher.replaceAll("PApplet.parse"
+ Character.toUpperCase(dataType.charAt(0)) + dataType.substring(1)
+ "(");
}
// replace with 0xff[webcolor] and others
webMatcher = webPattern.matcher(sourceAlt);
while (webMatcher.find()) {
// log("Found at: " + webMatcher.start());
String found = sourceAlt.substring(webMatcher.start(), webMatcher.end());
// log("-> " + found);
sourceAlt = webMatcher.replaceFirst("0xff" + found.substring(1));
webMatcher = webPattern.matcher(sourceAlt);
}
colorMatcher = colorPattern.matcher(sourceAlt);
sourceAlt = colorMatcher.replaceAll("int");
Messages.log("Converted:"+sourceAlt);
return sourceAlt;
}
private static int getLineNumber(ASTNode node) {
return ((CompilationUnit) node.getRoot()).getLineNumber(node
.getStartPosition());
}
/*private static int getLineNumber2(ASTNode thisNode) {
int jdocOffset = 0; Javadoc jd = null;
if(thisNode instanceof TypeDeclaration){
jd = ((TypeDeclaration)thisNode).getJavadoc();
log("Has t jdoc " + ((TypeDeclaration)thisNode).getJavadoc());
} else if(thisNode instanceof MethodDeclaration){
jd = ((MethodDeclaration)thisNode).getJavadoc();
log("Has m jdoc " + jd);
} else if(thisNode instanceof FieldDeclaration){
jd = ((FieldDeclaration)thisNode).getJavadoc();
log("Has f jdoc " + ((FieldDeclaration)thisNode).getJavadoc());
}
if(jd != null){
jdocOffset = 1+jd.getLength();
}
log("ln 2 = " + ((CompilationUnit) thisNode.getRoot()).getLineNumber(thisNode
.getStartPosition() + jdocOffset));
return ((CompilationUnit) thisNode.getRoot()).getLineNumber(thisNode
.getStartPosition() + jdocOffset);
}*/
static private String getNodeAsString(ASTNode node) {
if (node == null)
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 (node instanceof QualifiedName)
value = node.toString() + " | " + 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;
}
}

View File

@@ -36,10 +36,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
@@ -48,6 +50,7 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
@@ -956,19 +959,7 @@ public class ErrorCheckerService {
sketch.getCode(p.getTabIndex()).getPrettyName(),
Integer.toString(p.getLineNumber() + 1));
// Added +1 because lineNumbers internally are 0-indexed
// //TODO: This is temporary
// if (tempErrorLog.size() < 200) {
// tempErrorLog.put(p.getMessage(), p.getIProblem());
// }
}
// table.updateColumns();
// DefaultTableModel tm =
// new DefaultTableModel(errorData, XQErrorTable.columnNames);
// editor.updateTable(tm);
} catch (Exception e) {
Messages.loge("Exception at updateErrorTable()", e);
e.printStackTrace();
@@ -1014,215 +1005,45 @@ public class ErrorCheckerService {
}
/**
* Maps offset from java code to pde code. Returns a bunch of offsets as array
*
* @param line
* - line number in java code
* @param offset
* - offset from the start of the 'line'
* @return int[0] - tab number, int[1] - line number in the int[0] tab, int[2]
* - line start offset, int[3] - offset from line start. int[2] and
* int[3] are on TODO
*/
protected int[] JavaToPdeOffsets(int line, int offset) {
return new int[] { 0, 0 }; // TODO
/*
int codeIndex = 0;
int x = line - mainClassOffset;
if (x < 0) {
// log("Negative line number "
// + problem.getSourceLineNumber() + " , offset "
// + mainClassOffset);
x = line - 2; // Another -1 for 0 index
if (x < programImports.size() && x >= 0) {
ImportStatement is = programImports.get(x);
// log(is.importName + ", " + is.tab + ", "
// + is.lineNumber);
return new int[] { 0, 0 }; // TODO
} else {
// Some seriously ugly stray error, just can't find the source
// line! Simply return first line for first tab.
return new int[] { 0, 1 };
}
protected static int mapJavaToTab(PreprocessedSketch sketch, int offset) {
int tab = Arrays.binarySearch(sketch.tabStarts, offset);
if (tab < 0) {
tab = -(tab + 1) - 1;
}
try {
for (SketchCode sc : editor.getSketch().getCode()) {
if (sc.isExtension("pde")) {
int len;
if (editor.getSketch().getCurrentCode().equals(sc)) {
len = Util.countLines(sc.getDocumentText()) + 1;
} else {
len = Util.countLines(sc.getProgram()) + 1;
}
// log("x,len, CI: " + x + "," + len + ","
// + codeIndex);
if (x >= len) {
// We're in the last tab and the line count is greater
// than the no.
// of lines in the tab,
if (codeIndex >= editor.getSketch().getCodeCount() - 1) {
// log("Exceeds lc " + x + "," + len
// + problem.toString());
// x = len
x = editor.getSketch().getCode(codeIndex)
.getLineCount();
// TODO: Obtain line having last non-white space
// character in the code.
break;
} else {
x -= len;
codeIndex++;
}
} else {
if (codeIndex >= editor.getSketch().getCodeCount()) {
codeIndex = editor.getSketch().getCodeCount() - 1;
}
break;
}
}
}
} catch (Exception e) {
System.err.println("Error inside ErrorCheckerService.JavaToPdeOffset()");
e.printStackTrace();
}
return new int[] { codeIndex, x };
*/
return sketch.tabStarts[tab];
}
protected String getPdeCodeAtLine(int tab, int linenumber){
if(linenumber < 0) return null;
editor.getSketch().setCurrentCode(tab);
return editor.getTextArea().getLineText(linenumber);
protected static int mapJavaToProcessing(PreprocessedSketch sketch, int offset) {
SourceMapping syntaxMapping = sketch.syntaxMapping;
SourceMapping compilationMapping = sketch.compilationMapping;
if (compilationMapping != null) {
offset = compilationMapping.getInputOffset(offset);
}
if (syntaxMapping != null) {
offset = syntaxMapping.getInputOffset(offset);
}
return offset;
}
/**
* Calculates the tab number and line number of the error in that particular
* tab. Provides mapping between pure java and pde code.
*
* @param javalineNumber
* - int
* @return int[0] - tab number, int[1] - line number
*/
protected int[] calculateTabIndexAndLineNumber(int javalineNumber) {
return new int[] { 0, 0 }; // TODO
/*
// String[] lines = {};// = PApplet.split(sourceString, '\n');
int codeIndex = 0;
int x = javalineNumber - mainClassOffset;
if (x < 0) {
// log("Negative line number "
// + problem.getSourceLineNumber() + " , offset "
// + mainClassOffset);
x = javalineNumber - 2; // Another -1 for 0 index
if (x < programImports.size() && x >= 0) {
ImportStatement is = programImports.get(x);
// log(is.importName + ", " + is.tab + ", "
// + is.lineNumber);
return new int[] { 0, 0 }; // TODO
} else {
// Some seriously ugly stray error, just can't find the source
// line! Simply return first line for first tab.
return new int[] { 0, 1 };
}
protected static int mapProcessingToJava(PreprocessedSketch sketch, int offset) {
SourceMapping syntaxMapping = sketch.syntaxMapping;
SourceMapping compilationMapping = sketch.compilationMapping;
if (syntaxMapping != null) {
offset = syntaxMapping.getOutputOffset(offset);
}
try {
for (SketchCode sc : editor.getSketch().getCode()) {
if (sc.isExtension("pde")) {
int len;
if (editor.getSketch().getCurrentCode().equals(sc)) {
len = Util.countLines(sc.getDocumentText()) + 1;
} else {
len = Util.countLines(sc.getProgram()) + 1;
}
// log("x,len, CI: " + x + "," + len + ","
// + codeIndex);
if (x >= len) {
// We're in the last tab and the line count is greater
// than the no.
// of lines in the tab,
if (codeIndex >= editor.getSketch().getCodeCount() - 1) {
// log("Exceeds lc " + x + "," + len
// + problem.toString());
// x = len
x = editor.getSketch().getCode(codeIndex)
.getLineCount();
// TODO: Obtain line having last non-white space
// character in the code.
break;
} else {
x -= len;
codeIndex++;
}
} else {
if (codeIndex >= editor.getSketch().getCodeCount()) {
codeIndex = editor.getSketch().getCodeCount() - 1;
}
break;
}
}
}
} catch (Exception e) {
System.err.println("Things got messed up in ErrorCheckerService.calculateTabIndexAndLineNumber()");
if (compilationMapping != null) {
offset = compilationMapping.getOutputOffset(offset);
}
return new int[] { codeIndex, x };
*/
}
/**
* Now defunct.
* The super method that highlights any ASTNode in the pde editor =D
* @param awrap
* @return true - if highlighting happened correctly.
*/
private boolean highlightNode(ASTNodeWrapper awrap){
Messages.log("Highlighting: " + awrap);
try {
int pdeoffsets[] = awrap.getPDECodeOffsets(this);
int javaoffsets[] = awrap.getJavaCodeOffsets(this);
Messages.log("offsets: " +pdeoffsets[0] + "," +
pdeoffsets[1]+ "," +javaoffsets[1]+ "," +
javaoffsets[2]);
scrollToErrorLine(editor, pdeoffsets[0],
pdeoffsets[1],javaoffsets[1],
javaoffsets[2]);
return true;
} catch (Exception e) {
Messages.loge("Scrolling failed for " + awrap);
// e.printStackTrace();
}
return false;
}
public boolean highlightNode(ASTNode node){
ASTNodeWrapper awrap = new ASTNodeWrapper(node);
return highlightNode(awrap);
return offset;
}
@@ -1250,42 +1071,6 @@ public class ErrorCheckerService {
editor.repaint();
}
/**
* Static method for scroll to a particular line in the PDE. Also highlights
* the length of the text. Requires the editor instance as arguement.
*
* @param edt
* @param tabIndex
* @param lineNoInTab
* - line number in the corresponding tab
* @param lineStartOffset
* - selection start offset(from line start non-whitespace offset)
* @param length
* - length of selection
* @return - true, if scroll was successful
*/
protected static boolean scrollToErrorLine(Editor edt, int tabIndex, int lineNoInTab, int lineStartOffset, int length) {
if (edt == null) {
return false;
}
try {
edt.toFront();
edt.getSketch().setCurrentCode(tabIndex);
int lsno = edt.getTextArea()
.getLineStartNonWhiteSpaceOffset(lineNoInTab - 1) + lineStartOffset;
edt.setSelection(lsno, lsno + length);
edt.getTextArea().scrollTo(lineNoInTab - 1, 0);
edt.repaint();
Messages.log(lineStartOffset + " LSO,len " + length);
} catch (Exception e) {
System.err.println(e
+ " : Error while selecting text in static scrollToErrorLine()");
e.printStackTrace();
return false;
}
return true;
}
/**
* Checks if import statements in the sketch have changed. If they have,

View File

@@ -154,10 +154,9 @@ public class SketchOutline {
if (soTree.getLastSelectedPathComponent() != null) {
DefaultMutableTreeNode tnode = (DefaultMutableTreeNode) soTree
.getLastSelectedPathComponent();
if (tnode.getUserObject() instanceof ASTNodeWrapper) {
ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject();
awrap.highlightNode(editor);
//errorCheckerService.highlightNode(awrap);
if (tnode.getUserObject() instanceof ASTNode) {
ASTNode awrap = (ASTNode) tnode.getUserObject();
// TODO: highlight ASTNode
close();
}
}
@@ -274,11 +273,9 @@ public class SketchOutline {
}
DefaultMutableTreeNode tnode = (DefaultMutableTreeNode) soTree
.getLastSelectedPathComponent();
if (tnode.getUserObject() instanceof ASTNodeWrapper) {
ASTNodeWrapper awrap = (ASTNodeWrapper) tnode.getUserObject();
awrap.highlightNode(editor);
// log(awrap);
//errorCheckerService.highlightNode(awrap);
if (tnode.getUserObject() instanceof ASTNode) {
ASTNode awrap = (ASTNode) tnode.getUserObject();
// TODO: highlight ASTNode
close();
}
@@ -313,27 +310,19 @@ public class SketchOutline {
if (codetree == null)
return;
//log("Visi " + codetree + codetree.getUserObject().getClass().getSimpleName());
if (!(codetree.getUserObject() instanceof ASTNodeWrapper))
if (!(codetree.getUserObject() instanceof ASTNode))
return;
ASTNodeWrapper awnode = (ASTNodeWrapper) codetree.getUserObject(), aw2 = null;
ASTNode awnode = (ASTNode) codetree.getUserObject(), aw2 = null;
if (awnode.getNode() instanceof TypeDeclaration) {
aw2 = new ASTNodeWrapper( ((TypeDeclaration) awnode.getNode()).getName(),
((TypeDeclaration) awnode.getNode()).getName()
.toString());
} else if (awnode.getNode() instanceof MethodDeclaration) {
aw2 = new ASTNodeWrapper(
((MethodDeclaration) awnode.getNode()).getName(),
new CompletionCandidate(
((MethodDeclaration) awnode
.getNode()))
.toString());
} else if (awnode.getNode() instanceof FieldDeclaration) {
FieldDeclaration fd = (FieldDeclaration) awnode.getNode();
if (awnode instanceof TypeDeclaration) {
aw2 = ((TypeDeclaration) awnode).getName();
} else if (awnode instanceof MethodDeclaration) {
aw2 = ((MethodDeclaration) awnode).getName();
} else if (awnode instanceof FieldDeclaration) {
FieldDeclaration fd = (FieldDeclaration) awnode;
for (VariableDeclarationFragment vdf : (List<VariableDeclarationFragment>) fd.fragments()) {
final String text = new CompletionCandidate(vdf).toString();
DefaultMutableTreeNode newNode =
new DefaultMutableTreeNode(new ASTNodeWrapper(vdf.getName(), text));
new DefaultMutableTreeNode(vdf.getName());
node.add(newNode);
}
return;
@@ -380,11 +369,11 @@ public class SketchOutline {
}
public Icon getTreeIcon(Object o) {
if (((DefaultMutableTreeNode) o).getUserObject() instanceof ASTNodeWrapper) {
ASTNodeWrapper awrap = (ASTNodeWrapper)
if (((DefaultMutableTreeNode) o).getUserObject() instanceof ASTNode) {
ASTNode awrap = (ASTNode)
((DefaultMutableTreeNode) o).getUserObject();
int type = awrap.getNode().getParent().getNodeType();
int type = awrap.getParent().getNodeType();
if (type == ASTNode.METHOD_DECLARATION) {
return methodIcon;
} else if (type == ASTNode.TYPE_DECLARATION) {

View File

@@ -1,7 +1,5 @@
package processing.mode.java.pdex;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
@@ -180,52 +178,44 @@ public class SourceUtils {
return edits;
}
/**
* Replaces non-ascii characters with their unicode escape sequences and
* stuff. Used as it is from
* processing.src.processing.mode.java.preproc.PdePreprocessor
*
* @param program
* - Input String containing non ascii characters
* @return String - Converted String
*/
public static String substituteUnicode(String program) {
StringBuilder sb = new StringBuilder(program);
substituteUnicode(sb);
return sb.toString();
public static final Pattern COLOR_TYPE_REGEX =
Pattern.compile("(?:^|^\\p{javaJavaIdentifierPart})(color)\\s(?!\\s*\\()",
Pattern.MULTILINE | Pattern.UNICODE_CHARACTER_CLASS);
public static List<Edit> replaceColorRegex(CharSequence source) {
final List<Edit> edits = new ArrayList<>();
Matcher matcher = COLOR_TYPE_REGEX.matcher(source);
while (matcher.find()) {
int offset = matcher.start(1);
edits.add(Edit.replace(offset, 5, "int"));
}
return edits;
}
public static void substituteUnicode(StringBuilder p) {
// check for non-ascii chars (these will be/must be in unicode format)
int unicodeCount = 0;
for (int i = 0; i < p.length(); i++) {
if (p.charAt(i) > 127) {
unicodeCount++;
}
}
if (unicodeCount == 0) {
return;
}
public static final Pattern NUMBER_LITERAL_REGEX =
Pattern.compile("[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?");
StringBuilder p2 = new StringBuilder(p.length() + 4 * unicodeCount);
public static List<Edit> fixFloatsRegex(CharSequence source) {
final List<Edit> edits = new ArrayList<>();
// if non-ascii chars are in there, convert to unicode escapes
// add unicodeCount * 5.. replacing each unicode char
// with six digit uXXXX sequence (xxxx is in hex)
// (except for nbsp chars which will be a replaced with a space)
for (int i = 0; i < p.length(); i++) {
int c = p.charAt(i);
if (c < 128) {
p2.append(c);
} else if (c == 160) { // unicode for non-breaking space
p2.append(' ');
} else if (c >= 128){
p2.append("\\u").append(String.format("%04X", c));
Matcher matcher = NUMBER_LITERAL_REGEX.matcher(source);
while (matcher.find()) {
int offset = matcher.start();
int end = matcher.end();
String group = matcher.group().toLowerCase();
boolean isFloatingPoint = group.contains(".") || group.contains("e");
boolean hasSuffix = end < source.length() &&
Character.toLowerCase(source.charAt(end)) != 'f' &&
Character.toLowerCase(source.charAt(end)) != 'd';
if (isFloatingPoint && !hasSuffix) {
edits.add(Edit.insert(offset, "f"));
}
}
p.setLength(0);
p.append(p2);
return edits;
}