Commit e5e3fcaf authored by andrei's avatar andrei

New features for BCO view:

 - added code highlighting (limited to the java code style), also in ASMifier mode
 - added <Ctrl+Click> navigation to java types
 - added javadoc hover for java types
 - added opcode doc hover for opcodes
Fix for BC reference view:
 - in case nothing useful is selected, show the index page for all opcodes
parent 2fa0a025
/*****************************************************************************************
* Copyright (c) 2011 Andrey Loskutov. All rights reserved. This program and the
* accompanying materials are made available under the terms of the BSD License which
* accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php Contributor: Andrey Loskutov -
* initial API and implementation
****************************************************************************************/
/*******************************************************************************
* Copyright (c) 2011 Andrey Loskutov.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributor: Andrei Loskutov - initial API and implementation
*******************************************************************************/
package de.loskutov.bco.ui;
import java.io.File;
......@@ -34,6 +36,7 @@ import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IClassFile;
......@@ -53,6 +56,11 @@ import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameRequestor;
import org.eclipse.jface.text.ITextSelection;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InnerClassNode;
......@@ -1520,4 +1528,64 @@ public class JdtUtils {
return compilePrio;
}
}
/**
* Finds a type by the simple name.
* see org.eclipse.jdt.internal.corext.codemanipulation.AddImportsOperation
* @return null, if no types was found, empty array if more then one type was found,
* or only one element, if single match exists
*/
public static IType[] getTypeForName(String simpleTypeName,
final IJavaSearchScope searchScope, IProgressMonitor monitor)
throws JavaModelException {
final List<IType> result = new ArrayList<IType>();
final TypeFactory fFactory = new TypeFactory();
TypeNameRequestor requestor = new TypeNameRequestor() {
@Override
public void acceptType(int modifiers, char[] packageName,
char[] simpleTypeName1, char[][] enclosingTypeNames, String path) {
IType type = fFactory.create(packageName, simpleTypeName1,
enclosingTypeNames, modifiers, path, searchScope);
if (type != null) {
result.add(type);
}
}
};
int matchRule = SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE;
new SearchEngine().searchAllTypeNames(
null, matchRule,
simpleTypeName.toCharArray(), matchRule,
IJavaSearchConstants.TYPE, searchScope, requestor,
IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor);
return result.toArray(new IType[result.size()]);
}
/**
* Selects the openable elements out of the given ones.
*
* @param elements the elements to filter
* @return the openable elements
*/
public static IJavaElement[] selectOpenableElements(IJavaElement[] elements) {
List<IJavaElement> result= new ArrayList<IJavaElement>(elements.length);
for (int i= 0; i < elements.length; i++) {
IJavaElement element= elements[i];
if(element == null) {
continue;
}
switch (element.getElementType()) {
case IJavaElement.PACKAGE_DECLARATION:
case IJavaElement.PACKAGE_FRAGMENT:
case IJavaElement.PACKAGE_FRAGMENT_ROOT:
case IJavaElement.JAVA_PROJECT:
case IJavaElement.JAVA_MODEL:
break;
default:
result.add(element);
break;
}
}
return result.toArray(new IJavaElement[result.size()]);
}
}
This diff is collapsed.
/*****************************************************************************************
* Copyright (c) 2007 Andrei Loskutov. All rights reserved. This program and the
* Copyright (c) 2011 Andrey Loskutov. All rights reserved. This program and the
* accompanying materials are made available under the terms of the BSD License which
* accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
* Contributor: Eugene Kuleshov - initial API and implementation
* Contributors: Eugene Kuleshov - initial API and implementation
* Andrey Loskutov - fixes
****************************************************************************************/
package de.loskutov.bco.views;
......@@ -11,7 +12,6 @@ package de.loskutov.bco.views;
import java.net.URL;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.help.internal.base.BaseHelpSystem;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
......@@ -30,7 +30,6 @@ import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.objectweb.asm.util.Printer;
import de.loskutov.bco.BytecodeOutlinePlugin;
import de.loskutov.bco.editors.BytecodeClassFileEditor;
......@@ -40,7 +39,6 @@ import de.loskutov.bco.ui.actions.DefaultToggleAction;
public class BytecodeReferenceView extends ViewPart implements IPartListener2, ISelectionListener {
private static final String NLS_PREFIX = "BytecodeReferenceView.";
private Browser browser;
private DefaultToggleAction linkWithViewAction;
private boolean linkWithView;
......@@ -166,7 +164,6 @@ public class BytecodeReferenceView extends ViewPart implements IPartListener2, I
return;
}
int line = -1;
String opcodeName = null;
if (selection instanceof ITextSelection) {
line = ((ITextSelection)selection).getStartLine();
} else if(selection instanceof IStructuredSelection){
......@@ -177,74 +174,27 @@ public class BytecodeReferenceView extends ViewPart implements IPartListener2, I
}
}
if(line >= 0){
int opcode;
if(isViewSelection) {
opcode = ((BytecodeOutlineView)part).getBytecodeInstructionAtLine(line);
} else {
opcode = ((BytecodeClassFileEditor)part).getBytecodeInstructionAtLine(line);
}
if (opcode != -1) {
opcodeName = Printer.OPCODES[opcode];
}
if(line < 0) {
shouDefaultEmptyPage();
return;
}
if (opcodeName != null) {
opcodeName = checkOpcodeName(opcodeName);
URL url = getHelpResource(opcodeName);
if (url != null) {
browser.setUrl(url.toString());
} else {
shouDefaultEmptyPage();
}
int opcode;
if(isViewSelection) {
opcode = ((BytecodeOutlineView)part).getBytecodeInstructionAtLine(line);
} else {
opcode = ((BytecodeClassFileEditor)part).getBytecodeInstructionAtLine(line);
}
URL url = HelpUtils.getHelpResource(opcode);
if (url != null) {
browser.setUrl(url.toString());
} else {
shouDefaultEmptyPage();
}
}
private void shouDefaultEmptyPage() {
browser.setText(BytecodeOutlinePlugin.getResourceString(NLS_PREFIX
+ "empty.selection.text"));
browser.setUrl(HelpUtils.getHelpIndex().toString());
}
private static String checkOpcodeName(String opcodeName) {
opcodeName = opcodeName.toLowerCase();
/*
* we need an additional check for DCONST_1...5, FCONST_1...5 etc case
* to convert it to DCONST_D etc
*/
int sepIndex = opcodeName.indexOf('_');
if(sepIndex > 0 && Character.isDigit(opcodeName.charAt(sepIndex + 1))){
opcodeName = opcodeName.substring(0, sepIndex);
switch(opcodeName.charAt(0)){
case 'd':
opcodeName += "_d";
break;
case 'f':
opcodeName += "_f";
break;
case 'l':
opcodeName += "_l";
break;
default:
// ICONST uses "n"
opcodeName += "_n";
break;
}
}
return opcodeName;
}
private static URL getHelpResource(String name) {
try {
String href = "/"
+ BytecodeOutlinePlugin.getDefault().getBundle()
.getSymbolicName() + "/doc/ref-" + name + ".html";
return BaseHelpSystem.resolve(href, true);
} catch (Exception e) {
return null;
}
}
}
/*******************************************************************************
* Copyright (c) 2011 Andrey Loskutov.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributor: Andrei Loskutov - initial API and implementation
*******************************************************************************/
package de.loskutov.bco.views;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import org.eclipse.core.runtime.Platform;
import org.eclipse.help.internal.base.BaseHelpSystem;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jface.internal.text.html.HTMLPrinter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.objectweb.asm.util.Printer;
import org.osgi.framework.Bundle;
import de.loskutov.bco.BytecodeOutlinePlugin;
public class HelpUtils {
private static String styleSheet;
private static final RGB BG_COLOR_RGB = Display.getDefault().getSystemColor(SWT.COLOR_INFO_BACKGROUND).getRGB();
private static final RGB FG_COLOR_RGB = Display.getDefault().getSystemColor(SWT.COLOR_INFO_FOREGROUND).getRGB();
private static final String DOC_BASE = "/" + BytecodeOutlinePlugin.getDefault().getBundle().getSymbolicName() + "/doc/";
private static String checkOpcodeName(String opcodeName) {
opcodeName = opcodeName.toLowerCase();
/*
* we need an additional check for DCONST_1...5, FCONST_1...5 etc case
* to convert it to DCONST_D etc
*/
int sepIndex = opcodeName.indexOf('_');
if(sepIndex > 0 && Character.isDigit(opcodeName.charAt(sepIndex + 1))){
opcodeName = opcodeName.substring(0, sepIndex);
switch(opcodeName.charAt(0)){
case 'd':
opcodeName += "_d";
break;
case 'f':
opcodeName += "_f";
break;
case 'l':
opcodeName += "_l";
break;
default:
// ICONST uses "n"
opcodeName += "_n";
break;
}
}
return opcodeName;
}
public static URL getHelpResource(int opcode) {
if(opcode < 0 || opcode >= Printer.OPCODES.length) {
return null;
}
String opcodeName = Printer.OPCODES[opcode];
if (opcodeName != null) {
opcodeName = checkOpcodeName(opcodeName);
}
if(opcodeName == null) {
return null;
}
return getHelpResource(opcodeName);
}
private static URL getHelpResource(String name) {
String href = DOC_BASE + "ref-" + name + ".html";
return resolveToHelpUrl(href);
}
public static URL getHelpIndex() {
String href = DOC_BASE + "opcodes.html";
return resolveToHelpUrl(href);
}
private static String getDocBase() {
URL base = resolveToHelpUrl(DOC_BASE);
if (base != null) {
return base.toString();
}
return null;
}
private static URL resolveToHelpUrl(String path) {
try {
return BaseHelpSystem.resolve(path, true);
} catch (Exception e) {
return null;
}
}
private static void appendColor(StringBuilder buffer, RGB rgb) {
buffer.append('#');
appendAsHexString(buffer, rgb.red);
appendAsHexString(buffer, rgb.green);
appendAsHexString(buffer, rgb.blue);
}
private static void appendAsHexString(StringBuilder buffer, int intValue) {
String hexValue= Integer.toHexString(intValue);
if (hexValue.length() == 1) {
buffer.append('0');
}
buffer.append(hexValue);
}
/**
* From {@link JavadocHover} class: returns the Javadoc hover style sheet with the
* current Javadoc font from the preferences.
* @return the updated style sheet
*/
public static String getHelpStyleSheet() {
if (styleSheet == null) {
styleSheet = loadStyleSheet();
}
String css = styleSheet;
if (css == null || css.isEmpty()) {
return "";
}
FontData fontData= JFaceResources.getFontRegistry().getFontData(
PreferenceConstants.APPEARANCE_JAVADOC_FONT)[0];
css = HTMLPrinter.convertTopLevelFont(css, fontData);
StringBuilder sb = new StringBuilder(css);
sb.append("\nbody { background-color:");
appendColor(sb, BG_COLOR_RGB);
sb.append("; color:");
appendColor(sb, FG_COLOR_RGB);
sb.append("; }\n");
return sb.toString();
}
/**
* From {@link JavadocHover} class: loads and returns the Javadoc hover style sheet.
* @return the style sheet, or empty string if unable to load
*/
private static String loadStyleSheet() {
Bundle bundle= Platform.getBundle(JavaPlugin.getPluginId());
URL styleSheetURL= bundle.getEntry("/JavadocHoverStyleSheet.css"); //$NON-NLS-1$
if (styleSheetURL == null) {
return "";
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(styleSheetURL.openStream(), "UTF-8"));
StringBuilder sb = new StringBuilder(1500);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append('\n');
}
return sb.toString();
} catch (IOException ex) {
return "";
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
//
}
}
}
public static StringBuilder getOpcodeHelpFor(int opcode) {
URL helpResource = getHelpResource(opcode);
StringBuilder sb = new StringBuilder();
if(helpResource == null) {
return sb;
}
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(helpResource.openStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
return sb;
} finally {
if(in != null) {
try {
in.close();
} catch (IOException e) {
//
}
}
}
int styleEnd = sb.indexOf("</style>");
if(styleEnd > 0) {
sb.insert(styleEnd, getHelpStyleSheet());
}
int endHeadIdx= sb.indexOf("</head>"); //$NON-NLS-1$
String base = getDocBase();
if(base != null) {
sb.insert(endHeadIdx, "\n<base href='" + base + "'>\n");
}
return sb;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment