package bsh;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.ofbiz.plugin.Plugin;
import org.ofbiz.plugin.model.JavaHelper;
import org.ofbiz.plugin.model.JavaHelper.GotoJavaMethodAST;
import org.ofbiz.plugin.model.OfbizModelSingleton;
import org.ofbiz.plugin.model.hyperlink.HyperlinkMarker;
import org.ofbiz.plugin.parser.GoToFile;
public class BeanshellGotoDeclaration {
public static List<HyperlinkMarker> gotoDeclaration(String beanshellCode, final String selectedWord, int currentOffsetInLine, int selectedLineNumber, final IDocument doc) {
List<HyperlinkMarker> retValue = new ArrayList<HyperlinkMarker>();
Parser parser = new Parser(new StringReader(beanshellCode.replaceAll("\t", " ")));
List<String> imports = new ArrayList<String>();
imports.add("java.lang");
Map<String, Integer> variableDeclarations = new HashMap<String, Integer>();
try {
String variable = null;
int currentLineNumber = 0;
/**
* We store all the candidates here that are in the selection
*/
SimpleNode gotBshElement = null;
int prevBeginColumn = 0;
int prevEndColumn = Integer.MAX_VALUE;
Stack<SimpleNode> parseNextNodeStack = new Stack<SimpleNode>();
while (variable == null && !parser.Line()) {
SimpleNode popNode = parser.popNode();
parseNextNodeStack.add(popNode);
while (parseNextNodeStack.size() > 0) {
SimpleNode parseNextNode = parseNextNodeStack.pop();
currentLineNumber = parseNextNode.getLineNumber() - 1;
int beginColumn = parseNextNode.firstToken.beginColumn -1 ;
int endColumn = parseNextNode.lastToken.endColumn + 1;
if (currentLineNumber == selectedLineNumber) {
if (beginColumn <= currentOffsetInLine && endColumn >= currentOffsetInLine) {
if (prevBeginColumn <= beginColumn && prevEndColumn >= endColumn) {
prevBeginColumn = beginColumn;
prevEndColumn = endColumn;
gotBshElement = parseNextNode;
}
}
}
if (parseNextNode.children != null && parseNextNode.children.length > 0) {
parseNextNodeStack.addAll((List<? extends SimpleNode>) Arrays.asList(parseNextNode.children));
}
if (parseNextNode instanceof BSHVariableDeclarator) {
String text = ((BSHVariableDeclarator) parseNextNode).firstToken.image;
Integer integer = variableDeclarations.get(text);
if (integer == null || integer > parseNextNode.getLineNumber()) {
variableDeclarations.put(text, parseNextNode.getLineNumber());
}
}
if (parseNextNode instanceof BSHAssignment) {
String text = ((BSHAssignment) parseNextNode).firstToken.image;
Integer integer = variableDeclarations.get(text);
if (integer == null || integer > parseNextNode.getLineNumber()) {
variableDeclarations.put(text, parseNextNode.getLineNumber());
}
}
if (parseNextNode instanceof BSHImportDeclaration) {
BSHAmbiguousName node = (BSHAmbiguousName) ((BSHImportDeclaration) parseNextNode).children[0];
imports.add(node.text);
}
}
}
if (gotBshElement != null) {
currentLineNumber = gotBshElement.getLineNumber();
SimpleNode bshElement = gotBshElement;
//try to parse every bsh elements in the selection
if (bshElement instanceof BSHAmbiguousName) {
BSHAmbiguousName bshAmbiguousName = (BSHAmbiguousName) bshElement;
String image = bshAmbiguousName.firstToken.image;
final Integer lineNumber = variableDeclarations.get(image);
if (lineNumber != null && bshAmbiguousName.firstToken.beginColumn <= currentOffsetInLine && bshAmbiguousName.firstToken.endColumn >= currentOffsetInLine) { //if it's a variable
int length = bshAmbiguousName.firstToken.endColumn-bshAmbiguousName.firstToken.beginColumn;
addHyperLink(selectedWord, retValue, selectedLineNumber, bshAmbiguousName.firstToken.beginColumn, length, doc, lineNumber);
} else if (bshAmbiguousName.parent instanceof BSHAllocationExpression || bshAmbiguousName.parent instanceof BSHMethodInvocation || bshAmbiguousName.parent instanceof BSHPrimaryExpression) { //try to find the java element
String text;
String method = null;
if (bshAmbiguousName.parent instanceof BSHAllocationExpression ) {
text = bshAmbiguousName.text;
} else if(bshAmbiguousName.parent instanceof BSHMethodInvocation) {
text = bshAmbiguousName.text;
text = text.substring(0, text.indexOf(bshAmbiguousName.lastToken.image) - 1);
method = bshAmbiguousName.lastToken.image;
} else {
text = bshAmbiguousName.firstToken.image;
}
final int offset = bshAmbiguousName.lastToken.beginColumn;
final int length = bshAmbiguousName.lastToken.endColumn - offset;
if (bshAmbiguousName.lastToken.beginColumn <= currentOffsetInLine && bshAmbiguousName.lastToken.endColumn >= currentOffsetInLine) {
IJavaProject javaproject = OfbizModelSingleton.get().findActiveEclipseProject().getJavaproject();
try {
List<String> typesToLookUp = new ArrayList<String>();
if (text.equals("delegator")) {
typesToLookUp.add("org.ofbiz.entity.GenericDelegator");
} else if (text.equals("dispatcher")) {
typesToLookUp.add("org.ofbiz.service.GenericDispatcher");
} else {
typesToLookUp.add(text);
for (String importWord : imports) {
if (importWord.endsWith(text)) {
typesToLookUp.add(importWord);
} else if (importWord.toLowerCase().equals(importWord)) { //is it a import vasdf.*
typesToLookUp.add(importWord + "." + text);
}
}
}
for (final String typeToLookUp : typesToLookUp) {
if (typeToLookUp != null) {
final IType findType = javaproject.findType(typeToLookUp);
if (findType != null) {
if (method != null) {
CompilationUnit parse = JavaHelper.parse(findType.getCompilationUnit());
if (parse != null) {
ASTVisitor astVisitor = new GotoJavaMethodAST(findType, retValue, parse, method, doc, selectedLineNumber, offset, length, bshAmbiguousName.parent.jjtGetChild(1).jjtGetNumChildren());
parse.accept(astVisitor);
}
} else {
retValue.add(new HyperlinkMarker() {
@Override
public String getTypeLabel() {
return null;
}
@Override
public String getHyperlinkText() {
return "Java type: " + typeToLookUp;
}
@Override
public void open() {
try {
IDE.openEditor(GoToFile.getActiveWorkbenchPage(), (IFile) findType.getCompilationUnit().getResource());
} catch (PartInitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
}
}
} catch (JavaModelException e) {
}
}
}
} else if (bshElement instanceof BSHTypedVariableDeclaration) {
BSHTypedVariableDeclaration bshTypedVariableDeclaration = (BSHTypedVariableDeclaration) bshElement;
String firstToken = ((BSHVariableDeclarator)bshTypedVariableDeclaration.children[1]).firstToken.toString();
variable = firstToken;
int lineNumber = bshElement.getLineNumber();
int length = ((BSHVariableDeclarator)bshTypedVariableDeclaration.children[1]).lastToken.endColumn-((BSHVariableDeclarator)bshTypedVariableDeclaration.children[1]).firstToken.beginColumn;
addHyperLink(firstToken, retValue, selectedLineNumber, ((BSHVariableDeclarator)bshTypedVariableDeclaration.children[1]).firstToken.beginColumn, length, doc, lineNumber);
} else if (bshElement instanceof BSHVariableDeclarator) {
BSHVariableDeclarator bshTypedVariableDeclaration = (BSHVariableDeclarator) bshElement;
bshElement.getLineNumber();
String firstToken = bshTypedVariableDeclaration.firstToken.toString();
int lineNumber = bshElement.getLineNumber();
variable = firstToken;
addHyperLink(firstToken, retValue, selectedLineNumber, bshTypedVariableDeclaration.firstToken.beginColumn, bshTypedVariableDeclaration.firstToken.endColumn-bshTypedVariableDeclaration.firstToken.beginColumn, doc, lineNumber);
} else if (bshElement instanceof BSHAssignment) {
BSHAssignment bshTypedVariableDeclaration = (BSHAssignment) bshElement;
bshElement.getLineNumber();
String firstToken = bshTypedVariableDeclaration.firstToken.toString();
if (firstToken.equals(selectedWord)) {
variable = firstToken;
}
bshTypedVariableDeclaration.getText();
}
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return retValue;
}
private static void addHyperLink(final String selectedWord,
List<HyperlinkMarker> retValue, final Integer lineNumber, final int offset, final int length, final IDocument doc, final int linkLineNumber) {
retValue.add(new HyperlinkMarker() {
@Override
public String getTypeLabel() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getHyperlinkText() {
return "Bsh variable first assignment: " + selectedWord;
}
@Override
public void open() {
IFile activeFile = OfbizModelSingleton.get().getActiveFile();
IMarker marker;
try {
marker = activeFile.createMarker(Plugin.TEXT_MARKER);
marker.setAttribute(IMarker.LINE_NUMBER, linkLineNumber);
IDE.openEditor(GoToFile.getActiveWorkbenchPage(), marker);
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public IRegion getHyperlinkRegion() {
try {
return new Region(doc.getLineOffset(lineNumber) + offset - 1, length + 1);
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
});
}
}