Skip to content

Commit

Permalink
Add call graph display in method view menu
Browse files Browse the repository at this point in the history
  • Loading branch information
Col-E committed Jun 12, 2024
1 parent 0ccfae9 commit 2acd33a
Show file tree
Hide file tree
Showing 8 changed files with 501 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public ClassLookup(@Nonnull Workspace workspace) {

@Override
public JvmClassInfo apply(String name) {
if (name == null) return null;
ClassPathNode classPath = workspace.findJvmClass(name);
if (classPath == null) classPath = workspace.findLatestVersionedJvmClass(name);
if (classPath == null) return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dev.xdark.jlinker.ClassInfo;
import dev.xdark.jlinker.MemberInfo;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import software.coley.recaf.analytics.logging.DebuggingLogger;
import software.coley.recaf.analytics.logging.Logging;
import software.coley.recaf.info.JvmClassInfo;
Expand Down Expand Up @@ -111,10 +112,12 @@ public int accessFlags() {
return info.getAccess();
}

@Nonnull
@Nullable
@Override
public ClassInfo<JvmClassInfo> superClass() {
return superClassLookup.apply(info.getSuperName());
String superName = info.getSuperName();
if (superName == null) return null;
return superClassLookup.apply(superName);
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ public ContextMenuProvider getMethodContextMenuProvider(@Nonnull ContextSource s
// - Add annotation
}

// TODO: implement additional operations
// - View
// - Control flow graph
// - Application flow graph
var view = builder.submenu("menu.view", VIEW);
if (declaringClass.isJvmClass()) {
JvmClassBundle jvmBundle = (JvmClassBundle) bundle;
JvmClassInfo declaringJvmClass = declaringClass.asJvmClass();
view.item("menu.view.methodcallgraph", FLOW, () -> actions.openMethodCallGraph(workspace, resource, jvmBundle,declaringJvmClass, method));
}

// TODO: implement additional operations
// - Deobfuscate
// - Regenerate variable names
// - Optimize with pattern matchers
// - Optimize with SSVM
// - Simulate with SSVM (Virtualize > Run)

// Search actions
builder.item("menu.search.method-references", CODE_REFERENCE, () -> {
MemberReferenceSearchPane pane = actions.openNewMemberReferenceSearch();
Expand All @@ -113,15 +131,6 @@ public ContextMenuProvider getMethodContextMenuProvider(@Nonnull ContextSource s
// Refactor actions
builder.memberItem("menu.refactor.rename", TAG_EDIT, actions::renameMethod);

// TODO: implement additional operations
// - View
// - Control flow graph
// - Application flow graph
// - Deobfuscate
// - Regenerate variable names
// - Optimize with pattern matchers
// - Optimize with SSVM
// - Simulate with SSVM (Virtualize > Run)
return menu;
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import software.coley.recaf.services.mapping.MappingResults;
import software.coley.recaf.services.window.WindowFactory;
import software.coley.recaf.ui.control.FontIconView;
import software.coley.recaf.ui.control.graph.MethodCallGraphsPane;
import software.coley.recaf.ui.control.popup.AddMemberPopup;
import software.coley.recaf.ui.control.popup.ItemListSelectionPopup;
import software.coley.recaf.ui.control.popup.ItemTreeSelectionPopup;
Expand Down Expand Up @@ -96,11 +97,12 @@ public class Actions implements Service {
private final Instance<VideoFilePane> videoPaneProvider;
private final Instance<AssemblerPane> assemblerPaneProvider;
private final Instance<CommentEditPane> documentationPaneProvider;
private final ActionsConfig config;
private final Instance<MethodCallGraphsPane> callGraphsPaneProvider;
private final Instance<StringSearchPane> stringSearchPaneProvider;
private final Instance<NumberSearchPane> numberSearchPaneProvider;
private final Instance<ClassReferenceSearchPane> classReferenceSearchPaneProvider;
private final Instance<MemberReferenceSearchPane> memberReferenceSearchPaneProvider;
private final ActionsConfig config;

@Inject
public Actions(@Nonnull ActionsConfig config,
Expand All @@ -122,6 +124,7 @@ public Actions(@Nonnull ActionsConfig config,
@Nonnull Instance<CommentEditPane> documentationPaneProvider,
@Nonnull Instance<StringSearchPane> stringSearchPaneProvider,
@Nonnull Instance<NumberSearchPane> numberSearchPaneProvider,
@Nonnull Instance<MethodCallGraphsPane> callGraphsPaneProvider,
@Nonnull Instance<ClassReferenceSearchPane> classReferenceSearchPaneProvider,
@Nonnull Instance<MemberReferenceSearchPane> memberReferenceSearchPaneProvider) {
this.config = config;
Expand All @@ -143,6 +146,7 @@ public Actions(@Nonnull ActionsConfig config,
this.documentationPaneProvider = documentationPaneProvider;
this.stringSearchPaneProvider = stringSearchPaneProvider;
this.numberSearchPaneProvider = numberSearchPaneProvider;
this.callGraphsPaneProvider = callGraphsPaneProvider;
this.classReferenceSearchPaneProvider = classReferenceSearchPaneProvider;
this.memberReferenceSearchPaneProvider = memberReferenceSearchPaneProvider;
}
Expand Down Expand Up @@ -1512,6 +1516,44 @@ else if (path instanceof ClassMemberPathNode classMemberPathNode)
});
}


/**
* Exports a class, prompting the user to select a location to save the class to.
*
* @param workspace
* Containing workspace.
* @param resource
* Containing resource.
* @param bundle
* Containing bundle.
* @param declaringClass
* Class declaring the method
* @param method
* Method to show the incoming/outgoing calls of.
*
* @return Navigable reference to the call graph pane.
*/
@Nonnull
public Navigable openMethodCallGraph(@Nonnull Workspace workspace,
@Nonnull WorkspaceResource resource,
@Nonnull JvmClassBundle bundle,
@Nonnull JvmClassInfo declaringClass,
@Nonnull MethodMember method) {
return createContent(() -> {
// Create text/graphic for the tab to create.
String title = Lang.get("menu.view.methodcallgraph") + ": " + method.getName();
Node graphic = new FontIconView(CarbonIcons.FLOW);

// Create content for the tab.
MethodCallGraphsPane content = callGraphsPaneProvider.get();
content.onUpdatePath(PathNodes.memberPath(workspace, resource, bundle, declaringClass, method));

// Build the tab.
return createTab(dockingManager.getPrimaryRegion(), title, graphic, content);
});
}


/**
* Exports a class, prompting the user to select a location to save the class to.
*
Expand Down

0 comments on commit 2acd33a

Please sign in to comment.