Skip to content

Commit b2117b4

Browse files
committed
Add a new context menu command to load dependencies
1 parent 991dce4 commit b2117b4

18 files changed

+352
-20
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.Composition;
4+
using System.Diagnostics;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Windows.Threading;
9+
using dnlib.DotNet;
10+
using dnSpy.AsmEditor.Commands;
11+
using dnSpy.AsmEditor.Properties;
12+
using dnSpy.AsmEditor.UndoRedo;
13+
using dnSpy.Contracts.AsmEditor.Compiler;
14+
using dnSpy.Contracts.Documents;
15+
using dnSpy.Contracts.Documents.Tabs;
16+
using dnSpy.Contracts.Documents.TreeView;
17+
using dnSpy.Contracts.Images;
18+
using dnSpy.Contracts.Menus;
19+
using dnSpy.Contracts.MVVM;
20+
using dnSpy.Contracts.Utilities;
21+
22+
namespace dnSpy.AsmEditor.Compiler {
23+
[DebuggerDisplay("{Description}")]
24+
sealed class LoadAllDependenciesCommand : EditCodeCommandBase {
25+
[ExportMenuItem(Header = "res:LoadAllDependenciesCommand", Group = MenuConstants.GROUP_CTX_DOCUMENTS_ASMED_ILED, Order = 29.999)]
26+
sealed class DocumentsCommand : DocumentsContextMenuHandler {
27+
readonly Lazy<IUndoCommandService> undoCommandService;
28+
readonly Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider;
29+
readonly IAppService appService;
30+
31+
[ImportingConstructor]
32+
DocumentsCommand(Lazy<IUndoCommandService> undoCommandService, Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider, IAppService appService) {
33+
this.undoCommandService = undoCommandService;
34+
this.addUpdatedNodesHelperProvider = addUpdatedNodesHelperProvider;
35+
this.appService = appService;
36+
}
37+
38+
public override bool IsVisible(AsmEditorContext context) => LoadAllDependenciesCommand.CanExecute(context.Nodes);
39+
public override void Execute(AsmEditorContext context) => LoadAllDependenciesCommand.Execute(addUpdatedNodesHelperProvider, undoCommandService, appService, context.Nodes);
40+
}
41+
42+
[ExportMenuItem(OwnerGuid = MenuConstants.APP_MENU_EDIT_GUID, Header = "res:LoadAllDependenciesCommand", Group = MenuConstants.GROUP_APP_MENU_EDIT_ASMED_SETTINGS, Order = 59.999)]
43+
sealed class EditMenuCommand : EditMenuHandler {
44+
readonly Lazy<IUndoCommandService> undoCommandService;
45+
readonly Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider;
46+
readonly IAppService appService;
47+
48+
[ImportingConstructor]
49+
EditMenuCommand(Lazy<IUndoCommandService> undoCommandService, Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider, IAppService appService)
50+
: base(appService.DocumentTreeView) {
51+
this.undoCommandService = undoCommandService;
52+
this.addUpdatedNodesHelperProvider = addUpdatedNodesHelperProvider;
53+
this.appService = appService;
54+
}
55+
56+
public override bool IsVisible(AsmEditorContext context) => LoadAllDependenciesCommand.CanExecute(context.Nodes);
57+
public override void Execute(AsmEditorContext context) => LoadAllDependenciesCommand.Execute(addUpdatedNodesHelperProvider, undoCommandService, appService, context.Nodes);
58+
}
59+
60+
static bool CanExecute(DocumentTreeNodeData[] nodes) => nodes.Length == 1 && GetModuleNode(nodes[0]) is not null;
61+
62+
static ModuleDocumentNode? GetModuleNode(DocumentTreeNodeData node) {
63+
if (node is AssemblyDocumentNode asmNode) {
64+
asmNode.TreeNode.EnsureChildrenLoaded();
65+
return asmNode.TreeNode.DataChildren.FirstOrDefault() as ModuleDocumentNode;
66+
}
67+
else
68+
return node.GetModuleNode();
69+
}
70+
71+
static void Execute(Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider, Lazy<IUndoCommandService> undoCommandService, IAppService appService, DocumentTreeNodeData[] nodes) {
72+
if (!CanExecute(nodes))
73+
return;
74+
75+
var modNode = GetModuleNode(nodes[0]);
76+
Debug2.Assert(modNode is not null);
77+
if (modNode is null)
78+
return;
79+
var module = modNode.Document.ModuleDef;
80+
Debug2.Assert(module is not null);
81+
if (module is null)
82+
throw new InvalidOperationException();
83+
84+
var loadeds = new HashSet<ModuleDef>();
85+
LoadAllDependencies(modNode.Context.DocumentTreeView, module, loadeds);
86+
}
87+
88+
static void LoadAllDependencies(IDocumentTreeView documentTreeView, ModuleDef module, HashSet<ModuleDef> loadeds) {
89+
if (loadeds.Contains(module))
90+
return;
91+
92+
loadeds.Add(module);
93+
foreach (var assemblyRef in module.GetAssemblyRefs()) {
94+
var asm = documentTreeView.DocumentService.Resolve(assemblyRef, module);
95+
if (asm?.ModuleDef is null)
96+
continue;
97+
if (FrameworkFileUtils.IsFrameworkAssembly("", assemblyRef.Name))
98+
continue;
99+
LoadAllDependencies(documentTreeView, asm.ModuleDef, loadeds);
100+
}
101+
}
102+
103+
readonly struct ModuleResult {
104+
public IAssembly? Assembly { get; }
105+
public byte[] RawBytes { get; }
106+
public DebugFileResult DebugFile { get; }
107+
public ModuleResult(IAssembly? assembly, byte[] bytes, DebugFileResult debugFile) {
108+
Assembly = assembly;
109+
RawBytes = bytes;
110+
DebugFile = debugFile;
111+
}
112+
}
113+
114+
LoadAllDependenciesCommand(Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider, ModuleDocumentNode modNode, ModuleImporter importer)
115+
: base(addUpdatedNodesHelperProvider, modNode, importer) {
116+
}
117+
118+
public override string Description => dnSpy_AsmEditor_Resources.LoadAllDependenciesCommand;
119+
}
120+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using System;
2+
using System.ComponentModel.Composition;
3+
using System.Diagnostics;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Windows.Threading;
8+
using dnlib.DotNet;
9+
using dnSpy.AsmEditor.Commands;
10+
using dnSpy.AsmEditor.Properties;
11+
using dnSpy.AsmEditor.UndoRedo;
12+
using dnSpy.Contracts.AsmEditor.Compiler;
13+
using dnSpy.Contracts.Documents.Tabs;
14+
using dnSpy.Contracts.Documents.TreeView;
15+
using dnSpy.Contracts.Images;
16+
using dnSpy.Contracts.Menus;
17+
using dnSpy.Contracts.MVVM;
18+
19+
namespace dnSpy.AsmEditor.Compiler {
20+
[DebuggerDisplay("{Description}")]
21+
sealed class LoadDependenciesCommand : EditCodeCommandBase {
22+
[ExportMenuItem(Header = "res:LoadDependenciesCommand", Group = MenuConstants.GROUP_CTX_DOCUMENTS_ASMED_ILED, Order = 28.999)]
23+
sealed class DocumentsCommand : DocumentsContextMenuHandler {
24+
readonly Lazy<IUndoCommandService> undoCommandService;
25+
readonly Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider;
26+
readonly IAppService appService;
27+
28+
[ImportingConstructor]
29+
DocumentsCommand(Lazy<IUndoCommandService> undoCommandService, Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider, IAppService appService) {
30+
this.undoCommandService = undoCommandService;
31+
this.addUpdatedNodesHelperProvider = addUpdatedNodesHelperProvider;
32+
this.appService = appService;
33+
}
34+
35+
public override bool IsVisible(AsmEditorContext context) => LoadDependenciesCommand.CanExecute(context.Nodes);
36+
public override void Execute(AsmEditorContext context) => LoadDependenciesCommand.Execute(addUpdatedNodesHelperProvider, undoCommandService, appService, context.Nodes);
37+
}
38+
39+
[ExportMenuItem(OwnerGuid = MenuConstants.APP_MENU_EDIT_GUID, Header = "res:LoadDependenciesCommand", Group = MenuConstants.GROUP_APP_MENU_EDIT_ASMED_SETTINGS, Order = 58.999)]
40+
sealed class EditMenuCommand : EditMenuHandler {
41+
readonly Lazy<IUndoCommandService> undoCommandService;
42+
readonly Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider;
43+
readonly IAppService appService;
44+
45+
[ImportingConstructor]
46+
EditMenuCommand(Lazy<IUndoCommandService> undoCommandService, Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider, IAppService appService)
47+
: base(appService.DocumentTreeView) {
48+
this.undoCommandService = undoCommandService;
49+
this.addUpdatedNodesHelperProvider = addUpdatedNodesHelperProvider;
50+
this.appService = appService;
51+
}
52+
53+
public override bool IsVisible(AsmEditorContext context) => LoadDependenciesCommand.CanExecute(context.Nodes);
54+
public override void Execute(AsmEditorContext context) => LoadDependenciesCommand.Execute(addUpdatedNodesHelperProvider, undoCommandService, appService, context.Nodes);
55+
}
56+
57+
static bool CanExecute(DocumentTreeNodeData[] nodes) => nodes.Length == 1 && GetModuleNode(nodes[0]) is not null;
58+
59+
static ModuleDocumentNode? GetModuleNode(DocumentTreeNodeData node) {
60+
if (node is AssemblyDocumentNode asmNode) {
61+
asmNode.TreeNode.EnsureChildrenLoaded();
62+
return asmNode.TreeNode.DataChildren.FirstOrDefault() as ModuleDocumentNode;
63+
}
64+
else
65+
return node.GetModuleNode();
66+
}
67+
68+
static void Execute(Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider, Lazy<IUndoCommandService> undoCommandService, IAppService appService, DocumentTreeNodeData[] nodes) {
69+
if (!CanExecute(nodes))
70+
return;
71+
72+
var modNode = GetModuleNode(nodes[0]);
73+
Debug2.Assert(modNode is not null);
74+
if (modNode is null)
75+
return;
76+
77+
var module = modNode.Document.ModuleDef;
78+
Debug2.Assert(module is not null);
79+
if (module is null)
80+
throw new InvalidOperationException();
81+
82+
foreach (var assemblyRef in module.GetAssemblyRefs()) {
83+
modNode.Context.DocumentTreeView.DocumentService.Resolve(assemblyRef, module);
84+
}
85+
}
86+
87+
readonly struct ModuleResult {
88+
public IAssembly? Assembly { get; }
89+
public byte[] RawBytes { get; }
90+
public DebugFileResult DebugFile { get; }
91+
public ModuleResult(IAssembly? assembly, byte[] bytes, DebugFileResult debugFile) {
92+
Assembly = assembly;
93+
RawBytes = bytes;
94+
DebugFile = debugFile;
95+
}
96+
}
97+
98+
LoadDependenciesCommand(Lazy<IAddUpdatedNodesHelperProvider> addUpdatedNodesHelperProvider, ModuleDocumentNode modNode, ModuleImporter importer)
99+
: base(addUpdatedNodesHelperProvider, modNode, importer) {
100+
}
101+
102+
public override string Description => dnSpy_AsmEditor_Resources.LoadDependenciesCommand;
103+
}
104+
}

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.Designer.cs

+25-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.cs.resx

+6
Original file line numberDiff line numberDiff line change
@@ -2312,4 +2312,10 @@ nutný, pokud jsou metody obfuskovány</value>
23122312
<data name="Type_Flags_Visibility" xml:space="preserve">
23132313
<value>Viditelnost</value>
23142314
</data>
2315+
<data name="LoadDependenciesCommand" xml:space="preserve">
2316+
<value />
2317+
</data>
2318+
<data name="LoadAllDependenciesCommand" xml:space="preserve">
2319+
<value />
2320+
</data>
23152321
</root>

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.de.resx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -2311,4 +2311,10 @@ Möchten Sie das Fenster wirklich schließen?</value>
23112311
<data name="Type_Flags_Visibility" xml:space="preserve">
23122312
<value>Visibilit_y</value>
23132313
</data>
2314+
<data name="LoadDependenciesCommand" xml:space="preserve">
2315+
<value />
2316+
</data>
2317+
<data name="LoadAllDependenciesCommand" xml:space="preserve">
2318+
<value />
2319+
</data>
23142320
</root>

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.es-ES.resx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -2308,4 +2308,10 @@
23082308
<data name="Type_Flags_Visibility" xml:space="preserve">
23092309
<value>Visibilida_d</value>
23102310
</data>
2311+
<data name="LoadDependenciesCommand" xml:space="preserve">
2312+
<value />
2313+
</data>
2314+
<data name="LoadAllDependenciesCommand" xml:space="preserve">
2315+
<value />
2316+
</data>
23112317
</root>

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.fa.resx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -2315,4 +2315,10 @@
23152315
<data name="Type_Flags_Visibility" xml:space="preserve">
23162316
<value>Visibilit_y</value>
23172317
</data>
2318+
<data name="LoadDependenciesCommand" xml:space="preserve">
2319+
<value />
2320+
</data>
2321+
<data name="LoadAllDependenciesCommand" xml:space="preserve">
2322+
<value />
2323+
</data>
23182324
</root>

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.fr.resx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -2309,4 +2309,10 @@ La plupart des options seront réinitialisées si cette option est cochée</valu
23092309
<data name="Type_Flags_Visibility" xml:space="preserve">
23102310
<value>Visibili_té</value>
23112311
</data>
2312+
<data name="LoadDependenciesCommand" xml:space="preserve">
2313+
<value />
2314+
</data>
2315+
<data name="LoadAllDependenciesCommand" xml:space="preserve">
2316+
<value />
2317+
</data>
23122318
</root>

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.hu.resx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -2315,4 +2315,10 @@ A legtöbb beállítás újra lesz inicializálva ha ez a jelölőnégyzet vált
23152315
<data name="Type_Flags_Visibility" xml:space="preserve">
23162316
<value>Lá_thatóság</value>
23172317
</data>
2318+
<data name="LoadDependenciesCommand" xml:space="preserve">
2319+
<value />
2320+
</data>
2321+
<data name="LoadAllDependenciesCommand" xml:space="preserve">
2322+
<value />
2323+
</data>
23182324
</root>

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.it.resx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -2309,4 +2309,10 @@ Sei sicuro di volere uscire?</value>
23092309
<data name="Type_Flags_Visibility" xml:space="preserve">
23102310
<value>Visibilit_y</value>
23112311
</data>
2312+
<data name="LoadDependenciesCommand" xml:space="preserve">
2313+
<value />
2314+
</data>
2315+
<data name="LoadAllDependenciesCommand" xml:space="preserve">
2316+
<value />
2317+
</data>
23122318
</root>

Extensions/dnSpy.AsmEditor/Properties/dnSpy.AsmEditor.Resources.pt-BR.resx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -2312,4 +2312,10 @@ A maioria das opções são reinicializadas quando essa caixa de seleção é cl
23122312
<data name="Type_Flags_Visibility" xml:space="preserve">
23132313
<value>Visibilidade_y</value>
23142314
</data>
2315+
<data name="LoadDependenciesCommand" xml:space="preserve">
2316+
<value />
2317+
</data>
2318+
<data name="LoadAllDependenciesCommand" xml:space="preserve">
2319+
<value />
2320+
</data>
23152321
</root>

0 commit comments

Comments
 (0)